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.
8 from integration_tests
import chrome_proxy_metrics
as metrics
9 from integration_tests
import network_metrics_unittest
as network_unittest
10 from telemetry
.unittest_util
import test_page_test_results
12 TEST_EXTRA_VIA_HEADER
= '1.1 EXTRA_VIA_HEADER'
14 # Timeline events used in tests.
15 # An HTML not via proxy.
16 EVENT_HTML_DIRECT
= network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
17 url
='http://test.html1',
19 'Content-Type': 'text/html',
20 'Content-Length': str(len(network_unittest
.HTML_BODY
)),
22 body
=network_unittest
.HTML_BODY
)
25 EVENT_HTML_PROXY_VIA
= (
26 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
27 url
='http://test.html2',
29 'Content-Type': 'text/html',
30 'Content-Encoding': 'gzip',
31 'X-Original-Content-Length': str(len(network_unittest
.HTML_BODY
)),
32 'Via': '1.1 ' + metrics
.CHROME_PROXY_VIA_HEADER
,
34 body
=network_unittest
.HTML_BODY
,
37 # An HTML via proxy with extra header.
38 EVENT_HTML_PROXY_EXTRA_VIA
= (
39 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
40 url
='http://test.html2',
42 'Content-Type': 'text/html',
43 'Content-Encoding': 'gzip',
44 'X-Original-Content-Length': str(len(network_unittest
.HTML_BODY
)),
45 'Via': '1.1 ' + metrics
.CHROME_PROXY_VIA_HEADER
+ ", " +
46 TEST_EXTRA_VIA_HEADER
,
48 body
=network_unittest
.HTML_BODY
,
51 # An HTML via the HTTP fallback proxy.
52 EVENT_HTML_PROXY_VIA_HTTP_FALLBACK
= (
53 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
54 url
='http://test.html2',
56 'Content-Type': 'text/html',
57 'Content-Encoding': 'gzip',
58 'X-Original-Content-Length': str(len(network_unittest
.HTML_BODY
)),
59 'Via': '1.1 ' + metrics
.CHROME_PROXY_VIA_HEADER
,
61 body
=network_unittest
.HTML_BODY
,
64 # An image via proxy with Via header.
65 EVENT_IMAGE_PROXY_VIA
= (
66 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
67 url
='http://test.image',
69 'Content-Type': 'image/jpeg',
70 'Content-Encoding': 'gzip',
71 'X-Original-Content-Length': str(network_unittest
.IMAGE_OCL
),
72 'Via': '1.1 ' + metrics
.CHROME_PROXY_VIA_HEADER
,
74 body
=base64
.b64encode(network_unittest
.IMAGE_BODY
),
75 base64_encoded_body
=True,
78 # An image via the HTTP fallback proxy.
79 EVENT_IMAGE_PROXY_VIA_HTTP_FALLBACK
= (
80 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
81 url
='http://test.image',
83 'Content-Type': 'image/jpeg',
84 'Content-Encoding': 'gzip',
85 'X-Original-Content-Length': str(network_unittest
.IMAGE_OCL
),
86 'Via': '1.1 ' + metrics
.CHROME_PROXY_VIA_HEADER
,
88 body
=base64
.b64encode(network_unittest
.IMAGE_BODY
),
89 base64_encoded_body
=True,
92 # An image via proxy with Via header and it is cached.
93 EVENT_IMAGE_PROXY_CACHED
= (
94 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
95 url
='http://test.image',
97 'Content-Type': 'image/jpeg',
98 'Content-Encoding': 'gzip',
99 'X-Original-Content-Length': str(network_unittest
.IMAGE_OCL
),
100 'Via': '1.1 ' + metrics
.CHROME_PROXY_VIA_HEADER
,
102 body
=base64
.b64encode(network_unittest
.IMAGE_BODY
),
103 base64_encoded_body
=True,
104 served_from_cache
=True))
106 # An image fetched directly.
107 EVENT_IMAGE_DIRECT
= (
108 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
109 url
='http://test.image',
111 'Content-Type': 'image/jpeg',
112 'Content-Encoding': 'gzip',
114 body
=base64
.b64encode(network_unittest
.IMAGE_BODY
),
115 base64_encoded_body
=True))
117 # A safe-browsing malware response.
118 EVENT_MALWARE_PROXY
= (
119 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
120 url
='http://test.malware',
122 'X-Malware-Url': '1',
123 'Via': '1.1 ' + metrics
.CHROME_PROXY_VIA_HEADER
,
124 'Location': 'http://test.malware',
128 # An HTML via proxy with the Via header.
129 EVENT_IMAGE_BYPASS
= (
130 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
131 url
='http://test.image',
133 'Chrome-Proxy': 'bypass=1',
134 'Content-Type': 'text/html',
135 'Via': '1.1 ' + metrics
.CHROME_PROXY_VIA_HEADER
,
139 # An image fetched directly.
140 EVENT_IMAGE_DIRECT
= (
141 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
142 url
='http://test.image',
144 'Content-Type': 'image/jpeg',
145 'Content-Encoding': 'gzip',
147 body
=base64
.b64encode(network_unittest
.IMAGE_BODY
),
148 base64_encoded_body
=True))
151 class ChromeProxyMetricTest(unittest
.TestCase
):
153 _test_proxy_info
= {}
155 def _StubGetProxyInfo(self
, info
):
156 def stub(unused_tab
, unused_url
=''): # pylint: disable=W0613
157 return ChromeProxyMetricTest
._test
_proxy
_info
158 metrics
.GetProxyInfoFromNetworkInternals
= stub
159 ChromeProxyMetricTest
._test
_proxy
_info
= info
161 def testChromeProxyResponse(self
):
162 # An https non-proxy response.
163 resp
= metrics
.ChromeProxyResponse(
164 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
165 url
='https://test.url',
167 'Content-Type': 'text/html',
168 'Content-Length': str(len(network_unittest
.HTML_BODY
)),
169 'Via': 'some other via',
171 body
=network_unittest
.HTML_BODY
))
172 self
.assertFalse(resp
.ShouldHaveChromeProxyViaHeader())
173 self
.assertFalse(resp
.HasChromeProxyViaHeader())
174 self
.assertTrue(resp
.IsValidByViaHeader())
176 # A proxied JPEG image response
177 resp
= metrics
.ChromeProxyResponse(
178 network_unittest
.NetworkMetricTest
.MakeNetworkTimelineEvent(
179 url
='http://test.image',
181 'Content-Type': 'image/jpeg',
182 'Content-Encoding': 'gzip',
183 'Via': '1.1 ' + metrics
.CHROME_PROXY_VIA_HEADER
,
184 'X-Original-Content-Length': str(network_unittest
.IMAGE_OCL
),
186 body
=base64
.b64encode(network_unittest
.IMAGE_BODY
),
187 base64_encoded_body
=True))
188 self
.assertTrue(resp
.ShouldHaveChromeProxyViaHeader())
189 self
.assertTrue(resp
.HasChromeProxyViaHeader())
190 self
.assertTrue(resp
.IsValidByViaHeader())
192 def testChromeProxyMetricForDataSaving(self
):
193 metric
= metrics
.ChromeProxyMetric()
196 EVENT_HTML_PROXY_VIA
,
197 EVENT_IMAGE_PROXY_CACHED
,
199 metric
.SetEvents(events
)
201 self
.assertTrue(len(events
), len(list(metric
.IterResponses(None))))
202 results
= test_page_test_results
.TestPageTestResults(self
)
204 metric
.AddResultsForDataSaving(None, results
)
205 results
.AssertHasPageSpecificScalarValue('resources_via_proxy', 'count', 2)
206 results
.AssertHasPageSpecificScalarValue('resources_from_cache', 'count', 1)
207 results
.AssertHasPageSpecificScalarValue('resources_direct', 'count', 2)
209 # Passing in zero responses should cause a failure.
211 no_responses_exception
= False
213 metric
.AddResultsForDataSaving(None, results
)
214 except metrics
.ChromeProxyMetricException
:
215 no_responses_exception
= True
216 self
.assertTrue(no_responses_exception
)
218 def testChromeProxyMetricForHeaderValidation(self
):
219 metric
= metrics
.ChromeProxyMetric()
222 EVENT_HTML_PROXY_VIA
,
223 EVENT_IMAGE_PROXY_CACHED
,
226 results
= test_page_test_results
.TestPageTestResults(self
)
228 missing_via_exception
= False
230 metric
.AddResultsForHeaderValidation(None, results
)
231 except metrics
.ChromeProxyMetricException
:
232 missing_via_exception
= True
233 # Only the HTTP image response does not have a valid Via header.
234 self
.assertTrue(missing_via_exception
)
236 # Two events with valid Via headers.
238 EVENT_HTML_PROXY_VIA
,
239 EVENT_IMAGE_PROXY_CACHED
])
240 metric
.AddResultsForHeaderValidation(None, results
)
241 results
.AssertHasPageSpecificScalarValue('checked_via_header', 'count', 2)
243 # Passing in zero responses should cause a failure.
245 no_responses_exception
= False
247 metric
.AddResultsForHeaderValidation(None, results
)
248 except metrics
.ChromeProxyMetricException
:
249 no_responses_exception
= True
250 self
.assertTrue(no_responses_exception
)
252 def testChromeProxyMetricForExtraViaHeader(self
):
253 metric
= metrics
.ChromeProxyMetric()
254 metric
.SetEvents([EVENT_HTML_DIRECT
,
255 EVENT_HTML_PROXY_EXTRA_VIA
])
256 results
= test_page_test_results
.TestPageTestResults(self
)
257 metric
.AddResultsForExtraViaHeader(None, results
, TEST_EXTRA_VIA_HEADER
)
258 # The direct page should not count an extra via header, but should also not
259 # throw an exception.
260 results
.AssertHasPageSpecificScalarValue('extra_via_header', 'count', 1)
262 metric
.SetEvents([EVENT_HTML_PROXY_VIA
])
263 exception_occurred
= False
265 metric
.AddResultsForExtraViaHeader(None, results
, TEST_EXTRA_VIA_HEADER
)
266 except metrics
.ChromeProxyMetricException
:
267 exception_occurred
= True
268 # The response had the chrome proxy via header, but not the extra expected
270 self
.assertTrue(exception_occurred
)
272 def testChromeProxyMetricForBypass(self
):
273 metric
= metrics
.ChromeProxyMetric()
276 EVENT_HTML_PROXY_VIA
,
277 EVENT_IMAGE_PROXY_CACHED
,
279 results
= test_page_test_results
.TestPageTestResults(self
)
281 bypass_exception
= False
283 metric
.AddResultsForBypass(None, results
)
284 except metrics
.ChromeProxyMetricException
:
285 bypass_exception
= True
286 # Two of the first three events have Via headers.
287 self
.assertTrue(bypass_exception
)
289 # Use directly fetched image only. It is treated as bypassed.
290 metric
.SetEvents([EVENT_IMAGE_DIRECT
])
291 metric
.AddResultsForBypass(None, results
)
292 results
.AssertHasPageSpecificScalarValue('bypass', 'count', 1)
294 # Passing in zero responses should cause a failure.
296 no_responses_exception
= False
298 metric
.AddResultsForBypass(None, results
)
299 except metrics
.ChromeProxyMetricException
:
300 no_responses_exception
= True
301 self
.assertTrue(no_responses_exception
)
303 def testChromeProxyMetricForCorsBypass(self
):
304 metric
= metrics
.ChromeProxyMetric()
305 metric
.SetEvents([EVENT_HTML_PROXY_VIA
,
308 results
= test_page_test_results
.TestPageTestResults(self
)
309 metric
.AddResultsForCorsBypass(None, results
)
310 results
.AssertHasPageSpecificScalarValue('cors_bypass', 'count', 1)
312 # Passing in zero responses should cause a failure.
314 no_responses_exception
= False
316 metric
.AddResultsForCorsBypass(None, results
)
317 except metrics
.ChromeProxyMetricException
:
318 no_responses_exception
= True
319 self
.assertTrue(no_responses_exception
)
321 def testChromeProxyMetricForBlockOnce(self
):
322 metric
= metrics
.ChromeProxyMetric()
323 metric
.SetEvents([EVENT_HTML_DIRECT
,
324 EVENT_IMAGE_PROXY_VIA
])
325 results
= test_page_test_results
.TestPageTestResults(self
)
326 metric
.AddResultsForBlockOnce(None, results
)
327 results
.AssertHasPageSpecificScalarValue('eligible_responses', 'count', 2)
328 results
.AssertHasPageSpecificScalarValue('bypass', 'count', 1)
330 metric
.SetEvents([EVENT_HTML_DIRECT
,
332 exception_occurred
= False
334 metric
.AddResultsForBlockOnce(None, results
)
335 except metrics
.ChromeProxyMetricException
:
336 exception_occurred
= True
337 # The second response was over direct, but was expected via proxy.
338 self
.assertTrue(exception_occurred
)
340 # Passing in zero responses should cause a failure.
342 no_responses_exception
= False
344 metric
.AddResultsForBlockOnce(None, results
)
345 except metrics
.ChromeProxyMetricException
:
346 no_responses_exception
= True
347 self
.assertTrue(no_responses_exception
)
349 def testChromeProxyMetricForSafebrowsingOn(self
):
350 metric
= metrics
.ChromeProxyMetric()
351 metric
.SetEvents([EVENT_MALWARE_PROXY
])
352 results
= test_page_test_results
.TestPageTestResults(self
)
354 metric
.AddResultsForSafebrowsingOn(None, results
)
355 results
.AssertHasPageSpecificScalarValue(
356 'safebrowsing', 'timeout responses', 1)
358 # Clear results and metrics to test no response for safebrowsing
359 results
= test_page_test_results
.TestPageTestResults(self
)
361 metric
.AddResultsForSafebrowsingOn(None, results
)
362 results
.AssertHasPageSpecificScalarValue(
363 'safebrowsing', 'timeout responses', 1)
365 def testChromeProxyMetricForHTTPFallback(self
):
366 metric
= metrics
.ChromeProxyMetric()
367 metric
.SetEvents([EVENT_HTML_PROXY_VIA_HTTP_FALLBACK
,
368 EVENT_IMAGE_PROXY_VIA_HTTP_FALLBACK
])
369 results
= test_page_test_results
.TestPageTestResults(self
)
370 metric
.AddResultsForHTTPFallback(None, results
)
371 results
.AssertHasPageSpecificScalarValue('via_fallback', 'count', 2)
373 metric
.SetEvents([EVENT_HTML_PROXY_VIA
,
374 EVENT_IMAGE_PROXY_VIA
])
375 exception_occurred
= False
377 metric
.AddResultsForHTTPFallback(None, results
)
378 except metrics
.ChromeProxyMetricException
:
379 exception_occurred
= True
380 # The responses came through the SPDY proxy, but were expected through the
381 # HTTP fallback proxy.
382 self
.assertTrue(exception_occurred
)
384 # Passing in zero responses should cause a failure.
386 no_responses_exception
= False
388 metric
.AddResultsForHTTPFallback(None, results
)
389 except metrics
.ChromeProxyMetricException
:
390 no_responses_exception
= True
391 self
.assertTrue(no_responses_exception
)
393 def testChromeProxyMetricForHTTPToDirectFallback(self
):
394 metric
= metrics
.ChromeProxyMetric()
395 metric
.SetEvents([EVENT_HTML_PROXY_VIA_HTTP_FALLBACK
,
398 results
= test_page_test_results
.TestPageTestResults(self
)
399 metric
.AddResultsForHTTPToDirectFallback(None, results
, 'test.html2')
400 results
.AssertHasPageSpecificScalarValue('via_fallback', 'count', 1)
401 results
.AssertHasPageSpecificScalarValue('bypass', 'count', 2)
403 metric
.SetEvents([EVENT_HTML_PROXY_VIA
,
405 exception_occurred
= False
407 metric
.AddResultsForHTTPToDirectFallback(None, results
, 'test.html2')
408 except metrics
.ChromeProxyMetricException
:
409 exception_occurred
= True
410 # The first response was expected through the HTTP fallback proxy.
411 self
.assertTrue(exception_occurred
)
413 metric
.SetEvents([EVENT_HTML_PROXY_VIA_HTTP_FALLBACK
,
414 EVENT_HTML_PROXY_VIA_HTTP_FALLBACK
,
415 EVENT_IMAGE_PROXY_VIA_HTTP_FALLBACK
])
416 exception_occurred
= False
418 metric
.AddResultsForHTTPToDirectFallback(None, results
, 'test.html2')
419 except metrics
.ChromeProxyMetricException
:
420 exception_occurred
= True
421 # All but the first response were expected to be over direct.
422 self
.assertTrue(exception_occurred
)
424 metric
.SetEvents([EVENT_HTML_DIRECT
,
427 exception_occurred
= False
429 metric
.AddResultsForHTTPToDirectFallback(None, results
, 'test.html2')
430 except metrics
.ChromeProxyMetricException
:
431 exception_occurred
= True
432 # The first response was expected through the HTTP fallback proxy.
433 self
.assertTrue(exception_occurred
)
435 # Passing in zero responses should cause a failure.
437 no_responses_exception
= False
439 metric
.AddResultsForHTTPToDirectFallback(None, results
, 'test.html2')
440 except metrics
.ChromeProxyMetricException
:
441 no_responses_exception
= True
442 self
.assertTrue(no_responses_exception
)