<!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>