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