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.
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."""
24 def Start(self
, page
, tab
):
27 def Stop(self
, page
, tab
):
30 def AddResults(self
, tab
, results
):
33 def AddSummaryResults(self
, tab
, results
):
37 class FakePage(object):
38 """Used to mock loading a page."""
39 def __init__(self
, url
):
41 self
.is_file
= url
.startswith('file://')
44 class FakeTab(object):
45 """Used to mock a browser tab."""
47 self
.clear_cache_calls
= 0
48 self
.navigated_urls
= []
49 def ClearCache(self
, force
=False):
51 self
.clear_cache_calls
+= 1
52 def EvaluateJavaScript(self
, _
):
54 def Navigate(self
, url
):
55 self
.navigated_urls
.append(url
)
56 def WaitForJavaScriptExpression(self
, _
, __
):
62 class FakeBrowser(object):
67 FakeBrowser
._iteration
+= 1
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}
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):
91 def CanMonitorPower(self
):
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(
125 real_memory_module
= page_cycler
.memory
127 page_cycler
.memory
= mock_memory_module
128 browser
= FakeBrowser()
129 cycler
.WillStartBrowser(options
.browser_options
.platform
)
130 cycler
.DidStartBrowser(browser
)
132 page_cycler
.memory
= real_memory_module
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
)
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')]
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')]
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')]
241 self
.assertEqual([], tab
.navigated_urls
)
242 for page
in pages
* 2:
243 cycler
.WillNavigateToPage(page
, tab
)
245 ['http://fakeserver:99999/nonexistent.html'], tab
.navigated_urls
)