OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 # These tests access private methods in the speedindex module. | 5 # These tests access private methods in the speedindex module. |
6 # pylint: disable=W0212 | 6 # pylint: disable=W0212 |
7 | 7 |
8 import json | 8 import json |
9 import os | 9 import os |
10 import unittest | 10 import unittest |
11 | 11 |
12 from telemetry.core.timeline import model | 12 from telemetry.core.timeline import model |
13 from metrics import speedindex | 13 from metrics import speedindex |
14 | 14 |
15 # Sample timeline data in the json format provided by devtools. | 15 # Sample timeline data in the json format provided by devtools. |
16 # The sample events will be used in several tests below. | 16 # The sample events will be used in several tests below. |
17 _TEST_DIR = os.path.join(os.path.dirname(__file__), 'unittest_data') | 17 _TEST_DIR = os.path.join(os.path.dirname(__file__), 'unittest_data') |
18 _SAMPLE_DATA = json.load(open(os.path.join(_TEST_DIR, 'sample_timeline.json'))) | 18 _SAMPLE_DATA = json.load(open(os.path.join(_TEST_DIR, 'sample_timeline.json'))) |
19 _SAMPLE_EVENTS = model.TimelineModel(event_data=_SAMPLE_DATA).GetAllEvents() | 19 _SAMPLE_EVENTS = model.TimelineModel(event_data=_SAMPLE_DATA).GetAllEvents() |
20 | 20 |
21 | 21 |
| 22 class FakeTimelineModel(object): |
| 23 |
| 24 def __init__(self): |
| 25 self._events = [] |
| 26 |
| 27 def SetAllEvents(self, events): |
| 28 self._events = events |
| 29 |
| 30 def GetAllEvents(self): |
| 31 return self._events |
| 32 |
| 33 |
| 34 class FakeTab(object): |
| 35 |
| 36 def __init__(self): |
| 37 self._timeline_model = FakeTimelineModel() |
| 38 self._javascript_result = None |
| 39 |
| 40 @property |
| 41 def timeline_model(self): |
| 42 return self._timeline_model |
| 43 |
| 44 def SetEvaluateJavaScriptResult(self, result): |
| 45 self._javascript_result = result |
| 46 |
| 47 def EvaluateJavaScript(self, _): |
| 48 return self._javascript_result |
| 49 |
| 50 |
22 class IncludedPaintEventsTest(unittest.TestCase): | 51 class IncludedPaintEventsTest(unittest.TestCase): |
23 def testNumberPaintEvents(self): | 52 def testNumberPaintEvents(self): |
| 53 impl = speedindex.PaintRectSpeedIndexImpl(None) |
24 # In the sample data, there's one event that occurs before the layout event, | 54 # In the sample data, there's one event that occurs before the layout event, |
25 # and one paint event that's not a leaf paint event. | 55 # and one paint event that's not a leaf paint event. |
26 events = speedindex._IncludedPaintEvents(_SAMPLE_EVENTS) | 56 events = impl._IncludedPaintEvents(_SAMPLE_EVENTS) |
27 self.assertEquals(len(events), 5) | 57 self.assertEquals(len(events), 5) |
28 | 58 |
29 | 59 |
30 class TimeAreaDictTest(unittest.TestCase): | 60 class TimeAreaDictTest(unittest.TestCase): |
31 def testAdjustedAreaDict(self): | 61 def testAdjustedAreaDict(self): |
32 paint_events = speedindex._IncludedPaintEvents(_SAMPLE_EVENTS) | 62 impl = speedindex.PaintRectSpeedIndexImpl(None) |
| 63 paint_events = impl._IncludedPaintEvents(_SAMPLE_EVENTS) |
33 viewport = 1000, 1000 | 64 viewport = 1000, 1000 |
34 time_area_dict = speedindex._TimeAreaDict(paint_events, viewport) | 65 time_area_dict = impl._TimeAreaDict(paint_events, viewport) |
35 self.assertEquals(len(time_area_dict), 4) | 66 self.assertEquals(len(time_area_dict), 4) |
36 # The event that ends at time 100 is a fullscreen; it's discounted by half. | 67 # The event that ends at time 100 is a fullscreen; it's discounted by half. |
37 self.assertEquals(time_area_dict[100], 500000) | 68 self.assertEquals(time_area_dict[100], 500000) |
38 self.assertEquals(time_area_dict[300], 100000) | 69 self.assertEquals(time_area_dict[300], 100000) |
39 self.assertEquals(time_area_dict[400], 200000) | 70 self.assertEquals(time_area_dict[400], 200000) |
40 self.assertEquals(time_area_dict[800], 200000) | 71 self.assertEquals(time_area_dict[800], 200000) |
41 | 72 |
42 | 73 |
43 class SpeedIndexTest(unittest.TestCase): | 74 class SpeedIndexTest(unittest.TestCase): |
44 def testWithSampleData(self): | 75 def testWithSampleData(self): |
| 76 tab = FakeTab() |
| 77 impl = speedindex.PaintRectSpeedIndexImpl(tab) |
45 viewport = 1000, 1000 | 78 viewport = 1000, 1000 |
46 # Add up the parts of the speed index for each time interval. | 79 # Add up the parts of the speed index for each time interval. |
47 # Each part is the time interval multiplied by the proportion of the | 80 # Each part is the time interval multiplied by the proportion of the |
48 # total area value that is not yet painted for that interval. | 81 # total area value that is not yet painted for that interval. |
49 parts = [] | 82 parts = [] |
50 parts.append(100 * 1.0) | 83 parts.append(100 * 1.0) |
51 parts.append(200 * 0.5) | 84 parts.append(200 * 0.5) |
52 parts.append(100 * 0.4) | 85 parts.append(100 * 0.4) |
53 parts.append(400 * 0.2) | 86 parts.append(400 * 0.2) |
54 expected = sum(parts) # 330.0 | 87 expected = sum(parts) # 330.0 |
55 actual = speedindex._SpeedIndex(_SAMPLE_EVENTS, viewport) | 88 tab.timeline_model.SetAllEvents(_SAMPLE_EVENTS) |
| 89 tab.SetEvaluateJavaScriptResult(viewport) |
| 90 actual = impl.CalculateSpeedIndex() |
56 self.assertEqual(actual, expected) | 91 self.assertEqual(actual, expected) |
57 | 92 |
58 | 93 |
59 class WPTComparisonTest(unittest.TestCase): | 94 class WPTComparisonTest(unittest.TestCase): |
60 """Compare the speed index results with results given by webpagetest.org. | 95 """Compare the speed index results with results given by webpagetest.org. |
61 | 96 |
62 Given the same timeline data, both this speedindex metric and webpagetest.org | 97 Given the same timeline data, both this speedindex metric and webpagetest.org |
63 should both return the same results. Fortunately, webpagetest.org also | 98 should both return the same results. Fortunately, webpagetest.org also |
64 provides timeline data in json format along with the speed index results. | 99 provides timeline data in json format along with the speed index results. |
65 """ | 100 """ |
66 | 101 |
67 def _TestJsonTimelineExpectation(self, filename, viewport, expected): | 102 def _TestJsonTimelineExpectation(self, filename, viewport, expected): |
68 """Check whether the result for some timeline data is as expected. | 103 """Check whether the result for some timeline data is as expected. |
69 | 104 |
70 Args: | 105 Args: |
71 filename: Filename of a json file which contains a | 106 filename: Filename of a json file which contains a |
72 expected: The result expected based on the WPT result. | 107 expected: The result expected based on the WPT result. |
73 """ | 108 """ |
| 109 tab = FakeTab() |
| 110 impl = speedindex.PaintRectSpeedIndexImpl(tab) |
74 file_path = os.path.join(_TEST_DIR, filename) | 111 file_path = os.path.join(_TEST_DIR, filename) |
75 with open(file_path) as json_file: | 112 with open(file_path) as json_file: |
76 raw_events = json.load(json_file) | 113 raw_events = json.load(json_file) |
77 events = model.TimelineModel(event_data=raw_events).GetAllEvents() | 114 tab.timeline_model.SetAllEvents( |
78 actual = speedindex._SpeedIndex(events, viewport) | 115 model.TimelineModel(event_data=raw_events).GetAllEvents()) |
| 116 tab.SetEvaluateJavaScriptResult(viewport) |
| 117 actual = impl.CalculateSpeedIndex() |
79 # The result might differ by 1 or more milliseconds due to rounding, | 118 # The result might differ by 1 or more milliseconds due to rounding, |
80 # so compare to the nearest 10 milliseconds. | 119 # so compare to the nearest 10 milliseconds. |
81 self.assertAlmostEqual(actual, expected, places=-1) | 120 self.assertAlmostEqual(actual, expected, places=-1) |
82 | 121 |
83 def testCern(self): | 122 def testCern(self): |
84 # Page: http://info.cern.ch/hypertext/WWW/TheProject.html | 123 # Page: http://info.cern.ch/hypertext/WWW/TheProject.html |
85 # This page has only one paint event. | 124 # This page has only one paint event. |
86 self._TestJsonTimelineExpectation( | 125 self._TestJsonTimelineExpectation( |
87 'cern_repeat_timeline.json', (1014, 650), 379.0) | 126 'cern_repeat_timeline.json', (1014, 650), 379.0) |
88 | 127 |
89 def testBaidu(self): | 128 def testBaidu(self): |
90 # Page: http://www.baidu.com/ | 129 # Page: http://www.baidu.com/ |
91 # This page has several paint events, but no nested paint events. | 130 # This page has several paint events, but no nested paint events. |
92 self._TestJsonTimelineExpectation( | 131 self._TestJsonTimelineExpectation( |
93 'baidu_repeat_timeline.json', (1014, 650), 1761.43) | 132 'baidu_repeat_timeline.json', (1014, 650), 1761.43) |
94 | 133 |
95 def test2ch(self): | 134 def test2ch(self): |
96 # Page: http://2ch.net/ | 135 # Page: http://2ch.net/ |
97 # This page has several paint events, including nested paint events. | 136 # This page has several paint events, including nested paint events. |
98 self._TestJsonTimelineExpectation( | 137 self._TestJsonTimelineExpectation( |
99 '2ch_repeat_timeline.json', (997, 650), 674.58) | 138 '2ch_repeat_timeline.json', (997, 650), 674.58) |
100 | 139 |
101 | 140 |
102 if __name__ == "__main__": | 141 if __name__ == "__main__": |
103 unittest.main() | 142 unittest.main() |
104 | 143 |
OLD | NEW |