Index: chrome/test/functional/webpagereplay.py |
=================================================================== |
--- chrome/test/functional/webpagereplay.py (revision 261231) |
+++ chrome/test/functional/webpagereplay.py (working copy) |
@@ -1,255 +0,0 @@ |
-#!/usr/bin/env python |
-# Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-# 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. |
- |
-Of the public module names, the following one is key: |
- ReplayServer: a class to start/stop Web Page Replay. |
-""" |
- |
-import logging |
-import os |
-import re |
-import signal |
-import subprocess |
-import sys |
-import time |
-import urllib |
- |
- |
-_CHROME_SRC_DIR = os.path.abspath(os.path.join( |
- os.path.dirname(__file__), os.pardir, os.pardir, os.pardir)) |
-REPLAY_DIR = os.path.join( |
- _CHROME_SRC_DIR, 'third_party', 'webpagereplay') |
-LOG_PATH = os.path.join( |
- _CHROME_SRC_DIR, 'webpagereplay_logs', 'logs.txt') |
- |
- |
-# Chrome options to make it work with Web Page Replay. |
-def GetChromeFlags(replay_host, http_port, https_port): |
- assert replay_host and http_port and https_port, 'All arguments required' |
- return [ |
- '--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', |
- ] |
- |
- |
-# Signal masks on Linux are inherited from parent processes. If anything |
-# invoking us accidentally masks SIGINT (e.g. by putting a process in the |
-# background from a shell script), sending a SIGINT to the child will fail |
-# to terminate it. Running this signal handler before execing should fix that |
-# problem. |
-def ResetInterruptHandler(): |
- signal.signal(signal.SIGINT, signal.SIG_DFL) |
- |
- |
-class ReplayError(Exception): |
- """Catch-all exception for the module.""" |
- pass |
- |
- |
-class ReplayNotFoundError(ReplayError): |
- 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 |
- |
- |
-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(archive_path): |
- self.NavigateToURL(start_url) |
- self.WaitUntil(...) |
- |
- 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_host, dns_port, http_port, https_port, |
- replay_options=None, replay_dir=None, |
- log_path=None): |
- """Initialize ReplayServer. |
- |
- Args: |
- archive_path: a path to a specific WPR archive (required). |
- replay_host: the hostname to serve traffic. |
- dns_port: an integer port on which to serve DNS traffic. May be zero |
- to let the OS choose an available port. If None DNS forwarding is |
- disabled. |
- http_port: an integer port on which to serve HTTP traffic. May be zero |
- to let the OS choose an available port. |
- https_port: an integer port on which to serve HTTPS traffic. May be zero |
- to let the OS choose an available port. |
- replay_options: an iterable of options strings to forward to replay.py. |
- 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 = list(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 |
- self.dns_port = dns_port |
- self.http_port = http_port |
- self.https_port = https_port |
- self._replay_host = replay_host |
- |
- 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_fh = None |
- self.replay_process = None |
- |
- def _AddDefaultReplayOptions(self): |
- """Set WPR command-line options. Can be overridden if needed.""" |
- self.replay_options = [ |
- '--host', str(self._replay_host), |
- '--port', str(self.http_port), |
- '--ssl_port', str(self.https_port), |
- '--use_closest_match', |
- '--no-dns_forwarding', |
- '--log_level', 'warning' |
- ] + self.replay_options |
- if self.dns_port is not None: |
- self.replay_options.extend(['--dns_port', str(self.dns_port)]) |
- |
- def _CheckPath(self, label, path): |
- if not os.path.exists(path): |
- raise ReplayNotFoundError(label, path) |
- |
- def _OpenLogFile(self): |
- 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 WaitForStart(self, timeout): |
- """Checks to see if the server is up and running.""" |
- port_re = re.compile( |
- '.*?(?P<protocol>[A-Z]+) server started on (?P<host>.*):(?P<port>\d+)') |
- |
- start_time = time.time() |
- elapsed_time = 0 |
- while elapsed_time < timeout: |
- if self.replay_process.poll() is not None: |
- break # The process has exited. |
- |
- # Read the ports from the WPR log. |
- if not self.http_port or not self.https_port or not self.dns_port: |
- for line in open(self.log_path).readlines(): |
- m = port_re.match(line.strip()) |
- if m: |
- if not self.http_port and m.group('protocol') == 'HTTP': |
- self.http_port = int(m.group('port')) |
- elif not self.https_port and m.group('protocol') == 'HTTPS': |
- self.https_port = int(m.group('port')) |
- elif not self.dns_port and m.group('protocol') == 'DNS': |
- self.dns_port = int(m.group('port')) |
- |
- # Try to connect to the WPR ports. |
- if self.http_port and self.https_port: |
- try: |
- up_url = '%s://%s:%s/web-page-replay-generate-200' |
- http_up_url = up_url % ('http', self._replay_host, self.http_port) |
- https_up_url = up_url % ('https', self._replay_host, self.https_port) |
- if (200 == urllib.urlopen(http_up_url, None, {}).getcode() and |
- 200 == urllib.urlopen(https_up_url, None, {}).getcode()): |
- return True |
- except IOError: |
- pass |
- |
- poll_interval = min(max(elapsed_time / 10., .1), 5) |
- time.sleep(poll_interval) |
- elapsed_time = time.time() - start_time |
- |
- return False |
- |
- def StartServer(self): |
- """Start Web Page Replay and verify that it started. |
- |
- Raises: |
- ReplayNotStartedError: if Replay start-up fails. |
- """ |
- cmd_line = [sys.executable, 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) |
- kwargs = {'stdout': self.log_fh, 'stderr': subprocess.STDOUT} |
- if sys.platform.startswith('linux') or sys.platform == 'darwin': |
- kwargs['preexec_fn'] = ResetInterruptHandler |
- self.replay_process = subprocess.Popen(cmd_line, **kwargs) |
- if not self.WaitForStart(30): |
- log = open(self.log_path).read() |
- raise ReplayNotStartedError( |
- 'Web Page Replay failed to start. Log output:\n%s' % log) |
- |
- def StopServer(self): |
- """Stop Web Page Replay.""" |
- if self.replay_process: |
- logging.debug('Trying to stop Web-Page-Replay gracefully') |
- try: |
- url = 'http://localhost:%s/web-page-replay-command-exit' |
- urllib.urlopen(url % self.http_port, None, {}) |
- except IOError: |
- # IOError is possible because the server might exit without response. |
- pass |
- |
- start_time = time.time() |
- while time.time() - start_time < 10: # Timeout after 10 seconds. |
- if self.replay_process.poll() is not None: |
- break |
- time.sleep(1) |
- else: |
- try: |
- # Use a SIGINT so that it can do graceful cleanup. |
- self.replay_process.send_signal(signal.SIGINT) |
- except: # pylint: disable=W0702 |
- # On Windows, we are left with no other option than terminate(). |
- if 'no-dns_forwarding' not in self.replay_options: |
- logging.warning('DNS configuration might not be restored!') |
- try: |
- self.replay_process.terminate() |
- except: # pylint: disable=W0702 |
- pass |
- self.replay_process.wait() |
- if self.log_fh: |
- self.log_fh.close() |
- |
- def __enter__(self): |
- """Add support for with-statement.""" |
- self.StartServer() |
- return self |
- |
- def __exit__(self, unused_exc_type, unused_exc_val, unused_exc_tb): |
- """Add support for with-statement.""" |
- self.StopServer() |