Fix import error in mac_platform_backend.py
[chromium-blink-merge.git] / tools / perf / metrics / speedindex_unittest.py
bloba16d56bb7e9a823cc27dd543a6686d489b4386e5
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
3 # found in the LICENSE file.
5 # These tests access private methods in the speedindex module.
6 # pylint: disable=W0212
8 import json
9 import os
10 import unittest
12 from telemetry.core.timeline import model
13 from metrics import speedindex
15 # Sample timeline data in the json format provided by devtools.
16 # The sample events will be used in several tests below.
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')))
19 _SAMPLE_EVENTS = model.TimelineModel(event_data=_SAMPLE_DATA).GetAllEvents()
22 class FakeTimelineModel(object):
24 def __init__(self):
25 self._events = []
27 def SetAllEvents(self, events):
28 self._events = events
30 def GetAllEvents(self):
31 return self._events
34 class FakeBitmap(object):
36 def __init__(self, histogram):
37 self._histogram = histogram
39 # pylint: disable=W0613
40 def ColorHistogram(self, ignore_color=None, tolerance=None):
41 return self._histogram
44 class FakeTab(object):
46 def __init__(self, video_capture_result=None):
47 self._timeline_model = FakeTimelineModel()
48 self._javascript_result = None
49 self._video_capture_result = video_capture_result
51 @property
52 def timeline_model(self):
53 return self._timeline_model
55 @property
56 def video_capture_supported(self):
57 return self._video_capture_result is not None
59 def SetEvaluateJavaScriptResult(self, result):
60 self._javascript_result = result
62 def EvaluateJavaScript(self, _):
63 return self._javascript_result
65 def StartVideoCapture(self, min_bitrate_mbps=1):
66 assert self.video_capture_supported
67 assert min_bitrate_mbps > 0
69 def StopVideoCapture(self):
70 assert self.video_capture_supported
71 return self._video_capture_result
73 def Highlight(self, _):
74 pass
77 class IncludedPaintEventsTest(unittest.TestCase):
78 def testNumberPaintEvents(self):
79 impl = speedindex.PaintRectSpeedIndexImpl()
80 # In the sample data, there's one event that occurs before the layout event,
81 # and one paint event that's not a leaf paint event.
82 events = impl._IncludedPaintEvents(_SAMPLE_EVENTS)
83 self.assertEquals(len(events), 5)
86 class SpeedIndexImplTest(unittest.TestCase):
87 def testAdjustedAreaDict(self):
88 impl = speedindex.PaintRectSpeedIndexImpl()
89 paint_events = impl._IncludedPaintEvents(_SAMPLE_EVENTS)
90 viewport = 1000, 1000
91 time_area_dict = impl._TimeAreaDict(paint_events, viewport)
92 self.assertEquals(len(time_area_dict), 4)
93 # The event that ends at time 100 is a fullscreen; it's discounted by half.
94 self.assertEquals(time_area_dict[100], 500000)
95 self.assertEquals(time_area_dict[300], 100000)
96 self.assertEquals(time_area_dict[400], 200000)
97 self.assertEquals(time_area_dict[800], 200000)
99 def testVideoCompleteness(self):
100 frames = [
101 (0.0, FakeBitmap([100, 0, 0])),
102 (0.1, FakeBitmap([50, 25, 25])),
103 (0.2, FakeBitmap([60, 0, 40])),
104 (0.3, FakeBitmap([0, 10, 90]))
106 tab = FakeTab(frames)
107 impl = speedindex.VideoSpeedIndexImpl()
108 impl.Start(tab)
109 impl.Stop(tab)
110 time_completeness = impl.GetTimeCompletenessList(tab)
111 self.assertEquals(len(time_completeness), 4)
112 self.assertEquals(time_completeness[0], (0.0, 0.0))
113 self.assertEquals(time_completeness[1], (0.1, 0.425))
114 self.assertEquals(time_completeness[2], (0.2, 0.4))
115 self.assertEquals(time_completeness[3], (0.3, 1.0))
118 class SpeedIndexTest(unittest.TestCase):
119 def testWithSampleData(self):
120 tab = FakeTab()
121 impl = speedindex.PaintRectSpeedIndexImpl()
122 viewport = 1000, 1000
123 # Add up the parts of the speed index for each time interval.
124 # Each part is the time interval multiplied by the proportion of the
125 # total area value that is not yet painted for that interval.
126 parts = []
127 parts.append(100 * 1.0)
128 parts.append(200 * 0.5)
129 parts.append(100 * 0.4)
130 parts.append(400 * 0.2)
131 expected = sum(parts) # 330.0
132 tab.timeline_model.SetAllEvents(_SAMPLE_EVENTS)
133 tab.SetEvaluateJavaScriptResult(viewport)
134 actual = impl.CalculateSpeedIndex(tab)
135 self.assertEqual(actual, expected)
138 class WPTComparisonTest(unittest.TestCase):
139 """Compare the speed index results with results given by webpagetest.org.
141 Given the same timeline data, both this speedindex metric and webpagetest.org
142 should both return the same results. Fortunately, webpagetest.org also
143 provides timeline data in json format along with the speed index results.
146 def _TestJsonTimelineExpectation(self, filename, viewport, expected):
147 """Check whether the result for some timeline data is as expected.
149 Args:
150 filename: Filename of a json file which contains a
151 expected: The result expected based on the WPT result.
153 tab = FakeTab()
154 impl = speedindex.PaintRectSpeedIndexImpl()
155 file_path = os.path.join(_TEST_DIR, filename)
156 with open(file_path) as json_file:
157 raw_events = json.load(json_file)
158 tab.timeline_model.SetAllEvents(
159 model.TimelineModel(event_data=raw_events).GetAllEvents())
160 tab.SetEvaluateJavaScriptResult(viewport)
161 actual = impl.CalculateSpeedIndex(tab)
162 # The result might differ by 1 or more milliseconds due to rounding,
163 # so compare to the nearest 10 milliseconds.
164 self.assertAlmostEqual(actual, expected, places=-1)
166 def testCern(self):
167 # Page: http://info.cern.ch/hypertext/WWW/TheProject.html
168 # This page has only one paint event.
169 self._TestJsonTimelineExpectation(
170 'cern_repeat_timeline.json', (1014, 650), 379.0)
172 def testBaidu(self):
173 # Page: http://www.baidu.com/
174 # This page has several paint events, but no nested paint events.
175 self._TestJsonTimelineExpectation(
176 'baidu_repeat_timeline.json', (1014, 650), 1761.43)
178 def test2ch(self):
179 # Page: http://2ch.net/
180 # This page has several paint events, including nested paint events.
181 self._TestJsonTimelineExpectation(
182 '2ch_repeat_timeline.json', (997, 650), 674.58)
185 if __name__ == "__main__":
186 unittest.main()