| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2011 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 """Playback driver.""" | |
| 5 | |
| 6 import cgi | |
| 7 import simplejson as json | |
| 8 import os | |
| 9 import string | |
| 10 import sys | |
| 11 import threading | |
| 12 import urlparse | |
| 13 | |
| 14 START_PAGE = """<html> | |
| 15 <script type="text/javascript"> | |
| 16 var runCount = $run_count; | |
| 17 var results = []; | |
| 18 | |
| 19 function run() { | |
| 20 var wnd = window.open('?resource=start_page_popup', '', | |
| 21 'width=$width, height=$height'); | |
| 22 var timerId = setInterval(function() { | |
| 23 wnd.postMessage('ping', '$target_origin'); | |
| 24 }, 300); | |
| 25 var handleMessage = function(event) { | |
| 26 clearInterval(timerId); | |
| 27 wnd.close(); | |
| 28 document.writeln('<div>' + event.data + '</div>'); | |
| 29 results.push(event.data); | |
| 30 runCount -= 1; | |
| 31 window.removeEventListener('message', handleMessage); | |
| 32 if (runCount > 0) { | |
| 33 run(); | |
| 34 } else { | |
| 35 var xmlHttpRequest = new XMLHttpRequest(); | |
| 36 xmlHttpRequest.open("POST", '/benchmark/', true); | |
| 37 xmlHttpRequest.setRequestHeader("Content-type", "application/json"); | |
| 38 xmlHttpRequest.send(JSON.stringify({results: results})); | |
| 39 } | |
| 40 } | |
| 41 window.addEventListener('message', handleMessage, false); | |
| 42 } | |
| 43 | |
| 44 run(); | |
| 45 </script> | |
| 46 </html> | |
| 47 """ | |
| 48 | |
| 49 START_PAGE_POPUP = """<html> | |
| 50 <script type="text/javascript"> | |
| 51 window.setTimeout(function() { | |
| 52 console.log(window.innerWidth, window.innerHeight); | |
| 53 if (window.innerWidth == $width && window.innerHeight == $height) { | |
| 54 window.location = '$start_url'; | |
| 55 } else { | |
| 56 window.resizeBy($width - window.innerWidth, $height - window.innerHeight); | |
| 57 window.location = window.location; | |
| 58 } | |
| 59 }, 200); | |
| 60 </script> | |
| 61 </html> | |
| 62 """ | |
| 63 | |
| 64 DATA_JS = 'Benchmark.data = $data;' | |
| 65 | |
| 66 | |
| 67 def ReadFile(file_name, mode='r'): | |
| 68 f = open(file_name, mode) | |
| 69 data = f.read() | |
| 70 f.close() | |
| 71 return data | |
| 72 | |
| 73 | |
| 74 def ReadJSON(file_name): | |
| 75 f = open(file_name, 'r') | |
| 76 data = json.load(f) | |
| 77 f.close() | |
| 78 return data | |
| 79 | |
| 80 | |
| 81 class PlaybackRequestHandler(object): | |
| 82 """This class is used to process HTTP requests during test playback. | |
| 83 | |
| 84 Attributes: | |
| 85 test_dir: directory containing test files. | |
| 86 test_callback: function to be called when the test is finished. | |
| 87 script_dir: directory where javascript files are located. | |
| 88 """ | |
| 89 | |
| 90 def __init__(self, test_dir, test_callback=None, script_dir=os.getcwd()): | |
| 91 self.test_dir = test_dir | |
| 92 self.test_callback = test_callback | |
| 93 self.script_dir = script_dir | |
| 94 | |
| 95 def ProcessRequest(self, handler): | |
| 96 "Processes single HTTP request." | |
| 97 | |
| 98 parse_result = urlparse.urlparse(handler.path) | |
| 99 if parse_result.path.endswith('/benchmark/'): | |
| 100 query = cgi.parse_qs(parse_result.query) | |
| 101 if 'run_test' in query: | |
| 102 run_count = 1 | |
| 103 if 'run_count' in query: | |
| 104 run_count = query['run_count'][0] | |
| 105 self._StartTest(handler, self.test_dir, run_count) | |
| 106 elif 'resource' in query: | |
| 107 self._GetBenchmarkResource(query['resource'][0], handler) | |
| 108 else: | |
| 109 self._ProcessBenchmarkReport(handler.body, handler) | |
| 110 else: | |
| 111 self._GetApplicationResource(handler) | |
| 112 | |
| 113 def _StartTest(self, handler, test_dir, run_count): | |
| 114 "Sends test start page to browser." | |
| 115 | |
| 116 cache_data = ReadJSON(os.path.join(test_dir, 'cache.json')) | |
| 117 | |
| 118 # Load cached responses. | |
| 119 self.cache = {} | |
| 120 responses_dir = os.path.join(test_dir, 'responses') | |
| 121 for request in cache_data['requests']: | |
| 122 response_file = os.path.join(responses_dir, request['response_file']) | |
| 123 response = ReadFile(response_file, 'rb') | |
| 124 key = (request['method'], request['path']) | |
| 125 self.cache[key] = {'response': response, 'headers': request['headers']} | |
| 126 | |
| 127 # Load benchmark scripts. | |
| 128 self.benchmark_resources = {} | |
| 129 data = ReadFile(os.path.join(test_dir, 'data.json')) | |
| 130 data = string.Template(DATA_JS).substitute(data=data) | |
| 131 self.benchmark_resources['data.js'] = {'data': data, | |
| 132 'type': 'application/javascript'} | |
| 133 for resource in ('common.js', 'playback.js'): | |
| 134 resource_file = os.path.join(self.script_dir, resource) | |
| 135 self.benchmark_resources[resource] = {'data': ReadFile(resource_file), | |
| 136 'type': 'application/javascript'} | |
| 137 | |
| 138 # Format start page. | |
| 139 parse_result = urlparse.urlparse(cache_data['start_url']) | |
| 140 target_origin = '%s://%s' % (parse_result.scheme, parse_result.netloc) | |
| 141 start_page = string.Template(START_PAGE).substitute( | |
| 142 run_count=run_count, target_origin=target_origin, | |
| 143 width=cache_data['width'], height=cache_data['height']) | |
| 144 self.benchmark_resources['start_page'] = { | |
| 145 'data': start_page, | |
| 146 'type': 'text/html; charset=UTF-8' | |
| 147 } | |
| 148 | |
| 149 start_page_popup = string.Template(START_PAGE_POPUP).substitute( | |
| 150 start_url=cache_data['start_url'], | |
| 151 width=cache_data['width'], height=cache_data['height']) | |
| 152 self.benchmark_resources['start_page_popup'] = { | |
| 153 'data': start_page_popup, | |
| 154 'type': 'text/html; charset=UTF-8' | |
| 155 } | |
| 156 | |
| 157 self._GetBenchmarkResource('start_page', handler) | |
| 158 | |
| 159 def _GetBenchmarkResource(self, resource, handler): | |
| 160 "Sends requested resource to browser." | |
| 161 | |
| 162 if resource in self.benchmark_resources: | |
| 163 resource = self.benchmark_resources[resource] | |
| 164 handler.send_response(200) | |
| 165 handler.send_header('content-length', len(resource['data'])) | |
| 166 handler.send_header('content-type', resource['type']) | |
| 167 handler.end_headers() | |
| 168 handler.wfile.write(resource['data']) | |
| 169 else: | |
| 170 handler.send_response(404) | |
| 171 handler.end_headers() | |
| 172 | |
| 173 def _ProcessBenchmarkReport(self, content, handler): | |
| 174 "Reads benchmark score from report content and invokes callback." | |
| 175 | |
| 176 handler.send_response(204) | |
| 177 handler.end_headers() | |
| 178 content = json.loads(content) | |
| 179 if 'results' in content: | |
| 180 results = content['results'] | |
| 181 sys.stdout.write('Results: %s\n' % results) | |
| 182 if self.test_callback: self.test_callback(results) | |
| 183 elif 'error' in content: | |
| 184 sys.stderr.write('Error: %s\n' % content['error']) | |
| 185 | |
| 186 def _GetApplicationResource(self, handler): | |
| 187 "Searches for response in cache. If not found, responds with 204." | |
| 188 key = (handler.command, handler.path) | |
| 189 if key in self.cache: | |
| 190 sys.stdout.write('%s %s -> found\n' % key) | |
| 191 handler.wfile.write(self.cache[key]['response']) | |
| 192 else: | |
| 193 sys.stderr.write('%s %s -> not found\n' % key) | |
| 194 handler.send_response(204, "not in cache") | |
| 195 handler.end_headers() | |
| OLD | NEW |