1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5'use strict'; 6 7base.require('base.events'); 8base.require('tracing.test_utils'); 9base.require('tracing.importer.timeline_stream_importer'); 10 11base.unittest.testSuite('tracing.importer.timeline_stream_importer', function() { // @suppress longLineCheck 12 var FakeWebSocket = function() { 13 base.EventTarget.call(this); 14 this.sendHook_ = undefined; 15 this.messages_ = []; 16 this.connected_ = false; 17 }; 18 19 FakeWebSocket.prototype = { 20 __proto__: base.EventTarget.prototype, 21 22 set connected(connected) { 23 if (this.connected_ == connected) 24 return; 25 this.connected_ = connected; 26 if (this.connected_) 27 base.dispatchSimpleEvent(this, 'connect'); 28 else 29 base.dispatchSimpleEvent(this, 'disconnect'); 30 }, 31 32 get readyState() { 33 if (this.connected_) 34 return WebSocket.OPEN; 35 return WebSocket.CLOSED; 36 }, 37 38 pushMessage: function(msg) { 39 this.messages_.push(JSON.stringify(msg)); 40 }, 41 42 get numPendingMessages() { 43 return this.messages_.length; 44 }, 45 46 dispatchAllPendingMessages: function() { 47 var messages = this.messages_.splice(0, this.messages_.length); 48 for (var i = 0; i < messages.length; i++) 49 this.dispatchEvent({type: 'message', data: messages[i]}); 50 }, 51 52 /** 53 * @param {function(message)} hook A function to call when send is 54 called on the socket. 55 */ 56 set sendHook(hook) { 57 this.sendHook_ = hook; 58 }, 59 60 send: function(message) { 61 if (this.sendHook_) 62 this.sendHook_(message); 63 }, 64 65 set onopen(handler) { 66 this.addEventListener('open', handler); 67 }, 68 69 set onclose(handler) { 70 this.addEventListener('close', handler); 71 }, 72 73 set onerror(handler) { 74 this.addEventListener('error', handler); 75 }, 76 77 set onmessage(handler) { 78 this.addEventListener('message', handler); 79 } 80 }; 81 82 test('importBasic', function() { 83 var model = new tracing.TraceModel(); 84 var importer = new tracing.importer.TimelineStreamImporter(model); 85 86 assertFalse(importer.paused); 87 assertFalse(importer.connected); 88 89 var socket = new FakeWebSocket(); 90 importer.connect(socket); 91 92 socket.connected = true; 93 assertTrue(importer.connected); 94 95 socket.pushMessage({ 96 cmd: 'ptd', 97 pid: 1, 98 td: { n: 3, 99 s: [ 100 {s: 10, e: 11, l: 'alligator'}, 101 {s: 14, e: 15, l: 'bandicoot'}, 102 {s: 17, e: 18, l: 'cheetah'} 103 ] 104 } 105 }); 106 socket.dispatchAllPendingMessages(); 107 108 assertNotUndefined(model.processes[1]); 109 assertNotUndefined(model.processes[1].threads[3]); 110 var t3 = model.processes[1].threads[3]; 111 assertEquals(3, t3.sliceGroup.length); 112 113 assertEquals(model.bounds.min, 10); 114 assertEquals(model.bounds.max, 18); 115 }); 116 117 test('pause', function() { 118 var model = new tracing.TraceModel(); 119 var importer = new tracing.importer.TimelineStreamImporter(model); 120 121 assertFalse(importer.paused); 122 123 var socket = new FakeWebSocket(); 124 importer.connect(socket); 125 socket.connected = true; 126 127 var didSend = false; 128 socket.sendHook = function(message) { 129 var data = JSON.parse(message); 130 didSend = true; 131 assertEquals('pause', data['cmd']); 132 }; 133 importer.pause(); 134 assertTrue(didSend); 135 assertTrue(importer.paused); 136 137 didSend = false; 138 socket.sendHook = function(message) { 139 var data = JSON.parse(message); 140 didSend = true; 141 assertEquals('resume', data['cmd']); 142 }; 143 importer.resume(); 144 assertTrue(didSend); 145 assertFalse(importer.paused); 146 }); 147 148 test('counters', function() { 149 var model = new tracing.TraceModel(); 150 var importer = new tracing.importer.TimelineStreamImporter(model); 151 152 assertFalse(importer.paused); 153 assertFalse(importer.connected); 154 155 var socket = new FakeWebSocket(); 156 importer.connect(socket); 157 158 socket.connected = true; 159 assertTrue(importer.connected); 160 161 socket.pushMessage({ 162 cmd: 'pcd', 163 pid: 1, 164 cd: { 165 n: 'Allocator', 166 sn: ['Bytes'], 167 sc: [4], 168 c: [ 169 { 170 t: 2, 171 v: [16] 172 }, 173 { 174 t: 16, 175 v: [32] 176 } 177 ] 178 } 179 }); 180 181 socket.pushMessage({ 182 cmd: 'pcd', 183 pid: 1, 184 cd: { 185 n: 'Allocator', 186 sn: ['Bytes'], 187 sc: [4], 188 c: [ 189 { 190 t: 32, 191 v: [48] 192 }, 193 { 194 t: 48, 195 v: [64] 196 }, 197 { 198 t: 64, 199 v: [16] 200 } 201 ] 202 } 203 }); 204 205 socket.dispatchAllPendingMessages(); 206 207 assertNotUndefined(model.processes[1]); 208 assertNotUndefined(model.processes[1].counters['streamed.Allocator']); 209 210 var counter = model.processes[1].counters['streamed.Allocator']; 211 assertNotUndefined(counter.series); 212 213 assertEquals(1, counter.series.length); 214 assertEquals(5, counter.series[0].length); 215 216 assertEquals(48, counter.series[0].getSample(2).value); 217 assertEquals(64, counter.timestamps[4]); 218 219 assertEquals(model.bounds.min, 2); 220 assertEquals(model.bounds.max, 64); 221 }); 222 223 test('counterImportErrors', function() { 224 var model = new tracing.TraceModel(); 225 var importer = new tracing.importer.TimelineStreamImporter(model); 226 227 assertFalse(importer.paused); 228 assertFalse(importer.connected); 229 230 var socket = new FakeWebSocket(); 231 importer.connect(socket); 232 233 socket.connected = true; 234 assertTrue(importer.connected); 235 236 socket.pushMessage({ 237 cmd: 'pcd', 238 pid: 1, 239 cd: { 240 n: 'Allocator', 241 sn: ['Bytes', 'Nibbles', 'Bits'], 242 sc: [4, 3, 2], 243 c: [ 244 { 245 t: 2, 246 v: [16, 12, 2] 247 }, 248 { 249 t: 16, 250 v: [32, 3, 4] 251 } 252 ] 253 } 254 }); 255 256 // Test for name change import error 257 socket.pushMessage({ 258 cmd: 'pcd', 259 pid: 1, 260 cd: { 261 n: 'Allocator', 262 sn: ['Bytes', 'NotNibbles', 'Bits'], 263 sc: [4, 3, 2], 264 c: [ 265 { 266 t: 18, 267 v: [16, 12, 2] 268 }, 269 { 270 t: 24, 271 v: [32, 3, 4] 272 } 273 ] 274 } 275 }); 276 277 socket.dispatchAllPendingMessages(); 278 279 assertNotUndefined(model.processes[1]); 280 assertEquals(model.importErrors.length, 1); 281 // test for series number change 282 socket.pushMessage({ 283 cmd: 'pcd', 284 pid: 1, 285 cd: { 286 n: 'Allocator', 287 sn: ['Bytes', 'Bits'], 288 sc: [4, 3], 289 c: [ 290 { 291 t: 26, 292 v: [16, 12] 293 }, 294 { 295 t: 32, 296 v: [32, 3] 297 } 298 ] 299 } 300 }); 301 302 socket.dispatchAllPendingMessages(); 303 assertEquals(model.importErrors.length, 2); 304 305 // test for sn.length != sc.length 306 socket.pushMessage({ 307 cmd: 'pcd', 308 pid: 1, 309 cd: { 310 n: 'Allocator', 311 sn: ['Bytes', 'Nibbles', 'Bits'], 312 sc: [4, 3, 2, 5], 313 c: [ 314 { 315 t: 2, 316 v: [16, 12, 2] 317 }, 318 { 319 t: 16, 320 v: [32, 3, 4] 321 } 322 ] 323 } 324 }); 325 326 327 socket.dispatchAllPendingMessages(); 328 assertEquals(model.importErrors.length, 3); 329 }); 330}); 331