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.
9 from common
.chrome_proxy_measurements
import ChromeProxyValidation
10 from integration_tests
import chrome_proxy_metrics
as metrics
11 from metrics
import loading
12 from telemetry
.core
import exceptions
13 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
)
20 self
._metrics
= metrics
.ChromeProxyMetric()
22 def CustomizeBrowserOptions(self
, options
):
23 options
.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
25 def WillNavigateToPage(self
, page
, tab
):
26 tab
.ClearCache(force
=True)
28 def ValidateAndMeasurePage(self
, page
, tab
, results
):
29 # Wait for the load event.
30 tab
.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
31 self
._metrics
.AddResultsForLatency(tab
, results
)
34 class ChromeProxyDataSaving(page_test
.PageTest
):
35 """Chrome proxy data saving measurement."""
36 def __init__(self
, *args
, **kwargs
):
37 super(ChromeProxyDataSaving
, self
).__init
__(*args
, **kwargs
)
38 self
._metrics
= metrics
.ChromeProxyMetric()
40 def CustomizeBrowserOptions(self
, options
):
41 options
.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
43 def WillNavigateToPage(self
, page
, tab
):
44 tab
.ClearCache(force
=True)
45 self
._metrics
.Start(page
, tab
)
47 def ValidateAndMeasurePage(self
, page
, tab
, results
):
48 # Wait for the load event.
49 tab
.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
50 self
._metrics
.Stop(page
, tab
)
51 self
._metrics
.AddResultsForDataSaving(tab
, results
)
54 class ChromeProxyHeaders(ChromeProxyValidation
):
55 """Correctness measurement for response headers."""
58 super(ChromeProxyHeaders
, self
).__init
__(
59 restart_after_each_page
=True,
60 metrics
=metrics
.ChromeProxyMetric())
62 def AddResults(self
, tab
, results
):
63 self
._metrics
.AddResultsForHeaderValidation(tab
, results
)
66 class ChromeProxyBypass(ChromeProxyValidation
):
67 """Correctness measurement for bypass responses."""
70 super(ChromeProxyBypass
, self
).__init
__(
71 restart_after_each_page
=True,
72 metrics
=metrics
.ChromeProxyMetric())
74 def AddResults(self
, tab
, results
):
75 self
._metrics
.AddResultsForBypass(tab
, results
)
78 class ChromeProxyCorsBypass(ChromeProxyValidation
):
79 """Correctness measurement for bypass responses for CORS requests."""
82 super(ChromeProxyCorsBypass
, self
).__init
__(
83 restart_after_each_page
=True,
84 metrics
=metrics
.ChromeProxyMetric())
86 def ValidateAndMeasurePage(self
, page
, tab
, results
):
87 # The test page sets window.xhrRequestCompleted to true when the XHR fetch
89 tab
.WaitForJavaScriptExpression('window.xhrRequestCompleted', 300)
90 super(ChromeProxyCorsBypass
,
91 self
).ValidateAndMeasurePage(page
, tab
, results
)
93 def AddResults(self
, tab
, results
):
94 self
._metrics
.AddResultsForCorsBypass(tab
, results
)
97 class ChromeProxyBlockOnce(ChromeProxyValidation
):
98 """Correctness measurement for block-once responses."""
101 super(ChromeProxyBlockOnce
, self
).__init
__(
102 restart_after_each_page
=True,
103 metrics
=metrics
.ChromeProxyMetric())
105 def AddResults(self
, tab
, results
):
106 self
._metrics
.AddResultsForBlockOnce(tab
, results
)
109 class ChromeProxySafebrowsingOn(ChromeProxyValidation
):
110 """Correctness measurement for safebrowsing."""
113 super(ChromeProxySafebrowsingOn
, self
).__init
__(
114 metrics
=metrics
.ChromeProxyMetric())
116 def WillNavigateToPage(self
, page
, tab
):
117 super(ChromeProxySafebrowsingOn
, self
).WillNavigateToPage(page
, tab
)
118 self
._expect
_timeout
= True
120 def AddResults(self
, tab
, results
):
121 self
._metrics
.AddResultsForSafebrowsingOn(tab
, results
)
123 class ChromeProxySafebrowsingOff(ChromeProxyValidation
):
124 """Correctness measurement for safebrowsing."""
127 super(ChromeProxySafebrowsingOff
, self
).__init
__(
128 metrics
=metrics
.ChromeProxyMetric())
130 def AddResults(self
, tab
, results
):
131 self
._metrics
.AddResultsForSafebrowsingOff(tab
, results
)
133 _FAKE_PROXY_AUTH_VALUE
= 'aabbccdd3b7579186c1b0620614fdb1f0000ffff'
134 _TEST_SERVER
= 'chromeproxy-test.appspot.com'
135 _TEST_SERVER_DEFAULT_URL
= 'http://' + _TEST_SERVER
+ '/default'
138 # We rely on the chromeproxy-test server to facilitate some of the tests.
139 # The test server code is at <TBD location> and runs at _TEST_SERVER
141 # The test server allow request to override response status, headers, and
142 # body through query parameters. See GetResponseOverrideURL.
143 def GetResponseOverrideURL(url
=_TEST_SERVER_DEFAULT_URL
, respStatus
=0,
144 respHeader
="", respBody
=""):
145 """ Compose the request URL with query parameters to override
146 the chromeproxy-test server response.
151 queries
.append('respStatus=%d' % respStatus
)
153 queries
.append('respHeader=%s' % base64
.b64encode(respHeader
))
155 queries
.append('respBody=%s' % base64
.b64encode(respBody
))
156 if len(queries
) == 0:
159 # url has query already
160 if urlparse
.urlparse(url
).query
:
161 return url
+ '&' + "&".join(queries
)
163 return url
+ '?' + "&".join(queries
)
166 class ChromeProxyHTTPFallbackProbeURL(ChromeProxyValidation
):
167 """Correctness measurement for proxy fallback.
169 In this test, the probe URL does not return 'OK'. Chrome is expected
170 to use the fallback proxy.
174 super(ChromeProxyHTTPFallbackProbeURL
, self
).__init
__(
175 restart_after_each_page
=True,
176 metrics
=metrics
.ChromeProxyMetric())
178 def CustomizeBrowserOptions(self
, options
):
179 super(ChromeProxyHTTPFallbackProbeURL
,
180 self
).CustomizeBrowserOptions(options
)
181 # Set the secure proxy check URL to the google.com favicon, which will be
182 # interpreted as a secure proxy check failure since the response body is not
183 # "OK". The google.com favicon is used because it will load reliably fast,
184 # and there have been problems with chromeproxy-test.appspot.com being slow
185 # and causing tests to flake.
186 options
.AppendExtraBrowserArgs(
187 '--data-reduction-proxy-secure-proxy-check-url='
188 'http://www.google.com/favicon.ico')
190 def AddResults(self
, tab
, results
):
191 self
._metrics
.AddResultsForHTTPFallback(tab
, results
)
194 class ChromeProxyHTTPFallbackViaHeader(ChromeProxyValidation
):
195 """Correctness measurement for proxy fallback.
197 In this test, the configured proxy is the chromeproxy-test server which
198 will send back a response without the expected Via header. Chrome is
199 expected to use the fallback proxy and add the configured proxy to the
204 super(ChromeProxyHTTPFallbackViaHeader
, self
).__init
__(
205 restart_after_each_page
=True,
206 metrics
=metrics
.ChromeProxyMetric())
208 def CustomizeBrowserOptions(self
, options
):
209 super(ChromeProxyHTTPFallbackViaHeader
,
210 self
).CustomizeBrowserOptions(options
)
211 options
.AppendExtraBrowserArgs('--ignore-certificate-errors')
212 options
.AppendExtraBrowserArgs(
213 '--spdy-proxy-auth-origin=http://%s' % _TEST_SERVER
)
215 def AddResults(self
, tab
, results
):
216 self
._metrics
.AddResultsForHTTPFallback(tab
, results
)
219 class ChromeProxyClientVersion(ChromeProxyValidation
):
220 """Correctness measurement for version directives in Chrome-Proxy header.
222 The test verifies that the version information provided in the Chrome-Proxy
223 request header overrides any version, if specified, that is provided in the
228 super(ChromeProxyClientVersion
, self
).__init
__(
229 metrics
=metrics
.ChromeProxyMetric())
231 def CustomizeBrowserOptions(self
, options
):
232 super(ChromeProxyClientVersion
,
233 self
).CustomizeBrowserOptions(options
)
234 options
.AppendExtraBrowserArgs('--user-agent="Chrome/32.0.1700.99"')
236 def AddResults(self
, tab
, results
):
237 self
._metrics
.AddResultsForClientVersion(tab
, results
)
240 class ChromeProxyClientType(ChromeProxyValidation
):
241 """Correctness measurement for Chrome-Proxy header client type directives."""
244 super(ChromeProxyClientType
, self
).__init
__(
245 restart_after_each_page
=True,
246 metrics
=metrics
.ChromeProxyMetric())
247 self
._chrome
_proxy
_client
_type
= None
249 def AddResults(self
, tab
, results
):
250 # Get the Chrome-Proxy client type from the first page in the page set, so
251 # that the client type value can be used to determine which of the later
252 # pages in the page set should be bypassed.
253 if not self
._chrome
_proxy
_client
_type
:
254 client_type
= self
._metrics
.GetClientTypeFromRequests(tab
)
256 self
._chrome
_proxy
_client
_type
= client_type
258 self
._metrics
.AddResultsForClientType(tab
,
260 self
._chrome
_proxy
_client
_type
,
261 self
._page
.bypass_for_client_type
)
264 class ChromeProxyLoFi(ChromeProxyValidation
):
265 """Correctness measurement for Lo-Fi in Chrome-Proxy header."""
268 super(ChromeProxyLoFi
, self
).__init
__(restart_after_each_page
=True,
269 metrics
=metrics
.ChromeProxyMetric())
271 def CustomizeBrowserOptions(self
, options
):
272 super(ChromeProxyLoFi
, self
).CustomizeBrowserOptions(options
)
273 options
.AppendExtraBrowserArgs('--enable-data-reduction-proxy-lo-fi')
275 def AddResults(self
, tab
, results
):
276 self
._metrics
.AddResultsForLoFi(tab
, results
)
278 class ChromeProxyExpDirective(ChromeProxyValidation
):
279 """Correctness measurement for experiment directives in Chrome-Proxy header.
281 This test verifies that "exp=test" in the Chrome-Proxy request header
282 causes a bypass on the experiment test page.
286 super(ChromeProxyExpDirective
, self
).__init
__(
287 restart_after_each_page
=True,
288 metrics
=metrics
.ChromeProxyMetric())
290 def CustomizeBrowserOptions(self
, options
):
291 super(ChromeProxyExpDirective
, self
).CustomizeBrowserOptions(options
)
292 options
.AppendExtraBrowserArgs('--data-reduction-proxy-experiment=test')
294 def AddResults(self
, tab
, results
):
295 self
._metrics
.AddResultsForBypass(tab
, results
)
298 class ChromeProxyHTTPToDirectFallback(ChromeProxyValidation
):
299 """Correctness measurement for HTTP proxy fallback to direct."""
302 super(ChromeProxyHTTPToDirectFallback
, self
).__init
__(
303 restart_after_each_page
=True,
304 metrics
=metrics
.ChromeProxyMetric())
306 def CustomizeBrowserOptions(self
, options
):
307 super(ChromeProxyHTTPToDirectFallback
,
308 self
).CustomizeBrowserOptions(options
)
309 # Set the primary proxy to something that will fail to be resolved so that
310 # this test will run using the HTTP fallback proxy.
311 options
.AppendExtraBrowserArgs(
312 '--spdy-proxy-auth-origin=http://nonexistent.googlezip.net')
314 def WillNavigateToPage(self
, page
, tab
):
315 super(ChromeProxyHTTPToDirectFallback
, self
).WillNavigateToPage(page
, tab
)
316 # Attempt to load a page through the nonexistent primary proxy in order to
317 # cause a proxy fallback, and have this test run starting from the HTTP
319 tab
.Navigate(_TEST_SERVER_DEFAULT_URL
)
320 tab
.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
322 def AddResults(self
, tab
, results
):
323 self
._metrics
.AddResultsForHTTPToDirectFallback(tab
, results
, _TEST_SERVER
)
326 class ChromeProxyReenableAfterBypass(ChromeProxyValidation
):
327 """Correctness measurement for re-enabling proxies after bypasses.
329 This test loads a page that causes all data reduction proxies to be bypassed
330 for 1 to 5 minutes, then waits 5 minutes and verifies that the proxy is no
335 super(ChromeProxyReenableAfterBypass
, self
).__init
__(
336 restart_after_each_page
=True,
337 metrics
=metrics
.ChromeProxyMetric())
339 def AddResults(self
, tab
, results
):
340 self
._metrics
.AddResultsForReenableAfterBypass(
341 tab
, results
, self
._page
.bypass_seconds_min
,
342 self
._page
.bypass_seconds_max
)
345 class ChromeProxySmoke(ChromeProxyValidation
):
346 """Smoke measurement for basic chrome proxy correctness."""
349 super(ChromeProxySmoke
, self
).__init
__(restart_after_each_page
=True,
350 metrics
=metrics
.ChromeProxyMetric())
352 def WillNavigateToPage(self
, page
, tab
):
353 super(ChromeProxySmoke
, self
).WillNavigateToPage(page
, tab
)
355 def AddResults(self
, tab
, results
):
356 # Map a page name to its AddResults func.
358 'header validation': [self
._metrics
.AddResultsForHeaderValidation
],
359 'compression: image': [
360 self
._metrics
.AddResultsForHeaderValidation
,
361 self
._metrics
.AddResultsForDataSaving
,
363 'compression: javascript': [
364 self
._metrics
.AddResultsForHeaderValidation
,
365 self
._metrics
.AddResultsForDataSaving
,
367 'compression: css': [
368 self
._metrics
.AddResultsForHeaderValidation
,
369 self
._metrics
.AddResultsForDataSaving
,
371 'bypass': [self
._metrics
.AddResultsForBypass
],
373 if not self
._page
.name
in page_to_metrics
:
374 raise page_test
.MeasurementFailure(
375 'Invalid page name (%s) in smoke. Page name must be one of:\n%s' % (
376 self
._page
.name
, page_to_metrics
.keys()))
377 for add_result
in page_to_metrics
[self
._page
.name
]:
378 add_result(tab
, results
)