3 Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
8 <link rel="import" href="/tracing/test_utils.html">
9 <link rel="import" href="/tracing/importer/trace_event_importer.html">
14 tv.unittest.testSuite(function() { // @suppress longLineCheck
15 var findSliceNamed = tracing.test_utils.findSliceNamed;
17 test('canImportEmpty', function() {
18 self.assertFalse(tracing.importer.TraceEventImporter.canImport([]));
19 self.assertFalse(tracing.importer.TraceEventImporter.canImport(''));
22 test('basicSingleThreadNonnestedParsing', function() {
24 {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
25 {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'},
26 {name: 'b', args: {}, pid: 52, ts: 629, cat: 'bar', tid: 53, ph: 'B'},
27 {name: 'b', args: {}, pid: 52, ts: 631, cat: 'bar', tid: 53, ph: 'E'}
30 var m = new tracing.TraceModel(events);
31 assertEquals(1, m.numProcesses);
32 var p = m.processes[52];
33 assertNotUndefined(p);
35 assertEquals(1, p.numThreads);
36 var t = p.threads[53];
37 assertNotUndefined(t);
38 assertEquals(2, t.sliceGroup.length);
39 assertEquals(53, t.tid);
40 var slice = t.sliceGroup.slices[0];
41 assertEquals('a', slice.title);
42 assertEquals('foo', slice.category);
43 assertEquals(0, slice.start);
44 assertAlmostEquals((560 - 520) / 1000, slice.duration);
45 assertEquals(0, slice.subSlices.length);
47 slice = t.sliceGroup.slices[1];
48 assertEquals('b', slice.title);
49 assertEquals('bar', slice.category);
50 assertAlmostEquals((629 - 520) / 1000, slice.start);
51 assertAlmostEquals((631 - 629) / 1000, slice.duration);
52 assertEquals(0, slice.subSlices.length);
55 test('basicSingleThreadNonnestedParsingWithCpuDuration', function() {
57 {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B', tts: 221}, // @suppress longLineCheck
58 {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E', tts: 259}, // @suppress longLineCheck
59 {name: 'b', args: {}, pid: 52, ts: 629, cat: 'bar', tid: 53, ph: 'B', tts: 329}, // @suppress longLineCheck
60 {name: 'b', args: {}, pid: 52, ts: 631, cat: 'bar', tid: 53, ph: 'E', tts: 331} // @suppress longLineCheck
63 var m = new tracing.TraceModel(events);
64 assertEquals(1, m.numProcesses);
65 var p = m.processes[52];
66 assertNotUndefined(p);
68 assertEquals(1, p.numThreads);
69 var t = p.threads[53];
70 assertNotUndefined(t);
71 assertEquals(2, t.sliceGroup.length);
72 assertEquals(53, t.tid);
73 var slice = t.sliceGroup.slices[0];
74 assertEquals('a', slice.title);
75 assertEquals('foo', slice.category);
76 assertEquals(0, slice.start);
77 assertAlmostEquals((560 - 520) / 1000, slice.duration);
78 assertAlmostEquals((259 - 221) / 1000, slice.cpuDuration);
79 assertEquals(0, slice.subSlices.length);
81 slice = t.sliceGroup.slices[1];
82 assertEquals('b', slice.title);
83 assertEquals('bar', slice.category);
84 assertAlmostEquals((629 - 520) / 1000, slice.start);
85 assertAlmostEquals((631 - 629) / 1000, slice.duration);
86 assertAlmostEquals((331 - 329) / 1000, slice.cpuDuration);
87 assertEquals(0, slice.subSlices.length);
90 test('argumentDupeCreatesNonFailingImportError', function() {
108 var m = new tracing.TraceModel(events);
109 var t = m.processes[1].threads[1];
110 var sA = findSliceNamed(t.sliceGroup, 'a');
112 assertEquals(2, sA.args.x);
113 assertTrue(m.hasImportWarnings);
114 assertEquals(m.importWarnings.length, 1);
117 test('importMissingArgs', function() {
119 {name: 'a', pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
120 {name: 'a', pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'},
121 {name: 'b', pid: 52, ts: 629, cat: 'bar', tid: 53, ph: 'I'}
124 // This should not throw an exception.
125 new tracing.TraceModel(events);
128 test('importDoesNotChokeOnNulls', function() {
130 {name: 'a', args: { foo: null }, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'}, // @suppress longLineCheck
131 {name: 'a', pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
134 // This should not throw an exception.
135 new tracing.TraceModel(events);
138 test('categoryBeginEndMismatchPrefersBegin', function() {
140 {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
141 {name: 'a', args: {}, pid: 52, ts: 560, cat: 'bar', tid: 53, ph: 'E'}
144 var m = new tracing.TraceModel(events);
145 assertEquals(1, m.numProcesses);
146 var p = m.processes[52];
147 assertNotUndefined(p);
149 assertEquals(1, p.numThreads);
150 var t = p.threads[53];
151 assertNotUndefined(t);
152 assertEquals(1, t.sliceGroup.length);
153 assertEquals(53, t.tid);
154 var slice = t.sliceGroup.slices[0];
155 assertEquals('a', slice.title);
156 assertEquals('foo', slice.category);
159 test('beginEndNameMismatch', function() {
161 {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
162 {name: 'b', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
165 var m = new tracing.TraceModel(events);
166 assertTrue(m.hasImportWarnings);
167 assertEquals(1, m.importWarnings.length);
170 test('nestedParsing', function() {
172 {name: 'a', args: {}, pid: 1, ts: 1, tts: 1, cat: 'foo', tid: 1, ph: 'B'},
173 {name: 'b', args: {}, pid: 1, ts: 2, tts: 2, cat: 'bar', tid: 1, ph: 'B'},
174 {name: 'b', args: {}, pid: 1, ts: 3, tts: 3, cat: 'bar', tid: 1, ph: 'E'},
175 {name: 'a', args: {}, pid: 1, ts: 4, tts: 3, cat: 'foo', tid: 1, ph: 'E'}
177 var m = new tracing.TraceModel(events, false);
178 var t = m.processes[1].threads[1];
180 var sA = findSliceNamed(t.sliceGroup, 'a');
181 var sB = findSliceNamed(t.sliceGroup, 'b');
183 assertEquals('a', sA.title);
184 assertEquals('foo', sA.category);
185 assertEquals(0.001, sA.start);
186 assertEquals(0.003, sA.duration);
187 assertEquals(0.002, sA.selfTime);
188 assertEquals(0.001, sA.cpuSelfTime);
190 assertEquals('b', sB.title);
191 assertEquals('bar', sB.category);
192 assertEquals(0.002, sB.start);
193 assertEquals(0.001, sB.duration);
195 assertTrue(sA.subSlices.length == 1);
196 assertTrue(sA.subSlices[0] == sB);
197 assertTrue(sB.parentSlice == sA);
200 test('nestedParsingWithTwoSubSlices', function() {
202 {name: 'a', args: {}, pid: 1, ts: 1, tts: 1, cat: 'foo', tid: 1, ph: 'B'},
203 {name: 'b', args: {}, pid: 1, ts: 2, tts: 2, cat: 'bar', tid: 1, ph: 'B'},
204 {name: 'b', args: {}, pid: 1, ts: 3, tts: 3, cat: 'bar', tid: 1, ph: 'E'},
205 {name: 'c', args: {}, pid: 1, ts: 5, tts: 5, cat: 'baz', tid: 1, ph: 'B'},
206 {name: 'c', args: {}, pid: 1, ts: 7, tts: 6, cat: 'baz', tid: 1, ph: 'E'},
207 {name: 'a', args: {}, pid: 1, ts: 8, tts: 8, cat: 'foo', tid: 1, ph: 'E'}
209 var m = new tracing.TraceModel(events, false);
210 var t = m.processes[1].threads[1];
212 var sA = findSliceNamed(t.sliceGroup, 'a');
213 var sB = findSliceNamed(t.sliceGroup, 'b');
214 var sC = findSliceNamed(t.sliceGroup, 'c');
216 assertEquals('a', sA.title);
217 assertEquals('foo', sA.category);
218 assertEquals(0.001, sA.start);
219 assertEquals(0.007, sA.duration);
220 assertEquals(0.004, sA.selfTime);
221 assertEquals(0.005, sA.cpuSelfTime);
223 assertEquals('b', sB.title);
224 assertEquals('bar', sB.category);
225 assertEquals(0.002, sB.start);
226 assertEquals(0.001, sB.duration);
228 assertEquals('c', sC.title);
229 assertEquals('baz', sC.category);
230 assertEquals(0.005, sC.start);
231 assertEquals(0.002, sC.duration);
233 assertTrue(sA.subSlices.length == 2);
234 assertTrue(sA.subSlices[0] == sB);
235 assertTrue(sA.subSlices[1] == sC);
236 assertTrue(sB.parentSlice == sA);
237 assertTrue(sC.parentSlice == sA);
240 test('nestedParsingWithDoubleNesting', function() {
242 {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
243 {name: 'b', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 1, ph: 'B'},
244 {name: 'c', args: {}, pid: 1, ts: 3, cat: 'baz', tid: 1, ph: 'B'},
245 {name: 'c', args: {}, pid: 1, ts: 5, cat: 'baz', tid: 1, ph: 'E'},
246 {name: 'b', args: {}, pid: 1, ts: 7, cat: 'bar', tid: 1, ph: 'E'},
247 {name: 'a', args: {}, pid: 1, ts: 8, cat: 'foo', tid: 1, ph: 'E'}
249 var m = new tracing.TraceModel(events, false);
250 var t = m.processes[1].threads[1];
252 var sA = findSliceNamed(t.sliceGroup, 'a');
253 var sB = findSliceNamed(t.sliceGroup, 'b');
254 var sC = findSliceNamed(t.sliceGroup, 'c');
256 assertEquals('a', sA.title);
257 assertEquals('foo', sA.category);
258 assertEquals(0.001, sA.start);
259 assertEquals(0.007, sA.duration);
260 assertEquals(0.002, sA.selfTime);
262 assertEquals('b', sB.title);
263 assertEquals('bar', sB.category);
264 assertEquals(0.002, sB.start);
265 assertEquals(0.005, sB.duration);
266 assertEquals(0.002, sA.selfTime);
268 assertEquals('c', sC.title);
269 assertEquals('baz', sC.category);
270 assertEquals(0.003, sC.start);
271 assertEquals(0.002, sC.duration);
273 assertTrue(sA.subSlices.length == 1);
274 assertTrue(sA.subSlices[0] == sB);
275 assertTrue(sB.parentSlice == sA);
277 assertTrue(sB.subSlices.length == 1);
278 assertTrue(sB.subSlices[0] == sC);
279 assertTrue(sC.parentSlice == sB);
283 test('autoclosing', function() {
285 // Slice that doesn't finish.
286 {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
288 // Slice that does finish to give an 'end time' to make autoclosing work.
289 {name: 'b', args: {}, pid: 1, ts: 1, cat: 'bar', tid: 2, ph: 'B'},
290 {name: 'b', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 2, ph: 'E'}
292 var m = new tracing.TraceModel(events);
293 var p = m.processes[1];
294 var t = p.threads[1];
295 var slice = t.sliceGroup.slices[0];
296 assertEquals('a', slice.title);
297 assertEquals('foo', slice.category);
298 assertTrue(slice.didNotFinish);
299 assertEquals(0, slice.start);
300 assertEquals((2 - 1) / 1000, slice.duration);
303 test('autoclosingLoneBegin', function() {
305 // Slice that doesn't finish.
306 {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'}
308 var m = new tracing.TraceModel(events);
309 var p = m.processes[1];
310 var t = p.threads[1];
311 var slice = t.sliceGroup.slices[0];
312 assertEquals('a', slice.title);
313 assertEquals('foo', slice.category);
314 assertTrue(slice.didNotFinish);
315 assertEquals(0, slice.start);
316 assertEquals(0, slice.duration);
319 test('autoclosingWithSubTasks', function() {
321 {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
322 {name: 'b1', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'B'},
323 {name: 'b1', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'E'},
324 {name: 'b2', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'B'}
326 var m = new tracing.TraceModel(events, false);
327 var t = m.processes[1].threads[1];
329 var sA = findSliceNamed(t.sliceGroup, 'a');
330 var sB1 = findSliceNamed(t.sliceGroup, 'b1');
331 var sB2 = findSliceNamed(t.sliceGroup, 'b2');
333 assertEquals(0.003, sA.end);
334 assertEquals(0.003, sB1.end);
335 assertEquals(0.003, sB2.end);
338 test('autoclosingWithEventsOutsideBounds', function() {
340 // Slice that begins before min and ends after max of the other threads.
341 {name: 'a', args: {}, pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'B'},
342 {name: 'b', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'B'},
344 // Slice that does finish to give an 'end time' to establish a basis
345 {name: 'c', args: {}, pid: 1, ts: 1, cat: 'bar', tid: 2, ph: 'B'},
346 {name: 'c', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 2, ph: 'E'}
348 var m = new tracing.TraceModel(events, false);
349 var p = m.processes[1];
350 var t = p.threads[1];
351 assertEquals(2, t.sliceGroup.length);
353 var slice = findSliceNamed(t.sliceGroup, 'a');
354 assertEquals('a', slice.title);
355 assertEquals('foo', slice.category);
356 assertEquals(0, slice.start);
357 assertEquals(0.003, slice.duration);
359 var t2 = p.threads[2];
360 var slice2 = findSliceNamed(t2.sliceGroup, 'c');
361 assertEquals('c', slice2.title);
362 assertEquals('bar', slice2.category);
363 assertEquals(0.001, slice2.start);
364 assertEquals(0.001, slice2.duration);
366 assertEquals(0.000, m.bounds.min);
367 assertEquals(0.003, m.bounds.max);
370 test('nestedAutoclosing', function() {
372 // Tasks that don't finish.
373 {name: 'a1', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
374 {name: 'a2', args: {}, pid: 1, ts: 1.5, cat: 'foo', tid: 1, ph: 'B'},
376 // Slice that does finish to give an 'end time' to make autoclosing work.
377 {name: 'b', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 2, ph: 'B'},
378 {name: 'b', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 2, ph: 'E'}
380 var m = new tracing.TraceModel(events, false);
381 var t1 = m.processes[1].threads[1];
382 var t2 = m.processes[1].threads[2];
384 var sA1 = findSliceNamed(t1.sliceGroup, 'a1');
385 var sA2 = findSliceNamed(t1.sliceGroup, 'a2');
386 var sB = findSliceNamed(t2.sliceGroup, 'b');
388 assertEquals(0.002, sA1.end);
389 assertEquals(0.002, sA2.end);
392 test('taskColoring', function() {
393 // The test below depends on hashing of 'a' != 'b'. Fail early if that
394 // assumption is incorrect.
395 assertNotEquals(tv.ui.getStringHash('a'), tv.ui.getStringHash('b'));
398 {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
399 {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
400 {name: 'b', args: {}, pid: 1, ts: 3, cat: 'bar', tid: 1, ph: 'B'},
401 {name: 'b', args: {}, pid: 1, ts: 4, cat: 'bar', tid: 1, ph: 'E'},
402 {name: 'a', args: {}, pid: 1, ts: 5, cat: 'baz', tid: 1, ph: 'B'},
403 {name: 'a', args: {}, pid: 1, ts: 6, cat: 'baz', tid: 1, ph: 'E'}
405 var m = new tracing.TraceModel(events);
406 var p = m.processes[1];
407 var t = p.threads[1];
408 var a1 = t.sliceGroup.slices[0];
409 assertEquals('a', a1.title);
410 assertEquals('foo', a1.category);
411 var b = t.sliceGroup.slices[1];
412 assertEquals('b', b.title);
413 assertEquals('bar', b.category);
414 assertNotEquals(a1.colorId, b.colorId);
415 var a2 = t.sliceGroup.slices[2];
416 assertEquals('a', a2.title);
417 assertEquals('baz', a2.category);
418 assertEquals(a1.colorId, a2.colorId);
421 test('multipleThreadParsing', function() {
423 {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
424 {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
425 {name: 'b', args: {}, pid: 1, ts: 3, cat: 'bar', tid: 2, ph: 'B'},
426 {name: 'b', args: {}, pid: 1, ts: 4, cat: 'bar', tid: 2, ph: 'E'}
428 var m = new tracing.TraceModel(events);
429 assertEquals(1, m.numProcesses);
430 var p = m.processes[1];
431 assertNotUndefined(p);
433 assertEquals(2, p.numThreads);
436 var t = p.threads[1];
437 assertNotUndefined(t);
438 assertEquals(1, t.sliceGroup.length);
439 assertEquals(1, t.tid);
441 var slice = t.sliceGroup.slices[0];
442 assertEquals('a', slice.title);
443 assertEquals('foo', slice.category);
444 assertEquals(0, slice.start);
445 assertEquals((2 - 1) / 1000, slice.duration);
446 assertEquals(0, slice.subSlices.length);
449 var t = p.threads[2];
450 assertNotUndefined(t);
451 assertEquals(1, t.sliceGroup.length);
452 assertEquals(2, t.tid);
454 slice = t.sliceGroup.slices[0];
455 assertEquals('b', slice.title);
456 assertEquals('bar', slice.category);
457 assertEquals((3 - 1) / 1000, slice.start);
458 assertEquals((4 - 3) / 1000, slice.duration);
459 assertEquals(0, slice.subSlices.length);
462 test('multiplePidParsing', function() {
464 {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
465 {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
466 {name: 'b', args: {}, pid: 2, ts: 3, cat: 'bar', tid: 2, ph: 'B'},
467 {name: 'b', args: {}, pid: 2, ts: 4, cat: 'bar', tid: 2, ph: 'E'}
469 var m = new tracing.TraceModel(events);
470 assertEquals(2, m.numProcesses);
471 var p = m.processes[1];
472 assertNotUndefined(p);
474 assertEquals(1, p.numThreads);
476 // Check process 1 thread 1.
477 var t = p.threads[1];
478 assertNotUndefined(t);
479 assertEquals(1, t.sliceGroup.length);
480 assertEquals(1, t.tid);
482 var slice = t.sliceGroup.slices[0];
483 assertEquals('a', slice.title);
484 assertEquals('foo', slice.category);
485 assertEquals(0, slice.start);
486 assertEquals((2 - 1) / 1000, slice.duration);
487 assertEquals(0, slice.subSlices.length);
489 // Check process 2 thread 2.
490 var p = m.processes[2];
491 assertNotUndefined(p);
492 assertEquals(1, p.numThreads);
493 var t = p.threads[2];
494 assertNotUndefined(t);
495 assertEquals(1, t.sliceGroup.length);
496 assertEquals(2, t.tid);
498 slice = t.sliceGroup.slices[0];
499 assertEquals('b', slice.title);
500 assertEquals('bar', slice.category);
501 assertEquals((3 - 1) / 1000, slice.start);
502 assertEquals((4 - 3) / 1000, slice.duration);
503 assertEquals(0, slice.subSlices.length);
505 // Check getAllThreads.
506 assertArrayEquals([m.processes[1].threads[1], m.processes[2].threads[2]],
511 test('processNames', function() {
513 {name: 'process_name', args: {name: 'SomeProcessName'},
514 pid: 1, ts: 0, tid: 1, ph: 'M'},
515 {name: 'process_name', args: {name: 'SomeProcessName'},
516 pid: 2, ts: 0, tid: 1, ph: 'M'}
518 var m = new tracing.TraceModel();
519 m.importTraces([events], false, false);
520 assertEquals('SomeProcessName', m.processes[1].name);
524 test('processLabels', function() {
526 {name: 'process_labels', args: {labels: 'foo,bar,bar,foo,baz'},
527 pid: 1, ts: 0, tid: 1, ph: 'M'},
528 {name: 'process_labels', args: {labels: 'baz'},
529 pid: 2, ts: 0, tid: 1, ph: 'M'}
531 var m = new tracing.TraceModel();
532 m.importTraces([events], false, false);
533 assertArrayEquals(['foo', 'bar', 'baz'], m.processes[1].labels);
534 assertArrayEquals(['baz'], m.processes[2].labels);
537 // Process sort index.
538 test('processSortIndex', function() {
540 {name: 'process_name', args: {name: 'First'},
541 pid: 2, ts: 0, tid: 1, ph: 'M'},
542 {name: 'process_name', args: {name: 'Second'},
543 pid: 2, ts: 0, tid: 1, ph: 'M'},
544 {name: 'process_sort_index', args: {sort_index: 1},
545 pid: 1, ts: 0, tid: 1, ph: 'M'}
547 var m = new tracing.TraceModel();
548 m.importTraces([events], false, false);
550 // By name, p1 is before p2. But, its sort index overrides that.
551 assertTrue(m.processes[1].compareTo(m.processes[2]) > 0);
555 test('threadNames', function() {
557 {name: 'thread_name', args: {name: 'Thread 1'},
558 pid: 1, ts: 0, tid: 1, ph: 'M'},
559 {name: 'thread_name', args: {name: 'Thread 2'},
560 pid: 2, ts: 0, tid: 2, ph: 'M'}
562 var m = new tracing.TraceModel(events);
563 m.importTraces([events], false, false);
564 assertEquals('Thread 1', m.processes[1].threads[1].name);
565 assertEquals('Thread 2', m.processes[2].threads[2].name);
568 // Thread sort index.
569 test('threadSortIndex', function() {
571 {name: 'thread_name', args: {name: 'Thread 1'},
572 pid: 1, ts: 0, tid: 1, ph: 'M'},
573 {name: 'thread_name', args: {name: 'Thread 2'},
574 pid: 1, ts: 0, tid: 2, ph: 'M'},
575 {name: 'thread_sort_index', args: {sort_index: 1},
576 pid: 1, ts: 0, tid: 1, ph: 'M'}
578 var m = new tracing.TraceModel();
579 m.importTraces([events], false, false);
581 // By name, t1 is before t2. But, its sort index overrides that.
582 var t1 = m.processes[1].threads[1];
583 var t2 = m.processes[1].threads[2];
584 assertTrue(t1.compareTo(t2) > 0);
588 test('cpuCounts', function() {
590 {name: 'num_cpus', args: {number: 4},
591 pid: 7, ts: 0, tid: 0, ph: 'M'},
592 {name: 'num_cpus', args: {number: 4},
593 pid: 14, ts: 0, tid: 0, ph: 'M'}
595 var m = new tracing.TraceModel();
596 m.importTraces([events], false, false);
597 assertEquals(4, m.kernel.softwareMeasuredCpuCount);
598 assertEquals(4, m.kernel.bestGuessAtCpuCount);
601 test('cpuCountsWithSandboxBeingConfused', function() {
603 {name: 'num_cpus', args: {number: 4},
604 pid: 7, ts: 0, tid: 0, ph: 'M'},
605 {name: 'num_cpus', args: {number: 1},
606 pid: 14, ts: 0, tid: 0, ph: 'M'}
608 var m = new tracing.TraceModel();
609 m.importTraces([events], false, false);
610 assertEquals(4, m.kernel.softwareMeasuredCpuCount);
611 assertEquals(4, m.kernel.bestGuessAtCpuCount);
614 test('parsingWhenEndComesFirst', function() {
616 {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'E'},
617 {name: 'a', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'B'},
618 {name: 'a', args: {}, pid: 1, ts: 5, cat: 'foo', tid: 1, ph: 'E'}
620 var m = new tracing.TraceModel(events, false);
621 var p = m.processes[1];
622 var t = p.threads[1];
623 assertEquals(1, t.sliceGroup.length);
624 assertEquals('a', t.sliceGroup.slices[0].title);
625 assertEquals('foo', t.sliceGroup.slices[0].category);
626 assertEquals(0.004, t.sliceGroup.slices[0].start);
627 assertEquals(0.001, t.sliceGroup.slices[0].duration);
628 assertTrue(m.hasImportWarnings);
629 assertEquals(1, m.importWarnings.length);
632 test('immediateParsing', function() {
634 // Need to include immediates inside a task so the timeline
635 // recentering/zeroing doesn't clobber their timestamp.
636 {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
637 {name: 'immediate', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 1, ph: 'I'},
638 {name: 'slower', args: {}, pid: 1, ts: 4, cat: 'baz', tid: 1, ph: 'i'},
639 {name: 'a', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'E'}
641 var m = new tracing.TraceModel(events, false);
642 var p = m.processes[1];
643 var t = p.threads[1];
645 assertEquals(3, t.sliceGroup.length);
646 assertEquals(0.001, t.sliceGroup.slices[0].start);
647 assertEquals(0.003, t.sliceGroup.slices[0].duration);
648 assertEquals(0.002, t.sliceGroup.slices[1].start);
649 assertEquals(0, t.sliceGroup.slices[1].duration);
650 assertEquals(0.004, t.sliceGroup.slices[2].start);
652 var slice = findSliceNamed(t.sliceGroup, 'a');
653 assertEquals('a', slice.title);
654 assertEquals('foo', slice.category);
655 assertEquals(0.003, slice.duration);
657 var immed = findSliceNamed(t.sliceGroup, 'immediate');
658 assertEquals('immediate', immed.title);
659 assertEquals('bar', immed.category);
660 assertEquals(0.002, immed.start);
661 assertEquals(0, immed.duration);
663 var slower = findSliceNamed(t.sliceGroup, 'slower');
664 assertEquals('slower', slower.title);
665 assertEquals('baz', slower.category);
666 assertEquals(0.004, slower.start);
667 assertEquals(0, slower.duration);
670 test('simpleCounter', function() {
672 {name: 'ctr', args: {'value': 0}, pid: 1, ts: 0, cat: 'foo', tid: 1,
674 {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
676 {name: 'ctr', args: {'value': 0}, pid: 1, ts: 20, cat: 'foo', tid: 1,
680 var m = new tracing.TraceModel(events);
681 var p = m.processes[1];
682 var ctr = m.processes[1].counters['foo.ctr'];
684 assertEquals('ctr', ctr.name);
685 assertEquals('foo', ctr.category);
686 assertEquals(3, ctr.numSamples);
687 assertEquals(1, ctr.numSeries);
689 assertEquals('value', ctr.series[0].name);
690 assertEquals(tv.ui.getStringColorId('ctr.value'), ctr.series[0].color);
692 assertArrayEquals([0, 0.01, 0.02], ctr.timestamps);
695 ctr.series[0].samples.forEach(function(sample) {
696 samples.push(sample.value);
698 assertArrayEquals([0, 10, 0], samples);
700 assertArrayEquals([0, 10, 0], ctr.totals);
701 assertEquals(10, ctr.maxTotal);
704 test('instanceCounter', function() {
706 {name: 'ctr', args: {'value': 0}, pid: 1, ts: 0, cat: 'foo', tid: 1,
708 {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
710 {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
712 {name: 'ctr', args: {'value': 20}, pid: 1, ts: 15, cat: 'foo', tid: 1,
714 {name: 'ctr', args: {'value': 30}, pid: 1, ts: 18, cat: 'foo', tid: 1,
716 {name: 'ctr', args: {'value': 40}, pid: 1, ts: 20, cat: 'bar', tid: 1,
719 var m = new tracing.TraceModel(events);
720 var p = m.processes[1];
721 var ctr = m.processes[1].counters['foo.ctr[0]'];
722 assertEquals('ctr[0]', ctr.name);
723 assertEquals('foo', ctr.category);
724 assertEquals(2, ctr.numSamples);
725 assertEquals(1, ctr.numSeries);
727 assertArrayEquals([0, 0.01], ctr.timestamps);
729 ctr.series[0].samples.forEach(function(sample) {
730 samples.push(sample.value);
732 assertArrayEquals([0, 10], samples);
734 ctr = m.processes[1].counters['foo.ctr[1]'];
735 assertEquals('ctr[1]', ctr.name);
736 assertEquals('foo', ctr.category);
737 assertEquals(3, ctr.numSamples);
738 assertEquals(1, ctr.numSeries);
739 assertArrayEquals([0.01, 0.015, 0.018], ctr.timestamps);
742 ctr.series[0].samples.forEach(function(sample) {
743 samples.push(sample.value);
745 assertArrayEquals([10, 20, 30], samples);
747 ctr = m.processes[1].counters['bar.ctr[2]'];
748 assertEquals('ctr[2]', ctr.name);
749 assertEquals('bar', ctr.category);
750 assertEquals(1, ctr.numSamples);
751 assertEquals(1, ctr.numSeries);
752 assertArrayEquals([0.02], ctr.timestamps);
754 ctr.series[0].samples.forEach(function(sample) {
755 samples.push(sample.value);
757 assertArrayEquals([40], samples);
760 test('multiCounterUpdateBounds', function() {
761 var ctr = new tracing.trace_model.Counter(undefined, 'testBasicCounter',
762 '', 'testBasicCounter');
763 var value1Series = new tracing.trace_model.CounterSeries(
764 'value1', 'testBasicCounter.value1');
765 var value2Series = new tracing.trace_model.CounterSeries(
766 'value2', 'testBasicCounter.value2');
767 ctr.addSeries(value1Series);
768 ctr.addSeries(value2Series);
770 value1Series.addCounterSample(0, 0);
771 value1Series.addCounterSample(1, 1);
772 value1Series.addCounterSample(2, 1);
773 value1Series.addCounterSample(3, 2);
774 value1Series.addCounterSample(4, 3);
775 value1Series.addCounterSample(5, 1);
776 value1Series.addCounterSample(6, 3);
777 value1Series.addCounterSample(7, 3.1);
779 value2Series.addCounterSample(0, 0);
780 value2Series.addCounterSample(1, 0);
781 value2Series.addCounterSample(2, 1);
782 value2Series.addCounterSample(3, 1.1);
783 value2Series.addCounterSample(4, 0);
784 value2Series.addCounterSample(5, 7);
785 value2Series.addCounterSample(6, 0);
786 value2Series.addCounterSample(7, 0.5);
790 assertEquals(0, ctr.bounds.min);
791 assertEquals(7, ctr.bounds.max);
792 assertEquals(8, ctr.maxTotal);
793 assertArrayEquals([0, 0,
800 3.1, 3.6], ctr.totals);
803 test('multiCounter', function() {
805 {name: 'ctr', args: {'value1': 0, 'value2': 7}, pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'C'}, // @suppress longLineCheck
806 {name: 'ctr', args: {'value1': 10, 'value2': 4}, pid: 1, ts: 10, cat: 'foo', tid: 1, ph: 'C'}, // @suppress longLineCheck
807 {name: 'ctr', args: {'value1': 0, 'value2': 1 }, pid: 1, ts: 20, cat: 'foo', tid: 1, ph: 'C'} // @suppress longLineCheck
809 var m = new tracing.TraceModel(events);
810 var p = m.processes[1];
811 var ctr = m.processes[1].counters['foo.ctr'];
812 assertEquals('ctr', ctr.name);
814 assertEquals('ctr', ctr.name);
815 assertEquals('foo', ctr.category);
816 assertEquals(3, ctr.numSamples);
817 assertEquals(2, ctr.numSeries);
819 assertEquals('value1', ctr.series[0].name);
820 assertEquals('value2', ctr.series[1].name);
821 assertEquals(tv.ui.getStringColorId('ctr.value1'), ctr.series[0].color);
822 assertEquals(tv.ui.getStringColorId('ctr.value2'), ctr.series[1].color);
824 assertArrayEquals([0, 0.01, 0.02], ctr.timestamps);
826 ctr.series[0].samples.forEach(function(sample) {
827 samples.push(sample.value);
829 assertArrayEquals([0, 10, 0], samples);
832 ctr.series[1].samples.forEach(function(sample) {
833 samples1.push(sample.value);
835 assertArrayEquals([7, 4, 1], samples1);
836 assertArrayEquals([0, 7,
839 assertEquals(14, ctr.maxTotal);
842 test('importObjectInsteadOfArray', function() {
843 var events = { traceEvents: [
844 {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
845 {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
848 var m = new tracing.TraceModel(events);
849 assertEquals(1, m.numProcesses);
852 test('importString', function() {
854 {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
855 {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
858 var m = new tracing.TraceModel(JSON.stringify(events));
859 assertEquals(1, m.numProcesses);
862 test('importStringWithTrailingNewLine', function() {
864 {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
865 {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
868 var m = new tracing.TraceModel(JSON.stringify(events) + '\n');
869 assertEquals(1, m.numProcesses);
872 test('importStringWithMissingCloseSquareBracket', function() {
874 {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
875 {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
878 var tmp = JSON.stringify(events);
879 assertEquals(']', tmp[tmp.length - 1]);
881 // Drop off the trailing ]
882 var dropped = tmp.substring(0, tmp.length - 1);
883 var m = new tracing.TraceModel(dropped);
884 assertEquals(1, m.numProcesses);
887 test('importStringWithEndingCommaButMissingCloseSquareBracket', function() {
890 '{"name": "a", "args": {}, "pid": 52, "ts": 524, "cat": "foo", "tid": 53, "ph": "B"},', // @suppress longLineCheck
891 '{"name": "a", "args": {}, "pid": 52, "ts": 560, "cat": "foo", "tid": 53, "ph": "E"},' // @suppress longLineCheck
893 var text = lines.join('\n');
895 var m = new tracing.TraceModel(text);
896 assertEquals(1, m.numProcesses);
897 assertEquals(1, m.processes[52].threads[53].sliceGroup.length);
900 test('importStringWithMissingCloseSquareBracketAndNewline', function() {
902 {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
903 {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
906 var tmp = JSON.stringify(events);
907 assertEquals(']', tmp[tmp.length - 1]);
909 // Drop off the trailing ] and add a newline
910 var dropped = tmp.substring(0, tmp.length - 1);
911 var m = new tracing.TraceModel(dropped + '\n');
912 assertEquals(1, m.numProcesses);
915 test('ImportStringEndingCommaButMissingCloseSquareBracketCRLF', function() {
918 '{"name": "a", "args": {}, "pid": 52, "ts": 524, "cat": "foo", "tid": 53, "ph": "B"},', // @suppress longLineCheck
919 '{"name": "a", "args": {}, "pid": 52, "ts": 560, "cat": "foo", "tid": 53, "ph": "E"},' // @suppress longLineCheck
921 var text = lines.join('\r\n');
923 var m = new tracing.TraceModel(text);
924 assertEquals(1, m.numProcesses);
925 assertEquals(1, m.processes[52].threads[53].sliceGroup.length);
928 test('importOldFormat', function() {
931 '{"cat":"a","pid":9,"tid":8,"ts":194,"ph":"E","name":"I","args":{}},',
932 '{"cat":"b","pid":9,"tid":8,"ts":194,"ph":"B","name":"I","args":{}}',
935 var text = lines.join('\n');
936 var m = new tracing.TraceModel(text);
937 assertEquals(1, m.numProcesses);
938 assertEquals(1, m.processes[9].threads[8].sliceGroup.length);
941 test('startFinishOneSliceOneThread', function() {
943 // Time is intentionally out of order.
944 {name: 'a', args: {}, pid: 52, ts: 560, cat: 'cat', tid: 53,
946 {name: 'a', pid: 52, ts: 524, cat: 'cat', tid: 53,
947 ph: 'S', id: 72, args: {'foo': 'bar'}}
950 var m = new tracing.TraceModel(events);
951 var t = m.processes[52].threads[53];
952 assertNotUndefined(t);
953 assertEquals(1, t.asyncSliceGroup.slices.length);
954 assertEquals('a', t.asyncSliceGroup.slices[0].title);
955 assertEquals('cat', t.asyncSliceGroup.slices[0].category);
956 assertEquals(72, t.asyncSliceGroup.slices[0].id);
957 assertEquals('bar', t.asyncSliceGroup.slices[0].args.foo);
958 assertEquals(0, t.asyncSliceGroup.slices[0].start);
959 assertAlmostEquals((60 - 24) / 1000, t.asyncSliceGroup.slices[0].duration);
960 assertEquals(t, t.asyncSliceGroup.slices[0].startThread);
961 assertEquals(t, t.asyncSliceGroup.slices[0].endThread);
964 test('endArgsAddedToSlice', function() {
966 {name: 'a', args: {x: 1}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
967 {name: 'a', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
970 var m = new tracing.TraceModel(events);
971 assertEquals(1, m.numProcesses);
972 var p = m.processes[52];
973 assertNotUndefined(p);
975 assertEquals(1, p.numThreads);
976 var t = p.threads[53];
977 assertNotUndefined(t);
978 assertEquals(1, t.sliceGroup.length);
979 assertEquals(53, t.tid);
980 var slice = t.sliceGroup.slices[0];
981 assertEquals('a', slice.title);
982 assertEquals('foo', slice.category);
983 assertEquals(0, slice.start);
984 assertEquals(0, slice.subSlices.length);
985 assertEquals(1, slice.args['x']);
986 assertEquals(2, slice.args['y']);
989 test('endArgOverrwritesOriginalArgValueIfDuplicated', function() {
991 {name: 'b', args: {z: 3}, pid: 52, ts: 629, cat: 'foo', tid: 53, ph: 'B'},
992 {name: 'b', args: {z: 4}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'}
995 var m = new tracing.TraceModel(events);
996 assertEquals(1, m.numProcesses);
997 var p = m.processes[52];
998 assertNotUndefined(p);
1000 assertEquals(1, p.numThreads);
1001 var t = p.threads[53];
1002 assertNotUndefined(t);
1003 var slice = t.sliceGroup.slices[0];
1004 assertEquals('b', slice.title);
1005 assertEquals('foo', slice.category);
1006 assertEquals(0, slice.start);
1007 assertEquals(0, slice.subSlices.length);
1008 assertEquals(4, slice.args['z']);
1011 test('asyncEndArgsAddedToSlice', function() {
1013 // Time is intentionally out of order.
1014 {name: 'c', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53,
1016 {name: 'c', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1020 var m = new tracing.TraceModel(events);
1021 var t = m.processes[52].threads[53];
1022 assertNotUndefined(t);
1023 assertEquals(1, t.asyncSliceGroup.slices.length);
1024 var parentSlice = t.asyncSliceGroup.slices[0];
1025 assertEquals('c', parentSlice.title);
1026 assertEquals('foo', parentSlice.category);
1028 assertNotUndefined(parentSlice.subSlices);
1029 assertEquals(1, parentSlice.subSlices.length);
1030 var subSlice = parentSlice.subSlices[0];
1031 assertEquals(1, subSlice.args['x']);
1032 assertEquals(2, subSlice.args['y']);
1035 test('asyncEndArgOverrwritesOriginalArgValueIfDuplicated', function() {
1037 // Time is intentionally out of order.
1038 {name: 'd', args: {z: 4}, pid: 52, ts: 560, cat: 'foo', tid: 53,
1040 {name: 'd', args: {z: 3}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1044 var m = new tracing.TraceModel(events);
1045 var t = m.processes[52].threads[53];
1046 assertNotUndefined(t);
1047 assertEquals(1, t.asyncSliceGroup.slices.length);
1048 var parentSlice = t.asyncSliceGroup.slices[0];
1049 assertEquals('d', parentSlice.title);
1050 assertEquals('foo', parentSlice.category);
1052 assertNotUndefined(parentSlice.subSlices);
1053 assertEquals(1, parentSlice.subSlices.length);
1054 var subSlice = parentSlice.subSlices[0];
1055 assertEquals(4, subSlice.args['z']);
1058 test('asyncStepsInOneThread', function() {
1060 // Time is intentionally out of order.
1061 {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'F', id: 72}, // @suppress longLineCheck
1062 {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo', tid: 53, ph: 'T', id: 72}, // @suppress longLineCheck
1063 {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'S', id: 72} // @suppress longLineCheck
1066 var m = new tracing.TraceModel(events);
1067 var t = m.processes[52].threads[53];
1068 assertNotUndefined(t);
1069 assertEquals(1, t.asyncSliceGroup.slices.length);
1070 var parentSlice = t.asyncSliceGroup.slices[0];
1071 assertEquals('a', parentSlice.title);
1072 assertEquals('foo', parentSlice.category);
1073 assertEquals(0, parentSlice.start);
1075 assertNotUndefined(parentSlice.subSlices);
1076 assertEquals(2, parentSlice.subSlices.length);
1077 var subSlice = parentSlice.subSlices[0];
1078 assertEquals('a', subSlice.title);
1079 assertEquals('foo', subSlice.category);
1080 assertEquals(0, subSlice.start);
1081 assertAlmostEquals((548 - 524) / 1000, subSlice.duration);
1082 assertEquals(1, subSlice.args['x']);
1084 var subSlice = parentSlice.subSlices[1];
1085 assertEquals('a:s1', subSlice.title);
1086 assertEquals('foo', subSlice.category);
1087 assertAlmostEquals((548 - 524) / 1000, subSlice.start);
1088 assertAlmostEquals((560 - 548) / 1000, subSlice.duration);
1089 assertEquals(1, subSlice.args['x']);
1090 assertEquals(2, subSlice.args['y']);
1091 assertEquals(3, subSlice.args['z']);
1094 test('asyncStepsMissingStart', function() {
1096 // Time is intentionally out of order.
1097 {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
1099 {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo',
1100 tid: 53, ph: 'T', id: 72}
1103 var m = new tracing.TraceModel(events);
1104 var t = m.processes[52].threads[53];
1108 test('asyncStepsMissingFinish', function() {
1110 // Time is intentionally out of order.
1111 {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo',
1112 tid: 53, ph: 'T', id: 72},
1113 {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
1117 var m = new tracing.TraceModel(events);
1118 var t = m.processes[52].threads[53];
1122 test('asyncStepEndEvent', function() {
1124 // Time is intentionally out of order.
1125 {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
1127 {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo',
1128 tid: 53, ph: 'p', id: 72},
1129 {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1133 var m = new tracing.TraceModel(events);
1134 var t = m.processes[52].threads[53];
1135 assertNotUndefined(t);
1136 assertEquals(1, t.asyncSliceGroup.slices.length);
1137 var parentSlice = t.asyncSliceGroup.slices[0];
1138 assertEquals('a', parentSlice.title);
1139 assertEquals('foo', parentSlice.category);
1140 assertEquals(0, parentSlice.start);
1142 assertNotUndefined(parentSlice.subSlices);
1143 assertEquals(2, parentSlice.subSlices.length);
1144 var subSlice = parentSlice.subSlices[0];
1145 assertEquals('a:s1', subSlice.title);
1146 assertEquals('foo', subSlice.category);
1147 assertEquals(0, subSlice.start);
1148 assertAlmostEquals((548 - 524) / 1000, subSlice.duration);
1149 assertEquals(1, subSlice.args['x']);
1150 assertEquals(2, subSlice.args['y']);
1152 var subSlice = parentSlice.subSlices[1];
1153 assertEquals('a', subSlice.title);
1154 assertEquals('foo', subSlice.category);
1155 assertAlmostEquals((548 - 524) / 1000, subSlice.start);
1156 assertAlmostEquals((560 - 548) / 1000, subSlice.duration);
1157 assertEquals(1, subSlice.args['x']);
1158 assertEquals(3, subSlice.args['z']);
1161 test('asyncStepMismatch', function() {
1163 // Time is intentionally out of order.
1164 {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
1166 {name: 'a', args: {step: 's2'}, pid: 52, ts: 548, cat: 'foo', tid: 53,
1168 {name: 'a', args: {step: 's1'}, pid: 52, ts: 548, cat: 'foo', tid: 53,
1170 {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1174 var m = new tracing.TraceModel(events);
1175 var t = m.processes[52].threads[53];
1177 assertTrue(m.hasImportWarnings);
1180 test('nestableAsyncBasic', function() {
1182 {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1184 {name: 'b', args: {x: 1}, pid: 52, ts: 525, cat: 'foo', tid: 53,
1186 {name: 'b', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53,
1188 {name: 'a', args: {}, pid: 52, ts: 565, cat: 'foo', tid: 53,
1192 var m = new tracing.TraceModel(events);
1193 var t = m.processes[52].threads[53];
1194 assertNotUndefined(t);
1195 assertEquals(1, t.asyncSliceGroup.slices.length);
1196 var parentSlice = t.asyncSliceGroup.slices[0];
1197 assertEquals('a', parentSlice.title);
1198 assertEquals('foo', parentSlice.category);
1200 assertNotUndefined(parentSlice.subSlices);
1201 assertEquals(1, parentSlice.subSlices.length);
1202 var subSlice = parentSlice.subSlices[0];
1203 // Arguments should include both BEGIN and END event.
1204 assertEquals(1, subSlice.args['x']);
1205 assertEquals(2, subSlice.args['y']);
1206 assertUndefined(subSlice.subSlices);
1209 test('nestableAsyncCombinedParams', function() {
1211 {name: 'a', args: {x: 1, params: {p1: 'hello', p2: 123}},
1212 pid: 52, ts: 525, cat: 'foo', tid: 53, ph: 'b', id: 72},
1213 {name: 'a', args: {y: 2, params: {p3: 'hi'}}, pid: 52, ts: 560,
1214 cat: 'foo', tid: 53, ph: 'e', id: 72},
1215 {name: 'b', args: {params: {p4: 'foo'}},
1216 pid: 52, ts: 525, cat: 'foo', tid: 53, ph: 'b', id: 73},
1217 {name: 'b', args: {params: ''}, pid: 52, ts: 560,
1218 cat: 'foo', tid: 53, ph: 'e', id: 73},
1219 {name: 'c', args: {params: {p5: 'bar'}},
1220 pid: 52, ts: 525, cat: 'foo', tid: 53, ph: 'b', id: 74},
1221 {name: 'c', args: {}, pid: 52, ts: 560,
1222 cat: 'foo', tid: 53, ph: 'e', id: 74}
1225 var m = new tracing.TraceModel(events);
1226 var t = m.processes[52].threads[53];
1227 assertNotUndefined(t);
1228 assertEquals(3, t.asyncSliceGroup.slices.length);
1230 var sliceA = t.asyncSliceGroup.slices[0];
1231 // Arguments should include both BEGIN and END event.
1232 assertEquals(1, sliceA.args['x']);
1233 assertEquals(2, sliceA.args['y']);
1234 var paramsA = sliceA.args['params'];
1235 assertNotUndefined(paramsA);
1236 assertEquals('hello', paramsA.p1);
1237 assertEquals(123, paramsA.p2);
1238 assertEquals('hi', paramsA.p3);
1240 var sliceB = t.asyncSliceGroup.slices[1];
1241 // Arguments should include both BEGIN and END event.
1242 var paramsB = sliceB.args['params'];
1243 assertNotUndefined(paramsB);
1244 assertEquals('foo', paramsB.p4);
1246 var sliceC = t.asyncSliceGroup.slices[2];
1247 // Arguments should include both BEGIN and END event.
1248 var paramsC = sliceC.args['params'];
1249 assertNotUndefined(paramsC);
1250 assertEquals('bar', paramsC.p5);
1253 test('nestableAsyncManyLevels', function() {
1254 // There are 5 nested levels.
1256 {name: 'l1', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1258 {name: 'l2', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
1260 {name: 'l3', args: {}, pid: 52, ts: 526, cat: 'foo', tid: 53,
1262 {name: 'l4', args: {}, pid: 52, ts: 527, cat: 'foo', tid: 53,
1264 {name: 'l5', args: {}, pid: 52, ts: 528, cat: 'foo', tid: 53,
1266 {name: 'l5', args: {}, pid: 52, ts: 529, cat: 'foo', tid: 53,
1268 {name: 'l4', args: {}, pid: 52, ts: 530, cat: 'foo', tid: 53,
1270 {name: 'l3', args: {}, pid: 52, ts: 531, cat: 'foo', tid: 53,
1272 {name: 'l2', args: {}, pid: 52, ts: 532, cat: 'foo', tid: 53,
1274 {name: 'l1', args: {}, pid: 52, ts: 533, cat: 'foo', tid: 53,
1278 var m = new tracing.TraceModel(events);
1279 var t = m.processes[52].threads[53];
1280 assertNotUndefined(t);
1281 // Perfectly matched events should not produce a warning.
1282 assertFalse(m.hasImportWarnings);
1283 assertEquals(1, t.asyncSliceGroup.slices.length);
1285 var l1Slice = t.asyncSliceGroup.slices[0];
1286 assertEquals('l1', l1Slice.title);
1287 assertAlmostEquals(0, l1Slice.start);
1288 assertAlmostEquals(9 / 1000, l1Slice.duration);
1290 assertNotUndefined(l1Slice.subSlices);
1291 assertEquals(1, l1Slice.subSlices.length);
1292 var l2Slice = l1Slice.subSlices[0];
1293 assertEquals('l2', l2Slice.title);
1294 assertAlmostEquals(1 / 1000, l2Slice.start);
1295 assertAlmostEquals(7 / 1000, l2Slice.duration);
1297 assertNotUndefined(l2Slice.subSlices);
1298 assertEquals(1, l2Slice.subSlices.length);
1299 var l3Slice = l2Slice.subSlices[0];
1300 assertEquals('l3', l3Slice.title);
1301 assertAlmostEquals(2 / 1000, l3Slice.start);
1302 assertAlmostEquals(5 / 1000, l3Slice.duration);
1304 assertNotUndefined(l3Slice.subSlices);
1305 assertEquals(1, l3Slice.subSlices.length);
1306 var l4Slice = l3Slice.subSlices[0];
1307 assertEquals('l4', l4Slice.title);
1308 assertAlmostEquals(3 / 1000, l4Slice.start);
1309 assertAlmostEquals(3 / 1000, l4Slice.duration);
1311 assertNotUndefined(l4Slice.subSlices);
1312 assertEquals(1, l4Slice.subSlices.length);
1313 var l5Slice = l4Slice.subSlices[0];
1314 assertEquals('l5', l5Slice.title);
1315 assertAlmostEquals(4 / 1000, l5Slice.start);
1316 assertAlmostEquals(1 / 1000, l5Slice.duration);
1319 test('nestableAsyncInstantEvent', function() {
1321 {name: 'c', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1323 {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1325 {name: 'd', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
1327 {name: 'a', args: {}, pid: 52, ts: 565, cat: 'foo', tid: 53,
1331 var m = new tracing.TraceModel(events);
1332 var t = m.processes[52].threads[53];
1333 assertNotUndefined(t);
1334 assertEquals(2, t.asyncSliceGroup.slices.length);
1335 var instantSlice = t.asyncSliceGroup.slices[0];
1336 assertEquals('c', instantSlice.title);
1337 assertAlmostEquals(0, instantSlice.start);
1338 assertAlmostEquals(0, instantSlice.duration);
1339 assertUndefined(instantSlice.subSlices);
1341 var nestedSlice = t.asyncSliceGroup.slices[1];
1342 assertEquals('a', nestedSlice.title);
1343 assertAlmostEquals(0, nestedSlice.start);
1344 assertAlmostEquals((565-524) / 1000, nestedSlice.duration);
1345 assertNotUndefined(nestedSlice.subSlices);
1346 assertEquals(1, nestedSlice.subSlices.length);
1347 var nestedInstantSlice = nestedSlice.subSlices[0];
1348 assertUndefined(nestedInstantSlice.subSlices);
1349 assertEquals('d', nestedInstantSlice.title);
1352 test('nestableAsyncUnmatchedOuterBeginEvent', function() {
1354 {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1356 {name: 'b', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
1358 {name: 'b', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53,
1362 var m = new tracing.TraceModel(events);
1363 var t = m.processes[52].threads[53];
1364 assertNotUndefined(t);
1365 // Unmatched BEGIN should produce a warning.
1366 assertTrue(m.hasImportWarnings);
1367 assertEquals(1, t.asyncSliceGroup.slices.length);
1368 var parentSlice = t.asyncSliceGroup.slices[0];
1369 assertEquals('a', parentSlice.title);
1370 assertEquals('foo', parentSlice.category);
1371 assertAlmostEquals(0, parentSlice.start);
1372 // Unmatched BEGIN event ends at the last event of that ID.
1373 assertAlmostEquals(36 / 1000, parentSlice.duration);
1374 // Arguments should include only include its arguments.
1375 assertUndefined(parentSlice.args['y']);
1376 assertEquals(1, parentSlice.args['x']);
1377 assertNotUndefined(parentSlice.error);
1379 assertNotUndefined(parentSlice.subSlices);
1380 assertEquals(1, parentSlice.subSlices.length);
1381 var subSlice = parentSlice.subSlices[0];
1382 assertAlmostEquals(1 / 1000, subSlice.start);
1383 assertAlmostEquals(35 / 1000, subSlice.duration);
1384 assertUndefined(subSlice.subSlices);
1385 // Arguments should include those of the END event.
1386 assertEquals(2, subSlice.args['y']);
1387 assertUndefined(subSlice.subSlices);
1390 test('nestableAsyncUnmatchedInnerBeginEvent', function() {
1392 {name: 'a', args: {z: 3}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1394 {name: 'c', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
1396 {name: 'b', args: {x: 1}, pid: 52, ts: 525, cat: 'foo', tid: 53,
1398 {name: 'a', args: {y: 2}, pid: 52, ts: 565, cat: 'foo', tid: 53,
1402 var m = new tracing.TraceModel(events);
1403 var t = m.processes[52].threads[53];
1404 assertNotUndefined(t);
1405 // Unmatched BEGIN should produce a warning.
1406 assertTrue(m.hasImportWarnings);
1407 assertEquals(1, t.asyncSliceGroup.slices.length);
1408 var parentSlice = t.asyncSliceGroup.slices[0];
1409 assertEquals('a', parentSlice.title);
1410 assertEquals('foo', parentSlice.category);
1411 assertAlmostEquals(0, parentSlice.start);
1412 assertAlmostEquals(41 / 1000, parentSlice.duration);
1413 // Arguments should include both BEGIN and END event.
1414 assertEquals(2, parentSlice.args['y']);
1415 assertEquals(3, parentSlice.args['z']);
1416 assertUndefined(parentSlice.args['x']);
1418 assertNotUndefined(parentSlice.subSlices);
1419 assertEquals(2, parentSlice.subSlices.length);
1420 var subSliceInstant = parentSlice.subSlices[0];
1421 var subSliceUnmatched = parentSlice.subSlices[1];
1422 assertEquals('c', subSliceInstant.title);
1423 assertEquals('b', subSliceUnmatched.title);
1424 // Unmatched BEGIN ends at the last event of that ID.
1425 assertAlmostEquals(1 / 1000, subSliceUnmatched.start);
1426 assertAlmostEquals(40 / 1000, subSliceUnmatched.duration);
1427 assertUndefined(subSliceUnmatched.subSlices);
1428 assertEquals(1, subSliceUnmatched.args['x']);
1429 assertUndefined(subSliceUnmatched['y']);
1430 assertNotUndefined(subSliceUnmatched.error);
1431 assertAlmostEquals(1 / 1000, subSliceInstant.start);
1432 assertAlmostEquals(0, subSliceInstant.duration);
1433 assertUndefined(subSliceInstant.subSlices);
1436 test('nestableAsyncUnmatchedOuterEndEvent', function() {
1437 // Events are intentionally out-of-order.
1439 {name: 'b', args: {x: 1}, pid: 52, ts: 525, cat: 'foo', tid: 53,
1441 {name: 'b', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53,
1443 {name: 'a', args: {z: 3}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1447 var m = new tracing.TraceModel(events);
1448 var t = m.processes[52].threads[53];
1449 assertNotUndefined(t);
1450 // Unmatched END should produce a warning.
1451 assertTrue(m.hasImportWarnings);
1452 assertEquals(2, t.asyncSliceGroup.slices.length);
1453 var unmatchedSlice = t.asyncSliceGroup.slices[0];
1454 var slice = t.asyncSliceGroup.slices[1];
1455 assertEquals('a', unmatchedSlice.title);
1456 assertAlmostEquals(0, unmatchedSlice.start);
1457 // Unmatched END event begins at the first event of that ID. In this
1458 // case, the first event happens to be the same unmatched event.
1459 assertAlmostEquals(0 / 1000, unmatchedSlice.duration);
1460 assertUndefined(unmatchedSlice.args['x']);
1461 assertUndefined(unmatchedSlice.args['y']);
1462 assertEquals(3, unmatchedSlice.args['z']);
1463 assertNotUndefined(unmatchedSlice.error);
1464 assertUndefined(unmatchedSlice.subSlices);
1466 assertEquals('b', slice.title);
1467 assertAlmostEquals(1 / 1000, slice.start);
1468 assertAlmostEquals(35 / 1000, slice.duration);
1469 // Arguments should include both BEGIN and END event.
1470 assertEquals(1, slice.args['x']);
1471 assertEquals(2, slice.args['y']);
1472 assertUndefined(slice.subSlices);
1475 test('nestableAsyncUnmatchedInnerEndEvent', function() {
1477 {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
1479 {name: 'c', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
1481 {name: 'b', args: {z: 3}, pid: 52, ts: 525, cat: 'foo', tid: 53,
1483 {name: 'a', args: {y: 2}, pid: 52, ts: 565, cat: 'foo', tid: 53,
1487 var m = new tracing.TraceModel(events);
1488 var t = m.processes[52].threads[53];
1489 assertNotUndefined(t);
1490 // Unmatched END should produce a warning.
1491 assertTrue(m.hasImportWarnings);
1492 assertEquals(1, t.asyncSliceGroup.slices.length);
1493 var parentSlice = t.asyncSliceGroup.slices[0];
1494 assertEquals('a', parentSlice.title);
1495 assertAlmostEquals(0, parentSlice.start);
1496 assertAlmostEquals(41 / 1000, parentSlice.duration);
1497 // Arguments should include both BEGIN and END event.
1498 assertEquals(1, parentSlice.args['x']);
1499 assertEquals(2, parentSlice.args['y']);
1501 assertNotUndefined(parentSlice.subSlices);
1502 assertEquals(2, parentSlice.subSlices.length);
1503 var subSliceInstant = parentSlice.subSlices[0];
1504 var subSliceUnmatched = parentSlice.subSlices[1];
1505 assertEquals('c', subSliceInstant.title);
1506 assertEquals('b', subSliceUnmatched.title);
1507 // Unmatched END begins at the first event of that ID.
1508 assertAlmostEquals(0 / 1000, subSliceUnmatched.start);
1509 assertAlmostEquals(1 / 1000, subSliceUnmatched.duration);
1510 // Arguments should include both BEGIN and END event.
1511 assertUndefined(subSliceUnmatched.args['x']);
1512 assertUndefined(subSliceUnmatched.args['y']);
1513 assertEquals(3, subSliceUnmatched.args['z']);
1514 assertNotUndefined(subSliceUnmatched.error);
1516 assertUndefined(subSliceUnmatched.subSlices);
1517 assertAlmostEquals(1 / 1000, subSliceInstant.start);
1518 assertAlmostEquals(0, subSliceInstant.duration);
1519 assertUndefined(subSliceInstant.subSlices);
1522 test('importSamples', function() {
1524 {name: 'a', args: {}, pid: 52, ts: 548, cat: 'test', tid: 53, ph: 'P'},
1525 {name: 'b', args: {}, pid: 52, ts: 548, cat: 'test', tid: 53, ph: 'P'},
1526 {name: 'c', args: {}, pid: 52, ts: 558, cat: 'test', tid: 53, ph: 'P'}
1528 var m = new tracing.TraceModel(events);
1529 var p = m.processes[52];
1530 assertNotUndefined(p);
1531 var t = p.threads[53];
1532 assertNotUndefined(t);
1533 assertEquals(3, t.samples_.length);
1534 assertEquals(0.0, t.samples_[0].start);
1535 assertEquals(0.0, t.samples_[1].start);
1536 assertApproxEquals(0.01, t.samples_[2].start);
1537 assertEquals('a', t.samples_[0].leafStackFrame.title);
1538 assertEquals('b', t.samples_[1].leafStackFrame.title);
1539 assertEquals('c', t.samples_[2].leafStackFrame.title);
1540 assertFalse(m.hasImportWarnings);
1543 test('importSamplesMissingArgs', function() {
1545 {name: 'a', pid: 52, ts: 548, cat: 'test', tid: 53, ph: 'P'},
1546 {name: 'b', pid: 52, ts: 548, cat: 'test', tid: 53, ph: 'P'},
1547 {name: 'c', pid: 52, ts: 549, cat: 'test', tid: 53, ph: 'P'}
1549 var m = new tracing.TraceModel(events);
1550 var p = m.processes[52];
1551 assertNotUndefined(p);
1552 var t = p.threads[53];
1553 assertNotUndefined(t);
1554 assertNotUndefined(t);
1555 assertEquals(3, t.samples_.length);
1556 assertFalse(m.hasImportWarnings);
1559 test('importSimpleObject', function() {
1561 {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
1562 {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: {snapshot: 15}}, // @suppress longLineCheck
1563 {ts: 20000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: {snapshot: 20}}, // @suppress longLineCheck
1564 {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'a', args: {}} // @suppress longLineCheck
1566 var m = new tracing.TraceModel();
1567 m.importTraces([events], false);
1568 assertEquals(10, m.bounds.min);
1569 assertEquals(50, m.bounds.max);
1570 assertFalse(m.hasImportWarnings);
1572 var p = m.processes[1];
1573 assertNotUndefined(p);
1575 var i10 = p.objects.getObjectInstanceAt('0x1000', 10);
1576 assertEquals('c', i10.category);
1577 assertEquals(10, i10.creationTs);
1578 assertEquals(50, i10.deletionTs);
1579 assertEquals(2, i10.snapshots.length);
1581 var s15 = i10.snapshots[0];
1582 assertEquals(15, s15.ts);
1583 assertEquals(15, s15.args);
1585 var s20 = i10.snapshots[1];
1586 assertEquals(20, s20.ts);
1587 assertEquals(20, s20.args);
1590 test('importImplicitObjects', function() {
1592 {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
1593 {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a',
1595 { id: 'subObject/0x1',
1599 {ts: 20000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a',
1601 { id: 'subObject/0x1',
1604 { id: 'subObject/0x2',
1610 var m = new tracing.TraceModel();
1611 m.importTraces([events], false);
1612 var p1 = m.processes[1];
1614 var iA = p1.objects.getObjectInstanceAt('0x1000', 10);
1615 var subObjectInstances = p1.objects.getAllInstancesByTypeName()[
1618 assertEquals(2, subObjectInstances.length);
1619 var subObject1 = p1.objects.getObjectInstanceAt('0x1', 15);
1620 assertEquals('subObject', subObject1.name);
1621 assertEquals(15, subObject1.creationTs);
1623 assertEquals(2, subObject1.snapshots.length);
1624 assertEquals(15, subObject1.snapshots[0].ts);
1625 assertEquals(1, subObject1.snapshots[0].args.foo);
1626 assertEquals(20, subObject1.snapshots[1].ts);
1627 assertEquals(2, subObject1.snapshots[1].args.foo);
1629 var subObject2 = p1.objects.getObjectInstanceAt('0x2', 20);
1630 assertEquals('subObject', subObject2.name);
1631 assertEquals(20, subObject2.creationTs);
1632 assertEquals(1, subObject2.snapshots.length);
1633 assertEquals(20, subObject2.snapshots[0].ts);
1636 test('importImplicitObjectWithCategoryOverride', function() {
1638 {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'cat', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
1639 {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'otherCat', id: '0x1000', name: 'a', // @suppress longLineCheck
1641 { id: 'subObject/0x1',
1648 var m = new tracing.TraceModel();
1649 m.importTraces([events], false);
1650 var p1 = m.processes[1];
1652 var iA = p1.objects.getObjectInstanceAt('0x1000', 10);
1653 var subObjectInstances = p1.objects.getAllInstancesByTypeName()[
1656 assertEquals(1, subObjectInstances.length);
1659 test('importImplicitObjectWithBaseTypeOverride', function() {
1661 {ts: 10000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'PictureLayerImpl', args: { // @suppress longLineCheck
1663 base_type: 'LayerImpl'
1666 {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'LayerImpl', args: {}} // @suppress longLineCheck
1669 var m = new tracing.TraceModel();
1670 m.importTraces([events], false);
1671 var p1 = m.processes[1];
1672 assertEquals(0, m.importWarnings.length);
1674 var iA = p1.objects.getObjectInstanceAt('0x1000', 10);
1675 assertEquals(1, iA.snapshots.length);
1678 test('importIDRefs', function() {
1680 // An object with two snapshots.
1681 {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
1682 {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: {snapshot: 15}}, // @suppress longLineCheck
1683 {ts: 20000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: {snapshot: 20}}, // @suppress longLineCheck
1684 {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
1686 // A slice that references the object.
1687 {ts: 17000, pid: 1, tid: 1, ph: 'B', cat: 'c', name: 'taskSlice', args: {my_object: {id_ref: '0x1000'}}}, // @suppress longLineCheck
1688 {ts: 17500, pid: 1, tid: 1, ph: 'E', cat: 'c', name: 'taskSlice', args: {}} // @suppress longLineCheck
1691 var m = new tracing.TraceModel();
1692 m.importTraces([events], false);
1693 var p1 = m.processes[1];
1695 var iA = p1.objects.getObjectInstanceAt('0x1000', 10);
1696 var s15 = iA.getSnapshotAt(15);
1698 var taskSlice = p1.threads[1].sliceGroup.slices[0];
1699 assertEquals(s15, taskSlice.args.my_object);
1702 test('importIDRefsThatPointAtEachOther', function() {
1705 {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
1706 {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: { // @suppress longLineCheck
1711 {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
1713 // A slice that references the object.
1714 {ts: 17000, pid: 1, tid: 1, ph: 'B', cat: 'c', name: 'taskSlice', args: {my_object: {id_ref: '0x1001'}}}, // @suppress longLineCheck
1715 {ts: 17500, pid: 1, tid: 1, ph: 'E', cat: 'c', name: 'taskSlice', args: {}} // @suppress longLineCheck
1718 var m = new tracing.TraceModel();
1719 m.importTraces([events], false);
1720 var p1 = m.processes[1];
1722 var iA = p1.objects.getObjectInstanceAt('0x1000', 15);
1723 var iFoo = p1.objects.getObjectInstanceAt('0x1001', 15);
1724 assertNotUndefined(iA);
1725 assertNotUndefined(iFoo);
1727 var a15 = iA.getSnapshotAt(15);
1728 var foo15 = iFoo.getSnapshotAt(15);
1730 var taskSlice = p1.threads[1].sliceGroup.slices[0];
1731 assertEquals(foo15, taskSlice.args.my_object);
1734 test('importArrayWithIDs', function() {
1736 {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: { // @suppress longLineCheck
1738 {id: 'foo/0x1001', value: 'bar1'},
1739 {id: 'foo/0x1002', value: 'bar2'},
1740 {id: 'foo/0x1003', value: 'bar3'}
1744 var m = new tracing.TraceModel();
1745 m.importTraces([events], false);
1746 var p1 = m.processes[1];
1748 var sA = p1.objects.getSnapshotAt('0x1000', 15);
1749 assertTrue(sA.args.x instanceof Array);
1750 assertEquals(3, sA.args.x.length);
1751 assertTrue(sA.args.x[0] instanceof tracing.trace_model.ObjectSnapshot);
1752 assertTrue(sA.args.x[1] instanceof tracing.trace_model.ObjectSnapshot);
1753 assertTrue(sA.args.x[2] instanceof tracing.trace_model.ObjectSnapshot);
1756 test('importDoesNotMutateEventList', function() {
1759 {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
1760 {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: { // @suppress longLineCheck
1761 snapshot: {foo: 15}}},
1762 {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
1764 // A slice that references the object.
1765 {ts: 17000, pid: 1, tid: 1, ph: 'B', cat: 'c', name: 'taskSlice', args: {
1766 my_object: {id_ref: '0x1000'}}
1768 {ts: 17500, pid: 1, tid: 1, ph: 'E', cat: 'c', name: 'taskSlice', args: {}} // @suppress longLineCheck
1771 // The A type family exists to mutate the args list provided to
1773 function ASnapshot() {
1774 tracing.trace_model.ObjectSnapshot.apply(this, arguments);
1777 ASnapshot.prototype = {
1778 __proto__: tracing.trace_model.ObjectSnapshot.prototype
1781 // Import event while the A types are registered, causing the
1782 // arguments of the snapshots to be mutated.
1783 var m = new tracing.TraceModel();
1785 tracing.trace_model.ObjectSnapshot.register('a', ASnapshot);
1786 m.importTraces([events], false);
1788 tracing.trace_model.ObjectSnapshot.unregister('a');
1790 assertFalse(m.hasImportWarnings);
1792 // Verify that the events array wasn't modified.
1795 {snapshot: {foo: 15}});
1798 {my_object: {id_ref: '0x1000'}});
1801 test('importFlowEvent', function() {
1803 { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {} }, // @suppress longLineCheck
1804 { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 560, ph: 't', args: {} }, // @suppress longLineCheck
1805 { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 580, ph: 'f', args: {} } // @suppress longLineCheck
1808 var m = new tracing.TraceModel(events);
1809 var t = m.processes[52].threads[53];
1811 assertNotUndefined(t);
1812 assertEquals(3, t.sliceGroup.slices.length);
1813 assertEquals(2, m.flowEvents.length);
1815 var start = m.flowEvents[0][0];
1816 var step = m.flowEvents[0][1];
1817 var finish = m.flowEvents[1][1];
1819 assertEquals('a', start.title);
1820 assertEquals('foo', start.category);
1821 assertEquals(72, start.id);
1822 assertEquals(0, start.start);
1823 assertEquals(0, start.duration);
1825 assertEquals(start.title, step.title);
1826 assertEquals(start.category, step.category);
1827 assertEquals(start.id, step.id);
1828 assertAlmostEquals(12 / 1000, step.start);
1829 assertEquals(0, step.duration);
1831 assertEquals(start.title, finish.title);
1832 assertEquals(start.category, finish.category);
1833 assertEquals(start.id, finish.id);
1834 assertAlmostEquals((20 + 12) / 1000, finish.start);
1835 assertEquals(0, finish.duration);
1837 assertEquals(2, m.flowIntervalTree.size);
1840 test('importOutOfOrderFlowEvent', function() {
1842 { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {} }, // @suppress longLineCheck
1843 { name: 'b', cat: 'foo', id: 73, pid: 52, tid: 53, ts: 148, ph: 's', args: {} }, // @suppress longLineCheck
1844 { name: 'b', cat: 'foo', id: 73, pid: 52, tid: 53, ts: 570, ph: 'f', args: {} }, // @suppress longLineCheck
1845 { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 560, ph: 't', args: {} }, // @suppress longLineCheck
1846 { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 580, ph: 'f', args: {} } // @suppress longLineCheck
1849 var expected = [0.4, 0.0, 0.412];
1850 var m = new tracing.TraceModel(events);
1851 assertEquals(3, m.flowIntervalTree.size);
1853 var order = m.flowEvents.map(function(x) { return x[0].start });
1854 for (var i = 0; i < expected.length; ++i)
1855 assertAlmostEquals(expected[i], order[i]);
1858 test('importCompleteEvent', function() {
1860 { name: 'a', args: {}, pid: 52, ts: 629, dur: 1, cat: 'baz', tid: 53, ph: 'X' }, // @suppress longLineCheck
1861 { name: 'b', args: {}, pid: 52, ts: 730, dur: 20, cat: 'foo', tid: 53, ph: 'X' }, // @suppress longLineCheck
1862 { name: 'c', args: {}, pid: 52, ts: 740, cat: 'baz', tid: 53, ph: 'X' }
1865 var m = new tracing.TraceModel(events);
1866 assertEquals(1, m.numProcesses);
1867 var p = m.processes[52];
1868 assertNotUndefined(p);
1870 assertEquals(1, p.numThreads);
1871 var t = p.threads[53];
1872 assertNotUndefined(t);
1873 assertEquals(3, t.sliceGroup.slices.length);
1874 assertEquals(53, t.tid);
1876 var slice = t.sliceGroup.slices[0];
1877 assertEquals('a', slice.title);
1878 assertEquals('baz', slice.category);
1879 assertAlmostEquals(0, slice.start);
1880 assertAlmostEquals(1 / 1000, slice.duration);
1881 assertEquals(0, slice.subSlices.length);
1883 slice = t.sliceGroup.slices[1];
1884 assertEquals('b', slice.title);
1885 assertEquals('foo', slice.category);
1886 assertAlmostEquals((730 - 629) / 1000, slice.start);
1887 assertAlmostEquals(20 / 1000, slice.duration);
1888 assertEquals(1, slice.subSlices.length);
1890 slice = t.sliceGroup.slices[2];
1891 assertEquals('c', slice.title);
1892 assertTrue(slice.didNotFinish);
1893 assertAlmostEquals(10 / 1000, slice.duration);
1896 test('importCompleteEventWithCpuDuration', function() {
1898 { name: 'a', args: {}, pid: 52, ts: 629, dur: 1, cat: 'baz', tid: 53, ph: 'X', tts: 12, tdur: 1 }, // @suppress longLineCheck
1899 { name: 'b', args: {}, pid: 52, ts: 730, dur: 20, cat: 'foo', tid: 53, ph: 'X', tts: 110, tdur: 16 }, // @suppress longLineCheck
1900 { name: 'c', args: {}, pid: 52, ts: 740, cat: 'baz', tid: 53, ph: 'X', tts: 115 } // @suppress longLineCheck
1903 var m = new tracing.TraceModel(events);
1904 assertEquals(1, m.numProcesses);
1905 var p = m.processes[52];
1906 assertNotUndefined(p);
1908 assertEquals(1, p.numThreads);
1909 var t = p.threads[53];
1910 assertNotUndefined(t);
1911 assertEquals(3, t.sliceGroup.slices.length);
1912 assertEquals(53, t.tid);
1914 var slice = t.sliceGroup.slices[0];
1915 assertEquals('a', slice.title);
1916 assertEquals('baz', slice.category);
1917 assertAlmostEquals(0, slice.start);
1918 assertAlmostEquals(1 / 1000, slice.duration);
1919 assertAlmostEquals(12 / 1000, slice.cpuStart);
1920 assertAlmostEquals(1 / 1000, slice.cpuDuration);
1921 assertEquals(0, slice.subSlices.length);
1923 slice = t.sliceGroup.slices[1];
1924 assertEquals('b', slice.title);
1925 assertEquals('foo', slice.category);
1926 assertAlmostEquals((730 - 629) / 1000, slice.start);
1927 assertAlmostEquals(20 / 1000, slice.duration);
1928 assertAlmostEquals(110 / 1000, slice.cpuStart);
1929 assertAlmostEquals(16 / 1000, slice.cpuDuration);
1930 assertEquals(1, slice.subSlices.length);
1932 slice = t.sliceGroup.slices[2];
1933 assertEquals('c', slice.title);
1934 assertTrue(slice.didNotFinish);
1935 assertAlmostEquals(10 / 1000, slice.duration);
1938 test('importNestedCompleteEventWithTightBounds', function() {
1940 { name: 'a', args: {}, pid: 52, ts: 244654227065, dur: 36075, cat: 'baz', tid: 53, ph: 'X' }, // @suppress longLineCheck
1941 { name: 'b', args: {}, pid: 52, ts: 244654227095, dur: 36045, cat: 'foo', tid: 53, ph: 'X' } // @suppress longLineCheck
1944 var m = new tracing.TraceModel(events, false);
1945 var t = m.processes[52].threads[53];
1947 var sA = findSliceNamed(t.sliceGroup, 'a');
1948 var sB = findSliceNamed(t.sliceGroup, 'b');
1950 assertEquals('a', sA.title);
1951 assertEquals('baz', sA.category);
1952 assertEquals(244654227.065, sA.start);
1953 assertEquals(36.075, sA.duration);
1954 assertAlmostEquals(0.03, sA.selfTime);
1956 assertEquals('b', sB.title);
1957 assertEquals('foo', sB.category);
1958 assertEquals(244654227.095, sB.start);
1959 assertEquals(36.045, sB.duration);
1961 assertTrue(sA.subSlices.length == 1);
1962 assertTrue(sA.subSlices[0] == sB);
1963 assertTrue(sB.parentSlice == sA);
1966 test('importAsyncEventWithSameTimestamp', function() {
1968 // Events are added with ts 0, 1, 1, 2, 2, 3, 3 ...500, 500, 1000
1969 // and use 'seq' to track the order of when the event is recorded.
1970 events.push({name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 0, ph: 'S', args: {'seq': 0}}); // @suppress longLineCheck
1972 for (var i = 1; i <= 1000; i++)
1973 events.push({name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: Math.round(i / 2) , ph: 'T', args: {'seq': i}}); // @suppress longLineCheck
1975 events.push({name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 1000, ph: 'F', args: {'seq': 1001}}); // @suppress longLineCheck
1977 var m = new tracing.TraceModel(events);
1978 var t = m.processes[52].threads[53];
1980 assertEquals(1, t.asyncSliceGroup.slices.length);
1981 var parentSlice = t.asyncSliceGroup.slices[0];
1982 assertEquals('a', parentSlice.title);
1983 assertEquals('foo', parentSlice.category);
1985 assertNotUndefined(parentSlice.subSlices);
1986 var subSlices = parentSlice.subSlices;
1987 assertEquals(1001, subSlices.length);
1988 // Slices should be sorted according to 'ts'. And if 'ts' is the same,
1989 // slices should keep the order that they were recorded.
1990 for (var i = 0; i < 1000; i++)
1991 assertEquals(subSlices[i].args['seq'], i);
1994 test('sampleDataSimple', function() {
2020 'cpu': 0, 'tid': 1, 'ts': 1000.0,
2021 'name': 'cycles:HG', 'sf': 3, 'weight': 1
2024 'cpu': 0, 'tid': 1, 'ts': 2000.0,
2025 'name': 'cycles:HG', 'sf': 2, 'weight': 1
2028 'cpu': 1, 'tid': 1, 'ts': 3000.0,
2029 'name': 'cycles:HG', 'sf': 3, 'weight': 1
2033 var m = new tracing.TraceModel(events, false);
2034 assertNotUndefined(m.kernel.cpus[0]);
2035 assertEquals(1, m.getAllThreads().length);
2037 assertEquals(4, tv.dictionaryKeys(m.stackFrames).length);
2038 assertEquals(3, m.samples.length);
2040 var t1 = m.processes[1].threads[1];
2041 assertEquals(3, t1.samples.length);
2043 var c0 = m.kernel.cpus[0];
2044 var c1 = m.kernel.cpus[1];
2045 assertEquals(2, c0.samples.length);
2046 assertEquals(1, c1.samples.length);
2048 assertEquals(c0, m.samples[0].cpu);
2049 assertEquals(t1, m.samples[0].thread);
2050 assertEquals('cycles:HG', m.samples[0].title);
2051 assertEquals(1, m.samples[0].start);
2053 ['main', 'a', 'a_sub'],
2054 m.samples[0].stackTrace.map(function(x) { return x.title; }));
2055 assertEquals(1, m.samples[0].weight);
2058 // TODO(nduca): one slice, two threads
2059 // TODO(nduca): one slice, two pids