1#!/usr/bin/env python3 2# Copyright (C) 2023 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License a 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16from python.generators.diff_tests.testing import Path, DataPath, Metric 17from python.generators.diff_tests.testing import Csv, Json, TextProto 18from python.generators.diff_tests.testing import DiffTestBlueprint 19from python.generators.diff_tests.testing import TestSuite 20 21 22class ChromeMetrics(TestSuite): 23 # Tests related to Chrome's use of Perfetto. Chrome histogram hashes 24 def test_chrome_histogram_hashes(self): 25 return DiffTestBlueprint( 26 trace=TextProto(r""" 27 packet { 28 trusted_packet_sequence_id: 1 29 timestamp: 0 30 incremental_state_cleared: true 31 track_event { 32 categories: "cat1" 33 type: 3 34 name_iid: 1 35 chrome_histogram_sample { 36 name_hash: 10 37 sample: 100 38 } 39 } 40 } 41 packet { 42 trusted_packet_sequence_id: 1 43 timestamp: 0 44 incremental_state_cleared: true 45 track_event { 46 categories: "cat2" 47 type: 3 48 name_iid: 2 49 chrome_histogram_sample { 50 name_hash: 20 51 } 52 } 53 } 54 """), 55 query=Metric('chrome_histogram_hashes'), 56 out=TextProto(r""" 57 [perfetto.protos.chrome_histogram_hashes]: { 58 hash: 10 59 hash: 20 60 } 61 """)) 62 63 # Chrome user events 64 def test_chrome_user_event_hashes(self): 65 return DiffTestBlueprint( 66 trace=TextProto(r""" 67 packet { 68 trusted_packet_sequence_id: 1 69 timestamp: 0 70 incremental_state_cleared: true 71 track_event { 72 categories: "cat1" 73 type: 3 74 name_iid: 1 75 chrome_user_event { 76 action_hash: 10 77 } 78 } 79 } 80 packet { 81 trusted_packet_sequence_id: 1 82 timestamp: 0 83 incremental_state_cleared: true 84 track_event { 85 categories: "cat2" 86 type: 3 87 name_iid: 2 88 chrome_user_event { 89 action_hash: 20 90 } 91 } 92 } 93 """), 94 query=Metric('chrome_user_event_hashes'), 95 out=TextProto(r""" 96 [perfetto.protos.chrome_user_event_hashes]: { 97 action_hash: 10 98 action_hash: 20 99 } 100 """)) 101 102 # Chrome performance mark 103 def test_chrome_performance_mark_hashes(self): 104 return DiffTestBlueprint( 105 trace=TextProto(r""" 106 packet { 107 trusted_packet_sequence_id: 1 108 timestamp: 0 109 incremental_state_cleared: true 110 track_event { 111 categories: "cat1" 112 type: 3 113 name: "name1" 114 [perfetto.protos.ChromeTrackEvent.chrome_hashed_performance_mark] { 115 site_hash: 10 116 mark_hash: 100 117 } 118 } 119 } 120 packet { 121 trusted_packet_sequence_id: 1 122 timestamp: 0 123 incremental_state_cleared: true 124 track_event { 125 categories: "cat2" 126 type: 3 127 name: "name2" 128 [perfetto.protos.ChromeTrackEvent.chrome_hashed_performance_mark] { 129 site_hash: 20 130 mark_hash: 200 131 } 132 } 133 } 134 """), 135 query=Metric('chrome_performance_mark_hashes'), 136 out=TextProto(r""" 137 [perfetto.protos.chrome_performance_mark_hashes]: { 138 site_hash: 10 139 site_hash: 20 140 mark_hash: 100 141 mark_hash: 200 142 } 143 """)) 144 145 # Chrome study 146 def test_chrome_study_hashes(self): 147 return DiffTestBlueprint( 148 trace=TextProto(r""" 149 packet { 150 trusted_packet_sequence_id: 1 151 timestamp: 0 152 incremental_state_cleared: true 153 chrome_trigger { 154 trigger_name_hash: 10 155 } 156 } 157 packet { 158 trusted_packet_sequence_id: 1 159 timestamp: 0 160 incremental_state_cleared: true 161 chrome_trigger { 162 trigger_name_hash: 20 163 } 164 } 165 """), 166 query=Metric('chrome_study_hashes'), 167 out=TextProto(r""" 168 [perfetto.protos.chrome_study_hashes]: { 169 hash: 10 170 hash: 20 171 } 172 """)) 173 174 # Chrome reliable range 175 def test_chrome_reliable_range(self): 176 return DiffTestBlueprint( 177 trace=Path('chrome_reliable_range.textproto'), 178 query=Path('chrome_reliable_range_test.sql'), 179 out=Csv(""" 180 "start","reason","debug_limiting_upid","debug_limiting_utid" 181 12,"First slice for utid=2","[NULL]",2 182 """)) 183 184 def test_chrome_reliable_range_cropping(self): 185 return DiffTestBlueprint( 186 trace=Path('chrome_reliable_range_cropping.textproto'), 187 query=Path('chrome_reliable_range_test.sql'), 188 out=Csv(""" 189 "start","reason","debug_limiting_upid","debug_limiting_utid" 190 10000,"Range of interest packet","[NULL]",2 191 """)) 192 193 def test_chrome_reliable_range_missing_processes(self): 194 return DiffTestBlueprint( 195 trace=Path('chrome_reliable_range_missing_processes.textproto'), 196 query=Path('chrome_reliable_range_test.sql'), 197 out=Csv(""" 198 "start","reason","debug_limiting_upid","debug_limiting_utid" 199 1011,"Missing process data for upid=2",2,1 200 """)) 201 202 def test_chrome_reliable_range_missing_browser_main(self): 203 return DiffTestBlueprint( 204 trace=Path('chrome_reliable_range_missing_browser_main.textproto'), 205 query=Path('chrome_reliable_range_test.sql'), 206 out=Csv(""" 207 "start","reason","debug_limiting_upid","debug_limiting_utid" 208 1011,"Missing main thread for upid=1",1,1 209 """)) 210 211 def test_chrome_reliable_range_missing_gpu_main(self): 212 return DiffTestBlueprint( 213 trace=Path('chrome_reliable_range_missing_gpu_main.textproto'), 214 query=Path('chrome_reliable_range_test.sql'), 215 out=Csv(""" 216 "start","reason","debug_limiting_upid","debug_limiting_utid" 217 1011,"Missing main thread for upid=1",1,1 218 """)) 219 220 def test_chrome_reliable_range_missing_renderer_main(self): 221 return DiffTestBlueprint( 222 trace=Path('chrome_reliable_range_missing_renderer_main.textproto'), 223 query=Path('chrome_reliable_range_test.sql'), 224 out=Csv(""" 225 "start","reason","debug_limiting_upid","debug_limiting_utid" 226 1011,"Missing main thread for upid=1",1,1 227 """)) 228 229 def test_chrome_reliable_range_non_chrome_process(self): 230 return DiffTestBlueprint( 231 # We need a trace with a large number of non-chrome slices, so that the 232 # reliable range is affected by their filtering. 233 trace=DataPath('example_android_trace_30s.pb'), 234 query=Path('chrome_reliable_range_test.sql'), 235 out=Csv(""" 236 "start","reason","debug_limiting_upid","debug_limiting_utid" 237 0,"[NULL]","[NULL]","[NULL]" 238 """)) 239 240 # Chrome slices 241 def test_chrome_slice_names(self): 242 return DiffTestBlueprint( 243 trace=TextProto(r""" 244 packet { 245 trusted_packet_sequence_id: 1 246 timestamp: 1000 247 track_event { 248 categories: "cat" 249 name: "Looper.Dispatch: class1" 250 type: 3 251 } 252 } 253 packet { 254 trusted_packet_sequence_id: 1 255 timestamp: 2000 256 track_event { 257 categories: "cat" 258 name: "name2" 259 type: 3 260 } 261 } 262 packet { 263 chrome_metadata { 264 chrome_version_code: 123 265 } 266 } 267 """), 268 query=Metric('chrome_slice_names'), 269 out=TextProto(r""" 270 [perfetto.protos.chrome_slice_names]: { 271 chrome_version_code: 123 272 slice_name: "Looper.Dispatch: class1" 273 slice_name: "name2" 274 } 275 """)) 276 277 # Chrome stack samples. 278 def test_chrome_stack_samples_for_task(self): 279 return DiffTestBlueprint( 280 trace=DataPath('chrome_stack_traces_symbolized_trace.pftrace'), 281 query=""" 282 SELECT RUN_METRIC('chrome/chrome_stack_samples_for_task.sql', 283 'target_duration_ms', '0.000001', 284 'thread_name', '"CrBrowserMain"', 285 'task_name', '"sendTouchEvent"'); 286 287 SELECT 288 sample.description, 289 sample.ts, 290 sample.depth 291 FROM chrome_stack_samples_for_task sample 292 JOIN ( 293 SELECT 294 ts, 295 dur 296 FROM slice 297 WHERE ts = 696373965001470 298 ) test_slice 299 ON sample.ts >= test_slice.ts 300 AND sample.ts <= test_slice.ts + test_slice.dur 301 ORDER BY sample.ts, sample.depth; 302 """, 303 out=Path('chrome_stack_samples_for_task_test.out')) 304 305 # Trace proto content 306 def test_proto_content(self): 307 return DiffTestBlueprint( 308 trace=DataPath('chrome_scroll_without_vsync.pftrace'), 309 query=Path('proto_content_test.sql'), 310 out=Path('proto_content.out')) 311 312 # TODO(mayzner): Uncomment when it works 313 # def test_proto_content_path(self): 314 # return DiffTestBlueprint( 315 # trace=DataPath('chrome_scroll_without_vsync.pftrace'), 316 # query=Path('proto_content_path_test.sql'), 317 # out=Csv(""" 318 # "total_size","field_type","field_name","parent_id","event_category","event_name" 319 # 137426,"TracePacket","[NULL]","[NULL]","[NULL]","[NULL]" 320 # 59475,"TrackEvent","#track_event",415,"[NULL]","[NULL]" 321 # 37903,"TrackEvent","#track_event",17,"[NULL]","[NULL]" 322 # 35904,"int32","#trusted_uid",17,"[NULL]","[NULL]" 323 # 35705,"TracePacket","[NULL]","[NULL]","input,benchmark","LatencyInfo.Flow" 324 # 29403,"TracePacket","[NULL]","[NULL]","cc,input","[NULL]" 325 # 24703,"ChromeLatencyInfo","#chrome_latency_info",18,"[NULL]","[NULL]" 326 # 22620,"uint64","#time_us",26,"[NULL]","[NULL]" 327 # 18711,"TrackEvent","#track_event",1467,"[NULL]","[NULL]" 328 # 15606,"uint64","#timestamp",17,"[NULL]","[NULL]" 329 # """)) 330