Index: chrome/test/functional/webpagereplay.py |
diff --git a/chrome/test/functional/webpagereplay.py b/chrome/test/functional/webpagereplay.py |
index 082b079b363d871600a1f8bb3398d6b5586eede0..b0910d92e3e9ed48c71fdedcd0c2721102856863 100755 |
--- a/chrome/test/functional/webpagereplay.py |
+++ b/chrome/test/functional/webpagereplay.py |
@@ -3,27 +3,36 @@ |
# Use of this source code is governed by a BSD-style license that can be |
# found in the LICENSE file. |
-"""Start and stop Web Page Replay.""" |
+"""Start and stop Web Page Replay. |
+ |
+Of the public module names, the following ones are key: |
+ CHROME_FLAGS: Chrome options to make it work with Web Page Replay. |
+ FormatChromiumPath: a convenience function to create OS-specific paths. |
+ ReplayServer: a class to start/stop Web Page Replay. |
+""" |
import logging |
-import optparse |
import os |
-import shutil |
import signal |
import subprocess |
-import sys |
-import tempfile |
import time |
import urllib |
-USAGE = '%s [options] CHROME_EXE TEST_NAME' % os.path.basename(sys.argv[0]) |
-USER_DATA_DIR = '{TEMP}/webpagereplay_utils-chrome' |
- |
-# The port numbers must match those in chrome/test/perf/page_cycler_test.cc. |
HTTP_PORT = 8080 |
HTTPS_PORT = 8413 |
REPLAY_HOST='127.0.0.1' |
+CHROME_FLAGS = [ |
+ '--host-resolver-rules=MAP * %s,EXCLUDE localhost' % REPLAY_HOST, |
+ '--testing-fixed-http-port=%s' % HTTP_PORT, |
+ '--testing-fixed-https-port=%s' % HTTPS_PORT, |
+ '--ignore-certificate-errors', |
+ ] |
+ |
+_BASE_DIR = os.path.abspath(os.path.join( |
+ os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir)) |
+REPLAY_DIR = os.path.join(_BASE_DIR, 'src', 'third_party', 'webpagereplay') |
+LOG_PATH = os.path.join(_BASE_DIR, 'src', 'webpagereplay_logs', 'logs.txt') |
class ReplayError(Exception): |
@@ -31,57 +40,102 @@ class ReplayError(Exception): |
pass |
class ReplayNotFoundError(ReplayError): |
- pass |
+ def __init__(self, label, path): |
+ self.args = (label, path) |
+ |
+ def __str__(self): |
+ label, path = self.args |
+ return 'Path does not exist for %s: %s' % (label, path) |
class ReplayNotStartedError(ReplayError): |
pass |
+def FormatChromiumPath(posix_path, **kwargs): |
+ """Convert a path relative to the Chromium root into an OS-specific path. |
+ |
+ Args: |
+ posix_path: a path string that may be a format(). |
+ Example: 'src/third_party/{module_name}/__init__.py' |
+ kwargs: args for the format replacement. |
+ Example: {'module_name': 'pylib'} |
+ Returns: |
+ an absolute path in the current Chromium tree with formatting applied. |
+ """ |
+ formated_path = posix_path.format(**kwargs) |
+ path_parts = formated_path.split('/') |
+ return os.path.join(_BASE_DIR, *path_parts) |
+ |
+ |
class ReplayServer(object): |
"""Start and Stop Web Page Replay. |
+ Web Page Replay is a proxy that can record and "replay" web pages with |
+ simulated network characteristics -- without having to edit the pages |
+ by hand. With WPR, tests can use "real" web content, and catch |
+ performance issues that may result from introducing network delays and |
+ bandwidth throttling. |
+ |
Example: |
- with ReplayServer(replay_dir, archive_path, log_dir, replay_options): |
+ with ReplayServer(archive_path): |
self.NavigateToURL(start_url) |
self.WaitUntil(...) |
- """ |
- LOG_FILE = 'log.txt' |
- def __init__(self, replay_dir, archive_path, log_dir, replay_options=None): |
+ Environment Variables (for development): |
+ WPR_ARCHIVE_PATH: path to alternate archive file (e.g. '/tmp/foo.wpr'). |
+ WPR_RECORD: if set, puts Web Page Replay in record mode instead of replay. |
+ WPR_REPLAY_DIR: path to alternate Web Page Replay source. |
+ """ |
+ def __init__(self, archive_path, replay_options=None, replay_dir=None, |
+ log_path=None): |
"""Initialize ReplayServer. |
Args: |
- replay_dir: directory that has replay.py and related modules. |
- archive_path: either a directory that contains WPR archives or, |
- a path to a specific WPR archive. |
- log_dir: where to write log.txt. |
+ archive_path: a path to a specific WPR archive (required). |
replay_options: a list of options strings to forward to replay.py. |
- """ |
- self.replay_dir = replay_dir |
- self.archive_path = archive_path |
- self.log_dir = log_dir |
- self.replay_options = replay_options if replay_options else [] |
+ replay_dir: directory that has replay.py and related modules. |
+ log_path: a path to a log file. |
+ """ |
+ self.archive_path = os.environ.get('WPR_ARCHIVE_PATH', archive_path) |
+ self.replay_options = replay_options or [] |
+ self.replay_dir = os.environ.get('WPR_REPLAY_DIR', replay_dir or REPLAY_DIR) |
+ self.log_path = log_path or LOG_PATH |
+ |
+ if 'WPR_RECORD' in os.environ and '--record' not in self.replay_options: |
+ self.replay_options.append('--record') |
+ self.is_record_mode = '--record' in self.replay_options |
+ self._AddDefaultReplayOptions() |
+ |
+ self.replay_py = os.path.join(self.replay_dir, 'replay.py') |
+ |
+ if self.is_record_mode: |
+ self._CheckPath('archive directory', os.path.dirname(self.archive_path)) |
+ elif not os.path.exists(self.archive_path): |
+ self._CheckPath('archive file', self.archive_path) |
+ self._CheckPath('replay script', self.replay_py) |
- self.log_name = os.path.join(self.log_dir, self.LOG_FILE) |
self.log_fh = None |
self.replay_process = None |
- self.wpr_py = os.path.join(self.replay_dir, 'replay.py') |
- if not os.path.exists(self.wpr_py): |
- raise ReplayNotFoundError('Path does not exist: %s' % self.wpr_py) |
- self.wpr_options = [ |
+ def _AddDefaultReplayOptions(self): |
+ """Set WPR command-line options. Can be overridden if needed.""" |
+ self.replay_options += [ |
'--port', str(HTTP_PORT), |
'--ssl_port', str(HTTPS_PORT), |
'--use_closest_match', |
- # TODO(slamm): Add traffic shaping (requires root): |
- # '--net', 'fios', |
+ '--no-dns_forwarding', |
+ # '--net', 'fios', # TODO(slamm): Add traffic shaping (requires root). |
] |
- self.wpr_options.extend(self.replay_options) |
+ |
+ def _CheckPath(self, label, path): |
+ if not os.path.exists(path): |
+ raise ReplayNotFoundError(label, path) |
def _OpenLogFile(self): |
- if not os.path.exists(self.log_dir): |
- os.makedirs(self.log_dir) |
- return open(self.log_name, 'w') |
+ log_dir = os.path.dirname(self.log_path) |
+ if not os.path.exists(log_dir): |
+ os.makedirs(log_dir) |
+ return open(self.log_path, 'w') |
def IsStarted(self): |
"""Checks to see if the server is up and running.""" |
@@ -106,8 +160,8 @@ class ReplayServer(object): |
Raises: |
ReplayNotStartedError if Replay start-up fails. |
""" |
- cmd_line = [self.wpr_py] |
- cmd_line.extend(self.wpr_options) |
+ cmd_line = [self.replay_py] |
+ cmd_line.extend(self.replay_options) |
cmd_line.append(self.archive_path) |
self.log_fh = self._OpenLogFile() |
logging.debug('Starting Web-Page-Replay: %s', cmd_line) |