• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html>
2<html>
3<!--
4Copyright (c) 2012 The Chromium Authors. All rights reserved.
5Use of this source code is governed by a BSD-style license that can be
6found in the LICENSE file.
7-->
8<head>
9<title>TraceEventImporter tests</title>
10<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
11<script src="../shared/js/cr.js"></script>
12<script src="../shared/js/cr/event_target.js"></script>
13<script src="test_utils.js"></script>
14<script src="timeline_model.js"></script>
15<script src="trace_event_importer.js"></script>
16<script>
17  goog.require('goog.testing.jsunit');
18</script>
19
20</head>
21<body>
22<script>
23
24function testCanImportEmpty() {
25  self.assertFalse(tracing.TraceEventImporter.canImport([]));
26  self.assertFalse(tracing.TraceEventImporter.canImport(''));
27}
28
29function testBasicSingleThreadNonnestedParsing() {
30  var events = [
31    {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
32    {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'},
33    {name: 'b', args: {}, pid: 52, ts: 629, cat: 'foo', tid: 53, ph: 'B'},
34    {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'}
35  ];
36
37  var m = new tracing.TimelineModel(events);
38  assertEquals(1, m.numProcesses);
39  var p = m.processes[52];
40  assertNotUndefined(p);
41
42  assertEquals(1, p.numThreads);
43  var t = p.threads[53];
44  assertNotUndefined(t);
45  assertEquals(1, t.subRows.length);
46  assertEquals(53, t.tid);
47  var subRow = t.subRows[0];
48  assertEquals(2, subRow.length);
49  var slice = subRow[0];
50  assertEquals('a', slice.title);
51  assertEquals(0, slice.start);
52  assertAlmostEquals((560 - 520) / 1000, slice.duration);
53  assertEquals(0, slice.subSlices.length);
54
55  slice = subRow[1];
56  assertEquals('b', slice.title);
57  assertAlmostEquals((629 - 520) / 1000, slice.start);
58  assertAlmostEquals((631 - 629) / 1000, slice.duration);
59  assertEquals(0, slice.subSlices.length);
60}
61
62function testNestedParsing() {
63  var events = [
64    {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
65    {name: 'b', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'B'},
66    {name: 'b', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'E'},
67    {name: 'a', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'E'}
68  ];
69  var m = new tracing.TimelineModel(events);
70
71  var p = m.processes[1];
72  var t = p.threads[1];
73  assertEquals(2, t.subRows.length);
74  var subRow = t.subRows[0];
75  assertEquals(1, subRow.length);
76  var slice = subRow[0];
77  assertEquals('a', slice.title);
78  assertEquals((4 - 1) / 1000, slice.duration);
79  assertEquals(1, slice.subSlices.length);
80
81  slice = slice.subSlices[0];
82  assertEquals('b', slice.title);
83  assertEquals((2 - 1) / 1000, slice.start);
84  assertEquals((3 - 2) / 1000, slice.duration);
85  assertEquals(0, slice.subSlices.length);
86
87  subRow = t.subRows[1];
88  slice = subRow[0];
89  assertEquals(t.subRows[0][0].subSlices[0], slice);
90}
91
92function testAutoclosing() {
93  var events = [
94    // Slice that doesn't finish.
95    {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
96
97    // Slice that does finish to give an 'end time' to make autoclosing work.
98    {name: 'b', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 2, ph: 'B'},
99    {name: 'b', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 2, ph: 'E'}
100  ];
101  var m = new tracing.TimelineModel(events);
102  var p = m.processes[1];
103  var t = p.threads[1];
104  var subRow = t.subRows[0];
105  var slice = subRow[0];
106  assertEquals('a', slice.title);
107  assertTrue(slice.didNotFinish);
108  assertEquals(0, slice.start);
109  assertEquals((2 - 1) / 1000, slice.duration);
110}
111
112function testAutoclosingLoneBegin() {
113  var events = [
114    // Slice that doesn't finish.
115    {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'}
116  ];
117  var m = new tracing.TimelineModel(events);
118  var p = m.processes[1];
119  var t = p.threads[1];
120  var subRow = t.subRows[0];
121  var slice = subRow[0];
122  assertEquals('a', slice.title);
123  assertTrue(slice.didNotFinish);
124  assertEquals(0, slice.start);
125  assertEquals(0, slice.duration);
126}
127
128function testAutoclosingWithSubTasks() {
129  var events = [
130    {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
131    {name: 'b1', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'B'},
132    {name: 'b1', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'E'},
133    {name: 'b2', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'B'}
134  ];
135  var m = new tracing.TimelineModel(events);
136  var p = m.processes[1];
137  var t = p.threads[1];
138  assertEquals(2, t.subRows.length);
139  assertEquals(1, t.subRows[0].length);
140  assertEquals(2, t.subRows[1].length);
141}
142
143function testAutoclosingWithEventsOutsideRange() {
144  var events = [
145    // Slice that begins before min and ends after max of the other threads.
146    {name: 'a', args: {}, pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'B'},
147    {name: 'a', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'B'},
148
149    // Slice that does finish to give an 'end time' to establish a basis
150    {name: 'b', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 2, ph: 'B'},
151    {name: 'b', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 2, ph: 'E'}
152  ];
153  var m = new tracing.TimelineModel(events);
154  var p = m.processes[1];
155  var t = p.threads[1];
156  var subRow = t.subRows[0];
157  assertEquals('a', subRow[0].title);
158  assertEquals(0, subRow[0].start);
159  assertEquals(0.003, subRow[0].duration);
160
161  var t = p.threads[2];
162  var subRow = t.subRows[0];
163  assertEquals('b', subRow[0].title);
164  assertEquals(0.001, subRow[0].start);
165  assertEquals(0.001, subRow[0].duration);
166
167  // 0.00345 instead of 0.003 because TimelineModel bloats the world range by
168  // 15%.
169  assertEquals(-0.00045, m.minTimestamp);
170  assertEquals(0.00345, m.maxTimestamp);
171
172}
173
174function testNestedAutoclosing() {
175  var events = [
176    // Tasks that dont finish.
177    {name: 'a1', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
178    {name: 'a2', args: {}, pid: 1, ts: 1.5, cat: 'foo', tid: 1, ph: 'B'},
179
180    // Slice that does finish to give an 'end time' to make autoclosing work.
181    {name: 'b', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 2, ph: 'B'},
182    {name: 'b', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 2, ph: 'E'}
183  ];
184  var m = new tracing.TimelineModel(events);
185  var p = m.processes[1];
186  var t = p.threads[1];
187  var subRow = t.subRows[0];
188  var slice = subRow[0];
189  assertEquals('a1', slice.title);
190  assertTrue(slice.didNotFinish);
191  assertEquals(0, slice.start);
192  assertEquals((2 - 1) / 1000, slice.duration);
193
194  var slice = slice.subSlices[0];
195  assertEquals('a2', slice.title);
196  assertTrue(slice.didNotFinish);
197  assertEquals((1.5 - 1) / 1000, slice.start);
198  assertEquals((2 - 1.5) / 1000, slice.duration);
199}
200
201function testTaskColoring() {
202  // The test below depends on hashing of 'a' != 'b'. Fail early if that
203  // assumption is incorrect.
204  assertNotEquals(tracing.getStringHash('a'), tracing.getStringHash('b'));
205
206  var events = [
207    {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
208    {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
209    {name: 'b', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'B'},
210    {name: 'b', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'E'},
211    {name: 'a', args: {}, pid: 1, ts: 5, cat: 'foo', tid: 1, ph: 'B'},
212    {name: 'a', args: {}, pid: 1, ts: 6, cat: 'foo', tid: 1, ph: 'E'}
213  ];
214  var m = new tracing.TimelineModel(events);
215  var p = m.processes[1];
216  var t = p.threads[1];
217  var subRow = t.subRows[0];
218  var a1 = subRow[0];
219  assertEquals('a', a1.title);
220  var b = subRow[1];
221  assertEquals('b', b.title);
222  assertNotEquals(a1.colorId, b.colorId);
223  var a2 = subRow[0];
224  assertEquals('a', a2.title);
225  assertEquals(a1.colorId, a2.colorId);
226}
227
228function testMultipleThreadParsing() {
229  var events = [
230    {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
231    {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
232    {name: 'b', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 2, ph: 'B'},
233    {name: 'b', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 2, ph: 'E'}
234  ];
235  var m = new tracing.TimelineModel(events);
236  assertEquals(1, m.numProcesses);
237  var p = m.processes[1];
238  assertNotUndefined(p);
239
240  assertEquals(2, p.numThreads);
241
242  // Check thread 1.
243  var t = p.threads[1];
244  assertNotUndefined(t);
245  assertEquals(1, t.subRows.length);
246  assertEquals(1, t.tid);
247
248  var subRow = t.subRows[0];
249  assertEquals(1, subRow.length);
250  var slice = subRow[0];
251  assertEquals('a', slice.title);
252  assertEquals(0, slice.start);
253  assertEquals((2 - 1) / 1000, slice.duration);
254  assertEquals(0, slice.subSlices.length);
255
256  // Check thread 2.
257  var t = p.threads[2];
258  assertNotUndefined(t);
259  assertEquals(1, t.subRows.length);
260  assertEquals(2, t.tid);
261
262  subRow = t.subRows[0];
263  assertEquals(1, subRow.length);
264  slice = subRow[0];
265  assertEquals('b', slice.title);
266  assertEquals((3 - 1) / 1000, slice.start);
267  assertEquals((4 - 3) / 1000, slice.duration);
268  assertEquals(0, slice.subSlices.length);
269}
270
271function testMultiplePidParsing() {
272  var events = [
273    {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
274    {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
275    {name: 'b', args: {}, pid: 2, ts: 3, cat: 'foo', tid: 2, ph: 'B'},
276    {name: 'b', args: {}, pid: 2, ts: 4, cat: 'foo', tid: 2, ph: 'E'}
277  ];
278  var m = new tracing.TimelineModel(events);
279  assertEquals(2, m.numProcesses);
280  var p = m.processes[1];
281  assertNotUndefined(p);
282
283  assertEquals(1, p.numThreads);
284
285  // Check process 1 thread 1.
286  var t = p.threads[1];
287  assertNotUndefined(t);
288  assertEquals(1, t.subRows.length);
289  assertEquals(1, t.tid);
290
291  var subRow = t.subRows[0];
292  assertEquals(1, subRow.length);
293  var slice = subRow[0];
294  assertEquals('a', slice.title);
295  assertEquals(0, slice.start);
296  assertEquals((2 - 1) / 1000, slice.duration);
297  assertEquals(0, slice.subSlices.length);
298
299  // Check process 2 thread 2.
300  var p = m.processes[2];
301  assertNotUndefined(p);
302  assertEquals(1, p.numThreads);
303  var t = p.threads[2];
304  assertNotUndefined(t);
305  assertEquals(1, t.subRows.length);
306  assertEquals(2, t.tid);
307
308  subRow = t.subRows[0];
309  assertEquals(1, subRow.length);
310  slice = subRow[0];
311  assertEquals('b', slice.title);
312  assertEquals((3 - 1) / 1000, slice.start);
313  assertEquals((4 - 3) / 1000, slice.duration);
314  assertEquals(0, slice.subSlices.length);
315
316  // Check getAllThreads.
317  assertArrayEquals([m.processes[1].threads[1], m.processes[2].threads[2]],
318                    m.getAllThreads());
319}
320
321// Thread names.
322function testThreadNames() {
323  var events = [
324    {name: 'thread_name', args: {name: 'Thread 1'},
325      pid: 1, ts: 0, tid: 1, ph: 'M'},
326    {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
327    {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
328    {name: 'b', args: {}, pid: 2, ts: 3, cat: 'foo', tid: 2, ph: 'B'},
329    {name: 'b', args: {}, pid: 2, ts: 4, cat: 'foo', tid: 2, ph: 'E'},
330    {name: 'thread_name', args: {name: 'Thread 2'},
331      pid: 2, ts: 0, tid: 2, ph: 'M'}
332  ];
333  var m = new tracing.TimelineModel(events);
334  assertEquals('Thread 1', m.processes[1].threads[1].name);
335  assertEquals('Thread 2', m.processes[2].threads[2].name);
336}
337
338// User time.
339function testUserTime() {
340  var events = [
341    {name: 'thread_name', args: {name: 'Thread 1'},
342      pid: 1, ts: 0, tid: 1, ph: 'M'},
343    {name: 'a', args: {}, pid: 1, ts: 1, uts: 10, cat: 'foo', tid: 1, ph: 'B'},
344    {name: 'a', args: {}, pid: 1, ts: 2, uts: 20, cat: 'foo', tid: 1, ph: 'E'},
345    {name: 'a', args: {}, pid: 1, ts: 2 , uts: 60, cat: 'foo', tid: 1, ph: 'I'}
346  ];
347  var m = new tracing.TimelineModel(events);
348  var subRow = m.processes[1].threads[1].subRows[0];
349  assertEquals(0.01, subRow[0].startInUserTime);
350  assertEquals(0.01, subRow[0].durationInUserTime);
351  assertEquals(0.06, subRow[1].startInUserTime);
352  assertEquals(0, subRow[1].durationInUserTime);
353}
354
355
356function testImmediateParsing() {
357  var events = [
358    // Need to include immediates inside a task so the timeline
359    // recentering/zeroing doesn't clobber their timestamp.
360    {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
361    {name: 'immediate', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'I'},
362    {name: 'a', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'E'}
363  ];
364  var m = new tracing.TimelineModel(events);
365  var p = m.processes[1];
366  var t = p.threads[1];
367  assertEquals(2, t.subRows.length);
368  var subRow = t.subRows[0];
369  assertEquals(1, subRow.length);
370  var slice = subRow[0];
371  assertEquals('a', slice.title);
372  assertEquals((4 - 1) / 1000, slice.duration);
373  assertEquals(1, slice.subSlices.length);
374
375  var immed = slice.subSlices[0];
376  assertEquals('immediate', immed.title);
377  assertEquals((2 - 1) / 1000, immed.start);
378  assertEquals(0, immed.duration);
379  assertEquals(0, immed.subSlices.length);
380
381  subRow = t.subRows[1];
382  assertEquals(immed, subRow[0]);
383}
384
385function testSimpleCounter() {
386  var events = [
387    {name: 'ctr', args: {'value': 0}, pid: 1, ts: 0, cat: 'foo', tid: 1,
388     ph: 'C'},
389    {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
390     ph: 'C'},
391    {name: 'ctr', args: {'value': 0}, pid: 1, ts: 20, cat: 'foo', tid: 1,
392     ph: 'C'}
393
394  ];
395  var m = new tracing.TimelineModel(events);
396  var p = m.processes[1];
397  var ctr = m.processes[1].counters['foo.ctr'];
398
399  assertEquals('ctr', ctr.name);
400  assertEquals(3, ctr.numSamples);
401  assertEquals(1, ctr.numSeries);
402
403  assertArrayEquals(['value'], ctr.seriesNames);
404  assertArrayEquals([tracing.getStringColorId('ctr.value')], ctr.seriesColors);
405  assertArrayEquals([0, 0.01, 0.02], ctr.timestamps);
406  assertArrayEquals([0, 10, 0], ctr.samples);
407  assertArrayEquals([0, 10, 0], ctr.totals);
408  assertEquals(10, ctr.maxTotal);
409}
410
411function testInstanceCounter() {
412  var events = [
413    {name: 'ctr', args: {'value': 0}, pid: 1, ts: 0, cat: 'foo', tid: 1,
414     ph: 'C', id: 0},
415    {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
416     ph: 'C', id: 0},
417    {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
418     ph: 'C', id: 1},
419    {name: 'ctr', args: {'value': 20}, pid: 1, ts: 15, cat: 'foo', tid: 1,
420     ph: 'C', id: 1},
421    {name: 'ctr', args: {'value': 30}, pid: 1, ts: 18, cat: 'foo', tid: 1,
422     ph: 'C', id: 1}
423  ];
424  var m = new tracing.TimelineModel(events);
425  var p = m.processes[1];
426  var ctr = m.processes[1].counters['foo.ctr[0]'];
427  assertEquals('ctr[0]', ctr.name);
428  assertEquals(2, ctr.numSamples);
429  assertEquals(1, ctr.numSeries);
430  assertArrayEquals([0, 0.01], ctr.timestamps);
431  assertArrayEquals([0, 10], ctr.samples);
432
433  var ctr = m.processes[1].counters['foo.ctr[1]'];
434  assertEquals('ctr[1]', ctr.name);
435  assertEquals(3, ctr.numSamples);
436  assertEquals(1, ctr.numSeries);
437  assertArrayEquals([0.01, 0.015, 0.018], ctr.timestamps);
438  assertArrayEquals([10, 20, 30], ctr.samples);
439}
440
441function testMultiCounterUpdateBounds() {
442  var ctr = new tracing.TimelineCounter(undefined, 'testBasicCounter',
443'testBasicCounter');
444  ctr.numSeries = 1;
445  ctr.seriesNames = ['value1', 'value2'];
446  ctr.seriesColors = ['testBasicCounter.value1', 'testBasicCounter.value2'];
447  ctr.timestamps = [0, 1, 2, 3, 4, 5, 6, 7];
448  ctr.samples = [0, 0,
449                 1, 0,
450                 1, 1,
451                 2, 1.1,
452                 3, 0,
453                 1, 7,
454                 3, 0,
455                 3.1, 0.5];
456  ctr.updateBounds();
457  assertEquals(0, ctr.minTimestamp);
458  assertEquals(7, ctr.maxTimestamp);
459  assertEquals(8, ctr.maxTotal);
460  assertArrayEquals([0, 0,
461                     1, 1,
462                     1, 2,
463                     2, 3.1,
464                     3, 3,
465                     1, 8,
466                     3, 3,
467                     3.1, 3.6], ctr.totals);
468}
469
470function testMultiCounter() {
471  var events = [
472    {name: 'ctr', args: {'value1': 0, 'value2': 7}, pid: 1, ts: 0, cat: 'foo',
473     tid: 1, ph: 'C'},
474    {name: 'ctr', args: {'value1': 10, 'value2': 4}, pid: 1, ts: 10, cat: 'foo',
475     tid: 1, ph: 'C'},
476    {name: 'ctr', args: {'value1': 0, 'value2': 1 }, pid: 1, ts: 20, cat: 'foo',
477     tid: 1, ph: 'C'}
478  ];
479  var m = new tracing.TimelineModel(events);
480  var p = m.processes[1];
481  var ctr = m.processes[1].counters['foo.ctr'];
482  assertEquals('ctr', ctr.name);
483
484  assertEquals('ctr', ctr.name);
485  assertEquals(3, ctr.numSamples);
486  assertEquals(2, ctr.numSeries);
487
488  assertArrayEquals(['value1', 'value2'], ctr.seriesNames);
489  assertArrayEquals([tracing.getStringColorId('ctr.value1'),
490                     tracing.getStringColorId('ctr.value2')],
491                    ctr.seriesColors);
492  assertArrayEquals([0, 0.01, 0.02], ctr.timestamps);
493  assertArrayEquals([0, 7,
494                     10, 4,
495                     0, 1], ctr.samples);
496  assertArrayEquals([0, 7,
497                     10, 14,
498                     0, 1], ctr.totals);
499  assertEquals(14, ctr.maxTotal);
500}
501
502function testImportObjectInsteadOfArray() {
503  var events = { traceEvents: [
504    {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
505    {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
506  ] };
507
508  var m = new tracing.TimelineModel(events);
509  assertEquals(1, m.numProcesses);
510}
511
512function testImportString() {
513  var events = [
514    {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
515    {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
516  ];
517
518  var m = new tracing.TimelineModel(JSON.stringify(events));
519  assertEquals(1, m.numProcesses);
520}
521
522function testImportStringWithTrailingNewLine() {
523  var events = [
524    {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
525    {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
526  ];
527
528  var m = new tracing.TimelineModel(JSON.stringify(events) + '\n');
529  assertEquals(1, m.numProcesses);
530}
531
532function testImportStringWithMissingCloseSquareBracket() {
533  var events = [
534    {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
535    {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
536  ];
537
538  var tmp = JSON.stringify(events);
539  assertEquals(']', tmp[tmp.length - 1]);
540
541  // Drop off the trailing ]
542  var dropped = tmp.substring(0, tmp.length - 1);
543  var m = new tracing.TimelineModel(dropped);
544  assertEquals(1, m.numProcesses);
545}
546
547function testImportStringWithMissingCloseSquareBracketAndNewline() {
548  var events = [
549    {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
550    {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
551  ];
552
553  var tmp = JSON.stringify(events);
554  assertEquals(']', tmp[tmp.length - 1]);
555
556  // Drop off the trailing ] and add a newline
557  var dropped = tmp.substring(0, tmp.length - 1);
558  var m = new tracing.TimelineModel(dropped + '\n');
559  assertEquals(1, m.numProcesses);
560}
561
562function testStartFinishOneSliceOneThread() {
563  var events = [
564    // Time is intentionally out of order.
565    {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53,
566       ph: 'F', id: 72},
567    {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
568       ph: 'S', id: 72, args: {foo: 'bar'}}
569  ];
570
571  var m = new tracing.TimelineModel(events);
572  var t = m.processes[52].threads[53];
573  assertNotUndefined(t);
574  assertEquals(1, t.asyncSlices.slices.length);
575  assertEquals('a', t.asyncSlices.slices[0].title);
576  assertEquals(72, t.asyncSlices.slices[0].id);
577  assertEquals('bar', t.asyncSlices.slices[0].args.foo);
578  assertEquals(0, t.asyncSlices.slices[0].start);
579  assertAlmostEquals((60 - 24) / 1000, t.asyncSlices.slices[0].duration);
580  assertEquals(t, t.asyncSlices.slices[0].startThread);
581  assertEquals(t, t.asyncSlices.slices[0].endThread);
582}
583
584function testEndArgsAddedToSlice() {
585  var events = [
586    {name: 'a', args: {x: 1}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
587    {name: 'a', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'},
588  ];
589
590  var m = new tracing.TimelineModel(events);
591  assertEquals(1, m.numProcesses);
592  var p = m.processes[52];
593  assertNotUndefined(p);
594
595  assertEquals(1, p.numThreads);
596  var t = p.threads[53];
597  assertNotUndefined(t);
598  assertEquals(1, t.subRows.length);
599  assertEquals(53, t.tid);
600  var subRow = t.subRows[0];
601  assertEquals(1, subRow.length);
602  var slice = subRow[0];
603  assertEquals('a', slice.title);
604  assertEquals(0, slice.start);
605  assertEquals(0, slice.subSlices.length);
606  assertEquals(1, slice.args['x']);
607  assertEquals(2, slice.args['y']);
608}
609
610function testEndArgOverrwritesOriginalArgValueIfDuplicated() {
611  var events = [
612    {name: 'b', args: {z: 3}, pid: 52, ts: 629, cat: 'foo', tid: 53, ph: 'B'},
613    {name: 'b', args: {z: 4}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'}
614  ];
615
616  var m = new tracing.TimelineModel(events);
617  assertEquals(1, m.numProcesses);
618  var p = m.processes[52];
619  assertNotUndefined(p);
620
621  assertEquals(1, p.numThreads);
622  var t = p.threads[53];
623  assertNotUndefined(t);
624  assertEquals(1, t.subRows.length);
625  assertEquals(53, t.tid);
626  var subRow = t.subRows[0];
627  assertEquals(1, subRow.length);
628  var slice = subRow[0];
629  assertEquals('b', slice.title);
630  assertEquals(0, slice.start);
631  assertEquals(0, slice.subSlices.length);
632  assertEquals(4, slice.args['z']);
633}
634
635function testAsyncEndArgsAddedToSlice() {
636  var events = [
637    // Time is intentionally out of order.
638    {name: 'c', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53,
639       ph: 'F', id: 72},
640    {name: 'c', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
641       ph: 'S', id: 72}
642  ];
643
644  var m = new tracing.TimelineModel(events);
645  var t = m.processes[52].threads[53];
646  assertNotUndefined(t);
647  assertEquals(1, t.asyncSlices.slices.length);
648  var parentSlice = t.asyncSlices.slices[0];
649  assertEquals('c', parentSlice.title);
650
651  assertNotUndefined(parentSlice.subSlices);
652  assertEquals(1, parentSlice.subSlices.length);
653  var subSlice = parentSlice.subSlices[0];
654  assertEquals(1, subSlice.args['x']);
655  assertEquals(2, subSlice.args['y']);
656}
657
658function testAsyncEndArgOverrwritesOriginalArgValueIfDuplicated() {
659  var events = [
660    // Time is intentionally out of order.
661    {name: 'd', args: {z: 4}, pid: 52, ts: 560, cat: 'foo', tid: 53,
662       ph: 'F', id: 72},
663    {name: 'd', args: {z: 3}, pid: 52, ts: 524, cat: 'foo', tid: 53,
664       ph: 'S', id: 72}
665  ];
666
667  var m = new tracing.TimelineModel(events);
668  var t = m.processes[52].threads[53];
669  assertNotUndefined(t);
670  assertEquals(1, t.asyncSlices.slices.length);
671  var parentSlice = t.asyncSlices.slices[0];
672  assertEquals('d', parentSlice.title);
673
674  assertNotUndefined(parentSlice.subSlices);
675  assertEquals(1, parentSlice.subSlices.length);
676  var subSlice = parentSlice.subSlices[0];
677  assertEquals(4, subSlice.args['z']);
678}
679
680function testAsyncStepsInOneThread() {
681  var events = [
682    // Time is intentionally out of order.
683    {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
684       ph: 'F', id: 72},
685    {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo', tid: 53,
686       ph: 'T', id: 72, },
687    {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
688       ph: 'S', id: 72}
689  ];
690
691  var m = new tracing.TimelineModel(events);
692  var t = m.processes[52].threads[53];
693  assertNotUndefined(t);
694  assertEquals(1, t.asyncSlices.slices.length);
695  var parentSlice = t.asyncSlices.slices[0];
696  assertEquals('a', parentSlice.title);
697  assertEquals(0, parentSlice.start);
698
699  assertNotUndefined(parentSlice.subSlices);
700  assertEquals(2, parentSlice.subSlices.length);
701  var subSlice = parentSlice.subSlices[0];
702  assertEquals('a', subSlice.title);
703  assertEquals(0, subSlice.start);
704  assertAlmostEquals((548 - 524) / 1000, subSlice.duration);
705  assertEquals(1, subSlice.args['x']);
706
707  var subSlice = parentSlice.subSlices[1];
708  assertEquals('a:s1', subSlice.title);
709  assertAlmostEquals((548 - 524) / 1000, subSlice.start);
710  assertAlmostEquals((560 - 548) / 1000, subSlice.duration);
711  assertEquals(2, subSlice.args['y']);
712  assertEquals(3, subSlice.args['z']);
713}
714
715function testAsyncStepsMissingStart() {
716  var events = [
717    // Time is intentionally out of order.
718    {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
719       ph: 'F', id: 72},
720    {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo', tid: 53,
721       ph: 'T', id: 72, },
722  ];
723
724  var m = new tracing.TimelineModel(events);
725  var t = m.processes[52].threads[53];
726  assertUndefined(t);
727}
728
729function testAsyncStepsMissingFinish() {
730  var events = [
731    // Time is intentionally out of order.
732    {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo', tid: 53,
733       ph: 'T', id: 72, },
734    {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
735       ph: 'S', id: 72},
736  ];
737
738  var m = new tracing.TimelineModel(events);
739  var t = m.processes[52].threads[53];
740  assertUndefined(t);
741}
742
743// TODO(nduca): one slice, two threads
744// TODO(nduca): one slice, two pids
745
746</script>
747</body>
748</html>
749