| <!DOCTYPE HTML> |
| <html> |
| <!-- |
| Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| <head> |
| <title>Timeline stream importer tests</title> |
| <script src="base.js"></script> |
| </head> |
| <body> |
| <script> |
| base.require('unittest'); |
| base.require('event_target'); |
| base.require('test_utils'); |
| base.require('timeline_stream_importer'); |
| </script> |
| <script> |
| 'use strict'; |
| |
| function FakeWebSocket() { |
| base.EventTarget.call(this); |
| this.sendHook_ = undefined; |
| this.messages_ = []; |
| this.connected_ = false; |
| }; |
| |
| FakeWebSocket.prototype = { |
| __proto__: base.EventTarget.prototype, |
| |
| set connected(connected) { |
| if (this.connected_ == connected) |
| return; |
| this.connected_ = connected; |
| if (this.connected_) |
| base.dispatchSimpleEvent(this, 'connect'); |
| else |
| base.dispatchSimpleEvent(this, 'disconnect'); |
| }, |
| |
| get readyState() { |
| if (this.connected_) |
| return WebSocket.OPEN; |
| return WebSocket.CLOSED; |
| }, |
| |
| pushMessage: function(msg) { |
| this.messages_.push(JSON.stringify(msg)); |
| }, |
| |
| get numPendingMessages() { |
| return this.messages_.length; |
| }, |
| |
| dispatchAllPendingMessages: function() { |
| var messages = this.messages_.splice(0, this.messages_.length); |
| for (var i = 0; i < messages.length; i++) |
| this.dispatchEvent({type: 'message', data: messages[i]}); |
| }, |
| |
| /** |
| * @param {function(message)} hook A function to call when send is |
| called on the socket. |
| */ |
| set sendHook(hook) { |
| this.sendHook_ = hook; |
| }, |
| |
| send: function(message) { |
| if (this.sendHook_) |
| this.sendHook_(message); |
| }, |
| |
| set onopen(handler) { |
| this.addEventListener('open', handler); |
| }, |
| |
| set onclose(handler) { |
| this.addEventListener('close', handler); |
| }, |
| |
| set onerror(handler) { |
| this.addEventListener('error', handler); |
| }, |
| |
| set onmessage(handler) { |
| this.addEventListener('message', handler); |
| } |
| }; |
| |
| function testImportBasic() { |
| var model = new tracing.TimelineModel(); |
| var importer = new tracing.TimelineStreamImporter(model); |
| |
| assertFalse(importer.paused); |
| assertFalse(importer.connected); |
| |
| var socket = new FakeWebSocket(); |
| importer.connect(socket); |
| |
| socket.connected = true; |
| assertTrue(importer.connected); |
| |
| socket.pushMessage({ |
| cmd: 'ptd', |
| pid: 1, |
| td: { n: 3, |
| s: [ |
| {s: 10, e: 11, l: 'alligator'}, |
| {s: 14, e: 15, l: 'bandicoot'}, |
| {s: 17, e: 18, l: 'cheetah'}, |
| ] |
| } |
| }); |
| socket.dispatchAllPendingMessages(); |
| |
| assertNotUndefined(model.processes[1]); |
| assertNotUndefined(model.processes[1].threads[3]); |
| var t3 = model.processes[1].threads[3]; |
| assertEquals(3, t3.slices.length); |
| |
| assertEquals(model.minTimestamp, 10); |
| assertEquals(model.maxTimestamp, 18); |
| } |
| |
| function testPause() { |
| var model = new tracing.TimelineModel(); |
| var importer = new tracing.TimelineStreamImporter(model); |
| |
| assertFalse(importer.paused); |
| |
| var socket = new FakeWebSocket(); |
| importer.connect(socket); |
| socket.connected = true; |
| |
| var didSend = false; |
| socket.sendHook = function(message) { |
| var data = JSON.parse(message); |
| didSend = true; |
| assertEquals('pause', data['cmd']); |
| } |
| importer.pause(); |
| assertTrue(didSend); |
| assertTrue(importer.paused); |
| |
| didSend = false; |
| socket.sendHook = function(message) { |
| var data = JSON.parse(message); |
| didSend = true; |
| assertEquals('resume', data['cmd']); |
| } |
| importer.resume(); |
| assertTrue(didSend); |
| assertFalse(importer.paused); |
| } |
| |
| function testCounters() { |
| var model = new tracing.TimelineModel(); |
| var importer = new tracing.TimelineStreamImporter(model); |
| |
| assertFalse(importer.paused); |
| assertFalse(importer.connected); |
| |
| var socket = new FakeWebSocket(); |
| importer.connect(socket); |
| |
| socket.connected = true; |
| assertTrue(importer.connected); |
| |
| socket.pushMessage({ |
| cmd: "pcd", |
| pid: 1, |
| cd: { |
| n: 'Allocator', |
| sn: ['Bytes'], |
| sc: [4], |
| c: [ |
| { |
| t: 2, |
| v: [16] |
| }, |
| { |
| t: 16, |
| v: [32] |
| } |
| ] |
| } |
| }); |
| |
| socket.pushMessage({ |
| cmd: "pcd", |
| pid: 1, |
| cd: { |
| n: 'Allocator', |
| sn: ['Bytes'], |
| sc: [4], |
| c: [ |
| { |
| t: 32, |
| v: [48] |
| }, |
| { |
| t: 48, |
| v: [64] |
| }, |
| { |
| t: 64, |
| v: [16] |
| } |
| ] |
| } |
| }); |
| |
| socket.dispatchAllPendingMessages(); |
| |
| assertNotUndefined(model.processes[1]); |
| assertNotUndefined(model.processes[1].counters['streamed.Allocator']); |
| var counter = model.processes[1].counters['streamed.Allocator']; |
| assertNotUndefined(counter.samples); |
| assertEquals(counter.samples.length, 5); |
| assertEquals(counter.seriesNames.length, 1); |
| assertEquals(counter.seriesColors.length, 1); |
| assertEquals(counter.samples[2], 48); |
| assertEquals(counter.timestamps[4], 64); |
| assertEquals(model.minTimestamp, 2); |
| assertEquals(model.maxTimestamp, 64); |
| } |
| |
| function testCounterImportErrors() { |
| var model = new tracing.TimelineModel(); |
| var importer = new tracing.TimelineStreamImporter(model); |
| |
| assertFalse(importer.paused); |
| assertFalse(importer.connected); |
| |
| var socket = new FakeWebSocket(); |
| importer.connect(socket); |
| |
| socket.connected = true; |
| assertTrue(importer.connected); |
| |
| socket.pushMessage({ |
| cmd: "pcd", |
| pid: 1, |
| cd: { |
| n: 'Allocator', |
| sn: ['Bytes', 'Nibbles', 'Bits'], |
| sc: [4,3,2], |
| c: [ |
| { |
| t: 2, |
| v: [16,12,2] |
| }, |
| { |
| t: 16, |
| v: [32,3,4] |
| } |
| ] |
| } |
| }); |
| |
| // Test for name change import error |
| socket.pushMessage({ |
| cmd: "pcd", |
| pid: 1, |
| cd: { |
| n: 'Allocator', |
| sn: ['Bytes', 'NotNibbles', 'Bits'], |
| sc: [4,3,2], |
| c: [ |
| { |
| t: 18, |
| v: [16,12,2] |
| }, |
| { |
| t: 24, |
| v: [32,3,4] |
| } |
| ] |
| } |
| }); |
| |
| socket.dispatchAllPendingMessages(); |
| |
| assertNotUndefined(model.processes[1]); |
| assertEquals(model.importErrors.length, 1); |
| // test for series number change |
| socket.pushMessage({ |
| cmd: "pcd", |
| pid: 1, |
| cd: { |
| n: 'Allocator', |
| sn: ['Bytes', 'Bits'], |
| sc: [4,3], |
| c: [ |
| { |
| t: 26, |
| v: [16,12] |
| }, |
| { |
| t: 32, |
| v: [32,3] |
| } |
| ] |
| } |
| }); |
| |
| socket.dispatchAllPendingMessages(); |
| assertEquals(model.importErrors.length, 2); |
| |
| // test for sn.length != sc.length |
| socket.pushMessage({ |
| cmd: "pcd", |
| pid: 1, |
| cd: { |
| n: 'Allocator', |
| sn: ['Bytes', 'Nibbles', 'Bits'], |
| sc: [4,3,2,5], |
| c: [ |
| { |
| t: 2, |
| v: [16,12,2] |
| }, |
| { |
| t: 16, |
| v: [32,3,4] |
| } |
| ] |
| } |
| }); |
| |
| |
| socket.dispatchAllPendingMessages(); |
| assertEquals(model.importErrors.length, 3); |
| } |
| </script> |
| </body> |
| </html> |