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