OLD | NEW |
| (Empty) |
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. | |
4 | |
5 import base64 | |
6 import logging | |
7 import urlparse | |
8 | |
9 from metrics import chrome_proxy | |
10 from metrics import loading | |
11 from telemetry.core import util | |
12 from telemetry.page import page_measurement | |
13 | |
14 | |
15 class ChromeProxyLatency(page_measurement.PageMeasurement): | |
16 """Chrome proxy latency measurement.""" | |
17 | |
18 def __init__(self, *args, **kwargs): | |
19 super(ChromeProxyLatency, self).__init__(*args, **kwargs) | |
20 | |
21 def WillNavigateToPage(self, page, tab): | |
22 tab.ClearCache(force=True) | |
23 | |
24 def MeasurePage(self, page, tab, results): | |
25 # Wait for the load event. | |
26 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300) | |
27 loading.LoadingMetric().AddResults(tab, results) | |
28 | |
29 | |
30 class ChromeProxyDataSaving(page_measurement.PageMeasurement): | |
31 """Chrome proxy data daving measurement.""" | |
32 def __init__(self, *args, **kwargs): | |
33 super(ChromeProxyDataSaving, self).__init__(*args, **kwargs) | |
34 self._metrics = chrome_proxy.ChromeProxyMetric() | |
35 | |
36 def WillNavigateToPage(self, page, tab): | |
37 tab.ClearCache(force=True) | |
38 self._metrics.Start(page, tab) | |
39 | |
40 def MeasurePage(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) | |
45 | |
46 | |
47 class ChromeProxyValidation(page_measurement.PageMeasurement): | |
48 """Base class for all chrome proxy correctness measurements.""" | |
49 | |
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 = chrome_proxy.ChromeProxyMetric() | |
54 self._page = None | |
55 # Whether a timeout exception is expected during the test. | |
56 self._expect_timeout = False | |
57 | |
58 def CustomizeBrowserOptions(self, options): | |
59 # Enable the chrome proxy (data reduction proxy). | |
60 options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth') | |
61 | |
62 def WillNavigateToPage(self, page, tab): | |
63 tab.ClearCache(force=True) | |
64 assert self._metrics | |
65 self._metrics.Start(page, tab) | |
66 | |
67 def MeasurePage(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) | |
74 | |
75 def AddResults(self, tab, results): | |
76 raise NotImplementedError | |
77 | |
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 | |
82 | |
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 except util.TimeoutException, e: | |
88 if self._expect_timeout: | |
89 logging.warning('Navigation timeout on page %s', | |
90 page.name if page.name else page.url) | |
91 else: | |
92 raise e | |
93 | |
94 | |
95 class ChromeProxyHeaders(ChromeProxyValidation): | |
96 """Correctness measurement for response headers.""" | |
97 | |
98 def __init__(self): | |
99 super(ChromeProxyHeaders, self).__init__(restart_after_each_page=True) | |
100 | |
101 def AddResults(self, tab, results): | |
102 self._metrics.AddResultsForHeaderValidation(tab, results) | |
103 | |
104 | |
105 class ChromeProxyBypass(ChromeProxyValidation): | |
106 """Correctness measurement for bypass responses.""" | |
107 | |
108 def __init__(self): | |
109 super(ChromeProxyBypass, self).__init__(restart_after_each_page=True) | |
110 | |
111 def AddResults(self, tab, results): | |
112 self._metrics.AddResultsForBypass(tab, results) | |
113 | |
114 | |
115 class ChromeProxySafebrowsing(ChromeProxyValidation): | |
116 """Correctness measurement for safebrowsing.""" | |
117 | |
118 def __init__(self): | |
119 super(ChromeProxySafebrowsing, self).__init__() | |
120 | |
121 def WillNavigateToPage(self, page, tab): | |
122 super(ChromeProxySafebrowsing, self).WillNavigateToPage(page, tab) | |
123 self._expect_timeout = True | |
124 | |
125 def AddResults(self, tab, results): | |
126 self._metrics.AddResultsForSafebrowsing(tab, results) | |
127 | |
128 | |
129 _FAKE_PROXY_AUTH_VALUE = 'aabbccdd3b7579186c1b0620614fdb1f0000ffff' | |
130 _TEST_SERVER = 'chromeproxy-test.appspot.com' | |
131 _TEST_SERVER_DEFAULT_URL = 'http://' + _TEST_SERVER + '/default' | |
132 | |
133 | |
134 # We rely on the chromeproxy-test server to facilitate some of the tests. | |
135 # The test server code is at <TBD location> and runs at _TEST_SERVER | |
136 # | |
137 # The test server allow request to override response status, headers, and | |
138 # body through query parameters. See GetResponseOverrideURL. | |
139 def GetResponseOverrideURL(url, respStatus=0, respHeader="", respBody=""): | |
140 """ Compose the request URL with query parameters to override | |
141 the chromeproxy-test server response. | |
142 """ | |
143 | |
144 queries = [] | |
145 if respStatus > 0: | |
146 queries.append('respStatus=%d' % respStatus) | |
147 if respHeader: | |
148 queries.append('respHeader=%s' % base64.b64encode(respHeader)) | |
149 if respBody: | |
150 queries.append('respBody=%s' % base64.b64encode(respBody)) | |
151 if len(queries) == 0: | |
152 return url | |
153 "&".join(queries) | |
154 # url has query already | |
155 if urlparse.urlparse(url).query: | |
156 return url + '&' + "&".join(queries) | |
157 else: | |
158 return url + '?' + "&".join(queries) | |
159 | |
160 | |
161 class ChromeProxyHTTPFallbackProbeURL(ChromeProxyValidation): | |
162 """Correctness measurement for proxy fallback. | |
163 | |
164 In this test, the probe URL does not return 'OK'. Chrome is expected | |
165 to use the fallback proxy. | |
166 """ | |
167 | |
168 def __init__(self): | |
169 super(ChromeProxyHTTPFallbackProbeURL, self).__init__() | |
170 | |
171 def CustomizeBrowserOptions(self, options): | |
172 super(ChromeProxyHTTPFallbackProbeURL, | |
173 self).CustomizeBrowserOptions(options) | |
174 # Use the test server probe URL which returns the response | |
175 # body as specified by respBody. | |
176 probe_url = GetResponseOverrideURL( | |
177 _TEST_SERVER_DEFAULT_URL, | |
178 respBody='not OK') | |
179 options.AppendExtraBrowserArgs( | |
180 '--data-reduction-proxy-probe-url=%s' % probe_url) | |
181 | |
182 def AddResults(self, tab, results): | |
183 self._metrics.AddResultsForHTTPFallback(tab, results) | |
184 | |
185 | |
186 # Depends on the fix of http://crbug.com/330342. | |
187 class ChromeProxyHTTPFallbackViaHeader(ChromeProxyValidation): | |
188 """Correctness measurement for proxy fallback. | |
189 | |
190 In this test, the configured proxy is the chromeproxy-test server which | |
191 will send back a response without the expected Via header. Chrome is | |
192 expected to use the fallback proxy and add the configured proxy to the | |
193 bad proxy list. | |
194 """ | |
195 | |
196 def __init__(self): | |
197 super(ChromeProxyHTTPFallbackViaHeader, self).__init__() | |
198 | |
199 def CustomizeBrowserOptions(self, options): | |
200 super(ChromeProxyHTTPFallbackViaHeader, | |
201 self).CustomizeBrowserOptions(options) | |
202 options.AppendExtraBrowserArgs('--ignore-certificate-errors') | |
203 options.AppendExtraBrowserArgs( | |
204 '--spdy-proxy-auth-origin=http://%s' % _TEST_SERVER) | |
205 options.AppendExtraBrowserArgs( | |
206 '--spdy-proxy-auth-value=%s' % _FAKE_PROXY_AUTH_VALUE) | |
207 | |
208 def AddResults(self, tab, results): | |
209 proxies = [ | |
210 _TEST_SERVER + ":80", | |
211 self._metrics.effective_proxies['fallback'], | |
212 self._metrics.effective_proxies['direct']] | |
213 bad_proxies = [_TEST_SERVER + ":80"] | |
214 self._metrics.AddResultsForHTTPFallback(tab, results, proxies, bad_proxies) | |
215 | |
216 | |
217 class ChromeProxySmoke(ChromeProxyValidation): | |
218 """Smoke measurement for basic chrome proxy correctness.""" | |
219 | |
220 def __init__(self): | |
221 super(ChromeProxySmoke, self).__init__() | |
222 | |
223 def WillNavigateToPage(self, page, tab): | |
224 super(ChromeProxySmoke, self).WillNavigateToPage(page, tab) | |
225 if page.name == 'safebrowsing': | |
226 self._expect_timeout = True | |
227 | |
228 def AddResults(self, tab, results): | |
229 # Map a page name to its AddResults func. | |
230 page_to_metrics = { | |
231 'header validation': [self._metrics.AddResultsForHeaderValidation], | |
232 'compression: image': [ | |
233 self._metrics.AddResultsForHeaderValidation, | |
234 self._metrics.AddResultsForDataSaving, | |
235 ], | |
236 'compression: javascript': [ | |
237 self._metrics.AddResultsForHeaderValidation, | |
238 self._metrics.AddResultsForDataSaving, | |
239 ], | |
240 'compression: css': [ | |
241 self._metrics.AddResultsForHeaderValidation, | |
242 self._metrics.AddResultsForDataSaving, | |
243 ], | |
244 'bypass': [self._metrics.AddResultsForBypass], | |
245 'safebrowsing': [self._metrics.AddResultsForSafebrowsing], | |
246 } | |
247 if not self._page.name in page_to_metrics: | |
248 raise page_measurement.MeasurementFailure( | |
249 'Invalid page name (%s) in smoke. Page name must be one of:\n%s' % ( | |
250 self._page.name, page_to_metrics.keys())) | |
251 for add_result in page_to_metrics[self._page.name]: | |
252 add_result(tab, results) | |
OLD | NEW |