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

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: Merge with HEAD and address reviewer comments. Created 5 years, 7 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 def HasChromeProxyLoFi(self): 82 def HasChromeProxyLoFi(self):
82 if 'Chrome-Proxy' not in self.response.request_headers: 83 if 'Chrome-Proxy' not in self.response.request_headers:
83 return False 84 return False
84 chrome_proxy_request_header = self.response.request_headers['Chrome-Proxy'] 85 chrome_proxy_request_header = self.response.request_headers['Chrome-Proxy']
85 values = [v.strip() for v in chrome_proxy_request_header.split(',')] 86 values = [v.strip() for v in chrome_proxy_request_header.split(',')]
86 for value in values: 87 for value in values:
87 if len(value) == 5 and value == 'q=low': 88 if len(value) == 5 and value == 'q=low':
88 return True 89 return True
89 return False 90 return False
90 91
92
91 class ChromeProxyMetric(network_metrics.NetworkMetric): 93 class ChromeProxyMetric(network_metrics.NetworkMetric):
92 """A Chrome proxy timeline metric.""" 94 """A Chrome proxy timeline metric."""
93 95
94 def __init__(self): 96 def __init__(self):
95 super(ChromeProxyMetric, self).__init__() 97 super(ChromeProxyMetric, self).__init__()
96 self.compute_data_saving = True 98 self.compute_data_saving = True
97 99
98 def SetEvents(self, events): 100 def SetEvents(self, events):
99 """Used for unittest.""" 101 """Used for unittest."""
100 self._events = events 102 self._events = events
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 via_count += 1 575 via_count += 1
574 if via_count == 0: 576 if via_count == 0:
575 raise ChromeProxyMetricException, ( 577 raise ChromeProxyMetricException, (
576 'Expected at least one response through the proxy after the bypass ' 578 'Expected at least one response through the proxy after the bypass '
577 'expired, but zero such responses were received.') 579 'expired, but zero such responses were received.')
578 580
579 results.AddValue(scalar.ScalarValue( 581 results.AddValue(scalar.ScalarValue(
580 results.current_page, 'bypass', 'count', bypass_count)) 582 results.current_page, 'bypass', 'count', bypass_count))
581 results.AddValue(scalar.ScalarValue( 583 results.AddValue(scalar.ScalarValue(
582 results.current_page, 'via', 'count', via_count)) 584 results.current_page, 'via', 'count', via_count))
585
586
587 PROXIED = 'proxied'
588 DIRECT = 'direct'
589
590 class ChromeProxyVideoMetric(network_metrics.NetworkMetric):
591 """Metrics for video pages.
592
593 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.
594 basic HTTP response headers such as Content-Type and Content-Length in
595 the video responses.
596 """
597
598 def __init__(self, tab):
599 super(ChromeProxyVideoMetric, self).__init__()
600 with open(os.path.join(os.path.dirname(__file__), 'videowrapper.js')) as f:
601 js = f.read()
602 tab.ExecuteJavaScript(js)
603
604 def Start(self, page, tab):
605 tab.ExecuteJavaScript('window.__chromeProxyCreateVideoWrappers()')
606 self.videoMetrics = None
607 super(ChromeProxyVideoMetric, self).Start(page, tab)
608
609 def Stop(self, page, tab):
610 tab.WaitForJavaScriptExpression('window.__chromeProxyVideoLoaded', 30)
611 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics')
612
613 # Now wait for the video to stop playing.
614 # Give it 2x the total duration to account for buffering.
615 waitTime = 2 * m['video_duration']
616 tab.WaitForJavaScriptExpression('window.__chromeProxyVideoEnded', waitTime)
617
618 # Load the final metrics.
619 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics')
620 self.videoMetrics = m
621 # Cast this to an integer as it is often approximate (for an unknown reason)
622 m['video_duration'] = int(m['video_duration'])
623 super(ChromeProxyVideoMetric, self).Stop(page, tab)
624
625 def ResponseFromEvent(self, event):
626 return ChromeProxyResponse(event)
627
628 def AddResults(self, tab, results):
629 raise NotImplementedError
630
631 def AddResultsForProxied(self, tab, results):
632 return self._AddResultsShared(PROXIED, tab, results)
633
634 def AddResultsForDirect(self, tab, results):
635 return self._AddResultsShared(DIRECT, tab, results)
636
637 def _AddResultsShared(self, kind, tab, results):
638 def err(s):
639 raise ChromeProxyMetricException, s
640
641 # Should have played the video.
642 if not self.videoMetrics['ready']:
643 err('%s: video not played' % kind)
644
645 # Should have an HTTP response for the video.
646 wantContentType = 'video/webm' if kind == PROXIED else 'video/mp4'
647 found = False
648 for r in self.IterResponses(tab):
649 resp = r.response
650 if kind == DIRECT and r.HasChromeProxyViaHeader():
651 err('%s: page has proxied Via header' % kind)
652 if resp.GetHeader('Content-Type') != wantContentType:
653 continue
654 if found:
655 err('%s: multiple video responses' % kind)
656 found = True
657
658 cl = resp.GetHeader('Content-Length')
659 xocl = resp.GetHeader('X-Original-Content-Length')
660 if cl != None:
661 self.videoMetrics['content_length_header'] = int(cl)
662 if xocl != None:
663 self.videoMetrics['x_original_content_length_header'] = int(xocl)
664
665 # Should have CL always.
666 if cl == None:
667 err('%s: missing ContentLength' % kind)
668 # Proxied: should have CL < XOCL
669 # Direct: should not have XOCL
670 if kind == PROXIED:
671 if xocl == None or int(cl) >= int(xocl):
672 err('%s: bigger response (%s > %s)' % (kind, str(cl), str(xocl)))
673 else:
674 if xocl != None:
675 err('%s: has XOriginalContentLength' % kind)
676
677 if not found:
678 err('%s: missing video response' % kind)
679
680 # Finally, add all the metrics to the results.
681 for (k,v) in self.videoMetrics.iteritems():
682 k = "%s_%s" % (k, kind)
683 results.AddValue(scalar.ScalarValue(results.current_page, k, "", v))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698