OLD | NEW |
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 json | 5 import json |
6 import logging | 6 import logging |
7 import os | 7 import os |
8 import time | 8 import time |
9 | 9 |
10 from common import chrome_proxy_metrics | 10 from common import chrome_proxy_metrics |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 raise ChromeProxyMetricException, ( | 75 raise ChromeProxyMetricException, ( |
76 'Expected at least one response through the proxy, but zero such ' | 76 'Expected at least one response through the proxy, but zero such ' |
77 'responses were received.') | 77 'responses were received.') |
78 results.AddValue(scalar.ScalarValue( | 78 results.AddValue(scalar.ScalarValue( |
79 results.current_page, 'checked_via_header', 'count', via_count)) | 79 results.current_page, 'checked_via_header', 'count', via_count)) |
80 | 80 |
81 def AddResultsForLatency(self, tab, results): | 81 def AddResultsForLatency(self, tab, results): |
82 # TODO(bustamante): This is a hack to workaround crbug.com/467174, | 82 # TODO(bustamante): This is a hack to workaround crbug.com/467174, |
83 # once fixed just pull down window.performance.timing object and | 83 # once fixed just pull down window.performance.timing object and |
84 # reference that everywhere. | 84 # reference that everywhere. |
85 load_event_start = tab.EvaluateJavaScript2( | 85 load_event_start = tab.EvaluateJavaScript( |
86 'window.performance.timing.loadEventStart') | 86 'window.performance.timing.loadEventStart') |
87 navigation_start = tab.EvaluateJavaScript2( | 87 navigation_start = tab.EvaluateJavaScript( |
88 'window.performance.timing.navigationStart') | 88 'window.performance.timing.navigationStart') |
89 dom_content_loaded_event_start = tab.EvaluateJavaScript2( | 89 dom_content_loaded_event_start = tab.EvaluateJavaScript( |
90 'window.performance.timing.domContentLoadedEventStart') | 90 'window.performance.timing.domContentLoadedEventStart') |
91 fetch_start = tab.EvaluateJavaScript2( | 91 fetch_start = tab.EvaluateJavaScript( |
92 'window.performance.timing.fetchStart') | 92 'window.performance.timing.fetchStart') |
93 request_start = tab.EvaluateJavaScript2( | 93 request_start = tab.EvaluateJavaScript( |
94 'window.performance.timing.requestStart') | 94 'window.performance.timing.requestStart') |
95 domain_lookup_end = tab.EvaluateJavaScript2( | 95 domain_lookup_end = tab.EvaluateJavaScript( |
96 'window.performance.timing.domainLookupEnd') | 96 'window.performance.timing.domainLookupEnd') |
97 domain_lookup_start = tab.EvaluateJavaScript2( | 97 domain_lookup_start = tab.EvaluateJavaScript( |
98 'window.performance.timing.domainLookupStart') | 98 'window.performance.timing.domainLookupStart') |
99 connect_end = tab.EvaluateJavaScript2( | 99 connect_end = tab.EvaluateJavaScript( |
100 'window.performance.timing.connectEnd') | 100 'window.performance.timing.connectEnd') |
101 connect_start = tab.EvaluateJavaScript2( | 101 connect_start = tab.EvaluateJavaScript( |
102 'window.performance.timing.connectStart') | 102 'window.performance.timing.connectStart') |
103 response_end = tab.EvaluateJavaScript2( | 103 response_end = tab.EvaluateJavaScript( |
104 'window.performance.timing.responseEnd') | 104 'window.performance.timing.responseEnd') |
105 response_start = tab.EvaluateJavaScript2( | 105 response_start = tab.EvaluateJavaScript( |
106 'window.performance.timing.responseStart') | 106 'window.performance.timing.responseStart') |
107 | 107 |
108 # NavigationStart relative markers in milliseconds. | 108 # NavigationStart relative markers in milliseconds. |
109 load_start = (float(load_event_start) - navigation_start) | 109 load_start = (float(load_event_start) - navigation_start) |
110 results.AddValue(scalar.ScalarValue( | 110 results.AddValue(scalar.ScalarValue( |
111 results.current_page, 'load_start', 'ms', load_start)) | 111 results.current_page, 'load_start', 'ms', load_start)) |
112 | 112 |
113 dom_content_loaded_start = ( | 113 dom_content_loaded_start = ( |
114 float(dom_content_loaded_event_start) - navigation_start) | 114 float(dom_content_loaded_event_start) - navigation_start) |
115 results.AddValue(scalar.ScalarValue( | 115 results.AddValue(scalar.ScalarValue( |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 raise ChromeProxyMetricException, ( | 424 raise ChromeProxyMetricException, ( |
425 'Expected at least one https response was expected, but zero such ' | 425 'Expected at least one https response was expected, but zero such ' |
426 'responses were received.') | 426 'responses were received.') |
427 | 427 |
428 results.AddValue(scalar.ScalarValue( | 428 results.AddValue(scalar.ScalarValue( |
429 results.current_page, 'bypass', 'count', bypass_count)) | 429 results.current_page, 'bypass', 'count', bypass_count)) |
430 | 430 |
431 def AddResultsForHTML5Test(self, tab, results): | 431 def AddResultsForHTML5Test(self, tab, results): |
432 # Wait for the number of "points" of HTML5 compatibility to appear to verify | 432 # Wait for the number of "points" of HTML5 compatibility to appear to verify |
433 # the HTML5 elements have loaded successfully. | 433 # the HTML5 elements have loaded successfully. |
434 tab.WaitForJavaScriptCondition2( | 434 tab.WaitForJavaScriptCondition( |
435 'document.getElementsByClassName("pointsPanel")', timeout=15) | 435 'document.getElementsByClassName("pointsPanel")', timeout=15) |
436 | 436 |
437 def AddResultsForYouTube(self, tab, results): | 437 def AddResultsForYouTube(self, tab, results): |
438 # Wait for the video to begin playing. | 438 # Wait for the video to begin playing. |
439 tab.WaitForJavaScriptCondition2( | 439 tab.WaitForJavaScriptCondition( |
440 'window.playerState == YT.PlayerState.PLAYING', timeout=30) | 440 'window.playerState == YT.PlayerState.PLAYING', timeout=30) |
441 | 441 |
442 def AddResultsForBypass(self, tab, results, url_pattern=""): | 442 def AddResultsForBypass(self, tab, results, url_pattern=""): |
443 bypass_count = 0 | 443 bypass_count = 0 |
444 skipped_count = 0 | 444 skipped_count = 0 |
445 | 445 |
446 for resp in self.IterResponses(tab): | 446 for resp in self.IterResponses(tab): |
447 # Only check the url's that contain the specified pattern. | 447 # Only check the url's that contain the specified pattern. |
448 if url_pattern and url_pattern not in resp.response.url: | 448 if url_pattern and url_pattern not in resp.response.url: |
449 skipped_count += 1 | 449 skipped_count += 1 |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 | 664 |
665 # Wait until 30 seconds before the bypass should expire, and fetch a page. | 665 # Wait until 30 seconds before the bypass should expire, and fetch a page. |
666 # It should not have the via header because the proxy should still be | 666 # It should not have the via header because the proxy should still be |
667 # bypassed. | 667 # bypassed. |
668 time.sleep(bypass_seconds_min - 30) | 668 time.sleep(bypass_seconds_min - 30) |
669 | 669 |
670 tab.ClearCache(force=True) | 670 tab.ClearCache(force=True) |
671 before_metrics = ChromeProxyMetric() | 671 before_metrics = ChromeProxyMetric() |
672 before_metrics.Start(results.current_page, tab) | 672 before_metrics.Start(results.current_page, tab) |
673 tab.Navigate('http://chromeproxy-test.appspot.com/default') | 673 tab.Navigate('http://chromeproxy-test.appspot.com/default') |
674 tab.WaitForJavaScriptCondition2( | 674 tab.WaitForJavaScriptCondition( |
675 'performance.timing.loadEventStart', timeout=10) | 675 'performance.timing.loadEventStart', timeout=10) |
676 before_metrics.Stop(results.current_page, tab) | 676 before_metrics.Stop(results.current_page, tab) |
677 | 677 |
678 for resp in before_metrics.IterResponses(tab): | 678 for resp in before_metrics.IterResponses(tab): |
679 if resp.HasChromeProxyViaHeader(): | 679 if resp.HasChromeProxyViaHeader(): |
680 r = resp.response | 680 r = resp.response |
681 raise ChromeProxyMetricException, ( | 681 raise ChromeProxyMetricException, ( |
682 'Response for %s should not have via header; proxy should still ' | 682 'Response for %s should not have via header; proxy should still ' |
683 'be bypassed.\nReponse: status=(%d, %s)\nHeaders:\n %s' % ( | 683 'be bypassed.\nReponse: status=(%d, %s)\nHeaders:\n %s' % ( |
684 r.url, r.status, r.status_text, r.headers)) | 684 r.url, r.status, r.status_text, r.headers)) |
685 else: | 685 else: |
686 bypass_count += 1 | 686 bypass_count += 1 |
687 if bypass_count == 0: | 687 if bypass_count == 0: |
688 raise ChromeProxyMetricException, ( | 688 raise ChromeProxyMetricException, ( |
689 'Expected at least one response to be bypassed before the bypass ' | 689 'Expected at least one response to be bypassed before the bypass ' |
690 'expired, but zero such responses were received.') | 690 'expired, but zero such responses were received.') |
691 | 691 |
692 # Wait until 30 seconds after the bypass should expire, and fetch a page. It | 692 # Wait until 30 seconds after the bypass should expire, and fetch a page. It |
693 # should have the via header since the proxy should no longer be bypassed. | 693 # should have the via header since the proxy should no longer be bypassed. |
694 time.sleep((bypass_seconds_max + 30) - (bypass_seconds_min - 30)) | 694 time.sleep((bypass_seconds_max + 30) - (bypass_seconds_min - 30)) |
695 | 695 |
696 tab.ClearCache(force=True) | 696 tab.ClearCache(force=True) |
697 after_metrics = ChromeProxyMetric() | 697 after_metrics = ChromeProxyMetric() |
698 after_metrics.Start(results.current_page, tab) | 698 after_metrics.Start(results.current_page, tab) |
699 tab.Navigate('http://chromeproxy-test.appspot.com/default') | 699 tab.Navigate('http://chromeproxy-test.appspot.com/default') |
700 tab.WaitForJavaScriptCondition2( | 700 tab.WaitForJavaScriptCondition( |
701 'performance.timing.loadEventStart', timeout=10) | 701 'performance.timing.loadEventStart', timeout=10) |
702 after_metrics.Stop(results.current_page, tab) | 702 after_metrics.Stop(results.current_page, tab) |
703 | 703 |
704 for resp in after_metrics.IterResponses(tab): | 704 for resp in after_metrics.IterResponses(tab): |
705 if not resp.HasChromeProxyViaHeader(): | 705 if not resp.HasChromeProxyViaHeader(): |
706 r = resp.response | 706 r = resp.response |
707 raise ChromeProxyMetricException, ( | 707 raise ChromeProxyMetricException, ( |
708 'Response for %s should have via header; proxy should no longer ' | 708 'Response for %s should have via header; proxy should no longer ' |
709 'be bypassed.\nReponse: status=(%d, %s)\nHeaders:\n %s' % ( | 709 'be bypassed.\nReponse: status=(%d, %s)\nHeaders:\n %s' % ( |
710 r.url, r.status, r.status_text, r.headers)) | 710 r.url, r.status, r.status_text, r.headers)) |
(...skipping 30 matching lines...) Expand all Loading... |
741 'Reponse: status=(%d, %s)\nHeaders:\n %s' % ( | 741 'Reponse: status=(%d, %s)\nHeaders:\n %s' % ( |
742 r.url, r.status, r.status_text, r.headers)) | 742 r.url, r.status, r.status_text, r.headers)) |
743 else: | 743 else: |
744 bypass_count += 1 | 744 bypass_count += 1 |
745 | 745 |
746 # Navigate to a test page and verify it's being bypassed. | 746 # Navigate to a test page and verify it's being bypassed. |
747 tab.ClearCache(force=True) | 747 tab.ClearCache(force=True) |
748 before_metrics = ChromeProxyMetric() | 748 before_metrics = ChromeProxyMetric() |
749 before_metrics.Start(results.current_page, tab) | 749 before_metrics.Start(results.current_page, tab) |
750 tab.Navigate('http://chromeproxy-test.appspot.com/default') | 750 tab.Navigate('http://chromeproxy-test.appspot.com/default') |
751 tab.WaitForJavaScriptCondition2( | 751 tab.WaitForJavaScriptCondition( |
752 'performance.timing.loadEventStart', timeout=10) | 752 'performance.timing.loadEventStart', timeout=10) |
753 before_metrics.Stop(results.current_page, tab) | 753 before_metrics.Stop(results.current_page, tab) |
754 | 754 |
755 for resp in before_metrics.IterResponses(tab): | 755 for resp in before_metrics.IterResponses(tab): |
756 if resp.HasChromeProxyViaHeader(): | 756 if resp.HasChromeProxyViaHeader(): |
757 r = resp.response | 757 r = resp.response |
758 raise ChromeProxyMetricException, ( | 758 raise ChromeProxyMetricException, ( |
759 'Response for %s should not have via header; proxy should still ' | 759 'Response for %s should not have via header; proxy should still ' |
760 'be bypassed.\nReponse: status=(%d, %s)\nHeaders:\n %s' % ( | 760 'be bypassed.\nReponse: status=(%d, %s)\nHeaders:\n %s' % ( |
761 r.url, r.status, r.status_text, r.headers)) | 761 r.url, r.status, r.status_text, r.headers)) |
762 else: | 762 else: |
763 bypass_count += 1 | 763 bypass_count += 1 |
764 if bypass_count == 0: | 764 if bypass_count == 0: |
765 raise ChromeProxyMetricException, ( | 765 raise ChromeProxyMetricException, ( |
766 'Expected at least one response to be bypassed before the bypass ' | 766 'Expected at least one response to be bypassed before the bypass ' |
767 'expired, but zero such responses were received.') | 767 'expired, but zero such responses were received.') |
768 | 768 |
769 # Wait for the bypass to expire, with the overhead of the previous steps | 769 # Wait for the bypass to expire, with the overhead of the previous steps |
770 # the bypass duration will have been exceeded after this delay. | 770 # the bypass duration will have been exceeded after this delay. |
771 time.sleep(bypass_seconds) | 771 time.sleep(bypass_seconds) |
772 | 772 |
773 # Navigate to the test pass again and verify data saver is no longer | 773 # Navigate to the test pass again and verify data saver is no longer |
774 # bypassed. | 774 # bypassed. |
775 tab.ClearCache(force=True) | 775 tab.ClearCache(force=True) |
776 after_metrics = ChromeProxyMetric() | 776 after_metrics = ChromeProxyMetric() |
777 after_metrics.Start(results.current_page, tab) | 777 after_metrics.Start(results.current_page, tab) |
778 tab.Navigate('http://chromeproxy-test.appspot.com/default') | 778 tab.Navigate('http://chromeproxy-test.appspot.com/default') |
779 tab.WaitForJavaScriptCondition2( | 779 tab.WaitForJavaScriptCondition( |
780 'performance.timing.loadEventStart', timeout=10) | 780 'performance.timing.loadEventStart', timeout=10) |
781 after_metrics.Stop(results.current_page, tab) | 781 after_metrics.Stop(results.current_page, tab) |
782 | 782 |
783 for resp in after_metrics.IterResponses(tab): | 783 for resp in after_metrics.IterResponses(tab): |
784 if not resp.HasChromeProxyViaHeader(): | 784 if not resp.HasChromeProxyViaHeader(): |
785 r = resp.response | 785 r = resp.response |
786 raise ChromeProxyMetricException, ( | 786 raise ChromeProxyMetricException, ( |
787 'Response for %s should have via header; proxy should no longer ' | 787 'Response for %s should have via header; proxy should no longer ' |
788 'be bypassed.\nReponse: status=(%d, %s)\nHeaders:\n %s' % ( | 788 'be bypassed.\nReponse: status=(%d, %s)\nHeaders:\n %s' % ( |
789 r.url, r.status, r.status_text, r.headers)) | 789 r.url, r.status, r.status_text, r.headers)) |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 | 973 |
974 Wraps the video metrics produced by videowrapper.js, such as the video | 974 Wraps the video metrics produced by videowrapper.js, such as the video |
975 duration and size in pixels. Also checks a few basic HTTP response headers | 975 duration and size in pixels. Also checks a few basic HTTP response headers |
976 such as Content-Type and Content-Length in the video responses. | 976 such as Content-Type and Content-Length in the video responses. |
977 """ | 977 """ |
978 | 978 |
979 def __init__(self, tab): | 979 def __init__(self, tab): |
980 super(ChromeProxyVideoMetric, self).__init__() | 980 super(ChromeProxyVideoMetric, self).__init__() |
981 with open(os.path.join(os.path.dirname(__file__), 'videowrapper.js')) as f: | 981 with open(os.path.join(os.path.dirname(__file__), 'videowrapper.js')) as f: |
982 js = f.read() | 982 js = f.read() |
983 tab.ExecuteJavaScript2(js) | 983 tab.ExecuteJavaScript(js) |
984 | 984 |
985 def Start(self, page, tab): | 985 def Start(self, page, tab): |
986 tab.ExecuteJavaScript2('window.__chromeProxyCreateVideoWrappers()') | 986 tab.ExecuteJavaScript('window.__chromeProxyCreateVideoWrappers()') |
987 self.videoMetrics = None | 987 self.videoMetrics = None |
988 super(ChromeProxyVideoMetric, self).Start(page, tab) | 988 super(ChromeProxyVideoMetric, self).Start(page, tab) |
989 | 989 |
990 def Stop(self, page, tab): | 990 def Stop(self, page, tab): |
991 tab.WaitForJavaScriptCondition2( | 991 tab.WaitForJavaScriptCondition( |
992 'window.__chromeProxyVideoLoaded', timeout=30) | 992 'window.__chromeProxyVideoLoaded', timeout=30) |
993 m = tab.EvaluateJavaScript2('window.__chromeProxyVideoMetrics') | 993 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics') |
994 | 994 |
995 # Now wait for the video to stop playing. | 995 # Now wait for the video to stop playing. |
996 # Give it 2x the total duration to account for buffering. | 996 # Give it 2x the total duration to account for buffering. |
997 waitTime = 2 * m['video_duration'] | 997 waitTime = 2 * m['video_duration'] |
998 tab.WaitForJavaScriptCondition2( | 998 tab.WaitForJavaScriptCondition( |
999 'window.__chromeProxyVideoEnded', timeout=waitTime) | 999 'window.__chromeProxyVideoEnded', timeout=waitTime) |
1000 | 1000 |
1001 # Load the final metrics. | 1001 # Load the final metrics. |
1002 m = tab.EvaluateJavaScript2('window.__chromeProxyVideoMetrics') | 1002 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics') |
1003 self.videoMetrics = m | 1003 self.videoMetrics = m |
1004 # Cast this to an integer as it is often approximate (for an unknown reason) | 1004 # Cast this to an integer as it is often approximate (for an unknown reason) |
1005 m['video_duration'] = int(m['video_duration']) | 1005 m['video_duration'] = int(m['video_duration']) |
1006 super(ChromeProxyVideoMetric, self).Stop(page, tab) | 1006 super(ChromeProxyVideoMetric, self).Stop(page, tab) |
1007 | 1007 |
1008 def ResponseFromEvent(self, event): | 1008 def ResponseFromEvent(self, event): |
1009 return chrome_proxy_metrics.ChromeProxyResponse(event) | 1009 return chrome_proxy_metrics.ChromeProxyResponse(event) |
1010 | 1010 |
1011 def AddResults(self, tab, results): | 1011 def AddResults(self, tab, results): |
1012 raise NotImplementedError | 1012 raise NotImplementedError |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 results.AddValue(scalar.ScalarValue(results.current_page, k, "", v)) | 1066 results.AddValue(scalar.ScalarValue(results.current_page, k, "", v)) |
1067 | 1067 |
1068 | 1068 |
1069 class ChromeProxyInstrumentedVideoMetric(Metric): | 1069 class ChromeProxyInstrumentedVideoMetric(Metric): |
1070 """Metric for pages instrumented to evaluate video transcoding.""" | 1070 """Metric for pages instrumented to evaluate video transcoding.""" |
1071 | 1071 |
1072 def __init__(self): | 1072 def __init__(self): |
1073 super(ChromeProxyInstrumentedVideoMetric, self).__init__() | 1073 super(ChromeProxyInstrumentedVideoMetric, self).__init__() |
1074 | 1074 |
1075 def Stop(self, page, tab): | 1075 def Stop(self, page, tab): |
1076 waitTime = tab.EvaluateJavaScript2('test.waitTime') | 1076 waitTime = tab.EvaluateJavaScript('test.waitTime') |
1077 tab.WaitForJavaScriptCondition2('test.metrics.complete', timeout=waitTime) | 1077 tab.WaitForJavaScriptCondition('test.metrics.complete', timeout=waitTime) |
1078 super(ChromeProxyInstrumentedVideoMetric, self).Stop(page, tab) | 1078 super(ChromeProxyInstrumentedVideoMetric, self).Stop(page, tab) |
1079 | 1079 |
1080 def AddResults(self, tab, results): | 1080 def AddResults(self, tab, results): |
1081 metrics = tab.EvaluateJavaScript2('test.metrics') | 1081 metrics = tab.EvaluateJavaScript('test.metrics') |
1082 for (k, v) in metrics.iteritems(): | 1082 for (k, v) in metrics.iteritems(): |
1083 results.AddValue(scalar.ScalarValue(results.current_page, k, '', v)) | 1083 results.AddValue(scalar.ScalarValue(results.current_page, k, '', v)) |
1084 try: | 1084 try: |
1085 complete = metrics['complete'] | 1085 complete = metrics['complete'] |
1086 failed = metrics['failed'] | 1086 failed = metrics['failed'] |
1087 if not complete: | 1087 if not complete: |
1088 raise ChromeProxyMetricException, 'Test not complete' | 1088 raise ChromeProxyMetricException, 'Test not complete' |
1089 if failed: | 1089 if failed: |
1090 raise ChromeProxyMetricException, 'failed' | 1090 raise ChromeProxyMetricException, 'failed' |
1091 except KeyError: | 1091 except KeyError: |
1092 raise ChromeProxyMetricException, 'No metrics found' | 1092 raise ChromeProxyMetricException, 'No metrics found' |
1093 | 1093 |
1094 # Returns whether |url| is a block-once test URL. Data Reduction Proxy has been | 1094 # Returns whether |url| is a block-once test URL. Data Reduction Proxy has been |
1095 # configured to always return block-once for these URLs. | 1095 # configured to always return block-once for these URLs. |
1096 def IsTestUrlForBlockOnce(url): | 1096 def IsTestUrlForBlockOnce(url): |
1097 return (url == 'http://check.googlezip.net/blocksingle/' or | 1097 return (url == 'http://check.googlezip.net/blocksingle/' or |
1098 url == ('http://chromeproxy-test.appspot.com/default?respBody=T0s=' | 1098 url == ('http://chromeproxy-test.appspot.com/default?respBody=T0s=' |
1099 '&respHeader=eyJBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4iOlsiKiJ' | 1099 '&respHeader=eyJBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4iOlsiKiJ' |
1100 'dfQ==&respStatus=200&flywheelAction=block-once')) | 1100 'dfQ==&respStatus=200&flywheelAction=block-once')) |
OLD | NEW |