@@ -516,3 +516,93 @@ def get_json_corr_id(x):
516516
517517 for a , b in zip (_csv_data_sorted , _js_data_sorted ):
518518 _perform_csv_json_match (a , b , keys_mapping [category ], json_data )
519+
520+
521+ def test_perfetto_hip_event_annotations (pftrace_data , pftrace_filename ):
522+ """
523+ Test that HIP event API calls have event handle annotations in perfetto.
524+ This validates the feature that adds event ID annotations for HIP event API arguments.
525+
526+ The feature adds annotations for:
527+ - hipEventRecord: 'event' argument
528+ - hipEventSynchronize: 'event' argument
529+ - hipEventElapsedTime: 'start' and 'stop' arguments
530+ - hipStreamWaitEvent: 'event' argument
531+
532+ Args:
533+ pftrace_data: DataFrame with perfetto trace data
534+ pftrace_filename: Path to the perfetto trace file for direct queries
535+ """
536+ import pytest
537+ from rocprofiler_sdk .pytest_utils .perfetto_reader import PerfettoReader
538+
539+ # Filter for HIP API traces
540+ hip_api_data = pftrace_data .loc [pftrace_data ["category" ] == "hip_api" ]
541+
542+ if hip_api_data .empty :
543+ pytest .skip ("No HIP API traces found" )
544+
545+ # Get the PerfettoReader to query the args table
546+ reader = PerfettoReader (pftrace_filename )
547+
548+ # Access the trace processor directly
549+ if not reader .trace_processor :
550+ pytest .skip ("Trace processor not available" )
551+
552+ # Query for HIP event API slices and their arguments
553+ # The args table joins with slice table on arg_set_id
554+ query = """
555+ SELECT
556+ slice.name as slice_name,
557+ slice.id as slice_id,
558+ args.key as arg_name,
559+ args.string_value as arg_value
560+ FROM slice
561+ JOIN args ON slice.arg_set_id = args.arg_set_id
562+ WHERE slice.category = 'hip_api'
563+ AND (
564+ slice.name LIKE '%hipEventRecord%' OR
565+ slice.name LIKE '%hipEventSynchronize%' OR
566+ slice.name LIKE '%hipEventElapsedTime%' OR
567+ slice.name LIKE '%hipStreamWaitEvent%'
568+ )
569+ AND (
570+ args.key = 'debug.event' OR
571+ args.key = 'debug.start' OR
572+ args.key = 'debug.stop'
573+ )
574+ """
575+
576+ result = reader .query_tp (query )
577+
578+ # Check if we found any event handle annotations
579+ if result .empty :
580+ pytest .skip (
581+ "No HIP event API calls with event annotations found. "
582+ )
583+
584+ print (f"\n { len (result )} HIP event argument annotations found:" )
585+ print (result .to_string ())
586+
587+ # Validate the structure
588+ assert "slice_name" in result .columns
589+ assert "arg_name" in result .columns
590+ assert "arg_value" in result .columns
591+
592+ # Validate that we have expected argument names
593+ found_arg_names = set (result ["arg_name" ].unique ())
594+ expected_arg_names = {"debug.event" , "debug.start" , "debug.stop" }
595+ assert found_arg_names .issubset (
596+ expected_arg_names
597+ ), f"Found unexpected arg names: { found_arg_names - expected_arg_names } "
598+
599+ # Validate that event values are present (non-null)
600+ null_values = result [result ["arg_value" ].isna ()]
601+ assert (
602+ null_values .empty
603+ ), f"Found { len (null_values )} event arguments with null values"
604+
605+ print (
606+ f"\n Validation passed: Found { len (result )} event handle annotations "
607+ f"with arg names: { found_arg_names } "
608+ )
0 commit comments