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

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: Apply Dennis' suggestions 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
« no previous file with comments | « chrome/test/functional/perf.py ('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
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
8 Of the public module names, the following ones are key:
9 CHROME_FLAGS: Chrome options to make it work with Web Page Replay.
10 ReplayServer: a class to start/stop Web Page Replay.
11 """
7 12
8 import logging 13 import logging
9 import optparse
10 import os 14 import os
11 import shutil
12 import signal 15 import signal
13 import subprocess 16 import subprocess
14 import sys
15 import tempfile
16 import time 17 import time
17 import urllib 18 import urllib
18 19
19 20
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 21 HTTP_PORT = 8080
25 HTTPS_PORT = 8413 22 HTTPS_PORT = 8413
26 REPLAY_HOST='127.0.0.1' 23 REPLAY_HOST='127.0.0.1'
24 CHROME_FLAGS = [
25 '--host-resolver-rules=MAP * %s,EXCLUDE localhost' % REPLAY_HOST,
26 '--testing-fixed-http-port=%s' % HTTP_PORT,
27 '--testing-fixed-https-port=%s' % HTTPS_PORT,
28 '--ignore-certificate-errors',
29 ]
30
31 _CHROME_BASE_DIR = os.path.abspath(os.path.join(
32 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir))
33 REPLAY_DIR = os.path.join(
34 _CHROME_BASE_DIR, 'src', 'third_party', 'webpagereplay')
35 LOG_PATH = os.path.join(
36 _CHROME_BASE_DIR, 'src', 'webpagereplay_logs', 'logs.txt')
27 37
28 38
29 class ReplayError(Exception): 39 class ReplayError(Exception):
30 """Catch-all exception for the module.""" 40 """Catch-all exception for the module."""
31 pass 41 pass
32 42
33 class ReplayNotFoundError(ReplayError): 43 class ReplayNotFoundError(ReplayError):
34 pass 44 def __init__(self, label, path):
45 self.args = (label, path)
46
47 def __str__(self):
48 label, path = self.args
49 return 'Path does not exist for %s: %s' % (label, path)
35 50
36 class ReplayNotStartedError(ReplayError): 51 class ReplayNotStartedError(ReplayError):
37 pass 52 pass
38 53
39 54
40 class ReplayServer(object): 55 class ReplayServer(object):
41 """Start and Stop Web Page Replay. 56 """Start and Stop Web Page Replay.
42 57
58 Web Page Replay is a proxy that can record and "replay" web pages with
59 simulated network characteristics -- without having to edit the pages
60 by hand. With WPR, tests can use "real" web content, and catch
61 performance issues that may result from introducing network delays and
62 bandwidth throttling.
63
43 Example: 64 Example:
44 with ReplayServer(replay_dir, archive_path, log_dir, replay_options): 65 with ReplayServer(archive_path):
45 self.NavigateToURL(start_url) 66 self.NavigateToURL(start_url)
46 self.WaitUntil(...) 67 self.WaitUntil(...)
68
69 Environment Variables (for development):
70 WPR_ARCHIVE_PATH: path to alternate archive file (e.g. '/tmp/foo.wpr').
71 WPR_RECORD: if set, puts Web Page Replay in record mode instead of replay.
72 WPR_REPLAY_DIR: path to alternate Web Page Replay source.
47 """ 73 """
48 LOG_FILE = 'log.txt' 74 def __init__(self, archive_path, replay_options=None, replay_dir=None,
49 75 log_path=None):
50 def __init__(self, replay_dir, archive_path, log_dir, replay_options=None):
51 """Initialize ReplayServer. 76 """Initialize ReplayServer.
52 77
53 Args: 78 Args:
79 archive_path: a path to a specific WPR archive (required).
80 replay_options: a list of options strings to forward to replay.py.
54 replay_dir: directory that has replay.py and related modules. 81 replay_dir: directory that has replay.py and related modules.
55 archive_path: either a directory that contains WPR archives or, 82 log_path: a path to a log file.
56 a path to a specific WPR archive. 83 """
57 log_dir: where to write log.txt. 84 self.archive_path = os.environ.get('WPR_ARCHIVE_PATH', archive_path)
58 replay_options: a list of options strings to forward to replay.py. 85 self.replay_options = replay_options or []
59 """ 86 self.replay_dir = os.environ.get('WPR_REPLAY_DIR', replay_dir or REPLAY_DIR)
60 self.replay_dir = replay_dir 87 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 88
65 self.log_name = os.path.join(self.log_dir, self.LOG_FILE) 89 if 'WPR_RECORD' in os.environ and '--record' not in self.replay_options:
90 self.replay_options.append('--record')
91 self.is_record_mode = '--record' in self.replay_options
92 self._AddDefaultReplayOptions()
93
94 self.replay_py = os.path.join(self.replay_dir, 'replay.py')
95
96 if self.is_record_mode:
97 self._CheckPath('archive directory', os.path.dirname(self.archive_path))
98 elif not os.path.exists(self.archive_path):
99 self._CheckPath('archive file', self.archive_path)
100 self._CheckPath('replay script', self.replay_py)
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 """Set WPR command-line options. Can be overridden if needed."""
71 raise ReplayNotFoundError('Path does not exist: %s' % self.wpr_py) 107 self.replay_options += [
72 self.wpr_options = [
73 '--port', str(HTTP_PORT), 108 '--port', str(HTTP_PORT),
74 '--ssl_port', str(HTTPS_PORT), 109 '--ssl_port', str(HTTPS_PORT),
75 '--use_closest_match', 110 '--use_closest_match',
76 # TODO(slamm): Add traffic shaping (requires root): 111 '--no-dns_forwarding',
77 # '--net', 'fios', 112 # '--net', 'fios', # TODO(slamm): Add traffic shaping (requires root).
78 ] 113 ]
79 self.wpr_options.extend(self.replay_options) 114
115 def _CheckPath(self, label, path):
116 if not os.path.exists(path):
117 raise ReplayNotFoundError(label, path)
80 118
81 def _OpenLogFile(self): 119 def _OpenLogFile(self):
82 if not os.path.exists(self.log_dir): 120 log_dir = os.path.dirname(self.log_path)
83 os.makedirs(self.log_dir) 121 if not os.path.exists(log_dir):
84 return open(self.log_name, 'w') 122 os.makedirs(log_dir)
123 return open(self.log_path, 'w')
85 124
86 def IsStarted(self): 125 def IsStarted(self):
87 """Checks to see if the server is up and running.""" 126 """Checks to see if the server is up and running."""
88 for _ in range(5): 127 for _ in range(5):
89 if self.replay_process.poll() is not None: 128 if self.replay_process.poll() is not None:
90 # The process has exited. 129 # The process has exited.
91 break 130 break
92 try: 131 try:
93 up_url = '%s://localhost:%s/web-page-replay-generate-200' 132 up_url = '%s://localhost:%s/web-page-replay-generate-200'
94 http_up_url = up_url % ('http', HTTP_PORT) 133 http_up_url = up_url % ('http', HTTP_PORT)
95 https_up_url = up_url % ('https', HTTPS_PORT) 134 https_up_url = up_url % ('https', HTTPS_PORT)
96 if (200 == urllib.urlopen(http_up_url, None, {}).getcode() and 135 if (200 == urllib.urlopen(http_up_url, None, {}).getcode() and
97 200 == urllib.urlopen(https_up_url, None, {}).getcode()): 136 200 == urllib.urlopen(https_up_url, None, {}).getcode()):
98 return True 137 return True
99 except IOError: 138 except IOError:
100 time.sleep(1) 139 time.sleep(1)
101 return False 140 return False
102 141
103 def StartServer(self): 142 def StartServer(self):
104 """Start Web Page Replay and verify that it started. 143 """Start Web Page Replay and verify that it started.
105 144
106 Raises: 145 Raises:
107 ReplayNotStartedError if Replay start-up fails. 146 ReplayNotStartedError if Replay start-up fails.
108 """ 147 """
109 cmd_line = [self.wpr_py] 148 cmd_line = [self.replay_py]
110 cmd_line.extend(self.wpr_options) 149 cmd_line.extend(self.replay_options)
111 cmd_line.append(self.archive_path) 150 cmd_line.append(self.archive_path)
112 self.log_fh = self._OpenLogFile() 151 self.log_fh = self._OpenLogFile()
113 logging.debug('Starting Web-Page-Replay: %s', cmd_line) 152 logging.debug('Starting Web-Page-Replay: %s', cmd_line)
114 self.replay_process = subprocess.Popen( 153 self.replay_process = subprocess.Popen(
115 cmd_line, stdout=self.log_fh, stderr=subprocess.STDOUT) 154 cmd_line, stdout=self.log_fh, stderr=subprocess.STDOUT)
116 if not self.IsStarted(): 155 if not self.IsStarted():
117 raise ReplayNotStartedError( 156 raise ReplayNotStartedError(
118 'Web Page Replay failed to start. See the log file: ' + self.log_name) 157 'Web Page Replay failed to start. See the log file: ' + self.log_name)
119 158
120 def StopServer(self): 159 def StopServer(self):
121 """Stop Web Page Replay.""" 160 """Stop Web Page Replay."""
122 if self.replay_process: 161 if self.replay_process:
123 logging.debug('Stopping Web-Page-Replay') 162 logging.debug('Stopping Web-Page-Replay')
124 # Use a SIGINT here so that it can do graceful cleanup. 163 # Use a SIGINT here so that it can do graceful cleanup.
125 # Otherwise, we will leave subprocesses hanging. 164 # Otherwise, we will leave subprocesses hanging.
126 self.replay_process.send_signal(signal.SIGINT) 165 self.replay_process.send_signal(signal.SIGINT)
127 self.replay_process.wait() 166 self.replay_process.wait()
128 if self.log_fh: 167 if self.log_fh:
129 self.log_fh.close() 168 self.log_fh.close()
130 169
131 def __enter__(self): 170 def __enter__(self):
132 """Add support for with-statement.""" 171 """Add support for with-statement."""
133 self.StartServer() 172 self.StartServer()
173 return self
134 174
135 def __exit__(self, unused_exc_type, unused_exc_val, unused_exc_tb): 175 def __exit__(self, unused_exc_type, unused_exc_val, unused_exc_tb):
136 """Add support for with-statement.""" 176 """Add support for with-statement."""
137 self.StopServer() 177 self.StopServer()
OLDNEW
« no previous file with comments | « chrome/test/functional/perf.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698