OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Setups a local Rietveld instance to test against a live server for |
| 6 integration tests. |
| 7 |
| 8 It makes sure Google AppEngine SDK is found, download Rietveld and Django code |
| 9 if necessary and starts the server on a free inbound TCP port. |
| 10 """ |
| 11 |
| 12 import os |
| 13 import socket |
| 14 import subprocess |
| 15 import time |
| 16 |
| 17 |
| 18 class Failure(Exception): |
| 19 pass |
| 20 |
| 21 |
| 22 def test_port(port): |
| 23 s = socket.socket() |
| 24 try: |
| 25 return s.connect_ex(('127.0.0.1', port)) == 0 |
| 26 finally: |
| 27 s.close() |
| 28 |
| 29 |
| 30 def find_free_port(): |
| 31 # Test to find an available port starting at 8080. |
| 32 port = 8080 |
| 33 max_val = (2<<16) |
| 34 while test_port(port) and port < max_val: |
| 35 port += 1 |
| 36 if port == max_val: |
| 37 raise Failure('Having issues finding an available port') |
| 38 return port |
| 39 |
| 40 |
| 41 class LocalRietveld(object): |
| 42 """Downloads everything needed to run a local instance of Rietveld.""" |
| 43 |
| 44 def __init__(self, base_dir=None): |
| 45 # Paths |
| 46 self.base_dir = base_dir |
| 47 if not self.base_dir: |
| 48 self.base_dir = os.path.dirname(os.path.abspath(__file__)) |
| 49 self.base_dir = os.path.realpath(os.path.join(self.base_dir, '..')) |
| 50 self.sdk_path = os.path.abspath( |
| 51 os.path.join(self.base_dir, '..', '..', 'google_appengine')) |
| 52 self.dev_app = os.path.join(self.sdk_path, 'dev_appserver.py') |
| 53 self.rietveld = os.path.join(self.base_dir, 'test', 'rietveld') |
| 54 self.django_path = os.path.join(self.rietveld, 'django') |
| 55 self.test_server = None |
| 56 self.port = None |
| 57 # Generate a friendly environment. |
| 58 self.env = os.environ.copy() |
| 59 self.env['LANGUAGE'] = 'en' |
| 60 if self.env.get('PYTHONPATH'): |
| 61 self.env['PYTHONPATH'] = ( |
| 62 self.env['PYTHONPATH'].rstrip(os.pathsep) + os.pathsep + |
| 63 self.django_path) |
| 64 else: |
| 65 self.env['PYTHONPATH'] = self.django_path |
| 66 |
| 67 def install_prerequisites(self): |
| 68 # First, verify the Google AppEngine SDK is available. |
| 69 if not os.path.isfile(self.dev_app): |
| 70 raise Failure('Install google_appengine sdk in %s' % self.sdk_path) |
| 71 |
| 72 def call(*args, **kwargs): |
| 73 kwargs['env'] = self.env |
| 74 x = subprocess.Popen(*args, **kwargs) |
| 75 x.communicate() |
| 76 return x.returncode == 0 |
| 77 |
| 78 # Second, checkout rietveld and django if not available. |
| 79 if not os.path.isdir(self.rietveld): |
| 80 print('Checking out rietveld...') |
| 81 if not call( |
| 82 ['svn', 'co', '-q', |
| 83 'http://rietveld.googlecode.com/svn/trunk@563', |
| 84 self.rietveld]): |
| 85 raise Failure('Failed to checkout rietveld') |
| 86 if not os.path.isdir(self.django_path): |
| 87 print('Checking out django...') |
| 88 if not call( |
| 89 ['svn', 'co', '-q', |
| 90 'http://code.djangoproject.com/' |
| 91 'svn/django/branches/releases/1.0.X/django@13637', |
| 92 self.django_path]): |
| 93 raise Failure('Failed to checkout django') |
| 94 |
| 95 def start_server(self, verbose=False): |
| 96 self.install_prerequisites() |
| 97 self.port = find_free_port() |
| 98 if verbose: |
| 99 stdout = None |
| 100 stderr = None |
| 101 else: |
| 102 stdout = subprocess.PIPE |
| 103 stderr = subprocess.PIPE |
| 104 output = [] |
| 105 self.test_server = subprocess.Popen( |
| 106 [self.dev_app, self.rietveld, '--port=%d' % self.port, |
| 107 '--datastore_path=' + os.path.join(self.rietveld, 'tmp.db'), '-c'], |
| 108 stdout=stdout, stderr=stderr, env=self.env) |
| 109 # Loop until port 127.0.0.1:port opens or the process dies. |
| 110 while not test_port(self.port): |
| 111 self.test_server.poll() |
| 112 if self.test_server.returncode is not None: |
| 113 raise Failure( |
| 114 'Test rietveld instance failed early on port %s' % |
| 115 self.port) |
| 116 time.sleep(0.001) |
| 117 |
| 118 def stop_server(self): |
| 119 if self.test_server: |
| 120 self.test_server.kill() |
| 121 self.test_server = None |
| 122 self.port = None |
| 123 |
| 124 |
| 125 def main(): |
| 126 print LocalRietveld().start_server() |
| 127 |
| 128 |
| 129 if __name__ == '__main__': |
| 130 main() |
| 131 |
| 132 # vim: ts=4:sw=4:tw=80:et: |
OLD | NEW |