| Index: tools/playback_benchmark/playback_driver.py
|
| ===================================================================
|
| --- tools/playback_benchmark/playback_driver.py (revision 0)
|
| +++ tools/playback_benchmark/playback_driver.py (revision 0)
|
| @@ -0,0 +1,196 @@
|
| +#!/usr/bin/env python
|
| +#
|
| +# Copyright 2010 Google Inc. All Rights Reserved.
|
| +
|
| +"""Playback driver."""
|
| +
|
| +import cgi
|
| +import simplejson as json
|
| +import os
|
| +import string
|
| +import sys
|
| +import threading
|
| +import urlparse
|
| +
|
| +START_PAGE = """<html>
|
| + <script type="text/javascript">
|
| +var runCount = $run_count;
|
| +var results = [];
|
| +
|
| +function run() {
|
| + var wnd = window.open('?resource=start_page_popup', '',
|
| + 'width=$width, height=$height');
|
| + var timerId = setInterval(function() {
|
| + wnd.postMessage('ping', '$target_origin');
|
| + }, 300);
|
| + var handleMessage = function(event) {
|
| + clearInterval(timerId);
|
| + wnd.close();
|
| + document.writeln('<div>' + event.data + '</div>');
|
| + results.push(event.data);
|
| + runCount -= 1;
|
| + window.removeEventListener('message', handleMessage);
|
| + if (runCount > 0) {
|
| + run();
|
| + } else {
|
| + var xmlHttpRequest = new XMLHttpRequest();
|
| + xmlHttpRequest.open("POST", '/benchmark/', true);
|
| + xmlHttpRequest.setRequestHeader("Content-type", "application/json");
|
| + xmlHttpRequest.send(JSON.stringify({results: results}));
|
| + }
|
| + }
|
| + window.addEventListener('message', handleMessage, false);
|
| +}
|
| +
|
| +run();
|
| + </script>
|
| +</html>
|
| +"""
|
| +
|
| +START_PAGE_POPUP = """<html>
|
| + <script type="text/javascript">
|
| +window.setTimeout(function() {
|
| + console.log(window.innerWidth, window.innerHeight);
|
| + if (window.innerWidth == $width && window.innerHeight == $height) {
|
| + window.location = '$start_url';
|
| + } else {
|
| + window.resizeBy($width - window.innerWidth, $height - window.innerHeight);
|
| + window.location = window.location;
|
| + }
|
| +}, 200);
|
| + </script>
|
| +</html>
|
| +"""
|
| +
|
| +DATA_JS = 'Benchmark.data = $data;'
|
| +
|
| +
|
| +def ReadFile(file_name, mode='r'):
|
| + f = open(file_name, mode)
|
| + data = f.read()
|
| + f.close()
|
| + return data
|
| +
|
| +
|
| +def ReadJSON(file_name):
|
| + f = open(file_name, 'r')
|
| + data = json.load(f)
|
| + f.close()
|
| + return data
|
| +
|
| +
|
| +class PlaybackRequestHandler(object):
|
| + """This class is used to process HTTP requests during test playback.
|
| +
|
| + Attributes:
|
| + test_dir: directory containing test files.
|
| + test_callback: function to be called when the test is finished.
|
| + script_dir: directory where javascript files are located.
|
| + """
|
| +
|
| + def __init__(self, test_dir, test_callback=None, script_dir=os.getcwd()):
|
| + self.test_dir = test_dir
|
| + self.test_callback = test_callback
|
| + self.script_dir = script_dir
|
| +
|
| + def ProcessRequest(self, handler):
|
| + "Processes single HTTP request."
|
| +
|
| + parse_result = urlparse.urlparse(handler.path)
|
| + if parse_result.path.endswith('/benchmark/'):
|
| + query = cgi.parse_qs(parse_result.query)
|
| + if 'run_test' in query:
|
| + run_count = 1
|
| + if 'run_count' in query:
|
| + run_count = query['run_count'][0]
|
| + self._StartTest(handler, self.test_dir, run_count)
|
| + elif 'resource' in query:
|
| + self._GetBenchmarkResource(query['resource'][0], handler)
|
| + else:
|
| + self._ProcessBenchmarkReport(handler.body, handler)
|
| + else:
|
| + self._GetApplicationResource(handler)
|
| +
|
| + def _StartTest(self, handler, test_dir, run_count):
|
| + "Sends test start page to browser."
|
| +
|
| + cache_data = ReadJSON(os.path.join(test_dir, 'cache.json'))
|
| +
|
| + # Load cached responses.
|
| + self.cache = {}
|
| + responses_dir = os.path.join(test_dir, 'responses')
|
| + for request in cache_data['requests']:
|
| + response_file = os.path.join(responses_dir, request['response_file'])
|
| + response = ReadFile(response_file, 'rb')
|
| + key = (request['method'], request['path'])
|
| + self.cache[key] = {'response': response, 'headers': request['headers']}
|
| +
|
| + # Load benchmark scripts.
|
| + self.benchmark_resources = {}
|
| + data = ReadFile(os.path.join(test_dir, 'data.json'))
|
| + data = string.Template(DATA_JS).substitute(data=data)
|
| + self.benchmark_resources['data.js'] = {'data': data,
|
| + 'type': 'application/javascript'}
|
| + for resource in ('common.js', 'playback.js'):
|
| + resource_file = os.path.join(self.script_dir, resource)
|
| + self.benchmark_resources[resource] = {'data': ReadFile(resource_file),
|
| + 'type': 'application/javascript'}
|
| +
|
| + # Format start page.
|
| + parse_result = urlparse.urlparse(cache_data['start_url'])
|
| + target_origin = '%s://%s' % (parse_result.scheme, parse_result.netloc)
|
| + start_page = string.Template(START_PAGE).substitute(
|
| + run_count=run_count, target_origin=target_origin,
|
| + width=cache_data['width'], height=cache_data['height'])
|
| + self.benchmark_resources['start_page'] = {
|
| + 'data': start_page,
|
| + 'type': 'text/html; charset=UTF-8'
|
| + }
|
| +
|
| + start_page_popup = string.Template(START_PAGE_POPUP).substitute(
|
| + start_url=cache_data['start_url'],
|
| + width=cache_data['width'], height=cache_data['height'])
|
| + self.benchmark_resources['start_page_popup'] = {
|
| + 'data': start_page_popup,
|
| + 'type': 'text/html; charset=UTF-8'
|
| + }
|
| +
|
| + self._GetBenchmarkResource('start_page', handler)
|
| +
|
| + def _GetBenchmarkResource(self, resource, handler):
|
| + "Sends requested resource to browser."
|
| +
|
| + if resource in self.benchmark_resources:
|
| + resource = self.benchmark_resources[resource]
|
| + handler.send_response(200)
|
| + handler.send_header('content-length', len(resource['data']))
|
| + handler.send_header('content-type', resource['type'])
|
| + handler.end_headers()
|
| + handler.wfile.write(resource['data'])
|
| + else:
|
| + handler.send_response(404)
|
| + handler.end_headers()
|
| +
|
| + def _ProcessBenchmarkReport(self, content, handler):
|
| + "Reads benchmark score from report content and invokes callback."
|
| +
|
| + handler.send_response(204)
|
| + handler.end_headers()
|
| + content = json.loads(content)
|
| + if 'results' in content:
|
| + results = content['results']
|
| + sys.stdout.write('Results: %s\n' % results)
|
| + if self.test_callback: self.test_callback(results)
|
| + elif 'error' in content:
|
| + sys.stderr.write('Error: %s\n' % content['error'])
|
| +
|
| + def _GetApplicationResource(self, handler):
|
| + "Searches for response in cache. If not found, responds with 204."
|
| + key = (handler.command, handler.path)
|
| + if key in self.cache:
|
| + sys.stdout.write('%s %s -> found\n' % key)
|
| + handler.wfile.write(self.cache[key]['response'])
|
| + else:
|
| + sys.stderr.write('%s %s -> not found\n' % key)
|
| + handler.send_response(204, "not in cache")
|
| + handler.end_headers()
|
|
|