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 3 # found in the LICENSE file. 4 5 import base64 6 import unittest 7 8 from integration_tests import network_metrics 9 from metrics import test_page_test_results 10 from telemetry.timeline import event 11 12 13 HTML_BODY = """<!DOCTYPE HTML> 14 <html> 15 <head> </head> 16 <body> 17 <div id="test"> TEST HTML</div> 18 </body> 19 </html>""" 20 IMAGE_BODY = """fake image data""" 21 GZIPPED_HTML_LEN = network_metrics.HTTPResponse.GetGizppedBodyLength(HTML_BODY) 22 # Make up original content length for the image. 23 IMAGE_OCL = 3 * len(IMAGE_BODY) 24 25 26 class NetworkMetricTest(unittest.TestCase): 27 @staticmethod 28 def MakeNetworkTimelineEvent( 29 url, response_headers, body=None, base64_encoded_body=False, 30 served_from_cache=False, request_headers=None, status=200): 31 if not request_headers: 32 request_headers = {} 33 e = event.TimelineEvent('network', 'HTTPResponse', 0, 0) 34 e.args = {} 35 e.args['requestId'] = 0 36 e.args['response'] = { 37 'status': status, 38 'url': url, 39 'headers': response_headers, 40 'requestHeaders': request_headers, 41 } 42 e.args['body'] = body 43 e.args['base64_encoded_body'] = base64_encoded_body 44 e.args['served_from_cache'] = served_from_cache 45 return e 46 47 def testHTTPResponse(self): 48 url = 'http://test.url' 49 self.assertLess(GZIPPED_HTML_LEN, len(HTML_BODY)) 50 51 # A plain text HTML response 52 resp = network_metrics.HTTPResponse(self.MakeNetworkTimelineEvent( 53 url=url, 54 response_headers={ 55 'Content-Type': 'text/html', 56 'Content-Length': str(len(HTML_BODY)), 57 }, 58 body=HTML_BODY)) 59 self.assertEqual(url, resp.response.url) 60 body, base64_encoded = resp.response.GetBody() 61 self.assertEqual(HTML_BODY, body) 62 self.assertFalse(base64_encoded) 63 self.assertEqual('text/html', resp.response.GetHeader('Content-Type')) 64 65 self.assertEqual(len(HTML_BODY), resp.content_length) 66 self.assertEqual(None, resp.response.GetHeader('Content-Encoding')) 67 self.assertFalse(resp.has_original_content_length) 68 self.assertEqual(0.0, resp.data_saving_rate) 69 70 # A gzipped HTML response 71 resp = network_metrics.HTTPResponse(self.MakeNetworkTimelineEvent( 72 url=url, 73 response_headers={ 74 'Content-Type': 'text/html', 75 'Content-Encoding': 'gzip', 76 'X-Original-Content-Length': str(len(HTML_BODY)), 77 }, 78 body=HTML_BODY)) 79 body, base64_encoded = resp.response.GetBody() 80 self.assertFalse(base64_encoded) 81 self.assertEqual(GZIPPED_HTML_LEN, resp.content_length) 82 self.assertEqual('gzip', resp.response.GetHeader('Content-Encoding')) 83 self.assertTrue(resp.has_original_content_length) 84 self.assertEqual(len(HTML_BODY), resp.original_content_length) 85 self.assertEqual( 86 float(len(HTML_BODY) - GZIPPED_HTML_LEN) / len(HTML_BODY), 87 resp.data_saving_rate) 88 89 # A JPEG image response. 90 resp = network_metrics.HTTPResponse(self.MakeNetworkTimelineEvent( 91 url='http://test.image', 92 response_headers={ 93 'Content-Type': 'image/jpeg', 94 'Content-Encoding': 'gzip', 95 'X-Original-Content-Length': str(IMAGE_OCL), 96 }, 97 body=base64.b64encode(IMAGE_BODY), 98 base64_encoded_body=True)) 99 body, base64_encoded = resp.response.GetBody() 100 self.assertTrue(base64_encoded) 101 self.assertEqual(IMAGE_BODY, base64.b64decode(body)) 102 self.assertEqual(len(IMAGE_BODY), resp.content_length) 103 self.assertTrue(resp.has_original_content_length) 104 self.assertEqual(IMAGE_OCL, resp.original_content_length) 105 self.assertFalse(resp.response.served_from_cache) 106 self.assertEqual(float(IMAGE_OCL - len(IMAGE_BODY)) / IMAGE_OCL, 107 resp.data_saving_rate) 108 109 # A JPEG image response from cache. 110 resp = network_metrics.HTTPResponse(self.MakeNetworkTimelineEvent( 111 url='http://test.image', 112 response_headers={ 113 'Content-Type': 'image/jpeg', 114 'Content-Encoding': 'gzip', 115 'X-Original-Content-Length': str(IMAGE_OCL), 116 }, 117 body=base64.b64encode(IMAGE_BODY), 118 base64_encoded_body=True, 119 served_from_cache=True)) 120 self.assertEqual(len(IMAGE_BODY), resp.content_length) 121 self.assertTrue(resp.has_original_content_length) 122 self.assertEqual(IMAGE_OCL, resp.original_content_length) 123 # Cached resource has zero saving. 124 self.assertTrue(resp.response.served_from_cache) 125 self.assertEqual(0.0, resp.data_saving_rate) 126 127 def testNetworkMetricResults(self): 128 events = [ 129 # A plain text HTML. 130 self.MakeNetworkTimelineEvent( 131 url='http://test.html1', 132 response_headers={ 133 'Content-Type': 'text/html', 134 'Content-Length': str(len(HTML_BODY)), 135 }, 136 body=HTML_BODY), 137 # A compressed HTML. 138 self.MakeNetworkTimelineEvent( 139 url='http://test.html2', 140 response_headers={ 141 'Content-Type': 'text/html', 142 'Content-Encoding': 'gzip', 143 'X-Original-Content-Length': str(len(HTML_BODY)), 144 }, 145 body=HTML_BODY), 146 # A base64 encoded image. 147 self.MakeNetworkTimelineEvent( 148 url='http://test.image', 149 response_headers={ 150 'Content-Type': 'image/jpeg', 151 'Content-Encoding': 'gzip', 152 'X-Original-Content-Length': str(IMAGE_OCL), 153 }, 154 body=base64.b64encode(IMAGE_BODY), 155 base64_encoded_body=True), 156 ] 157 metric = network_metrics.NetworkMetric() 158 metric._events = events 159 metric.compute_data_saving = True 160 161 self.assertTrue(len(events), len(list(metric.IterResponses(None)))) 162 results = test_page_test_results.TestPageTestResults(self) 163 metric.AddResults(None, results) 164 165 cl = len(HTML_BODY) + GZIPPED_HTML_LEN + len(IMAGE_BODY) 166 results.AssertHasPageSpecificScalarValue('content_length', 'bytes', cl) 167 168 ocl = len(HTML_BODY) + len(HTML_BODY) + IMAGE_OCL 169 results.AssertHasPageSpecificScalarValue( 170 'original_content_length', 'bytes', ocl) 171 172 saving_percent = float(ocl - cl) * 100/ ocl 173 results.AssertHasPageSpecificScalarValue( 174 'data_saving', 'percent', saving_percent) 175