| 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 |