Make Data Saver integration test use new secure proxy check URL flag.
[chromium-blink-merge.git] / tools / chrome_proxy / integration_tests / chrome_proxy_measurements.py
blobf58bb03de30dfdd5259a861a9ce820d565538a05
1 # Copyright 2014 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 base64
6 import logging
7 import urlparse
9 from integration_tests import chrome_proxy_metrics as metrics
10 from metrics import loading
11 from telemetry.core import exceptions
12 from telemetry.page import page_test
15 class ChromeProxyLatency(page_test.PageTest):
16 """Chrome proxy latency measurement."""
18 def __init__(self, *args, **kwargs):
19 super(ChromeProxyLatency, self).__init__(*args, **kwargs)
21 def WillNavigateToPage(self, page, tab):
22 tab.ClearCache(force=True)
24 def ValidateAndMeasurePage(self, page, tab, results):
25 # Wait for the load event.
26 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
27 loading.LoadingMetric().AddResults(tab, results)
30 class ChromeProxyDataSaving(page_test.PageTest):
31 """Chrome proxy data daving measurement."""
32 def __init__(self, *args, **kwargs):
33 super(ChromeProxyDataSaving, self).__init__(*args, **kwargs)
34 self._metrics = metrics.ChromeProxyMetric()
36 def WillNavigateToPage(self, page, tab):
37 tab.ClearCache(force=True)
38 self._metrics.Start(page, tab)
40 def ValidateAndMeasurePage(self, page, tab, results):
41 # Wait for the load event.
42 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
43 self._metrics.Stop(page, tab)
44 self._metrics.AddResultsForDataSaving(tab, results)
47 class ChromeProxyValidation(page_test.PageTest):
48 """Base class for all chrome proxy correctness measurements."""
50 def __init__(self, restart_after_each_page=False):
51 super(ChromeProxyValidation, self).__init__(
52 needs_browser_restart_after_each_page=restart_after_each_page)
53 self._metrics = metrics.ChromeProxyMetric()
54 self._page = None
55 # Whether a timeout exception is expected during the test.
56 self._expect_timeout = False
58 def CustomizeBrowserOptions(self, options):
59 # Enable the chrome proxy (data reduction proxy).
60 options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
62 def WillNavigateToPage(self, page, tab):
63 tab.ClearCache(force=True)
64 assert self._metrics
65 self._metrics.Start(page, tab)
67 def ValidateAndMeasurePage(self, page, tab, results):
68 self._page = page
69 # Wait for the load event.
70 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
71 assert self._metrics
72 self._metrics.Stop(page, tab)
73 self.AddResults(tab, results)
75 def AddResults(self, tab, results):
76 raise NotImplementedError
78 def StopBrowserAfterPage(self, browser, page): # pylint: disable=W0613
79 if hasattr(page, 'restart_after') and page.restart_after:
80 return True
81 return False
83 def RunNavigateSteps(self, page, tab):
84 # The redirect from safebrowsing causes a timeout. Ignore that.
85 try:
86 super(ChromeProxyValidation, self).RunNavigateSteps(page, tab)
87 if self._expect_timeout:
88 raise metrics.ChromeProxyMetricException, (
89 'Timeout was expected, but did not occur')
90 except exceptions.DevtoolsTargetCrashException, e:
91 if self._expect_timeout:
92 logging.warning('Navigation timeout on page %s',
93 page.name if page.name else page.url)
94 else:
95 raise e
98 class ChromeProxyHeaders(ChromeProxyValidation):
99 """Correctness measurement for response headers."""
101 def __init__(self):
102 super(ChromeProxyHeaders, self).__init__(restart_after_each_page=True)
104 def AddResults(self, tab, results):
105 self._metrics.AddResultsForHeaderValidation(tab, results)
108 class ChromeProxyBypass(ChromeProxyValidation):
109 """Correctness measurement for bypass responses."""
111 def __init__(self):
112 super(ChromeProxyBypass, self).__init__(restart_after_each_page=True)
114 def AddResults(self, tab, results):
115 self._metrics.AddResultsForBypass(tab, results)
118 class ChromeProxyCorsBypass(ChromeProxyValidation):
119 """Correctness measurement for bypass responses for CORS requests."""
121 def __init__(self):
122 super(ChromeProxyCorsBypass, self).__init__(restart_after_each_page=True)
124 def ValidateAndMeasurePage(self, page, tab, results):
125 # The test page sets window.xhrRequestCompleted to true when the XHR fetch
126 # finishes.
127 tab.WaitForJavaScriptExpression('window.xhrRequestCompleted', 300)
128 super(ChromeProxyCorsBypass,
129 self).ValidateAndMeasurePage(page, tab, results)
131 def AddResults(self, tab, results):
132 self._metrics.AddResultsForCorsBypass(tab, results)
135 class ChromeProxyBlockOnce(ChromeProxyValidation):
136 """Correctness measurement for block-once responses."""
138 def __init__(self):
139 super(ChromeProxyBlockOnce, self).__init__(restart_after_each_page=True)
141 def AddResults(self, tab, results):
142 self._metrics.AddResultsForBlockOnce(tab, results)
145 class ChromeProxySafebrowsingOn(ChromeProxyValidation):
146 """Correctness measurement for safebrowsing."""
148 def __init__(self):
149 super(ChromeProxySafebrowsingOn, self).__init__()
151 def WillNavigateToPage(self, page, tab):
152 super(ChromeProxySafebrowsingOn, self).WillNavigateToPage(page, tab)
153 self._expect_timeout = True
155 def AddResults(self, tab, results):
156 self._metrics.AddResultsForSafebrowsingOn(tab, results)
158 class ChromeProxySafebrowsingOff(ChromeProxyValidation):
159 """Correctness measurement for safebrowsing."""
161 def __init__(self):
162 super(ChromeProxySafebrowsingOff, self).__init__()
164 def AddResults(self, tab, results):
165 self._metrics.AddResultsForSafebrowsingOff(tab, results)
167 _FAKE_PROXY_AUTH_VALUE = 'aabbccdd3b7579186c1b0620614fdb1f0000ffff'
168 _TEST_SERVER = 'chromeproxy-test.appspot.com'
169 _TEST_SERVER_DEFAULT_URL = 'http://' + _TEST_SERVER + '/default'
172 # We rely on the chromeproxy-test server to facilitate some of the tests.
173 # The test server code is at <TBD location> and runs at _TEST_SERVER
175 # The test server allow request to override response status, headers, and
176 # body through query parameters. See GetResponseOverrideURL.
177 def GetResponseOverrideURL(url=_TEST_SERVER_DEFAULT_URL, respStatus=0,
178 respHeader="", respBody=""):
179 """ Compose the request URL with query parameters to override
180 the chromeproxy-test server response.
183 queries = []
184 if respStatus > 0:
185 queries.append('respStatus=%d' % respStatus)
186 if respHeader:
187 queries.append('respHeader=%s' % base64.b64encode(respHeader))
188 if respBody:
189 queries.append('respBody=%s' % base64.b64encode(respBody))
190 if len(queries) == 0:
191 return url
192 "&".join(queries)
193 # url has query already
194 if urlparse.urlparse(url).query:
195 return url + '&' + "&".join(queries)
196 else:
197 return url + '?' + "&".join(queries)
200 class ChromeProxyHTTPFallbackProbeURL(ChromeProxyValidation):
201 """Correctness measurement for proxy fallback.
203 In this test, the probe URL does not return 'OK'. Chrome is expected
204 to use the fallback proxy.
207 def __init__(self):
208 super(ChromeProxyHTTPFallbackProbeURL, self).__init__(
209 restart_after_each_page=True)
211 def CustomizeBrowserOptions(self, options):
212 super(ChromeProxyHTTPFallbackProbeURL,
213 self).CustomizeBrowserOptions(options)
214 # Use the test server probe URL which returns the response
215 # body as specified by respBody.
216 probe_url = GetResponseOverrideURL(respBody='not OK')
217 options.AppendExtraBrowserArgs(
218 '--data-reduction-proxy-secure-proxy-check-url=%s' % probe_url)
220 def AddResults(self, tab, results):
221 self._metrics.AddResultsForHTTPFallback(tab, results)
224 class ChromeProxyHTTPFallbackViaHeader(ChromeProxyValidation):
225 """Correctness measurement for proxy fallback.
227 In this test, the configured proxy is the chromeproxy-test server which
228 will send back a response without the expected Via header. Chrome is
229 expected to use the fallback proxy and add the configured proxy to the
230 bad proxy list.
233 def __init__(self):
234 super(ChromeProxyHTTPFallbackViaHeader, self).__init__(
235 restart_after_each_page=True)
237 def CustomizeBrowserOptions(self, options):
238 super(ChromeProxyHTTPFallbackViaHeader,
239 self).CustomizeBrowserOptions(options)
240 options.AppendExtraBrowserArgs('--ignore-certificate-errors')
241 options.AppendExtraBrowserArgs(
242 '--spdy-proxy-auth-origin=http://%s' % _TEST_SERVER)
244 def AddResults(self, tab, results):
245 self._metrics.AddResultsForHTTPFallback(tab, results)
248 class ChromeProxyClientVersion(ChromeProxyValidation):
249 """Correctness measurement for version directives in Chrome-Proxy header.
251 The test verifies that the version information provided in the Chrome-Proxy
252 request header overrides any version, if specified, that is provided in the
253 user agent string.
256 def __init__(self):
257 super(ChromeProxyClientVersion, self).__init__()
259 def CustomizeBrowserOptions(self, options):
260 super(ChromeProxyClientVersion,
261 self).CustomizeBrowserOptions(options)
262 options.AppendExtraBrowserArgs('--user-agent="Chrome/32.0.1700.99"')
264 def AddResults(self, tab, results):
265 self._metrics.AddResultsForClientVersion(tab, results)
268 class ChromeProxyClientType(ChromeProxyValidation):
269 """Correctness measurement for Chrome-Proxy header client type directives."""
271 def __init__(self):
272 super(ChromeProxyClientType, self).__init__(restart_after_each_page=True)
273 self._chrome_proxy_client_type = None
275 def AddResults(self, tab, results):
276 # Get the Chrome-Proxy client type from the first page in the page set, so
277 # that the client type value can be used to determine which of the later
278 # pages in the page set should be bypassed.
279 if not self._chrome_proxy_client_type:
280 client_type = self._metrics.GetClientTypeFromRequests(tab)
281 if client_type:
282 self._chrome_proxy_client_type = client_type
284 self._metrics.AddResultsForClientType(tab,
285 results,
286 self._chrome_proxy_client_type,
287 self._page.bypass_for_client_type)
290 class ChromeProxyHTTPToDirectFallback(ChromeProxyValidation):
291 """Correctness measurement for HTTP proxy fallback to direct."""
293 def __init__(self):
294 super(ChromeProxyHTTPToDirectFallback, self).__init__(
295 restart_after_each_page=True)
297 def CustomizeBrowserOptions(self, options):
298 super(ChromeProxyHTTPToDirectFallback,
299 self).CustomizeBrowserOptions(options)
300 # Set the primary proxy to something that will fail to be resolved so that
301 # this test will run using the HTTP fallback proxy.
302 options.AppendExtraBrowserArgs(
303 '--spdy-proxy-auth-origin=http://nonexistent.googlezip.net')
305 def WillNavigateToPage(self, page, tab):
306 super(ChromeProxyHTTPToDirectFallback, self).WillNavigateToPage(page, tab)
307 # Attempt to load a page through the nonexistent primary proxy in order to
308 # cause a proxy fallback, and have this test run starting from the HTTP
309 # fallback proxy.
310 tab.Navigate(_TEST_SERVER_DEFAULT_URL)
311 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
313 def AddResults(self, tab, results):
314 self._metrics.AddResultsForHTTPToDirectFallback(tab, results, _TEST_SERVER)
317 class ChromeProxyReenableAfterBypass(ChromeProxyValidation):
318 """Correctness measurement for re-enabling proxies after bypasses.
320 This test loads a page that causes all data reduction proxies to be bypassed
321 for 1 to 5 minutes, then waits 5 minutes and verifies that the proxy is no
322 longer bypassed.
325 def __init__(self):
326 super(ChromeProxyReenableAfterBypass, self).__init__(
327 restart_after_each_page=True)
329 def AddResults(self, tab, results):
330 self._metrics.AddResultsForReenableAfterBypass(
331 tab, results, self._page.bypass_seconds_min,
332 self._page.bypass_seconds_max)
335 class ChromeProxySmoke(ChromeProxyValidation):
336 """Smoke measurement for basic chrome proxy correctness."""
338 def __init__(self):
339 super(ChromeProxySmoke, self).__init__(restart_after_each_page=True)
341 def WillNavigateToPage(self, page, tab):
342 super(ChromeProxySmoke, self).WillNavigateToPage(page, tab)
344 def AddResults(self, tab, results):
345 # Map a page name to its AddResults func.
346 page_to_metrics = {
347 'header validation': [self._metrics.AddResultsForHeaderValidation],
348 'compression: image': [
349 self._metrics.AddResultsForHeaderValidation,
350 self._metrics.AddResultsForDataSaving,
352 'compression: javascript': [
353 self._metrics.AddResultsForHeaderValidation,
354 self._metrics.AddResultsForDataSaving,
356 'compression: css': [
357 self._metrics.AddResultsForHeaderValidation,
358 self._metrics.AddResultsForDataSaving,
360 'bypass': [self._metrics.AddResultsForBypass],
362 if not self._page.name in page_to_metrics:
363 raise page_test.MeasurementFailure(
364 'Invalid page name (%s) in smoke. Page name must be one of:\n%s' % (
365 self._page.name, page_to_metrics.keys()))
366 for add_result in page_to_metrics[self._page.name]:
367 add_result(tab, results)