Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / tools / perf / measurements / page_cycler_unittest.py
blob164e69f21ca19849cb9a05709be56dcd408231c6
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 import unittest
7 from telemetry.core import browser_options
8 from telemetry.results import page_test_results
9 from telemetry.unittest_util import simple_mock
10 from telemetry.user_story import user_story_runner
12 from measurements import page_cycler
15 # Allow testing protected members in the unit test.
16 # pylint: disable=W0212
18 class MockMemoryMetric(object):
19 """Used instead of simple_mock.MockObject so that the precise order and
20 number of calls need not be specified."""
21 def __init__(self):
22 pass
24 def Start(self, page, tab):
25 pass
27 def Stop(self, page, tab):
28 pass
30 def AddResults(self, tab, results):
31 pass
33 def AddSummaryResults(self, tab, results):
34 pass
37 class FakePage(object):
38 """Used to mock loading a page."""
39 def __init__(self, url):
40 self.url = url
41 self.is_file = url.startswith('file://')
44 class FakeTab(object):
45 """Used to mock a browser tab."""
46 def __init__(self):
47 self.clear_cache_calls = 0
48 self.navigated_urls = []
49 def ClearCache(self, force=False):
50 assert force
51 self.clear_cache_calls += 1
52 def EvaluateJavaScript(self, _):
53 return 1
54 def Navigate(self, url):
55 self.navigated_urls.append(url)
56 def WaitForJavaScriptExpression(self, _, __):
57 pass
58 @property
59 def browser(self):
60 return FakeBrowser()
62 class FakeBrowser(object):
63 _iteration = 0
65 @property
66 def cpu_stats(self):
67 FakeBrowser._iteration += 1
68 return {
69 'Browser': {'CpuProcessTime': FakeBrowser._iteration,
70 'TotalTime': FakeBrowser._iteration * 2},
71 'Renderer': {'CpuProcessTime': FakeBrowser._iteration,
72 'TotalTime': FakeBrowser._iteration * 3},
73 'Gpu': {'CpuProcessTime': FakeBrowser._iteration,
74 'TotalTime': FakeBrowser._iteration * 4}
76 @property
77 def platform(self):
78 return FakePlatform()
80 @property
81 def http_server(self):
82 class FakeHttpServer(object):
83 def UrlOf(self, url_path):
84 return 'http://fakeserver:99999/%s' % url_path
85 return FakeHttpServer()
88 class FakePlatform(object):
89 def GetOSName(self):
90 return 'fake'
91 def CanMonitorPower(self):
92 return False
95 class PageCyclerUnitTest(unittest.TestCase):
97 def SetUpCycler(self, page_repeat=1, pageset_repeat=10, cold_load_percent=50,
98 record_v8_object_stats=False, report_speed_index=False,
99 setup_memory_module=False):
100 cycler = page_cycler.PageCycler(
101 page_repeat = page_repeat,
102 pageset_repeat = pageset_repeat,
103 cold_load_percent = cold_load_percent,
104 record_v8_object_stats = record_v8_object_stats,
105 report_speed_index = report_speed_index)
106 options = browser_options.BrowserFinderOptions()
107 options.browser_options.platform = FakePlatform()
108 parser = options.CreateParser()
109 user_story_runner.AddCommandLineArgs(parser)
110 args = ['--page-repeat=%i' % page_repeat,
111 '--pageset-repeat=%i' % pageset_repeat]
112 parser.parse_args(args)
113 user_story_runner.ProcessCommandLineArgs(parser, options)
114 cycler.CustomizeBrowserOptions(options.browser_options)
116 if setup_memory_module:
117 # Mock out memory metrics; the real ones require a real browser.
118 mock_memory_metric = MockMemoryMetric()
120 mock_memory_module = simple_mock.MockObject()
121 mock_memory_module.ExpectCall(
122 'MemoryMetric').WithArgs(simple_mock.DONT_CARE).WillReturn(
123 mock_memory_metric)
125 real_memory_module = page_cycler.memory
126 try:
127 page_cycler.memory = mock_memory_module
128 browser = FakeBrowser()
129 cycler.WillStartBrowser(options.browser_options.platform)
130 cycler.DidStartBrowser(browser)
131 finally:
132 page_cycler.memory = real_memory_module
134 return cycler
136 def testOptionsColdLoadNoArgs(self):
137 cycler = self.SetUpCycler()
139 self.assertEquals(cycler._cold_run_start_index, 5)
141 def testOptionsColdLoadPagesetRepeat(self):
142 cycler = self.SetUpCycler(pageset_repeat=20, page_repeat=2)
144 self.assertEquals(cycler._cold_run_start_index, 20)
146 def testOptionsColdLoadRequested(self):
147 cycler = self.SetUpCycler(pageset_repeat=21, page_repeat=2,
148 cold_load_percent=40)
150 self.assertEquals(cycler._cold_run_start_index, 26)
152 def testCacheHandled(self):
153 cycler = self.SetUpCycler(pageset_repeat=5,
154 cold_load_percent=50,
155 setup_memory_module=True)
157 url_name = 'http://fakepage.com'
158 page = FakePage(url_name)
159 tab = FakeTab()
161 for i in range(5):
162 results = page_test_results.PageTestResults()
163 results.WillRunPage(page)
164 cycler.WillNavigateToPage(page, tab)
165 self.assertEqual(max(0, i - 2), tab.clear_cache_calls,
166 'Iteration %d tab.clear_cache_calls %d' %
167 (i, tab.clear_cache_calls))
168 cycler.ValidateAndMeasurePage(page, tab, results)
169 results.DidRunPage(page)
171 values = results.all_page_specific_values
172 self.assertGreater(len(values), 2)
174 self.assertEqual(values[0].page, page)
175 chart_name = 'cold_times' if i == 0 or i > 2 else 'warm_times'
176 self.assertEqual(values[0].name, '%s.page_load_time' % chart_name)
177 self.assertEqual(values[0].units, 'ms')
179 cycler.DidNavigateToPage(page, tab)
181 def testColdWarm(self):
182 cycler = self.SetUpCycler(pageset_repeat=3, setup_memory_module=True)
183 pages = [FakePage('http://fakepage1.com'), FakePage('http://fakepage2.com')]
184 tab = FakeTab()
185 for i in range(3):
186 for page in pages:
187 results = page_test_results.PageTestResults()
188 results.WillRunPage(page)
189 cycler.WillNavigateToPage(page, tab)
190 cycler.ValidateAndMeasurePage(page, tab, results)
191 results.DidRunPage(page)
193 values = results.all_page_specific_values
194 self.assertGreater(len(values), 2)
196 self.assertEqual(values[0].page, page)
198 chart_name = 'cold_times' if i == 0 or i > 1 else 'warm_times'
199 self.assertEqual(values[0].name, '%s.page_load_time' % chart_name)
200 self.assertEqual(values[0].units, 'ms')
202 cycler.DidNavigateToPage(page, tab)
204 def testResults(self):
205 cycler = self.SetUpCycler(setup_memory_module=True)
207 pages = [FakePage('http://fakepage1.com'), FakePage('http://fakepage2.com')]
208 tab = FakeTab()
210 for i in range(2):
211 for page in pages:
212 results = page_test_results.PageTestResults()
213 results.WillRunPage(page)
214 cycler.WillNavigateToPage(page, tab)
215 cycler.ValidateAndMeasurePage(page, tab, results)
216 results.DidRunPage(page)
218 values = results.all_page_specific_values
219 self.assertEqual(4, len(values))
221 self.assertEqual(values[0].page, page)
222 chart_name = 'cold_times' if i == 0 else 'warm_times'
223 self.assertEqual(values[0].name, '%s.page_load_time' % chart_name)
224 self.assertEqual(values[0].units, 'ms')
226 for value, expected in zip(values[1:], ['gpu', 'renderer', 'browser']):
227 self.assertEqual(value.page, page)
228 self.assertEqual(value.name,
229 'cpu_utilization.cpu_utilization_%s' % expected)
230 self.assertEqual(value.units, '%')
232 cycler.DidNavigateToPage(page, tab)
234 def testLegacyPagesAvoidCrossRenderNavigation(self):
235 # For legacy page cyclers with file URLs, verify that WillNavigateToPage
236 # does an initial navigate to avoid paying for a cross-renderer navigation.
237 cycler = self.SetUpCycler(setup_memory_module=True)
238 pages = [FakePage('file://fakepage1.com'), FakePage('file://fakepage2.com')]
239 tab = FakeTab()
241 self.assertEqual([], tab.navigated_urls)
242 for page in pages * 2:
243 cycler.WillNavigateToPage(page, tab)
244 self.assertEqual(
245 ['http://fakeserver:99999/nonexistent.html'], tab.navigated_urls)