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

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