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

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

Issue 10825025: Make it easy to use Web Page Replay with non-page_cycler tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rename PageCyclerWebPageReplay to shorter PageCyclerReplay. Created 8 years, 4 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 """Start and stop Web Page Replay.""" 6 """Start and stop Web Page Replay."""
7 7
8 import logging 8 import logging
9 import optparse
10 import os 9 import os
11 import shutil
12 import signal 10 import signal
13 import subprocess 11 import subprocess
14 import sys
15 import tempfile
16 import time 12 import time
17 import urllib 13 import urllib
18 14
19 15
20 USAGE = '%s [options] CHROME_EXE TEST_NAME' % os.path.basename(sys.argv[0])
21 USER_DATA_DIR = '{TEMP}/webpagereplay_utils-chrome'
22
23 # The port numbers must match those in chrome/test/perf/page_cycler_test.cc.
24 HTTP_PORT = 8080 16 HTTP_PORT = 8080
25 HTTPS_PORT = 8413 17 HTTPS_PORT = 8413
26 REPLAY_HOST='127.0.0.1' 18 REPLAY_HOST='127.0.0.1'
19 CHROME_FLAGS = [
20 '--host-resolver-rules=MAP * %s,EXCLUDE localhost' % REPLAY_HOST,
21 '--testing-fixed-http-port=%s' % HTTP_PORT,
22 '--testing-fixed-https-port=%s' % HTTPS_PORT,
23 '--ignore-certificate-errors',
24 ]
25
26 _BASE_DIR = os.path.abspath(os.path.join(
27 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir))
28 REPLAY_DIR = os.path.join(_BASE_DIR, 'src', 'third_party', 'webpagereplay')
29 LOG_PATH = os.path.join(_BASE_DIR, 'src', 'webpagereplay_logs', 'logs.txt')
27 30
28 31
29 class ReplayError(Exception): 32 class ReplayError(Exception):
30 """Catch-all exception for the module.""" 33 """Catch-all exception for the module."""
31 pass 34 pass
32 35
33 class ReplayNotFoundError(ReplayError): 36 class ReplayNotFoundError(ReplayError):
34 pass 37 pass
35 38
36 class ReplayNotStartedError(ReplayError): 39 class ReplayNotStartedError(ReplayError):
37 pass 40 pass
38 41
39 42
43 def FormatChromiumPath(posix_path, **kwargs):
slamm_google 2012/07/26 23:46:59 How about I move this to perf.py:PageCyclerReplay
fdeng1 2012/07/27 00:45:10 Yes, I agree it makes more sense to be that way. M
44 """Convert a path relative to the Chromium root into an OS-specific path.
45
46 Args:
47 posix_path: a path string that may be a format().
48 kwargs: args for the format replacement.
49 Examples:
50 FormatChromiumPath('src/third_party/pylib')
51 FormatChromiumPath('src/third_party/{module_name}/__init__.py',
52 module_name='pylib')
53 """
54 formated_path = posix_path.format(**kwargs)
55 path_parts = formated_path.split('/')
56 return os.path.join(_BASE_DIR, *path_parts)
57
58
40 class ReplayServer(object): 59 class ReplayServer(object):
41 """Start and Stop Web Page Replay. 60 """Start and Stop Web Page Replay.
42 61
62 Web Page Replay is a proxy that can record and "replay" web pages with
63 simulated network characteristics -- without having to edit the pages
64 by hand. With WPR, tests can use "real" web content, and catch
65 performance issues that may result from introducing network delays and
66 bandwidth throttling.
67
43 Example: 68 Example:
44 with ReplayServer(replay_dir, archive_path, log_dir, replay_options): 69 with ReplayServer(archive_path):
45 self.NavigateToURL(start_url) 70 self.NavigateToURL(start_url)
46 self.WaitUntil(...) 71 self.WaitUntil(...)
72
73 Environment Variables (for development):
74 WPR_ARCHIVE_PATH: path to alternate archive file (e.g. '/tmp/foo.wpr').
75 WPR_RECORD: if set, puts Web Page Replay in record mode instead of replay.
76 WPR_REPLAY_DIR: path to alternate Web Page Replay source.
47 """ 77 """
48 LOG_FILE = 'log.txt' 78 def __init__(self, archive_path, replay_options=None, replay_dir=None,
49 79 log_path=None):
50 def __init__(self, replay_dir, archive_path, log_dir, replay_options=None):
51 """Initialize ReplayServer. 80 """Initialize ReplayServer.
52 81
53 Args: 82 Args:
83 archive_path: a path to a specific WPR archive (required).
84 replay_options: a list of options strings to forward to replay.py.
54 replay_dir: directory that has replay.py and related modules. 85 replay_dir: directory that has replay.py and related modules.
55 archive_path: either a directory that contains WPR archives or, 86 log_path: a path to a log file.
56 a path to a specific WPR archive. 87 """
57 log_dir: where to write log.txt. 88 self.archive_path = os.environ.get('WPR_ARCHIVE_PATH', archive_path)
58 replay_options: a list of options strings to forward to replay.py. 89 self.replay_options = replay_options or []
59 """ 90 self.replay_dir = os.environ.get('WPR_REPLAY_DIR', replay_dir or REPLAY_DIR)
60 self.replay_dir = replay_dir 91 self.log_path = log_path or LOG_PATH
61 self.archive_path = archive_path
62 self.log_dir = log_dir
63 self.replay_options = replay_options if replay_options else []
64 92
65 self.log_name = os.path.join(self.log_dir, self.LOG_FILE) 93 if 'WPR_RECORD' in os.environ and '--record' not in self.replay_options:
94 replay_options.append('--record')
fdeng1 2012/07/26 20:51:19 -> self.replay.options.append('--record')
fdeng1 2012/07/26 20:52:51 sorry, should be self.replay_options.append(...) O
slamm_google 2012/07/26 23:46:59 Done.
95 self.is_record_mode = '--record' in self.replay_options
96 self._AddDefaultReplayOptions(self)
fdeng1 2012/07/26 20:51:19 remove the argument "self"?
slamm_google 2012/07/26 23:46:59 Done.
97
98 self.replay_py = os.path.join(self.replay_dir, 'replay.py')
99
100 self._CheckArgs()
101
66 self.log_fh = None 102 self.log_fh = None
67 self.replay_process = None 103 self.replay_process = None
68 104
69 self.wpr_py = os.path.join(self.replay_dir, 'replay.py') 105 def _AddDefaultReplayOptions(self):
70 if not os.path.exists(self.wpr_py): 106 self.replay_options += [
71 raise ReplayNotFoundError('Path does not exist: %s' % self.wpr_py)
72 self.wpr_options = [
73 '--port', str(HTTP_PORT), 107 '--port', str(HTTP_PORT),
74 '--ssl_port', str(HTTPS_PORT), 108 '--ssl_port', str(HTTPS_PORT),
75 '--use_closest_match', 109 '--use_closest_match',
76 # TODO(slamm): Add traffic shaping (requires root): 110 '--no-dns_forwarding',
77 # '--net', 'fios', 111 # '--net', 'fios', # TODO(slamm): Add traffic shaping (requires root).
78 ] 112 ]
79 self.wpr_options.extend(self.replay_options) 113
114 def _CheckArgs(self):
115 assert self.archive_path, 'Archive path is not set.'
116 if self.is_record_mode:
117 archive_dir = os.path.dirname(self.archive_path)
118 assert os.path.exists(archive_dir), \
119 'Archive directory does not exist: %s' % self.archive_dir
fdeng1 2012/07/26 20:51:19 self.archive_dir -> archive_dir
slamm_google 2012/07/26 23:46:59 I dropped the asserts in favor of raising exceptio
120 else:
121 assert os.path.exists(archive_path), \
122 'Archive file path does not exist: %s' % archive_path
fdeng1 2012/07/26 20:51:19 In above two lines: archive_path -> self.archive_p
123 if not os.path.exists(self.replay_py):
124 raise ReplayNotFoundError('Path does not exist: %s' % self.replay_py)
80 125
81 def _OpenLogFile(self): 126 def _OpenLogFile(self):
82 if not os.path.exists(self.log_dir): 127 log_dir = os.path.dirname(self.log_path)
83 os.makedirs(self.log_dir) 128 if not os.path.exists(log_dir):
84 return open(self.log_name, 'w') 129 os.makedirs(log_dir)
130 return open(self.log_path, 'w')
85 131
86 def IsStarted(self): 132 def IsStarted(self):
87 """Checks to see if the server is up and running.""" 133 """Checks to see if the server is up and running."""
88 for _ in range(5): 134 for _ in range(5):
89 if self.replay_process.poll() is not None: 135 if self.replay_process.poll() is not None:
90 # The process has exited. 136 # The process has exited.
91 break 137 break
92 try: 138 try:
93 up_url = '%s://localhost:%s/web-page-replay-generate-200' 139 up_url = '%s://localhost:%s/web-page-replay-generate-200'
94 http_up_url = up_url % ('http', HTTP_PORT) 140 http_up_url = up_url % ('http', HTTP_PORT)
95 https_up_url = up_url % ('https', HTTPS_PORT) 141 https_up_url = up_url % ('https', HTTPS_PORT)
96 if (200 == urllib.urlopen(http_up_url, None, {}).getcode() and 142 if (200 == urllib.urlopen(http_up_url, None, {}).getcode() and
97 200 == urllib.urlopen(https_up_url, None, {}).getcode()): 143 200 == urllib.urlopen(https_up_url, None, {}).getcode()):
98 return True 144 return True
99 except IOError: 145 except IOError:
100 time.sleep(1) 146 time.sleep(1)
101 return False 147 return False
102 148
103 def StartServer(self): 149 def StartServer(self):
104 """Start Web Page Replay and verify that it started. 150 """Start Web Page Replay and verify that it started.
105 151
106 Raises: 152 Raises:
107 ReplayNotStartedError if Replay start-up fails. 153 ReplayNotStartedError if Replay start-up fails.
108 """ 154 """
109 cmd_line = [self.wpr_py] 155 cmd_line = [self.replay_py]
110 cmd_line.extend(self.wpr_options) 156 cmd_line.extend(self.replay_options)
111 cmd_line.append(self.archive_path) 157 cmd_line.append(self.archive_path)
112 self.log_fh = self._OpenLogFile() 158 self.log_fh = self._OpenLogFile()
113 logging.debug('Starting Web-Page-Replay: %s', cmd_line) 159 logging.debug('Starting Web-Page-Replay: %s', cmd_line)
114 self.replay_process = subprocess.Popen( 160 self.replay_process = subprocess.Popen(
115 cmd_line, stdout=self.log_fh, stderr=subprocess.STDOUT) 161 cmd_line, stdout=self.log_fh, stderr=subprocess.STDOUT)
116 if not self.IsStarted(): 162 if not self.IsStarted():
117 raise ReplayNotStartedError( 163 raise ReplayNotStartedError(
118 'Web Page Replay failed to start. See the log file: ' + self.log_name) 164 'Web Page Replay failed to start. See the log file: ' + self.log_name)
119 165
120 def StopServer(self): 166 def StopServer(self):
121 """Stop Web Page Replay.""" 167 """Stop Web Page Replay."""
122 if self.replay_process: 168 if self.replay_process:
123 logging.debug('Stopping Web-Page-Replay') 169 logging.debug('Stopping Web-Page-Replay')
124 # Use a SIGINT here so that it can do graceful cleanup. 170 # Use a SIGINT here so that it can do graceful cleanup.
125 # Otherwise, we will leave subprocesses hanging. 171 # Otherwise, we will leave subprocesses hanging.
126 self.replay_process.send_signal(signal.SIGINT) 172 self.replay_process.send_signal(signal.SIGINT)
127 self.replay_process.wait() 173 self.replay_process.wait()
128 if self.log_fh: 174 if self.log_fh:
129 self.log_fh.close() 175 self.log_fh.close()
130 176
131 def __enter__(self): 177 def __enter__(self):
132 """Add support for with-statement.""" 178 """Add support for with-statement."""
133 self.StartServer() 179 self.StartServer()
134 180
135 def __exit__(self, unused_exc_type, unused_exc_val, unused_exc_tb): 181 def __exit__(self, unused_exc_type, unused_exc_val, unused_exc_tb):
136 """Add support for with-statement.""" 182 """Add support for with-statement."""
137 self.StopServer() 183 self.StopServer()
OLDNEW
« chrome/test/functional/perf.py ('K') | « chrome/test/functional/perf.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698