1# Copyright 2015 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
5import unittest
6
7import telemetry.timeline.event as timeline_event
8from telemetry.testing import test_page_test_results
9from telemetry.web_perf.metrics import startup
10
11
12class StartupTimelineMetricTest(unittest.TestCase):
13
14  def setUp(self):
15    self.events = []
16
17  def AddEvent(self, event_name, start, duration=None):
18    event = timeline_event.TimelineEvent('my_category', event_name,
19                                         start, duration)
20    self.events.append(event)
21
22  # Attributes defined outside __init__
23  # pylint: disable=attribute-defined-outside-init
24  def ComputeStartupMetrics(self):
25    results = test_page_test_results.TestPageTestResults(self)
26
27    # Create a mock model usable by
28    # StartupTimelineMetric.AddWholeTraceResults().
29    def IterateEvents(event_predicate):
30      for event in self.events:
31        if event_predicate(event):
32          yield event
33    class MockClass(object):
34      pass
35    model = MockClass()
36    model.browser_process = MockClass()
37    model.browser_process.parent = MockClass()
38    model.browser_process.parent.IterAllEvents = IterateEvents
39
40    startup.StartupTimelineMetric().AddWholeTraceResults(model, results)
41    return results
42
43  def testUntrackedvents(self):
44    # Code coverage for untracked events
45    self.AddEvent('uknown_event_0', 0)
46    self.AddEvent('uknown_event_1', 1)
47    self.ComputeStartupMetrics()
48
49  def testInstantEventsBasedValue(self):
50    # Test case with instant events to measure the duration between the first
51    # occurrences of two distinct events.
52    START0 = 7
53    START1 = 8
54    DURATION0 = 17
55    DURATION1 = 18
56
57    # Generate duplicated events to make sure we consider only the first one.
58    self.AddEvent(startup._MAIN_ENTRY_POINT, START0)
59    self.AddEvent(startup._MAIN_ENTRY_POINT, START1)
60    self.AddEvent('loadEventEnd', START0 + DURATION0)
61    self.AddEvent('loadEventEnd', START1 + DURATION1)
62    self.AddEvent('requestStart', START0 + DURATION0 * 2)
63    self.AddEvent('requestStart', START1 + DURATION1 * 2)
64
65    results = self.ComputeStartupMetrics()
66    results.AssertHasPageSpecificScalarValue('foreground_tab_load_complete',
67        'ms', DURATION0)
68    results.AssertHasPageSpecificScalarValue('foreground_tab_request_start',
69        'ms', DURATION0 * 2)
70
71  def testDurationEventsBasedValues(self):
72    DURATION_EVENTS = set([
73        'messageloop_start_time',
74        'window_display_time',
75        'open_tabs_time',
76        'first_non_empty_paint_time',
77        'first_main_frame_load_time'])
78
79    # Test case to get the duration of the first occurrence of a duration event.
80    i = 1
81    for display_name in DURATION_EVENTS:
82      self.assertTrue(len(startup._METRICS[display_name]) == 1)
83      event_name = startup._METRICS[display_name][0]
84
85      duration = 13 * i
86      i += 1
87
88      # Generate duplicated events to make sure only the first event is
89      # considered.
90      self.AddEvent(event_name, 5, duration)
91      self.AddEvent(event_name, 6, duration + 2)
92
93    results = self.ComputeStartupMetrics()
94
95    i = 1
96    for display_name in DURATION_EVENTS:
97      duration = 13 * i
98      i += 1
99
100      results.AssertHasPageSpecificScalarValue(display_name, 'ms', duration)
101