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 |