Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py

Issue 1065763002: Add data reduction proxy integration tests for video compression. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix reviewer comments, round #2 Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import logging 5 import logging
6 import os
6 import time 7 import time
7 8
8 from integration_tests import network_metrics 9 from integration_tests import network_metrics
9 from telemetry.page import page_test 10 from telemetry.page import page_test
10 from telemetry.value import scalar 11 from telemetry.value import scalar
11 12
12 13
13 class ChromeProxyMetricException(page_test.MeasurementFailure): 14 class ChromeProxyMetricException(page_test.MeasurementFailure):
14 pass 15 pass
15 16
16 17
17 CHROME_PROXY_VIA_HEADER = 'Chrome-Compression-Proxy' 18 CHROME_PROXY_VIA_HEADER = 'Chrome-Compression-Proxy'
18 19
19 20
20 class ChromeProxyResponse(network_metrics.HTTPResponse): 21 class ChromeProxyResponse(network_metrics.HTTPResponse):
21 """ Represents an HTTP response from a timeleine event.""" 22 """ Represents an HTTP response from a timeline event."""
22 def __init__(self, event): 23 def __init__(self, event):
23 super(ChromeProxyResponse, self).__init__(event) 24 super(ChromeProxyResponse, self).__init__(event)
24 25
25 def ShouldHaveChromeProxyViaHeader(self): 26 def ShouldHaveChromeProxyViaHeader(self):
26 resp = self.response 27 resp = self.response
27 # Ignore https and data url 28 # Ignore https and data url
28 if resp.url.startswith('https') or resp.url.startswith('data:'): 29 if resp.url.startswith('https') or resp.url.startswith('data:'):
29 return False 30 return False
30 # Ignore 304 Not Modified and cache hit. 31 # Ignore 304 Not Modified and cache hit.
31 if resp.status == 304 or resp.served_from_cache: 32 if resp.status == 304 or resp.served_from_cache:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 def HasChromeProxyLoFi(self): 75 def HasChromeProxyLoFi(self):
75 if 'Chrome-Proxy' not in self.response.request_headers: 76 if 'Chrome-Proxy' not in self.response.request_headers:
76 return False 77 return False
77 chrome_proxy_request_header = self.response.request_headers['Chrome-Proxy'] 78 chrome_proxy_request_header = self.response.request_headers['Chrome-Proxy']
78 values = [v.strip() for v in chrome_proxy_request_header.split(',')] 79 values = [v.strip() for v in chrome_proxy_request_header.split(',')]
79 for value in values: 80 for value in values:
80 if len(value) == 5 and value == 'q=low': 81 if len(value) == 5 and value == 'q=low':
81 return True 82 return True
82 return False 83 return False
83 84
85
84 class ChromeProxyMetric(network_metrics.NetworkMetric): 86 class ChromeProxyMetric(network_metrics.NetworkMetric):
85 """A Chrome proxy timeline metric.""" 87 """A Chrome proxy timeline metric."""
86 88
87 def __init__(self): 89 def __init__(self):
88 super(ChromeProxyMetric, self).__init__() 90 super(ChromeProxyMetric, self).__init__()
89 self.compute_data_saving = True 91 self.compute_data_saving = True
90 92
91 def SetEvents(self, events): 93 def SetEvents(self, events):
92 """Used for unittest.""" 94 """Used for unittest."""
93 self._events = events 95 self._events = events
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 via_count += 1 554 via_count += 1
553 if via_count == 0: 555 if via_count == 0:
554 raise ChromeProxyMetricException, ( 556 raise ChromeProxyMetricException, (
555 'Expected at least one response through the proxy after the bypass ' 557 'Expected at least one response through the proxy after the bypass '
556 'expired, but zero such responses were received.') 558 'expired, but zero such responses were received.')
557 559
558 results.AddValue(scalar.ScalarValue( 560 results.AddValue(scalar.ScalarValue(
559 results.current_page, 'bypass', 'count', bypass_count)) 561 results.current_page, 'bypass', 'count', bypass_count))
560 results.AddValue(scalar.ScalarValue( 562 results.AddValue(scalar.ScalarValue(
561 results.current_page, 'via', 'count', via_count)) 563 results.current_page, 'via', 'count', via_count))
564
565
566 PROXIED = 'proxied'
567 DIRECT = 'direct'
568
569 class ChromeProxyVideoMetric(network_metrics.NetworkMetric):
570 """Wraps the video metrics produced by videowrapper.js. Also checks a few
sclittle 2015/04/11 00:13:02 See style guide: https://google-styleguide.googlec
Tom Bergan 2015/05/01 23:48:28 Done.
571 basic HTTP response headers such as Content-Type and Content-Length for
572 the video responses.
573 """
574
575 def __init__(self, tab):
576 super(ChromeProxyVideoMetric, self).__init__()
577 with open(os.path.join(os.path.dirname(__file__), 'videowrapper.js')) as f:
578 js = f.read()
579 tab.ExecuteJavaScript(js)
580
581 def Start(self, page, tab):
582 tab.ExecuteJavaScript('window.__chromeProxyCreateVideoWrappers()')
583 self.videoMetrics = None
584 super(ChromeProxyVideoMetric, self).Start(page, tab)
585
586 def Stop(self, page, tab):
587 tab.WaitForJavaScriptExpression('window.__chromeProxyVideoLoaded', 30)
588 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics')
589
590 # Now wait for the video to stop playing.
591 # Give it 2x the total duration to account for buffering.
592 waitTime = 2 * m['video_duration']
593 tab.WaitForJavaScriptExpression('window.__chromeProxyVideoEnded', waitTime)
594
595 # Load the final metrics.
596 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics')
597 self.videoMetrics = m
598 # Cast this to an integer as it is often approximate (for an unknown reason)
599 m['video_duration'] = int(m['video_duration'])
600 super(ChromeProxyVideoMetric, self).Stop(page, tab)
601
602 def ResponseFromEvent(self, event):
603 return ChromeProxyResponse(event)
604
605 def AddResults(self, tab, results):
606 raise NotImplementedError
607
608 def AddResultsForProxied(self, tab, results):
609 return self._AddResultsShared(PROXIED, tab, results)
610
611 def AddResultsForDirect(self, tab, results):
612 return self._AddResultsShared(DIRECT, tab, results)
613
614 def _AddResultsShared(self, kind, tab, results):
615 def err(s):
616 raise ChromeProxyMetricException, s
617
618 # Should have played the video.
619 if not self.videoMetrics['ready']:
620 err('%s: video not played' % kind)
621
622 # Should have an HTTP response for the video.
623 wantContentType = 'video/webm' if kind == PROXIED else 'video/mp4'
624 found = False
625 for r in self.IterResponses(tab):
626 resp = r.response
627 if kind == DIRECT and r.HasChromeProxyViaHeader():
628 err('%s: page has proxied Via header' % kind)
629 if resp.GetHeader('Content-Type') != wantContentType:
630 continue
631 if found:
632 err('%s: multiple video responses' % kind)
633 found = True
634
635 cl = resp.GetHeader('Content-Length')
636 xocl = resp.GetHeader('X-Original-Content-Length')
637 if cl != None:
638 self.videoMetrics['content_length_header'] = int(cl)
639 if xocl != None:
640 self.videoMetrics['x_original_content_length_header'] = int(xocl)
641
642 # Should have CL always.
643 if cl == None:
644 err('%s: missing ContentLength' % kind)
645 # Proxied: should have CL < XOCL
646 # Direct: should not have XOCL
647 if kind == PROXIED:
648 if xocl == None or int(cl) >= int(xocl):
649 err('%s: bigger response (%s > %s)' % (kind, str(cl), str(xocl)))
650 else:
651 if xocl != None:
652 err('%s: has XOriginalContentLength' % kind)
653
654 if not found:
655 err('%s: missing video response' % kind)
656
657 # Finally, add all the metrics to the results.
658 for (k,v) in self.videoMetrics.iteritems():
sclittle 2015/04/11 00:13:02 Could you just call results.AddValue(...) inline a
Tom Bergan 2015/05/01 23:48:28 This dict is used by ChromeProxyVideoValidation (i
659 k = "%s_%s" % (k, kind)
660 results.AddValue(scalar.ScalarValue(results.current_page, k, "", v))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698