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