Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: tools/python/google/webpagereplay_utils.py

Issue 9956045: Add Web Page Replay test to page cycler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Windows compile error. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/page_cycler/webpagereplay/tests/2012Q2.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """A class to help start/stop a Web Page Replay Server.
7
8 The page cycler tests use this module to run Web Page Replay
9 (see tools/build/scripts/slave/runtest.py).
10
11 If run from the command-line, the module will launch Web Page Replay
12 and the specified test:
13
14 ./webpagereplay_utils.py --help # list options
15 ./webpagereplay_utils.py 2012Q2 # run a WPR-enabled test
16 """
17
18 import logging
19 import optparse
20 import os
21 import shutil
22 import signal
23 import subprocess
24 import sys
25 import tempfile
26 import time
27 import urllib
28
29
30 USAGE = '%s [options] CHROME_EXE TEST_NAME' % os.path.basename(sys.argv[0])
31 USER_DATA_DIR = '{TEMP}/webpagereplay_utils-chrome'
32
33 # The port numbers must match those in chrome/test/perf/page_cycler_test.cc.
34 HTTP_PORT = 8080
35 HTTPS_PORT = 8413
36
37
38 class ReplayError(Exception):
39 """Catch-all exception for the module."""
40 pass
41
42 class ReplayNotFoundError(Exception):
43 pass
44
45 class ReplayNotStartedError(Exception):
46 pass
47
48
49 class ReplayLauncher(object):
50 LOG_FILE = 'log.txt'
51
52 def __init__(self, replay_dir, archive_path, log_dir, replay_options=None):
53 """Initialize ReplayLauncher.
54
55 Args:
56 replay_dir: directory that has replay.py and related modules.
57 archive_path: either a directory that contains WPR archives or,
58 a path to a specific WPR archive.
59 log_dir: where to write log.txt.
60 replay_options: a list of options strings to forward to replay.py.
61 """
62 self.replay_dir = replay_dir
63 self.archive_path = archive_path
64 self.log_dir = log_dir
65 self.replay_options = replay_options if replay_options else []
66
67 self.log_name = os.path.join(self.log_dir, self.LOG_FILE)
68 self.log_fh = None
69 self.proxy_process = None
70
71 self.wpr_py = os.path.join(self.replay_dir, 'replay.py')
72 if not os.path.exists(self.wpr_py):
73 raise ReplayNotFoundError('Path does not exist: %s' % self.wpr_py)
74 self.wpr_options = [
75 '--port', str(HTTP_PORT),
76 '--ssl_port', str(HTTPS_PORT),
77 '--use_closest_match',
78 # TODO(slamm): Add traffic shaping (requires root):
79 # '--net', 'fios',
80 ]
81 self.wpr_options.extend(self.replay_options)
82
83 def _OpenLogFile(self):
84 if not os.path.exists(self.log_dir):
85 os.makedirs(self.log_dir)
86 return open(self.log_name, 'w')
87
88 def StartServer(self):
89 cmd_line = [self.wpr_py]
90 cmd_line.extend(self.wpr_options)
91 # TODO(slamm): Support choosing archive on-the-fly.
92 cmd_line.append(self.archive_path)
93 self.log_fh = self._OpenLogFile()
94 logging.debug('Starting Web-Page-Replay: %s', cmd_line)
95 self.proxy_process = subprocess.Popen(
96 cmd_line, stdout=self.log_fh, stderr=subprocess.STDOUT)
97 if not self.IsStarted():
98 raise ReplayNotStartedError(
99 'Web Page Replay failed to start. See the log file: ' + self.log_name)
100
101 def IsStarted(self):
102 """Checks to see if the server is up and running."""
103 for _ in range(5):
104 if self.proxy_process.poll() is not None:
105 # The process has exited.
106 break
107 try:
108 up_url = '%s://localhost:%s/web-page-replay-generate-200'
109 http_up_url = up_url % ('http', HTTP_PORT)
110 https_up_url = up_url % ('https', HTTPS_PORT)
111 if (200 == urllib.urlopen(http_up_url, None, {}).getcode() and
112 200 == urllib.urlopen(https_up_url, None, {}).getcode()):
113 return True
114 except IOError:
115 time.sleep(1)
116 return False
117
118 def StopServer(self):
119 if self.proxy_process:
120 logging.debug('Stopping Web-Page-Replay')
121 # Use a SIGINT here so that it can do graceful cleanup.
122 # Otherwise, we will leave subprocesses hanging.
123 self.proxy_process.send_signal(signal.SIGINT)
124 self.proxy_process.wait()
125 if self.log_fh:
126 self.log_fh.close()
127
128
129 class ChromiumPaths(object):
130 """Collect all the path handling together."""
131 PATHS = {
132 'archives': 'src/data/page_cycler/webpagereplay',
133 '.wpr': 'src/data/page_cycler/webpagereplay/{TEST_NAME}.wpr',
134 '.wpr_alt': 'src/tools/page_cycler/webpagereplay/tests/{TEST_NAME}.wpr',
135 'start.html': 'src/tools/page_cycler/webpagereplay/start.html',
136 'extension': 'src/tools/page_cycler/webpagereplay/extension',
137 'logs': 'src/webpagereplay_logs/{TEST_EXE_NAME}',
138 'replay': 'tools/build/third_party/webpagereplay',
139 }
140
141 def __init__(self, **replacements):
142 """Initialize ChromiumPaths.
143
144 Args:
145 replacements: a dict of format replacements for PATHS such as
146 {'TEST_NAME': '2012Q2', 'TEST_EXE_NAME': 'performance_ui_tests'}.
147 """
148 module_dir = os.path.dirname(__file__)
149 self.base_dir = os.path.abspath(os.path.join(
150 module_dir, '..', '..', '..', '..'))
151 self.replacements = replacements
152
153 def __getitem__(self, key):
154 path_parts = [x.format(**self.replacements)
155 for x in self.PATHS[key].split('/')]
156 return os.path.join(self.base_dir, *path_parts)
157
158
159 def LaunchChromium(chrome_exe, chromium_paths, test_name,
160 is_dns_forwarded, use_auto):
161 """Launch chromium to run WPR-backed page cycler tests.
162
163 These options need to be kept in sync with
164 src/chrome/test/perf/page_cycler_test.cc.
165 """
166 REPLAY_HOST='127.0.0.1'
167 user_data_dir = USER_DATA_DIR.format(**{'TEMP': tempfile.gettempdir()})
168 chromium_args = [
169 chrome_exe,
170 '--load-extension=%s' % chromium_paths['extension'],
171 '--testing-fixed-http-port=%s' % HTTP_PORT,
172 '--testing-fixed-https-port=%s' % HTTPS_PORT,
173 '--disable-background-networking',
174 '--enable-experimental-extension-apis',
175 '--enable-file-cookies',
176 '--enable-logging',
177 '--log-level=0',
178 '--enable-stats-table',
179 '--enable-benchmarking',
180 '--ignore-certificate-errors',
181 '--metrics-recording-only',
182 '--activate-on-launch',
183 '--no-first-run',
184 '--no-proxy-server',
185 '--user-data-dir=%s' % user_data_dir,
186 '--window-size=1280,1024',
187 ]
188 if not is_dns_forwarded:
189 chromium_args.append('--host-resolver-rules=MAP * %s' % REPLAY_HOST)
190 start_url = 'file://%s?test=%s' % (chromium_paths['start.html'], test_name)
191 if use_auto:
192 start_url += '&auto=1'
193 chromium_args.append(start_url)
194 if os.path.exists(user_data_dir):
195 shutil.rmtree(user_data_dir)
196 os.makedirs(user_data_dir)
197 try:
198 logging.debug('Starting Chrome: %s', chromium_args)
199 retval = subprocess.call(chromium_args)
200 finally:
201 shutil.rmtree(user_data_dir)
202
203
204 def main():
205 log_level = logging.DEBUG
206 logging.basicConfig(level=log_level,
207 format='%(asctime)s %(filename)s:%(lineno)-3d'
208 ' %(levelname)s %(message)s',
209 datefmt='%y%m%d %H:%M:%S')
210
211 option_parser = optparse.OptionParser(usage=USAGE)
212 option_parser.add_option(
213 '', '--auto', action='store_true', default=False,
214 help='Start test automatically.')
215 option_parser.add_option(
216 '', '--replay-dir', default=None,
217 help='Run replay from this directory instead of tools/build/third_party.')
218 replay_group = optparse.OptionGroup(option_parser,
219 'Options for replay.py', 'These options are passed through to replay.py.')
220 replay_group.add_option(
221 '', '--record', action='store_true', default=False,
222 help='Record a new WPR archive.')
223 replay_group.add_option( # use default that does not require sudo
224 '', '--dns_forwarding', default=False, action='store_true',
225 help='Forward DNS requests to the local replay server.')
226 option_parser.add_option_group(replay_group)
227 options, args = option_parser.parse_args()
228 if len(args) != 2:
229 option_parser.error('Need CHROME_EXE and TEST_NAME.')
230 return 1
231 chrome_exe, test_name = args
232
233 if not os.path.exists(chrome_exe):
234 print >>sys.stderr, 'Chrome path does not exist:', chrome_exe
235 return 1
236
237 chromium_paths = ChromiumPaths(
238 TEST_NAME=test_name,
239 TEST_EXE_NAME='webpagereplay_utils')
240 if os.path.exists(chromium_paths['archives']):
241 archive_path = chromium_paths['.wpr']
242 else:
243 archive_path = chromium_paths['.wpr_alt']
244 if not os.path.exists(archive_path) and not options.record:
245 print >>sys.stderr, 'Archive does not exist:', archive_path
246 return 1
247
248 replay_options = []
249 if options.record:
250 replay_options.append('--record')
251 if not options.dns_forwarding:
252 replay_options.append('--no-dns_forwarding')
253
254 if options.replay_dir:
255 replay_dir = options.replay_dir
256 else:
257 replay_dir = chromium_paths['replay']
258 wpr = ReplayLauncher(replay_dir, archive_path,
259 chromium_paths['logs'], replay_options)
260 try:
261 wpr.StartServer()
262 LaunchChromium(chrome_exe, chromium_paths, test_name,
263 options.dns_forwarding, options.auto)
264 finally:
265 wpr.StopServer()
266 return 0
267
268 if '__main__' == __name__:
269 sys.exit(main())
OLDNEW
« no previous file with comments | « tools/page_cycler/webpagereplay/tests/2012Q2.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698