1// Copyright (C) 2018 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {assertExists} from '../base/logging'; 16import {TraceConfig} from '../protos'; 17 18import {createEmptyRecordConfig} from './record_config_types'; 19import {genConfigProto, toPbtxt} from './record_controller'; 20 21test('encodeConfig', () => { 22 const config = createEmptyRecordConfig(); 23 config.durationMs = 20000; 24 const result = TraceConfig.decode( 25 genConfigProto(config, {os: 'Q', name: 'Android Q'}), 26 ); 27 expect(result.durationMs).toBe(20000); 28}); 29 30test('SysConfig', () => { 31 const config = createEmptyRecordConfig(); 32 config.cpuSyscall = true; 33 const result = TraceConfig.decode( 34 genConfigProto(config, {os: 'Q', name: 'Android Q'}), 35 ); 36 const sources = assertExists(result.dataSources); 37 // TODO(hjd): This is all bad. Should just match the whole config. 38 const srcConfig = assertExists(sources[1].config); 39 const ftraceConfig = assertExists(srcConfig.ftraceConfig); 40 const ftraceEvents = assertExists(ftraceConfig.ftraceEvents); 41 expect(ftraceEvents.includes('raw_syscalls/sys_enter')).toBe(true); 42 expect(ftraceEvents.includes('raw_syscalls/sys_exit')).toBe(true); 43}); 44 45test('cpu scheduling includes kSyms if OS >= S', () => { 46 const config = createEmptyRecordConfig(); 47 config.cpuSched = true; 48 const result = TraceConfig.decode( 49 genConfigProto(config, {os: 'S', name: 'Android S'}), 50 ); 51 const sources = assertExists(result.dataSources); 52 const srcConfig = assertExists(sources[2].config); 53 const ftraceConfig = assertExists(srcConfig.ftraceConfig); 54 const ftraceEvents = assertExists(ftraceConfig.ftraceEvents); 55 expect(ftraceConfig.symbolizeKsyms).toBe(true); 56 expect(ftraceEvents.includes('sched/sched_blocked_reason')).toBe(true); 57}); 58 59test('cpu scheduling does not include kSyms if OS <= S', () => { 60 const config = createEmptyRecordConfig(); 61 config.cpuSched = true; 62 const result = TraceConfig.decode( 63 genConfigProto(config, {os: 'Q', name: 'Android Q'}), 64 ); 65 const sources = assertExists(result.dataSources); 66 const srcConfig = assertExists(sources[2].config); 67 const ftraceConfig = assertExists(srcConfig.ftraceConfig); 68 const ftraceEvents = assertExists(ftraceConfig.ftraceEvents); 69 expect(ftraceConfig.symbolizeKsyms).toBe(false); 70 expect(ftraceEvents.includes('sched/sched_blocked_reason')).toBe(false); 71}); 72 73test('kSyms can be enabled individually', () => { 74 const config = createEmptyRecordConfig(); 75 config.ftrace = true; 76 config.symbolizeKsyms = true; 77 const result = TraceConfig.decode( 78 genConfigProto(config, {os: 'Q', name: 'Android Q'}), 79 ); 80 const sources = assertExists(result.dataSources); 81 const srcConfig = assertExists(sources[1].config); 82 const ftraceConfig = assertExists(srcConfig.ftraceConfig); 83 const ftraceEvents = assertExists(ftraceConfig.ftraceEvents); 84 expect(ftraceConfig.symbolizeKsyms).toBe(true); 85 expect(ftraceEvents.includes('sched/sched_blocked_reason')).toBe(true); 86}); 87 88test('kSyms can be disabled individually', () => { 89 const config = createEmptyRecordConfig(); 90 config.ftrace = true; 91 config.symbolizeKsyms = false; 92 const result = TraceConfig.decode( 93 genConfigProto(config, {os: 'Q', name: 'Android Q'}), 94 ); 95 const sources = assertExists(result.dataSources); 96 const srcConfig = assertExists(sources[1].config); 97 const ftraceConfig = assertExists(srcConfig.ftraceConfig); 98 const ftraceEvents = assertExists(ftraceConfig.ftraceEvents); 99 expect(ftraceConfig.symbolizeKsyms).toBe(false); 100 expect(ftraceEvents.includes('sched/sched_blocked_reason')).toBe(false); 101}); 102 103test('toPbtxt', () => { 104 const config = { 105 durationMs: 1000, 106 maxFileSizeBytes: 43, 107 buffers: [ 108 { 109 sizeKb: 42, 110 }, 111 ], 112 dataSources: [ 113 { 114 config: { 115 name: 'linux.ftrace', 116 targetBuffer: 1, 117 ftraceConfig: { 118 ftraceEvents: ['sched_switch', 'print'], 119 }, 120 }, 121 }, 122 ], 123 producers: [ 124 { 125 producerName: 'perfetto.traced_probes', 126 }, 127 ], 128 }; 129 130 const text = toPbtxt(TraceConfig.encode(config).finish()); 131 132 expect(text).toEqual(`buffers: { 133 size_kb: 42 134} 135data_sources: { 136 config { 137 name: "linux.ftrace" 138 target_buffer: 1 139 ftrace_config { 140 ftrace_events: "sched_switch" 141 ftrace_events: "print" 142 } 143 } 144} 145duration_ms: 1000 146producers: { 147 producer_name: "perfetto.traced_probes" 148} 149max_file_size_bytes: 43 150`); 151}); 152 153test('ChromeConfig', () => { 154 const config = createEmptyRecordConfig(); 155 config.ipcFlows = true; 156 config.jsExecution = true; 157 config.mode = 'STOP_WHEN_FULL'; 158 const result = TraceConfig.decode( 159 genConfigProto(config, {os: 'C', name: 'Chrome'}), 160 ); 161 const sources = assertExists(result.dataSources); 162 163 const traceConfigSource = assertExists(sources[0].config); 164 expect(traceConfigSource.name).toBe('org.chromium.trace_event'); 165 const chromeConfig = assertExists(traceConfigSource.chromeConfig); 166 expect(chromeConfig.privacyFilteringEnabled).toBe(false); 167 const traceConfig = assertExists(chromeConfig.traceConfig); 168 169 const trackEventConfigSource = assertExists(sources[1].config); 170 expect(trackEventConfigSource.name).toBe('track_event'); 171 const trackEventConfig = assertExists( 172 trackEventConfigSource.trackEventConfig, 173 ); 174 expect(trackEventConfig.filterDynamicEventNames).toBe(false); 175 expect(trackEventConfig.filterDebugAnnotations).toBe(false); 176 const chromeConfigT = assertExists(trackEventConfigSource.chromeConfig); 177 const traceConfigT = assertExists(chromeConfigT.traceConfig); 178 179 const metadataConfigSource = assertExists(sources[2].config); 180 expect(metadataConfigSource.name).toBe('org.chromium.trace_metadata'); 181 const chromeConfigM = assertExists(metadataConfigSource.chromeConfig); 182 const traceConfigM = assertExists(chromeConfigM.traceConfig); 183 184 const expectedTraceConfig = 185 '{"record_mode":"record-until-full",' + 186 '"included_categories":' + 187 '["toplevel","toplevel.flow","disabled-by-default-ipc.flow",' + 188 '"mojom","v8"],' + 189 '"excluded_categories":["*"],' + 190 '"memory_dump_config":{}}'; 191 expect(traceConfig).toEqual(expectedTraceConfig); 192 expect(traceConfigT).toEqual(expectedTraceConfig); 193 expect(traceConfigM).toEqual(expectedTraceConfig); 194}); 195 196test('ChromeConfig with privacy filtering', () => { 197 const config = createEmptyRecordConfig(); 198 config.ipcFlows = true; 199 config.jsExecution = true; 200 config.mode = 'STOP_WHEN_FULL'; 201 config.chromePrivacyFiltering = true; 202 const result = TraceConfig.decode( 203 genConfigProto(config, {os: 'C', name: 'Chrome'}), 204 ); 205 const sources = assertExists(result.dataSources); 206 207 const traceConfigSource = assertExists(sources[0].config); 208 expect(traceConfigSource.name).toBe('org.chromium.trace_event'); 209 const chromeConfig = assertExists(traceConfigSource.chromeConfig); 210 expect(chromeConfig.privacyFilteringEnabled).toBe(true); 211 212 const trackEventConfigSource = assertExists(sources[1].config); 213 expect(trackEventConfigSource.name).toBe('track_event'); 214 const trackEventConfig = assertExists( 215 trackEventConfigSource.trackEventConfig, 216 ); 217 expect(trackEventConfig.filterDynamicEventNames).toBe(true); 218 expect(trackEventConfig.filterDebugAnnotations).toBe(true); 219}); 220 221test('ChromeMemoryConfig', () => { 222 const config = createEmptyRecordConfig(); 223 config.chromeHighOverheadCategoriesSelected = [ 224 'disabled-by-default-memory-infra', 225 ]; 226 const result = TraceConfig.decode( 227 genConfigProto(config, {os: 'C', name: 'Chrome'}), 228 ); 229 const sources = assertExists(result.dataSources); 230 231 const traceConfigSource = assertExists(sources[0].config); 232 expect(traceConfigSource.name).toBe('org.chromium.trace_event'); 233 const chromeConfig = assertExists(traceConfigSource.chromeConfig); 234 const traceConfig = assertExists(chromeConfig.traceConfig); 235 236 const trackEventConfigSource = assertExists(sources[1].config); 237 expect(trackEventConfigSource.name).toBe('track_event'); 238 const chromeConfigT = assertExists(trackEventConfigSource.chromeConfig); 239 const traceConfigT = assertExists(chromeConfigT.traceConfig); 240 241 const metadataConfigSource = assertExists(sources[2].config); 242 expect(metadataConfigSource.name).toBe('org.chromium.trace_metadata'); 243 const chromeConfigM = assertExists(metadataConfigSource.chromeConfig); 244 const traceConfigM = assertExists(chromeConfigM.traceConfig); 245 246 const miConfigSource = assertExists(sources[3].config); 247 expect(miConfigSource.name).toBe('org.chromium.memory_instrumentation'); 248 const chromeConfigI = assertExists(miConfigSource.chromeConfig); 249 const traceConfigI = assertExists(chromeConfigI.traceConfig); 250 251 const hpConfigSource = assertExists(sources[4].config); 252 expect(hpConfigSource.name).toBe('org.chromium.native_heap_profiler'); 253 const chromeConfigH = assertExists(hpConfigSource.chromeConfig); 254 const traceConfigH = assertExists(chromeConfigH.traceConfig); 255 256 const expectedTraceConfig = 257 '{"record_mode":"record-until-full",' + 258 '"included_categories":["disabled-by-default-memory-infra"],' + 259 '"excluded_categories":["*"],' + 260 '"memory_dump_config":{"allowed_dump_modes":["background",' + 261 '"light","detailed"],"triggers":[{"min_time_between_dumps_ms":' + 262 '10000,"mode":"detailed","type":"periodic_interval"}]}}'; 263 expect(traceConfig).toEqual(expectedTraceConfig); 264 expect(traceConfigT).toEqual(expectedTraceConfig); 265 expect(traceConfigM).toEqual(expectedTraceConfig); 266 expect(traceConfigI).toEqual(expectedTraceConfig); 267 expect(traceConfigH).toEqual(expectedTraceConfig); 268}); 269 270test('ChromeCpuProfilerConfig', () => { 271 const config = createEmptyRecordConfig(); 272 config.chromeHighOverheadCategoriesSelected = [ 273 'disabled-by-default-cpu_profiler', 274 ]; 275 const decoded = TraceConfig.decode( 276 genConfigProto(config, {os: 'C', name: 'Chrome'}), 277 ); 278 const sources = assertExists(decoded.dataSources); 279 280 const traceConfigSource = assertExists(sources[0].config); 281 expect(traceConfigSource.name).toBe('org.chromium.trace_event'); 282 const traceEventChromeConfig = assertExists(traceConfigSource.chromeConfig); 283 const traceEventConfig = assertExists(traceEventChromeConfig.traceConfig); 284 285 const trackEventConfigSource = assertExists(sources[1].config); 286 expect(trackEventConfigSource.name).toBe('track_event'); 287 const chromeConfigT = assertExists(trackEventConfigSource.chromeConfig); 288 const traceConfigT = assertExists(chromeConfigT.traceConfig); 289 290 const metadataConfigSource = assertExists(sources[2].config); 291 expect(metadataConfigSource.name).toBe('org.chromium.trace_metadata'); 292 const traceMetadataChromeConfig = assertExists( 293 metadataConfigSource.chromeConfig, 294 ); 295 const traceMetadataConfig = assertExists( 296 traceMetadataChromeConfig.traceConfig, 297 ); 298 299 const profilerConfigSource = assertExists(sources[3].config); 300 expect(profilerConfigSource.name).toBe('org.chromium.sampler_profiler'); 301 const profilerChromeConfig = assertExists(profilerConfigSource.chromeConfig); 302 const profilerConfig = assertExists(profilerChromeConfig.traceConfig); 303 304 const expectedTraceConfig = 305 '{"record_mode":"record-until-full",' + 306 '"included_categories":["disabled-by-default-cpu_profiler"],' + 307 '"excluded_categories":["*"],"memory_dump_config":{}}'; 308 expect(traceEventConfig).toEqual(expectedTraceConfig); 309 expect(traceConfigT).toEqual(expectedTraceConfig); 310 expect(traceMetadataConfig).toEqual(expectedTraceConfig); 311 expect(profilerConfig).toEqual(expectedTraceConfig); 312}); 313 314test('ChromeCpuProfilerDebugConfig', () => { 315 const config = createEmptyRecordConfig(); 316 config.chromeHighOverheadCategoriesSelected = [ 317 'disabled-by-default-cpu_profiler.debug', 318 ]; 319 const decoded = TraceConfig.decode( 320 genConfigProto(config, {os: 'C', name: 'Chrome'}), 321 ); 322 const sources = assertExists(decoded.dataSources); 323 324 const traceConfigSource = assertExists(sources[0].config); 325 expect(traceConfigSource.name).toBe('org.chromium.trace_event'); 326 const traceEventChromeConfig = assertExists(traceConfigSource.chromeConfig); 327 const traceEventConfig = assertExists(traceEventChromeConfig.traceConfig); 328 329 const trackEventConfigSource = assertExists(sources[1].config); 330 expect(trackEventConfigSource.name).toBe('track_event'); 331 const chromeConfigT = assertExists(trackEventConfigSource.chromeConfig); 332 const traceConfigT = assertExists(chromeConfigT.traceConfig); 333 334 const metadataConfigSource = assertExists(sources[2].config); 335 expect(metadataConfigSource.name).toBe('org.chromium.trace_metadata'); 336 const traceMetadataChromeConfig = assertExists( 337 metadataConfigSource.chromeConfig, 338 ); 339 const traceMetadataConfig = assertExists( 340 traceMetadataChromeConfig.traceConfig, 341 ); 342 343 const profilerConfigSource = assertExists(sources[3].config); 344 expect(profilerConfigSource.name).toBe('org.chromium.sampler_profiler'); 345 const profilerChromeConfig = assertExists(profilerConfigSource.chromeConfig); 346 const profilerConfig = assertExists(profilerChromeConfig.traceConfig); 347 348 const expectedTraceConfig = 349 '{"record_mode":"record-until-full",' + 350 '"included_categories":["disabled-by-default-cpu_profiler.debug"],' + 351 '"excluded_categories":["*"],"memory_dump_config":{}}'; 352 expect(traceConfigT).toEqual(expectedTraceConfig); 353 expect(traceEventConfig).toEqual(expectedTraceConfig); 354 expect(traceMetadataConfig).toEqual(expectedTraceConfig); 355 expect(profilerConfig).toEqual(expectedTraceConfig); 356}); 357 358test('ChromeConfigRingBuffer', () => { 359 const config = createEmptyRecordConfig(); 360 config.ipcFlows = true; 361 config.jsExecution = true; 362 config.mode = 'RING_BUFFER'; 363 const result = TraceConfig.decode( 364 genConfigProto(config, {os: 'C', name: 'Chrome'}), 365 ); 366 const sources = assertExists(result.dataSources); 367 368 const traceConfigSource = assertExists(sources[0].config); 369 expect(traceConfigSource.name).toBe('org.chromium.trace_event'); 370 const chromeConfig = assertExists(traceConfigSource.chromeConfig); 371 const traceConfig = assertExists(chromeConfig.traceConfig); 372 373 const trackEventConfigSource = assertExists(sources[1].config); 374 expect(trackEventConfigSource.name).toBe('track_event'); 375 const chromeConfigT = assertExists(trackEventConfigSource.chromeConfig); 376 const traceConfigT = assertExists(chromeConfigT.traceConfig); 377 378 const metadataConfigSource = assertExists(sources[2].config); 379 expect(metadataConfigSource.name).toBe('org.chromium.trace_metadata'); 380 const chromeConfigM = assertExists(metadataConfigSource.chromeConfig); 381 const traceConfigM = assertExists(chromeConfigM.traceConfig); 382 383 const expectedTraceConfig = 384 '{"record_mode":"record-continuously",' + 385 '"included_categories":' + 386 '["toplevel","toplevel.flow","disabled-by-default-ipc.flow",' + 387 '"mojom","v8"],' + 388 '"excluded_categories":["*"],"memory_dump_config":{}}'; 389 expect(traceConfig).toEqual(expectedTraceConfig); 390 expect(traceConfigT).toEqual(expectedTraceConfig); 391 expect(traceConfigM).toEqual(expectedTraceConfig); 392}); 393 394test('ChromeConfigLongTrace', () => { 395 const config = createEmptyRecordConfig(); 396 config.ipcFlows = true; 397 config.jsExecution = true; 398 config.mode = 'RING_BUFFER'; 399 const result = TraceConfig.decode( 400 genConfigProto(config, {os: 'C', name: 'Chrome'}), 401 ); 402 const sources = assertExists(result.dataSources); 403 404 const traceConfigSource = assertExists(sources[0].config); 405 expect(traceConfigSource.name).toBe('org.chromium.trace_event'); 406 const chromeConfig = assertExists(traceConfigSource.chromeConfig); 407 const traceConfig = assertExists(chromeConfig.traceConfig); 408 409 const trackEventConfigSource = assertExists(sources[1].config); 410 expect(trackEventConfigSource.name).toBe('track_event'); 411 const chromeConfigT = assertExists(trackEventConfigSource.chromeConfig); 412 const traceConfigT = assertExists(chromeConfigT.traceConfig); 413 414 const metadataConfigSource = assertExists(sources[2].config); 415 expect(metadataConfigSource.name).toBe('org.chromium.trace_metadata'); 416 const chromeConfigM = assertExists(metadataConfigSource.chromeConfig); 417 const traceConfigM = assertExists(chromeConfigM.traceConfig); 418 419 const expectedTraceConfig = 420 '{"record_mode":"record-continuously",' + 421 '"included_categories":' + 422 '["toplevel","toplevel.flow","disabled-by-default-ipc.flow",' + 423 '"mojom","v8"],' + 424 '"excluded_categories":["*"],"memory_dump_config":{}}'; 425 expect(traceConfig).toEqual(expectedTraceConfig); 426 expect(traceConfigT).toEqual(expectedTraceConfig); 427 expect(traceConfigM).toEqual(expectedTraceConfig); 428}); 429 430test('ChromeConfigToPbtxt', () => { 431 const config = { 432 dataSources: [ 433 { 434 config: { 435 name: 'org.chromium.trace_event', 436 chromeConfig: { 437 traceConfig: JSON.stringify({included_categories: ['v8']}), 438 }, 439 }, 440 }, 441 ], 442 }; 443 const text = toPbtxt(TraceConfig.encode(config).finish()); 444 445 expect(text).toEqual(`data_sources: { 446 config { 447 name: "org.chromium.trace_event" 448 chrome_config { 449 trace_config: "{\\"included_categories\\":[\\"v8\\"]}" 450 } 451 } 452} 453`); 454}); 455