- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / data / webui / net_internals / timeline_view.js
1 // Copyright (c) 2012 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 // Include test fixture.
6 GEN_INCLUDE(['net_internals_test.js']);
7
8 // Anonymous namespace
9 (function() {
10
11 // Range of time set on a log once loaded used by sanity checks.
12 // Used by sanityCheckWithTimeRange.
13 var startTime = null;
14 var endTime = null;
15
16 function timelineView() {
17   return TimelineView.getInstance();
18 }
19
20 function graphView() {
21   return timelineView().graphView_;
22 }
23
24 function scrollbar() {
25   return graphView().scrollbar_;
26 }
27
28 function canvas() {
29   return graphView().canvas_;
30 }
31
32 /**
33  * A Task that creates a log dump, modifies it so |timeTicks| are all in UTC,
34  * clears all events from the log, and then adds two new SOCKET events, which
35  * have the specified start and end times.
36  *
37  * Most of these tests start with this task first.  This gives us a known
38  * starting state, and prevents the data from automatically updating.
39  *
40  * @param {int} startTime Time of the begin event.
41  * @param {int} endTime Time of the end event.
42  * @extends {NetInternalsTest.Task}
43  */
44 function LoadLogWithNewEventsTask(startTime, endTime) {
45   NetInternalsTest.Task.call(this);
46   this.startTime_ = startTime;
47   this.endTime_ = endTime;
48 }
49
50 LoadLogWithNewEventsTask.prototype = {
51   __proto__: NetInternalsTest.Task.prototype,
52
53   /**
54    * Starts creating a log dump.
55    */
56   start: function() {
57     log_util.createLogDumpAsync('test', this.onLogDumpCreated.bind(this), true);
58   },
59
60   /**
61    * Modifies the log dump and loads it.
62    */
63   onLogDumpCreated: function(logDumpText) {
64     var logDump = JSON.parse(logDumpText);
65
66     logDump.constants.timeTickOffset = '0';
67     logDump.events = [];
68
69     var source = new NetInternalsTest.Source(1, EventSourceType.SOCKET);
70     logDump.events.push(
71         NetInternalsTest.createBeginEvent(source, EventType.SOCKET_ALIVE,
72                                           this.startTime_, null));
73     logDump.events.push(
74         NetInternalsTest.createMatchingEndEvent(logDump.events[0],
75                                                 this.endTime_, null));
76     logDumpText = JSON.stringify(logDump);
77
78     assertEquals('Log loaded.', log_util.loadLogFile(logDumpText));
79
80     endTime = this.endTime_;
81     startTime = this.startTime_;
82     if (startTime >= endTime)
83       --startTime;
84
85     sanityCheckWithTimeRange(false);
86
87     this.onTaskDone();
88   }
89 };
90
91 /**
92  * Checks certain invariant properties of the TimelineGraphView and the
93  * scroll bar.
94  */
95 function sanityCheck() {
96   expectLT(graphView().startTime_, graphView().endTime_);
97   expectLE(0, scrollbar().getPosition());
98   expectLE(scrollbar().getPosition(), scrollbar().getRange());
99 }
100
101 /**
102  * Checks what sanityCheck does, but also checks that |startTime| and |endTime|
103  * are the same as those used by the graph, as well as whether we have a timer
104  * running to update the graph's end time.  To avoid flake, this should only
105  * be used synchronously relative to when |startTime| and |endTime| were set,
106  * unless |expectUpdateTimer| is false.
107  * @param {bool} expectUpdateTimer true if the TimelineView should currently
108  *     have an update end time timer running.
109  */
110 function sanityCheckWithTimeRange(expectUpdateTimer) {
111   if (!expectUpdateTimer) {
112     expectEquals(null, timelineView().updateIntervalId_);
113   } else {
114     expectNotEquals(null, timelineView().updateIntervalId_);
115   }
116   assertNotEquals(startTime, null);
117   assertNotEquals(endTime, null);
118   expectEquals(startTime, graphView().startTime_);
119   expectEquals(endTime, graphView().endTime_);
120   sanityCheck(false);
121 }
122
123 /**
124  * Checks what sanityCheck does, but also checks that |startTime| and |endTime|
125  * are the same as those used by the graph.
126  */
127 function sanityCheckNotUpdating() {
128   expectEquals(null, timelineView().updateIntervalId_);
129   sanityCheckWithTimeRange();
130 }
131
132 /**
133  * Simulates mouse wheel movement over the canvas element.
134  * @param {number} ticks Number of mouse wheel ticks to simulate.
135  */
136 function mouseZoom(ticks) {
137   var scrollbarStartedAtEnd =
138       (scrollbar().getRange() == scrollbar().getPosition());
139
140   var event = document.createEvent('WheelEvent');
141   event.initWebKitWheelEvent(0, ticks, window, 0, 0, 0, 0,
142                              false, false, false, false);
143   canvas().dispatchEvent(event);
144
145   // If the scrollbar started at the end of the range, make sure it ends there
146   // as well.
147   if (scrollbarStartedAtEnd)
148     expectEquals(scrollbar().getRange(), scrollbar().getPosition());
149
150   sanityCheck();
151 }
152
153 /**
154  * Simulates moving the mouse wheel up.
155  * @param {number} ticks Number of mouse wheel ticks to simulate.
156  */
157 function mouseZoomIn(ticks) {
158   assertGT(ticks, 0);
159   var oldScale = graphView().scale_;
160   var oldRange = scrollbar().getRange();
161
162   mouseZoom(ticks);
163
164   if (oldScale == graphView().scale_) {
165     expectEquals(oldScale, TimelineGraphView.MIN_SCALE);
166   } else {
167     expectLT(graphView().scale_, oldScale);
168   }
169   expectGE(scrollbar().getRange(), oldRange);
170 }
171
172 /**
173  * Simulates moving the mouse wheel down.
174  * @param {number} ticks Number of mouse wheel ticks to simulate.
175  */
176 function mouseZoomOut(ticks) {
177   assertGT(ticks, 0);
178   var oldScale = graphView().scale_;
179   var oldRange = scrollbar().getRange();
180
181   mouseZoom(-ticks);
182
183   expectGT(graphView().scale_, oldScale);
184   expectLE(scrollbar().getRange(), oldRange);
185 }
186
187 /**
188  * Simulates zooming all the way with multiple mouse wheel events.
189  */
190 function mouseZoomAllTheWayIn() {
191   expectLT(TimelineGraphView.MIN_SCALE, graphView().scale_);
192   while (graphView().scale_ != TimelineGraphView.MIN_SCALE)
193     mouseZoomIn(8);
194   // Verify that zooming in when already at max zoom works.
195   mouseZoomIn(1);
196 }
197
198 /**
199  * A Task that scrolls the scrollbar by manipulating the DOM, and then waits
200  * for the scroll to complete.  Has to be a task because onscroll and DOM
201  * manipulations both occur asynchronously.
202  *
203  * Not safe to use when other asynchronously running code may try to
204  * manipulate the scrollbar itself, or adjust the length of the scrollbar.
205  *
206  * @param {int} position Position to scroll to.
207  * @extends {NetInternalsTest.Task}
208  */
209 function MouseScrollTask(position) {
210   NetInternalsTest.Task.call(this);
211   this.position_ = position;
212   // If the scrollbar's |position| and its node's |scrollLeft| values don't
213   // currently match, we set this to true and wait for |scrollLeft| to be
214   // updated, which will trigger an onscroll event.
215   this.waitingToStart_ = false;
216 }
217
218 MouseScrollTask.prototype = {
219   __proto__: NetInternalsTest.Task.prototype,
220
221   start: function() {
222     this.waitingToStart_ = false;
223     // If the scrollbar is already in the correct position, do nothing.
224     if (scrollbar().getNode().scrollLeft == this.position_) {
225       // We may still have a timer going to adjust the position of the
226       // scrollbar to some other value.  If so, this will clear it.
227       scrollbar().setPosition(this.position_);
228       this.onTaskDone();
229       return;
230     }
231
232     // Replace the onscroll event handler with our own.
233     this.oldOnScroll_ = scrollbar().getNode().onscroll;
234     scrollbar().getNode().onscroll = this.onScroll_.bind(this);
235     if (scrollbar().getNode().scrollLeft != scrollbar().getPosition()) {
236       this.waitingToStart_ = true;
237       return;
238     }
239
240     window.setTimeout(this.startScrolling_.bind(this), 0);
241   },
242
243   onScroll_: function(event) {
244     // Restore the original onscroll function.
245     scrollbar().getNode().onscroll = this.oldOnScroll_;
246     // Call the original onscroll function.
247     this.oldOnScroll_(event);
248
249     if (this.waitingToStart_) {
250       this.start();
251       return;
252     }
253
254     assertEquals(this.position_, scrollbar().getNode().scrollLeft);
255     assertEquals(this.position_, scrollbar().getPosition());
256
257     sanityCheck();
258     this.onTaskDone();
259   },
260
261   startScrolling_: function() {
262     scrollbar().getNode().scrollLeft = this.position_;
263   }
264 };
265
266 /**
267  * Tests setting and updating range.
268  */
269 TEST_F('NetInternalsTest', 'netInternalsTimelineViewRange', function() {
270   NetInternalsTest.switchToView('timeline');
271
272   // Set startTime/endTime for sanity checks.
273   startTime = graphView().startTime_;
274   endTime = graphView().endTime_;
275   sanityCheckWithTimeRange(true);
276
277   startTime = 0;
278   endTime = 10;
279   graphView().setDateRange(new Date(startTime), new Date(endTime));
280   sanityCheckWithTimeRange(true);
281
282   endTime = (new Date()).getTime();
283   graphView().updateEndDate();
284
285   expectGE(graphView().endTime_, endTime);
286   sanityCheck();
287
288   testDone();
289 });
290
291 /**
292  * Tests using the scroll bar.
293  */
294 TEST_F('NetInternalsTest', 'netInternalsTimelineViewScrollbar', function() {
295   // The range we want the graph to have.
296   var expectedGraphRange = canvas().width;
297
298   function checkGraphRange() {
299     expectEquals(expectedGraphRange, scrollbar().getRange());
300   }
301
302   var taskQueue = new NetInternalsTest.TaskQueue(true);
303   // Load a log and then switch to the timeline view.  The end time is
304   // calculated so that the range is exactly |expectedGraphRange|.
305   taskQueue.addTask(
306       new LoadLogWithNewEventsTask(
307           55,
308           55 + graphView().scale_ * (canvas().width + expectedGraphRange)));
309   taskQueue.addFunctionTask(
310       NetInternalsTest.switchToView.bind(null, 'timeline'));
311   taskQueue.addFunctionTask(checkGraphRange);
312
313   taskQueue.addTask(new MouseScrollTask(0));
314   taskQueue.addTask(new MouseScrollTask(expectedGraphRange));
315   taskQueue.addTask(new MouseScrollTask(1));
316   taskQueue.addTask(new MouseScrollTask(expectedGraphRange - 1));
317
318   taskQueue.addFunctionTask(checkGraphRange);
319   taskQueue.addFunctionTask(sanityCheckWithTimeRange.bind(null, false));
320   taskQueue.run();
321 });
322
323 /**
324  * Dumps a log file to memory, modifies its events, loads it again, and
325  * makes sure the range is correctly set and not automatically updated.
326  */
327 TEST_F('NetInternalsTest', 'netInternalsTimelineViewLoadLog', function() {
328   // After loading the log file, the rest of the test runs synchronously.
329   function testBody() {
330     NetInternalsTest.switchToView('timeline');
331     sanityCheckWithTimeRange(false);
332
333     // Make sure everything's still fine when we switch to another view.
334     NetInternalsTest.switchToView('events');
335     sanityCheckWithTimeRange(false);
336   }
337
338   // Load a log and then run the rest of the test.
339   var taskQueue = new NetInternalsTest.TaskQueue(true);
340   taskQueue.addTask(new LoadLogWithNewEventsTask(55, 10055));
341   taskQueue.addFunctionTask(testBody);
342   taskQueue.run();
343 });
344
345 /**
346  * Zooms out twice, and then zooms in once.
347  */
348 TEST_F('NetInternalsTest', 'netInternalsTimelineViewZoomOut', function() {
349   // After loading the log file, the rest of the test runs synchronously.
350   function testBody() {
351     NetInternalsTest.switchToView('timeline');
352     mouseZoomOut(1);
353     mouseZoomOut(1);
354     mouseZoomIn(1);
355     sanityCheckWithTimeRange(false);
356   }
357
358   // Load a log and then run the rest of the test.
359   var taskQueue = new NetInternalsTest.TaskQueue(true);
360   taskQueue.addTask(new LoadLogWithNewEventsTask(55, 10055));
361   taskQueue.addFunctionTask(testBody);
362   taskQueue.run();
363 });
364
365 /**
366  * Zooms in as much as allowed, and zooms out once.
367  */
368 TEST_F('NetInternalsTest', 'netInternalsTimelineViewZoomIn', function() {
369   // After loading the log file, the rest of the test runs synchronously.
370   function testBody() {
371     NetInternalsTest.switchToView('timeline');
372     mouseZoomAllTheWayIn();
373     mouseZoomOut(1);
374     sanityCheckWithTimeRange(false);
375   }
376
377   // Load a log and then run the rest of the test.
378   var taskQueue = new NetInternalsTest.TaskQueue(true);
379   taskQueue.addTask(new LoadLogWithNewEventsTask(55, 10055));
380   taskQueue.addFunctionTask(testBody);
381   taskQueue.run();
382 });
383
384 /**
385  * Tests case of all events having the same time.
386  */
387 TEST_F('NetInternalsTest', 'netInternalsTimelineViewDegenerate', function() {
388   // After loading the log file, the rest of the test runs synchronously.
389   function testBody() {
390     NetInternalsTest.switchToView('timeline');
391     mouseZoomOut(1);
392     mouseZoomAllTheWayIn();
393     mouseZoomOut(1);
394     sanityCheckWithTimeRange(false);
395   }
396
397   // Load a log and then run the rest of the test.
398   var taskQueue = new NetInternalsTest.TaskQueue(true);
399   taskQueue.addTask(new LoadLogWithNewEventsTask(55, 55));
400   taskQueue.addFunctionTask(testBody);
401   taskQueue.run();
402 });
403
404 /**
405  * Tests case of having no events.  Runs synchronously.
406  */
407 TEST_F('NetInternalsTest', 'netInternalsTimelineViewNoEvents', function() {
408   // Click the button to clear all the captured events, and then switch to
409   // timeline
410   $(CaptureView.RESET_BUTTON_ID).click();
411   NetInternalsTest.switchToView('timeline');
412
413   // Set startTime/endTime for sanity checks.
414   startTime = graphView().startTime_;
415   endTime = graphView().endTime_;
416
417   sanityCheckWithTimeRange(true);
418
419   mouseZoomOut(1);
420   sanityCheckWithTimeRange(true);
421
422   mouseZoomAllTheWayIn();
423   sanityCheckWithTimeRange(true);
424
425   mouseZoomOut(1);
426   sanityCheckWithTimeRange(true);
427
428   testDone();
429 });
430
431 })();  // Anonymous namespace