OLD | NEW |
| (Empty) |
1 # Copyright 2013 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 """Host driven test server controller. | |
6 | |
7 This class controls the startup and shutdown of a python driven test server that | |
8 runs in a separate process. | |
9 | |
10 The server starts up automatically when the object is created. | |
11 | |
12 After it starts up, it is possible to retreive the hostname it started on | |
13 through accessing the member field |host| and the port name through |port|. | |
14 | |
15 For shutting down the server, call TearDown(). | |
16 """ | |
17 | |
18 import logging | |
19 import subprocess | |
20 import os | |
21 import os.path | |
22 import time | |
23 import urllib2 | |
24 | |
25 from pylib import constants | |
26 | |
27 # NOTE: when adding or modifying these lines, omit any leading slashes! | |
28 # Otherwise os.path.join() will (correctly) treat them as absolute paths | |
29 # instead of relative paths, and will do nothing. | |
30 _PYTHONPATH_DIRS = [ | |
31 'net/tools/testserver/', | |
32 'third_party/', | |
33 'third_party/pyftpdlib/src/', | |
34 'third_party/pywebsocket/src', | |
35 'third_party/tlslite/', | |
36 ] | |
37 | |
38 # Python files in these directories are generated as part of the build. | |
39 # These dirs are located in out/(Debug|Release) directory. | |
40 # The correct path is determined based on the build type. E.g. out/Debug for | |
41 # debug builds and out/Release for release builds. | |
42 _GENERATED_PYTHONPATH_DIRS = [ | |
43 'pyproto/policy/proto/', | |
44 'pyproto/sync/protocol/', | |
45 'pyproto/' | |
46 ] | |
47 | |
48 _TEST_SERVER_HOST = '127.0.0.1' | |
49 # Paths for supported test server executables. | |
50 TEST_NET_SERVER_PATH = 'net/tools/testserver/testserver.py' | |
51 TEST_SYNC_SERVER_PATH = 'sync/tools/testserver/sync_testserver.py' | |
52 TEST_POLICY_SERVER_PATH = 'chrome/browser/policy/test/policy_testserver.py' | |
53 # Parameters to check that the server is up and running. | |
54 TEST_SERVER_CHECK_PARAMS = { | |
55 TEST_NET_SERVER_PATH: { | |
56 'url_path': '/', | |
57 'response': 'Default response given for path' | |
58 }, | |
59 TEST_SYNC_SERVER_PATH: { | |
60 'url_path': 'chromiumsync/time', | |
61 'response': '0123456789' | |
62 }, | |
63 TEST_POLICY_SERVER_PATH: { | |
64 'url_path': 'test/ping', | |
65 'response': 'Policy server is up.' | |
66 }, | |
67 } | |
68 | |
69 class TestServer(object): | |
70 """Sets up a host driven test server on the host machine. | |
71 | |
72 For shutting down the server, call TearDown(). | |
73 """ | |
74 | |
75 def __init__(self, shard_index, test_server_port, test_server_path, | |
76 test_server_flags=None): | |
77 """Sets up a Python driven test server on the host machine. | |
78 | |
79 Args: | |
80 shard_index: Index of the current shard. | |
81 test_server_port: Port to run the test server on. This is multiplexed with | |
82 the shard index. To retrieve the real port access the | |
83 member variable |port|. | |
84 test_server_path: The path (relative to the root src dir) of the server | |
85 test_server_flags: Optional list of additional flags to the test server | |
86 """ | |
87 self.host = _TEST_SERVER_HOST | |
88 self.port = test_server_port + shard_index | |
89 | |
90 src_dir = constants.DIR_SOURCE_ROOT | |
91 # Make dirs into a list of absolute paths. | |
92 abs_dirs = [os.path.join(src_dir, d) for d in _PYTHONPATH_DIRS] | |
93 # Add the generated python files to the path | |
94 abs_dirs.extend([os.path.join(src_dir, constants.GetOutDirectory(), d) | |
95 for d in _GENERATED_PYTHONPATH_DIRS]) | |
96 current_python_path = os.environ.get('PYTHONPATH') | |
97 extra_python_path = ':'.join(abs_dirs) | |
98 if current_python_path: | |
99 python_path = current_python_path + ':' + extra_python_path | |
100 else: | |
101 python_path = extra_python_path | |
102 | |
103 # NOTE: A separate python process is used to simplify getting the right | |
104 # system path for finding includes. | |
105 test_server_flags = test_server_flags or [] | |
106 cmd = ['python', os.path.join(src_dir, test_server_path), | |
107 '--log-to-console', | |
108 ('--host=%s' % self.host), | |
109 ('--port=%d' % self.port), | |
110 '--on-remote-server'] + test_server_flags | |
111 self._test_server_process = subprocess.Popen( | |
112 cmd, env={'PYTHONPATH': python_path}) | |
113 test_url = 'http://%s:%d/%s' % (self.host, self.port, | |
114 TEST_SERVER_CHECK_PARAMS[test_server_path]['url_path']) | |
115 expected_response = TEST_SERVER_CHECK_PARAMS[test_server_path]['response'] | |
116 retries = 0 | |
117 while retries < 5: | |
118 try: | |
119 d = urllib2.urlopen(test_url).read() | |
120 logging.info('URL %s GOT: %s' % (test_url, d)) | |
121 if d.startswith(expected_response): | |
122 break | |
123 except Exception as e: | |
124 logging.info('URL %s GOT: %s' % (test_url, e)) | |
125 time.sleep(retries * 0.1) | |
126 retries += 1 | |
127 | |
128 def TearDown(self): | |
129 self._test_server_process.kill() | |
130 self._test_server_process.wait() | |
OLD | NEW |