Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / tools / chrome_proxy / integration_tests / chrome_proxy_measurements.py
blob9b5a7e5397ce2aa0c99e1284fdfb45baa8b46920
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
14 class ChromeProxyLatency(page_test.PageTest):
15 """Chrome proxy latency measurement."""
17 def __init__(self, *args, **kwargs):
18 super(ChromeProxyLatency, self).__init__(*args, **kwargs)
19 self._metrics = metrics.ChromeProxyMetric()
21 def CustomizeBrowserOptions(self, options):
22 options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
24 def WillNavigateToPage(self, page, tab):
25 tab.ClearCache(force=True)
27 def ValidateAndMeasurePage(self, page, tab, results):
28 # Wait for the load event.
29 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
30 self._metrics.AddResultsForLatency(tab, results)
33 class ChromeProxyDataSaving(page_test.PageTest):
34 """Chrome proxy data saving measurement."""
35 def __init__(self, *args, **kwargs):
36 super(ChromeProxyDataSaving, self).__init__(*args, **kwargs)
37 self._metrics = metrics.ChromeProxyMetric()
39 def CustomizeBrowserOptions(self, options):
40 options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
42 def WillNavigateToPage(self, page, tab):
43 tab.ClearCache(force=True)
44 self._metrics.Start(page, tab)
46 def ValidateAndMeasurePage(self, page, tab, results):
47 # Wait for the load event.
48 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
49 self._metrics.Stop(page, tab)
50 self._metrics.AddResultsForDataSaving(tab, results)
53 class ChromeProxyValidation(page_test.PageTest):
54 """Base class for all chrome proxy correctness measurements."""
56 # Value of the extra via header. |None| if no extra via header is expected.
57 extra_via_header = None
59 def __init__(self, restart_after_each_page=False):
60 super(ChromeProxyValidation, self).__init__(
61 needs_browser_restart_after_each_page=restart_after_each_page)
62 self._metrics = metrics.ChromeProxyMetric()
63 self._page = None
64 # Whether a timeout exception is expected during the test.
65 self._expect_timeout = False
67 def CustomizeBrowserOptions(self, options):
68 # Enable the chrome proxy (data reduction proxy).
69 options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
71 def WillNavigateToPage(self, page, tab):
72 tab.ClearCache(force=True)
73 assert self._metrics
74 self._metrics.Start(page, tab)
76 def ValidateAndMeasurePage(self, page, tab, results):
77 self._page = page
78 # Wait for the load event.
79 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
80 assert self._metrics
81 self._metrics.Stop(page, tab)
82 if ChromeProxyValidation.extra_via_header:
83 self._metrics.AddResultsForExtraViaHeader(
84 tab, results, ChromeProxyValidation.extra_via_header)
85 self.AddResults(tab, results)
87 def AddResults(self, tab, results):
88 raise NotImplementedError
90 def StopBrowserAfterPage(self, browser, page): # pylint: disable=W0613
91 if hasattr(page, 'restart_after') and page.restart_after:
92 return True
93 return False
95 def RunNavigateSteps(self, page, tab):
96 # The redirect from safebrowsing causes a timeout. Ignore that.
97 try:
98 super(ChromeProxyValidation, self).RunNavigateSteps(page, tab)
99 if self._expect_timeout:
100 raise metrics.ChromeProxyMetricException, (
101 'Timeout was expected, but did not occur')
102 except exceptions.TimeoutException as e:
103 if self._expect_timeout:
104 logging.warning('Navigation timeout on page %s',
105 page.name if page.name else page.url)
106 else:
107 raise e
110 class ChromeProxyHeaders(ChromeProxyValidation):
111 """Correctness measurement for response headers."""
113 def __init__(self):
114 super(ChromeProxyHeaders, self).__init__(restart_after_each_page=True)
116 def AddResults(self, tab, results):
117 self._metrics.AddResultsForHeaderValidation(tab, results)
120 class ChromeProxyBypass(ChromeProxyValidation):
121 """Correctness measurement for bypass responses."""
123 def __init__(self):
124 super(ChromeProxyBypass, self).__init__(restart_after_each_page=True)
126 def AddResults(self, tab, results):
127 self._metrics.AddResultsForBypass(tab, results)
130 class ChromeProxyCorsBypass(ChromeProxyValidation):
131 """Correctness measurement for bypass responses for CORS requests."""
133 def __init__(self):
134 super(ChromeProxyCorsBypass, self).__init__(restart_after_each_page=True)
136 def ValidateAndMeasurePage(self, page, tab, results):
137 # The test page sets window.xhrRequestCompleted to true when the XHR fetch
138 # finishes.
139 tab.WaitForJavaScriptExpression('window.xhrRequestCompleted', 300)
140 super(ChromeProxyCorsBypass,
141 self).ValidateAndMeasurePage(page, tab, results)
143 def AddResults(self, tab, results):
144 self._metrics.AddResultsForCorsBypass(tab, results)
147 class ChromeProxyBlockOnce(ChromeProxyValidation):
148 """Correctness measurement for block-once responses."""
150 def __init__(self):
151 super(ChromeProxyBlockOnce, self).__init__(restart_after_each_page=True)
153 def AddResults(self, tab, results):
154 self._metrics.AddResultsForBlockOnce(tab, results)
157 class ChromeProxySafebrowsingOn(ChromeProxyValidation):
158 """Correctness measurement for safebrowsing."""
160 def __init__(self):
161 super(ChromeProxySafebrowsingOn, self).__init__()
163 def WillNavigateToPage(self, page, tab):
164 super(ChromeProxySafebrowsingOn, self).WillNavigateToPage(page, tab)
165 self._expect_timeout = True
167 def AddResults(self, tab, results):
168 self._metrics.AddResultsForSafebrowsingOn(tab, results)
170 class ChromeProxySafebrowsingOff(ChromeProxyValidation):
171 """Correctness measurement for safebrowsing."""
173 def __init__(self):
174 super(ChromeProxySafebrowsingOff, self).__init__()
176 def AddResults(self, tab, results):
177 self._metrics.AddResultsForSafebrowsingOff(tab, results)
179 _FAKE_PROXY_AUTH_VALUE = 'aabbccdd3b7579186c1b0620614fdb1f0000ffff'
180 _TEST_SERVER = 'chromeproxy-test.appspot.com'
181 _TEST_SERVER_DEFAULT_URL = 'http://' + _TEST_SERVER + '/default'
184 # We rely on the chromeproxy-test server to facilitate some of the tests.
185 # The test server code is at <TBD location> and runs at _TEST_SERVER
187 # The test server allow request to override response status, headers, and
188 # body through query parameters. See GetResponseOverrideURL.
189 def GetResponseOverrideURL(url=_TEST_SERVER_DEFAULT_URL, respStatus=0,
190 respHeader="", respBody=""):
191 """ Compose the request URL with query parameters to override
192 the chromeproxy-test server response.
195 queries = []
196 if respStatus > 0:
197 queries.append('respStatus=%d' % respStatus)
198 if respHeader:
199 queries.append('respHeader=%s' % base64.b64encode(respHeader))
200 if respBody:
201 queries.append('respBody=%s' % base64.b64encode(respBody))
202 if len(queries) == 0:
203 return url
204 "&".join(queries)
205 # url has query already
206 if urlparse.urlparse(url).query:
207 return url + '&' + "&".join(queries)
208 else:
209 return url + '?' + "&".join(queries)
212 class ChromeProxyHTTPFallbackProbeURL(ChromeProxyValidation):
213 """Correctness measurement for proxy fallback.
215 In this test, the probe URL does not return 'OK'. Chrome is expected
216 to use the fallback proxy.
219 def __init__(self):
220 super(ChromeProxyHTTPFallbackProbeURL, self).__init__(
221 restart_after_each_page=True)
223 def CustomizeBrowserOptions(self, options):
224 super(ChromeProxyHTTPFallbackProbeURL,
225 self).CustomizeBrowserOptions(options)
226 # Set the secure proxy check URL to the google.com favicon, which will be
227 # interpreted as a secure proxy check failure since the response body is not
228 # "OK". The google.com favicon is used because it will load reliably fast,
229 # and there have been problems with chromeproxy-test.appspot.com being slow
230 # and causing tests to flake.
231 options.AppendExtraBrowserArgs(
232 '--data-reduction-proxy-secure-proxy-check-url='
233 'http://www.google.com/favicon.ico')
235 def AddResults(self, tab, results):
236 self._metrics.AddResultsForHTTPFallback(tab, results)
239 class ChromeProxyHTTPFallbackViaHeader(ChromeProxyValidation):
240 """Correctness measurement for proxy fallback.
242 In this test, the configured proxy is the chromeproxy-test server which
243 will send back a response without the expected Via header. Chrome is
244 expected to use the fallback proxy and add the configured proxy to the
245 bad proxy list.
248 def __init__(self):
249 super(ChromeProxyHTTPFallbackViaHeader, self).__init__(
250 restart_after_each_page=True)
252 def CustomizeBrowserOptions(self, options):
253 super(ChromeProxyHTTPFallbackViaHeader,
254 self).CustomizeBrowserOptions(options)
255 options.AppendExtraBrowserArgs('--ignore-certificate-errors')
256 options.AppendExtraBrowserArgs(
257 '--spdy-proxy-auth-origin=http://%s' % _TEST_SERVER)
259 def AddResults(self, tab, results):
260 self._metrics.AddResultsForHTTPFallback(tab, results)
263 class ChromeProxyClientVersion(ChromeProxyValidation):
264 """Correctness measurement for version directives in Chrome-Proxy header.
266 The test verifies that the version information provided in the Chrome-Proxy
267 request header overrides any version, if specified, that is provided in the
268 user agent string.
271 def __init__(self):
272 super(ChromeProxyClientVersion, self).__init__()
274 def CustomizeBrowserOptions(self, options):
275 super(ChromeProxyClientVersion,
276 self).CustomizeBrowserOptions(options)
277 options.AppendExtraBrowserArgs('--user-agent="Chrome/32.0.1700.99"')
279 def AddResults(self, tab, results):
280 self._metrics.AddResultsForClientVersion(tab, results)
283 class ChromeProxyClientType(ChromeProxyValidation):
284 """Correctness measurement for Chrome-Proxy header client type directives."""
286 def __init__(self):
287 super(ChromeProxyClientType, self).__init__(restart_after_each_page=True)
288 self._chrome_proxy_client_type = None
290 def AddResults(self, tab, results):
291 # Get the Chrome-Proxy client type from the first page in the page set, so
292 # that the client type value can be used to determine which of the later
293 # pages in the page set should be bypassed.
294 if not self._chrome_proxy_client_type:
295 client_type = self._metrics.GetClientTypeFromRequests(tab)
296 if client_type:
297 self._chrome_proxy_client_type = client_type
299 self._metrics.AddResultsForClientType(tab,
300 results,
301 self._chrome_proxy_client_type,
302 self._page.bypass_for_client_type)
305 class ChromeProxyLoFi(ChromeProxyValidation):
306 """Correctness measurement for Lo-Fi in Chrome-Proxy header."""
308 def __init__(self):
309 super(ChromeProxyLoFi, self).__init__(restart_after_each_page=True)
311 def CustomizeBrowserOptions(self, options):
312 super(ChromeProxyLoFi, self).CustomizeBrowserOptions(options)
313 options.AppendExtraBrowserArgs('--enable-data-reduction-proxy-lo-fi')
315 def AddResults(self, tab, results):
316 self._metrics.AddResultsForLoFi(tab, results)
318 class ChromeProxyExpDirective(ChromeProxyValidation):
319 """Correctness measurement for experiment directives in Chrome-Proxy header.
321 This test verifies that "exp=test" in the Chrome-Proxy request header
322 causes a bypass on the experiment test page.
325 def __init__(self):
326 super(ChromeProxyExpDirective, self).__init__(restart_after_each_page=True)
328 def CustomizeBrowserOptions(self, options):
329 super(ChromeProxyExpDirective, self).CustomizeBrowserOptions(options)
330 options.AppendExtraBrowserArgs('--data-reduction-proxy-experiment=test')
332 def AddResults(self, tab, results):
333 self._metrics.AddResultsForBypass(tab, results)
336 class ChromeProxyHTTPToDirectFallback(ChromeProxyValidation):
337 """Correctness measurement for HTTP proxy fallback to direct."""
339 def __init__(self):
340 super(ChromeProxyHTTPToDirectFallback, self).__init__(
341 restart_after_each_page=True)
343 def CustomizeBrowserOptions(self, options):
344 super(ChromeProxyHTTPToDirectFallback,
345 self).CustomizeBrowserOptions(options)
346 # Set the primary proxy to something that will fail to be resolved so that
347 # this test will run using the HTTP fallback proxy.
348 options.AppendExtraBrowserArgs(
349 '--spdy-proxy-auth-origin=http://nonexistent.googlezip.net')
351 def WillNavigateToPage(self, page, tab):
352 super(ChromeProxyHTTPToDirectFallback, self).WillNavigateToPage(page, tab)
353 # Attempt to load a page through the nonexistent primary proxy in order to
354 # cause a proxy fallback, and have this test run starting from the HTTP
355 # fallback proxy.
356 tab.Navigate(_TEST_SERVER_DEFAULT_URL)
357 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
359 def AddResults(self, tab, results):
360 self._metrics.AddResultsForHTTPToDirectFallback(tab, results, _TEST_SERVER)
363 class ChromeProxyReenableAfterBypass(ChromeProxyValidation):
364 """Correctness measurement for re-enabling proxies after bypasses.
366 This test loads a page that causes all data reduction proxies to be bypassed
367 for 1 to 5 minutes, then waits 5 minutes and verifies that the proxy is no
368 longer bypassed.
371 def __init__(self):
372 super(ChromeProxyReenableAfterBypass, self).__init__(
373 restart_after_each_page=True)
375 def AddResults(self, tab, results):
376 self._metrics.AddResultsForReenableAfterBypass(
377 tab, results, self._page.bypass_seconds_min,
378 self._page.bypass_seconds_max)
381 class ChromeProxySmoke(ChromeProxyValidation):
382 """Smoke measurement for basic chrome proxy correctness."""
384 def __init__(self):
385 super(ChromeProxySmoke, self).__init__(restart_after_each_page=True)
387 def WillNavigateToPage(self, page, tab):
388 super(ChromeProxySmoke, self).WillNavigateToPage(page, tab)
390 def AddResults(self, tab, results):
391 # Map a page name to its AddResults func.
392 page_to_metrics = {
393 'header validation': [self._metrics.AddResultsForHeaderValidation],
394 'compression: image': [
395 self._metrics.AddResultsForHeaderValidation,
396 self._metrics.AddResultsForDataSaving,
398 'compression: javascript': [
399 self._metrics.AddResultsForHeaderValidation,
400 self._metrics.AddResultsForDataSaving,
402 'compression: css': [
403 self._metrics.AddResultsForHeaderValidation,
404 self._metrics.AddResultsForDataSaving,
406 'bypass': [self._metrics.AddResultsForBypass],
408 if not self._page.name in page_to_metrics:
409 raise page_test.MeasurementFailure(
410 'Invalid page name (%s) in smoke. Page name must be one of:\n%s' % (
411 self._page.name, page_to_metrics.keys()))
412 for add_result in page_to_metrics[self._page.name]:
413 add_result(tab, results)