Chromium Code Reviews| Index: tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py |
| diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py b/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py |
| index f21e3d8f3ed72c42adeeb8bbba5beae1aa8de6f5..bdfed774ca6449aa92d0542e705e97aaf2d949ea 100644 |
| --- a/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py |
| +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py |
| @@ -3,6 +3,7 @@ |
| # found in the LICENSE file. |
| import logging |
| +import os |
| import time |
| from integration_tests import network_metrics |
| @@ -18,7 +19,7 @@ CHROME_PROXY_VIA_HEADER = 'Chrome-Compression-Proxy' |
| class ChromeProxyResponse(network_metrics.HTTPResponse): |
| - """ Represents an HTTP response from a timeleine event.""" |
| + """ Represents an HTTP response from a timeline event.""" |
| def __init__(self, event): |
| super(ChromeProxyResponse, self).__init__(event) |
| @@ -81,6 +82,7 @@ class ChromeProxyResponse(network_metrics.HTTPResponse): |
| return True |
| return False |
| + |
| class ChromeProxyMetric(network_metrics.NetworkMetric): |
| """A Chrome proxy timeline metric.""" |
| @@ -559,3 +561,100 @@ class ChromeProxyMetric(network_metrics.NetworkMetric): |
| results.current_page, 'bypass', 'count', bypass_count)) |
| results.AddValue(scalar.ScalarValue( |
| results.current_page, 'via', 'count', via_count)) |
| + |
| + |
| +PROXIED = 'proxied' |
| +DIRECT = 'direct' |
| + |
| +class ChromeProxyVideoMetric(network_metrics.NetworkMetric): |
| + """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.
|
| + basic HTTP response headers such as Content-Type and Content-Length for |
| + the video responses. |
| + """ |
| + |
| + def __init__(self, tab): |
| + super(ChromeProxyVideoMetric, self).__init__() |
| + with open(os.path.join(os.path.dirname(__file__), 'videowrapper.js')) as f: |
| + js = f.read() |
| + tab.ExecuteJavaScript(js) |
| + |
| + def Start(self, page, tab): |
| + tab.ExecuteJavaScript('window.__chromeProxyCreateVideoWrappers()') |
| + self.videoMetrics = None |
| + super(ChromeProxyVideoMetric, self).Start(page, tab) |
| + |
| + def Stop(self, page, tab): |
| + tab.WaitForJavaScriptExpression('window.__chromeProxyVideoLoaded', 30) |
| + m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics') |
| + |
| + # Now wait for the video to stop playing. |
| + # Give it 2x the total duration to account for buffering. |
| + waitTime = 2 * m['video_duration'] |
| + tab.WaitForJavaScriptExpression('window.__chromeProxyVideoEnded', waitTime) |
| + |
| + # Load the final metrics. |
| + m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics') |
| + self.videoMetrics = m |
| + # Cast this to an integer as it is often approximate (for an unknown reason) |
| + m['video_duration'] = int(m['video_duration']) |
| + super(ChromeProxyVideoMetric, self).Stop(page, tab) |
| + |
| + def ResponseFromEvent(self, event): |
| + return ChromeProxyResponse(event) |
| + |
| + def AddResults(self, tab, results): |
| + raise NotImplementedError |
| + |
| + def AddResultsForProxied(self, tab, results): |
| + return self._AddResultsShared(PROXIED, tab, results) |
| + |
| + def AddResultsForDirect(self, tab, results): |
| + return self._AddResultsShared(DIRECT, tab, results) |
| + |
| + def _AddResultsShared(self, kind, tab, results): |
| + def err(s): |
| + raise ChromeProxyMetricException, s |
| + |
| + # Should have played the video. |
| + if not self.videoMetrics['ready']: |
| + err('%s: video not played' % kind) |
| + |
| + # Should have an HTTP response for the video. |
| + wantContentType = 'video/webm' if kind == PROXIED else 'video/mp4' |
| + found = False |
| + for r in self.IterResponses(tab): |
| + resp = r.response |
| + if kind == DIRECT and r.HasChromeProxyViaHeader(): |
| + err('%s: page has proxied Via header' % kind) |
| + if resp.GetHeader('Content-Type') != wantContentType: |
| + continue |
| + if found: |
| + err('%s: multiple video responses' % kind) |
| + found = True |
| + |
| + cl = resp.GetHeader('Content-Length') |
| + xocl = resp.GetHeader('X-Original-Content-Length') |
| + if cl != None: |
| + self.videoMetrics['content_length_header'] = int(cl) |
| + if xocl != None: |
| + self.videoMetrics['x_original_content_length_header'] = int(xocl) |
| + |
| + # Should have CL always. |
| + if cl == None: |
| + err('%s: missing ContentLength' % kind) |
| + # Proxied: should have CL < XOCL |
| + # Direct: should not have XOCL |
| + if kind == PROXIED: |
| + if xocl == None or int(cl) >= int(xocl): |
| + err('%s: bigger response (%s > %s)' % (kind, str(cl), str(xocl))) |
| + else: |
| + if xocl != None: |
| + err('%s: has XOriginalContentLength' % kind) |
| + |
| + if not found: |
| + err('%s: missing video response' % kind) |
| + |
| + # Finally, add all the metrics to the results. |
| + 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
|
| + k = "%s_%s" % (k, kind) |
| + results.AddValue(scalar.ScalarValue(results.current_page, k, "", v)) |