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

Side by Side Diff: chrome/test/functional/webpagereplay.py

Issue 10411011: Add Web Page Replay enabled page cycler tests to pyauto. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 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
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """A class to help start/stop a Web Page Replay Server. 6 """A class to help start/stop a Web Page Replay Server.
7 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 8 If run from the command-line, the module will launch Web Page Replay
12 and the specified test: 9 and the specified test:
13 10
14 ./webpagereplay_utils.py --help # list options 11 python webpagereplay.py --help # list options
15 ./webpagereplay_utils.py 2012Q2 # run a WPR-enabled test 12 python webpagereplay.py CHROME_EXE 2012Q2 # run a WPR-enabled test
16 """ 13 """
17 14
18 import logging 15 import logging
19 import optparse 16 import optparse
20 import os 17 import os
21 import shutil 18 import shutil
22 import signal 19 import signal
23 import subprocess 20 import subprocess
24 import sys 21 import sys
25 import tempfile 22 import tempfile
26 import time 23 import time
27 import urllib 24 import urllib
28 25
29 26
30 USAGE = '%s [options] CHROME_EXE TEST_NAME' % os.path.basename(sys.argv[0]) 27 USAGE = '%s [options] CHROME_EXE TEST_NAME' % os.path.basename(sys.argv[0])
31 USER_DATA_DIR = '{TEMP}/webpagereplay_utils-chrome' 28 USER_DATA_DIR = '{TEMP}/webpagereplay_utils-chrome'
32 29
33 # The port numbers must match those in chrome/test/perf/page_cycler_test.cc. 30 # The port numbers must match those in chrome/test/perf/page_cycler_test.cc.
34 HTTP_PORT = 8080 31 HTTP_PORT = 8080
35 HTTPS_PORT = 8413 32 HTTPS_PORT = 8413
33 REPLAY_HOST='127.0.0.1'
36 34
37 35
38 class ReplayError(Exception): 36 class ReplayError(Exception):
39 """Catch-all exception for the module.""" 37 """Catch-all exception for the module."""
40 pass 38 pass
41 39
42 class ReplayNotFoundError(Exception): 40 class ReplayNotFoundError(Exception):
43 pass 41 pass
44 42
45 class ReplayNotStartedError(Exception): 43 class ReplayNotStartedError(Exception):
46 pass 44 pass
47 45
48 46
49 class ReplayLauncher(object): 47 class ReplayServer(object):
tonyg 2012/05/18 15:37:54 Probably worth a brief comment explaining how this
slamm_google 2012/05/18 23:59:29 Done.
50 LOG_FILE = 'log.txt' 48 LOG_FILE = 'log.txt'
51 49
52 def __init__(self, replay_dir, archive_path, log_dir, replay_options=None): 50 def __init__(self, replay_dir, archive_path, log_dir, replay_options=None):
53 """Initialize ReplayLauncher. 51 """Initialize ReplayServer.
54 52
55 Args: 53 Args:
56 replay_dir: directory that has replay.py and related modules. 54 replay_dir: directory that has replay.py and related modules.
57 archive_path: either a directory that contains WPR archives or, 55 archive_path: either a directory that contains WPR archives or,
58 a path to a specific WPR archive. 56 a path to a specific WPR archive.
59 log_dir: where to write log.txt. 57 log_dir: where to write log.txt.
60 replay_options: a list of options strings to forward to replay.py. 58 replay_options: a list of options strings to forward to replay.py.
61 """ 59 """
62 self.replay_dir = replay_dir 60 self.replay_dir = replay_dir
63 self.archive_path = archive_path 61 self.archive_path = archive_path
(...skipping 14 matching lines...) Expand all
78 # TODO(slamm): Add traffic shaping (requires root): 76 # TODO(slamm): Add traffic shaping (requires root):
79 # '--net', 'fios', 77 # '--net', 'fios',
80 ] 78 ]
81 self.wpr_options.extend(self.replay_options) 79 self.wpr_options.extend(self.replay_options)
82 80
83 def _OpenLogFile(self): 81 def _OpenLogFile(self):
84 if not os.path.exists(self.log_dir): 82 if not os.path.exists(self.log_dir):
85 os.makedirs(self.log_dir) 83 os.makedirs(self.log_dir)
86 return open(self.log_name, 'w') 84 return open(self.log_name, 'w')
87 85
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): 86 def IsStarted(self):
102 """Checks to see if the server is up and running.""" 87 """Checks to see if the server is up and running."""
103 for _ in range(5): 88 for _ in range(5):
104 if self.proxy_process.poll() is not None: 89 if self.proxy_process.poll() is not None:
105 # The process has exited. 90 # The process has exited.
106 break 91 break
107 try: 92 try:
108 up_url = '%s://localhost:%s/web-page-replay-generate-200' 93 up_url = '%s://localhost:%s/web-page-replay-generate-200'
109 http_up_url = up_url % ('http', HTTP_PORT) 94 http_up_url = up_url % ('http', HTTP_PORT)
110 https_up_url = up_url % ('https', HTTPS_PORT) 95 https_up_url = up_url % ('https', HTTPS_PORT)
111 if (200 == urllib.urlopen(http_up_url, None, {}).getcode() and 96 if (200 == urllib.urlopen(http_up_url, None, {}).getcode() and
112 200 == urllib.urlopen(https_up_url, None, {}).getcode()): 97 200 == urllib.urlopen(https_up_url, None, {}).getcode()):
113 return True 98 return True
114 except IOError: 99 except IOError:
115 time.sleep(1) 100 time.sleep(1)
116 return False 101 return False
117 102
118 def StopServer(self): 103 def __enter__(self):
104 cmd_line = [self.wpr_py]
105 cmd_line.extend(self.wpr_options)
106 # TODO(slamm): Support choosing archive on-the-fly.
107 cmd_line.append(self.archive_path)
108 self.log_fh = self._OpenLogFile()
109 logging.debug('Starting Web-Page-Replay: %s', cmd_line)
110 self.proxy_process = subprocess.Popen(
111 cmd_line, stdout=self.log_fh, stderr=subprocess.STDOUT)
112 if not self.IsStarted():
113 raise ReplayNotStartedError(
114 'Web Page Replay failed to start. See the log file: ' + self.log_name)
115
116 def __exit__(self, unused_exc_type, unused_exc_val, unused_exc_tb):
119 if self.proxy_process: 117 if self.proxy_process:
120 logging.debug('Stopping Web-Page-Replay') 118 logging.debug('Stopping Web-Page-Replay')
121 # Use a SIGINT here so that it can do graceful cleanup. 119 # Use a SIGINT here so that it can do graceful cleanup.
122 # Otherwise, we will leave subprocesses hanging. 120 # Otherwise, we will leave subprocesses hanging.
123 self.proxy_process.send_signal(signal.SIGINT) 121 self.proxy_process.send_signal(signal.SIGINT)
124 self.proxy_process.wait() 122 self.proxy_process.wait()
125 if self.log_fh: 123 if self.log_fh:
126 self.log_fh.close() 124 self.log_fh.close()
127 125
128 126
129 class ChromiumPaths(object): 127 class ChromiumPaths(object):
130 """Collect all the path handling together.""" 128 """Collect all the path handling together."""
131 PATHS = { 129 PATHS = {
132 'archives': 'src/data/page_cycler/webpagereplay', 130 'archives': 'src/data/page_cycler/webpagereplay',
133 '.wpr': 'src/data/page_cycler/webpagereplay/{TEST_NAME}.wpr', 131 '.wpr': 'src/data/page_cycler/webpagereplay/{TEST_NAME}.wpr',
134 '.wpr_alt': 'src/tools/page_cycler/webpagereplay/tests/{TEST_NAME}.wpr', 132 '.wpr_alt': 'src/tools/page_cycler/webpagereplay/tests/{TEST_NAME}.wpr',
135 'start.html': 'src/tools/page_cycler/webpagereplay/start.html', 133 'start_url': ('src/tools/page_cycler/webpagereplay/start.html'
134 '?test={TEST_NAME}'),
136 'extension': 'src/tools/page_cycler/webpagereplay/extension', 135 'extension': 'src/tools/page_cycler/webpagereplay/extension',
137 'replay': 'src/third_party/webpagereplay', 136 'replay': 'src/third_party/webpagereplay',
138 'logs': 'src/webpagereplay_logs/{TEST_EXE_NAME}', 137 'logs': 'src/webpagereplay_logs/{TEST_EXE_NAME}',
139 } 138 }
140 139
141 def __init__(self, **replacements): 140 def __init__(self, **replacements):
142 """Initialize ChromiumPaths. 141 """Initialize ChromiumPaths.
143 142
144 Args: 143 Args:
145 replacements: a dict of format replacements for PATHS such as 144 replacements: a dict of format replacements for PATHS such as
146 {'TEST_NAME': '2012Q2', 'TEST_EXE_NAME': 'performance_ui_tests'}. 145 {'TEST_NAME': '2012Q2', 'TEST_EXE_NAME': 'performance_ui_tests'}.
147 """ 146 """
148 module_dir = os.path.dirname(__file__) 147 module_dir = os.path.dirname(__file__)
149 self.base_dir = os.path.abspath(os.path.join( 148 self.base_dir = os.path.abspath(os.path.join(
150 module_dir, '..', '..', '..', '..')) 149 module_dir, '..', '..', '..', '..'))
151 self.replacements = replacements 150 self.replacements = replacements
152 151
152 def GetArchivePath(self):
153 if os.path.exists(self['archives']):
154 return self['.wpr']
155 return self['.wpr_alt']
156
157 def GetStartUrl(self, iterations=None, use_auto=False):
158 start_url = self['start_url']
159 if iterations is not None:
160 start_url += '&iterations=%d' % iterations
161 if use_auto:
162 start_url += '&auto=1'
163 return start_url
164
153 def __getitem__(self, key): 165 def __getitem__(self, key):
154 path_parts = [x.format(**self.replacements) 166 path_parts = [x.format(**self.replacements)
155 for x in self.PATHS[key].split('/')] 167 for x in self.PATHS[key].split('/')]
156 return os.path.join(self.base_dir, *path_parts) 168 return os.path.join(self.base_dir, *path_parts)
157 169
158 170
159 def LaunchChromium(chrome_exe, chromium_paths, test_name, 171 def ChromeFlags(existing_flags=None, extension_path=None,
172 is_dns_forwarded=False):
173 flags = []
174 if existing_flags:
175 flags.extend(existing_flags)
176 if extension_path:
177 flags.append('--load-extension=%s' % extension_path)
178 if not is_dns_forwarded:
179 flags.append('--host-resolver-rules=MAP * %s' % REPLAY_HOST)
180 flags.extend([
181 '--testing-fixed-http-port=%s' % HTTP_PORT,
182 '--testing-fixed-https-port=%s' % HTTPS_PORT,
183 '--log-level=0',
184 ])
185 extra_flags = [
186 '--disable-background-networking',
187 '--enable-experimental-extension-apis',
188 '--enable-file-cookies',
tonyg 2012/05/18 15:37:54 This one isn't necessary since we aren't using fil
slamm_google 2012/05/18 23:59:29 The start URL is a file URL, and that is where the
189 '--enable-logging',
190 '--enable-stats-table',
191 '--enable-benchmarking',
192 '--ignore-certificate-errors',
193 '--metrics-recording-only',
194 '--activate-on-launch',
195 '--no-first-run',
196 '--no-proxy-server',
197 ]
198 flags.extend(f for f in extra_flags if f not in flags)
199 return flags
200
201
202 def LaunchChrome(chrome_exe, chromium_paths, test_name,
160 is_dns_forwarded, use_auto): 203 is_dns_forwarded, use_auto):
161 """Launch chromium to run WPR-backed page cycler tests. 204 """Launch chrome to run WPR-backed page cycler tests.
162 205
163 These options need to be kept in sync with 206 These options need to be kept in sync with
164 src/chrome/test/perf/page_cycler_test.cc. 207 src/chrome/test/perf/page_cycler_test.cc.
165 """ 208 """
166 REPLAY_HOST='127.0.0.1'
167 user_data_dir = USER_DATA_DIR.format(**{'TEMP': tempfile.gettempdir()}) 209 user_data_dir = USER_DATA_DIR.format(**{'TEMP': tempfile.gettempdir()})
168 chromium_args = [ 210 chromium_args = [
169 chrome_exe, 211 chrome_exe,
170 '--load-extension=%s' % chromium_paths['extension'], 212 '--load-extension=%s' % chromium_paths['extension'],
171 '--testing-fixed-http-port=%s' % HTTP_PORT, 213 '--testing-fixed-http-port=%s' % HTTP_PORT,
172 '--testing-fixed-https-port=%s' % HTTPS_PORT, 214 '--testing-fixed-https-port=%s' % HTTPS_PORT,
173 '--disable-background-networking', 215 '--disable-background-networking',
174 '--enable-experimental-extension-apis', 216 '--enable-experimental-extension-apis',
175 '--enable-file-cookies', 217 '--enable-file-cookies',
176 '--enable-logging', 218 '--enable-logging',
177 '--log-level=0', 219 '--log-level=0',
178 '--enable-stats-table', 220 '--enable-stats-table',
179 '--enable-benchmarking', 221 '--enable-benchmarking',
180 '--ignore-certificate-errors', 222 '--ignore-certificate-errors',
181 '--metrics-recording-only', 223 '--metrics-recording-only',
182 '--activate-on-launch', 224 '--activate-on-launch',
183 '--no-first-run', 225 '--no-first-run',
184 '--no-proxy-server', 226 '--no-proxy-server',
slamm_google 2012/05/18 00:20:24 This list will go away in favor of the one above.
227
228
185 '--user-data-dir=%s' % user_data_dir, 229 '--user-data-dir=%s' % user_data_dir,
186 '--window-size=1280,1024', 230 '--window-size=1280,1024',
187 ] 231 ]
188 if not is_dns_forwarded: 232 if not is_dns_forwarded:
189 chromium_args.append('--host-resolver-rules=MAP * %s' % REPLAY_HOST) 233 chromium_args.append('--host-resolver-rules=MAP * %s' % REPLAY_HOST)
190 start_url = 'file://%s?test=%s' % (chromium_paths['start.html'], test_name) 234 start_url = chromium_paths.GetStartUrl(test_name, use_auto=use_auto)
191 if use_auto:
192 start_url += '&auto=1'
193 chromium_args.append(start_url) 235 chromium_args.append(start_url)
194 if os.path.exists(user_data_dir): 236 if os.path.exists(user_data_dir):
195 shutil.rmtree(user_data_dir) 237 shutil.rmtree(user_data_dir)
196 os.makedirs(user_data_dir) 238 os.makedirs(user_data_dir)
197 try: 239 try:
198 logging.debug('Starting Chrome: %s', chromium_args) 240 logging.debug('Starting Chrome: %s', chromium_args)
199 retval = subprocess.call(chromium_args) 241 retval = subprocess.call(chromium_args)
200 finally: 242 finally:
201 shutil.rmtree(user_data_dir) 243 shutil.rmtree(user_data_dir)
202 244
203 245
204 def main(): 246 def main():
tonyg 2012/05/18 15:37:54 Any reason not to just remove main entirely in thi
slamm_google 2012/05/18 23:59:29 Ah, nice to toss this.
205 log_level = logging.DEBUG 247 log_level = logging.DEBUG
206 logging.basicConfig(level=log_level, 248 logging.basicConfig(level=log_level,
207 format='%(asctime)s %(filename)s:%(lineno)-3d' 249 format='%(asctime)s %(filename)s:%(lineno)-3d'
208 ' %(levelname)s %(message)s', 250 ' %(levelname)s %(message)s',
209 datefmt='%y%m%d %H:%M:%S') 251 datefmt='%y%m%d %H:%M:%S')
210 252
211 option_parser = optparse.OptionParser(usage=USAGE) 253 option_parser = optparse.OptionParser(usage=USAGE)
212 option_parser.add_option( 254 option_parser.add_option(
213 '', '--auto', action='store_true', default=False, 255 '', '--auto', action='store_true', default=False,
214 help='Start test automatically.') 256 help='Start test automatically.')
(...skipping 15 matching lines...) Expand all
230 return 1 272 return 1
231 chrome_exe, test_name = args 273 chrome_exe, test_name = args
232 274
233 if not os.path.exists(chrome_exe): 275 if not os.path.exists(chrome_exe):
234 print >>sys.stderr, 'Chrome path does not exist:', chrome_exe 276 print >>sys.stderr, 'Chrome path does not exist:', chrome_exe
235 return 1 277 return 1
236 278
237 chromium_paths = ChromiumPaths( 279 chromium_paths = ChromiumPaths(
238 TEST_NAME=test_name, 280 TEST_NAME=test_name,
239 TEST_EXE_NAME='webpagereplay_utils') 281 TEST_EXE_NAME='webpagereplay_utils')
240 if os.path.exists(chromium_paths['archives']): 282 archive_path = chromium_paths.GetArchivePath()
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: 283 if not os.path.exists(archive_path) and not options.record:
245 print >>sys.stderr, 'Archive does not exist:', archive_path 284 print >>sys.stderr, 'Archive does not exist:', archive_path
246 return 1 285 return 1
247 286
248 replay_options = [] 287 replay_options = []
249 if options.record: 288 if options.record:
250 replay_options.append('--record') 289 replay_options.append('--record')
251 if not options.dns_forwarding: 290 if not options.dns_forwarding:
252 replay_options.append('--no-dns_forwarding') 291 replay_options.append('--no-dns_forwarding')
253 292
254 if options.replay_dir: 293 if options.replay_dir:
255 replay_dir = options.replay_dir 294 replay_dir = options.replay_dir
256 else: 295 else:
257 replay_dir = chromium_paths['replay'] 296 replay_dir = chromium_paths['replay']
258 wpr = ReplayLauncher(replay_dir, archive_path, 297 with ReplayServer(
259 chromium_paths['logs'], replay_options) 298 replay_dir, archive_path, chromium_paths['logs'], replay_options):
260 try: 299 LaunchChrome(chrome_exe, chromium_paths, test_name,
261 wpr.StartServer() 300 options.dns_forwarding, options.auto)
262 LaunchChromium(chrome_exe, chromium_paths, test_name,
263 options.dns_forwarding, options.auto)
264 finally:
265 wpr.StopServer()
266 return 0 301 return 0
267 302
268 if '__main__' == __name__: 303 if '__main__' == __name__:
269 sys.exit(main()) 304 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698