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 68ba33fa311af9bf05d99f082f3cadc31ed68379..6aaefcfaaac1cbb94f9b89844ad6a3ace7d8f03f 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) |
@@ -88,6 +89,7 @@ class ChromeProxyResponse(network_metrics.HTTPResponse): |
return True |
return False |
+ |
class ChromeProxyMetric(network_metrics.NetworkMetric): |
"""A Chrome proxy timeline metric.""" |
@@ -580,3 +582,102 @@ 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): |
+ """Metrics for video pages. |
+ |
+ Wraps the video metrics produced by videowrapper.js. Also checks a few |
sclittle
2015/05/12 18:05:40
Which metrics? You don't necessarily need to list
Tom Bergan
2015/05/20 00:42:05
Done.
|
+ basic HTTP response headers such as Content-Type and Content-Length in |
+ 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(): |
+ k = "%s_%s" % (k, kind) |
+ results.AddValue(scalar.ScalarValue(results.current_page, k, "", v)) |