#!/usr/bin/env python3 # MIT License # # Copyright (c) 2023-2025 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import sys import pytest test_api_traces = [ "hip_api_traces", "hsa_api_traces", "marker_api_traces", "rccl_api_traces", ] # helper function def node_exists(name, data, min_len=1): assert name in data assert data[name] is not None if isinstance(data[name], (list, tuple, dict, set)): assert len(data[name]) >= min_len def test_data_structure(input_data): """verify minimum amount of expected data is present""" data = input_data node_exists("rocprofiler-sdk-json-tool", data) sdk_data = data["rocprofiler-sdk-json-tool"] node_exists("metadata", sdk_data) node_exists("pid", sdk_data["metadata"]) node_exists("main_tid", sdk_data["metadata"]) node_exists("init_time", sdk_data["metadata"]) node_exists("fini_time", sdk_data["metadata"]) node_exists("agents", sdk_data) node_exists("call_stack", sdk_data) node_exists("callback_records", sdk_data) node_exists("buffer_records", sdk_data) node_exists("names", sdk_data["callback_records"]) node_exists("names", sdk_data["buffer_records"]) for titr in test_api_traces: min_len = ( 1 if titr in [ "hip_api_traces", "hsa_api_traces", ] else 0 ) node_exists(titr, sdk_data["callback_records"], min_len) node_exists(titr, sdk_data["buffer_records"], min_len) node_exists("retired_correlation_ids", sdk_data["buffer_records"]) def test_timestamps(input_data): data = input_data sdk_data = data["rocprofiler-sdk-json-tool"] cb_start = {} cb_end = {} for titr in test_api_traces: for itr in sdk_data["callback_records"][titr]: cid = itr["correlation_id"]["internal"] phase = itr["phase"] if phase == 1: cb_start[cid] = itr["timestamp"] elif phase == 2: cb_end[cid] = itr["timestamp"] assert cb_start[cid] <= itr["timestamp"] else: assert phase == 1 or phase == 2 for itr in sdk_data["buffer_records"][titr]: assert itr["start_timestamp"] <= itr["end_timestamp"] def test_retired_correlation_ids(input_data): data = input_data sdk_data = data["rocprofiler-sdk-json-tool"] def _sort_dict(inp): return dict(sorted(inp.items())) api_corr_ids = {} for titr in test_api_traces: for itr in sdk_data["buffer_records"][titr]: corr_id = itr["correlation_id"]["internal"] assert corr_id not in api_corr_ids.keys() api_corr_ids[corr_id] = itr retired_corr_ids = {} for itr in sdk_data["buffer_records"]["retired_correlation_ids"]: corr_id = itr["internal_correlation_id"] assert corr_id not in retired_corr_ids.keys() retired_corr_ids[corr_id] = itr api_corr_ids = _sort_dict(api_corr_ids) retired_corr_ids = _sort_dict(retired_corr_ids) for cid, itr in api_corr_ids.items(): assert cid in retired_corr_ids.keys() retired_ts = retired_corr_ids[cid]["timestamp"] end_ts = itr["end_timestamp"] assert (retired_ts - end_ts) > 0, f"correlation-id: {cid}, data: {itr}" assert len(api_corr_ids.keys()) == (len(retired_corr_ids.keys())) if __name__ == "__main__": exit_code = pytest.main(["-x", __file__] + sys.argv[1:]) sys.exit(exit_code)