OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """A "Test Server Spawner" that handles killing/stopping per-test test servers. | 5 """A "Test Server Spawner" that handles killing/stopping per-test test servers. |
6 | 6 |
7 It's used to accept requests from the device to spawn and kill instances of the | 7 It's used to accept requests from the device to spawn and kill instances of the |
8 chrome test server on the host. | 8 chrome test server on the host. |
9 """ | 9 """ |
10 # pylint: disable=W0702 | 10 # pylint: disable=W0702 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 """ | 57 """ |
58 sleep_time_sec = 0.025 | 58 sleep_time_sec = 0.025 |
59 for _ in xrange(1, max_attempts): | 59 for _ in xrange(1, max_attempts): |
60 if predicate(): | 60 if predicate(): |
61 return True | 61 return True |
62 time.sleep(sleep_time_sec) | 62 time.sleep(sleep_time_sec) |
63 sleep_time_sec = min(1, sleep_time_sec * 2) # Don't wait more than 1 sec. | 63 sleep_time_sec = min(1, sleep_time_sec * 2) # Don't wait more than 1 sec. |
64 return False | 64 return False |
65 | 65 |
66 | 66 |
67 def _CheckPortStatus(port, expected_status): | 67 def _CheckPortAvailable(port): |
68 """Returns True if port has expected_status. | 68 """Returns True if |port| is available.""" |
| 69 return _WaitUntil(lambda: ports.IsHostPortAvailable(port)) |
69 | 70 |
70 Args: | |
71 port: the port number. | |
72 expected_status: boolean of expected status. | |
73 | 71 |
74 Returns: | 72 def _CheckPortNotAvailable(port): |
75 Returns True if the status is expected. Otherwise returns False. | 73 """Returns True if |port| is not available.""" |
76 """ | 74 return _WaitUntil(lambda: not ports.IsHostPortAvailable(port)) |
77 return _WaitUntil(lambda: ports.IsHostPortUsed(port) == expected_status) | |
78 | 75 |
79 | 76 |
80 def _CheckDevicePortStatus(device, port): | 77 def _CheckDevicePortStatus(device, port): |
81 """Returns whether the provided port is used.""" | 78 """Returns whether the provided port is used.""" |
82 return _WaitUntil(lambda: ports.IsDevicePortUsed(device, port)) | 79 return _WaitUntil(lambda: ports.IsDevicePortUsed(device, port)) |
83 | 80 |
84 | 81 |
85 def _GetServerTypeCommandLine(server_type): | 82 def _GetServerTypeCommandLine(server_type): |
86 """Returns the command-line by the given server type. | 83 """Returns the command-line by the given server type. |
87 | 84 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 logging.error('Failed to get length of server data.') | 157 logging.error('Failed to get length of server data.') |
161 return False | 158 return False |
162 port_json = os.read(self.pipe_in, data_length) | 159 port_json = os.read(self.pipe_in, data_length) |
163 if not port_json: | 160 if not port_json: |
164 logging.error('Failed to get server data.') | 161 logging.error('Failed to get server data.') |
165 return False | 162 return False |
166 logging.info('Got port json data: %s', port_json) | 163 logging.info('Got port json data: %s', port_json) |
167 port_json = json.loads(port_json) | 164 port_json = json.loads(port_json) |
168 if port_json.has_key('port') and isinstance(port_json['port'], int): | 165 if port_json.has_key('port') and isinstance(port_json['port'], int): |
169 self.host_port = port_json['port'] | 166 self.host_port = port_json['port'] |
170 return _CheckPortStatus(self.host_port, True) | 167 return _CheckPortNotAvailable(self.host_port) |
171 logging.error('Failed to get port information from the server data.') | 168 logging.error('Failed to get port information from the server data.') |
172 return False | 169 return False |
173 | 170 |
174 def _GenerateCommandLineArguments(self): | 171 def _GenerateCommandLineArguments(self): |
175 """Generates the command line to run the test server. | 172 """Generates the command line to run the test server. |
176 | 173 |
177 Note that all options are processed by following the definitions in | 174 Note that all options are processed by following the definitions in |
178 testserver.py. | 175 testserver.py. |
179 """ | 176 """ |
180 if self.command_line: | 177 if self.command_line: |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 logging.info('Running: %s', command) | 226 logging.info('Running: %s', command) |
230 # Pass DIR_SOURCE_ROOT as the child's working directory so that relative | 227 # Pass DIR_SOURCE_ROOT as the child's working directory so that relative |
231 # paths in the arguments are resolved correctly. | 228 # paths in the arguments are resolved correctly. |
232 self.process = subprocess.Popen( | 229 self.process = subprocess.Popen( |
233 command, preexec_fn=self._CloseUnnecessaryFDsForTestServerProcess, | 230 command, preexec_fn=self._CloseUnnecessaryFDsForTestServerProcess, |
234 cwd=constants.DIR_SOURCE_ROOT) | 231 cwd=constants.DIR_SOURCE_ROOT) |
235 if self.process: | 232 if self.process: |
236 if self.pipe_out: | 233 if self.pipe_out: |
237 self.is_ready = self._WaitToStartAndGetPortFromTestServer() | 234 self.is_ready = self._WaitToStartAndGetPortFromTestServer() |
238 else: | 235 else: |
239 self.is_ready = _CheckPortStatus(self.host_port, True) | 236 self.is_ready = _CheckPortNotAvailable(self.host_port) |
240 if self.is_ready: | 237 if self.is_ready: |
241 Forwarder.Map([(0, self.host_port)], self.device, self.tool) | 238 Forwarder.Map([(0, self.host_port)], self.device, self.tool) |
242 # Check whether the forwarder is ready on the device. | 239 # Check whether the forwarder is ready on the device. |
243 self.is_ready = False | 240 self.is_ready = False |
244 device_port = Forwarder.DevicePortForHostPort(self.host_port) | 241 device_port = Forwarder.DevicePortForHostPort(self.host_port) |
245 if device_port and _CheckDevicePortStatus(self.device, device_port): | 242 if device_port and _CheckDevicePortStatus(self.device, device_port): |
246 self.is_ready = True | 243 self.is_ready = True |
247 self.forwarder_device_port = device_port | 244 self.forwarder_device_port = device_port |
248 # Wake up the request handler thread. | 245 # Wake up the request handler thread. |
249 self.ready_event.set() | 246 self.ready_event.set() |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 def _KillTestServer(self): | 336 def _KillTestServer(self): |
340 """Stops the test server instance.""" | 337 """Stops the test server instance.""" |
341 # There should only ever be one test server at a time. This may do the | 338 # There should only ever be one test server at a time. This may do the |
342 # wrong thing if we try and start multiple test servers. | 339 # wrong thing if we try and start multiple test servers. |
343 if not self.server.test_server_instance: | 340 if not self.server.test_server_instance: |
344 return | 341 return |
345 port = self.server.test_server_instance.host_port | 342 port = self.server.test_server_instance.host_port |
346 logging.info('Handling request to kill a test server on port: %d.', port) | 343 logging.info('Handling request to kill a test server on port: %d.', port) |
347 self.server.test_server_instance.Stop() | 344 self.server.test_server_instance.Stop() |
348 # Make sure the status of test server is correct before sending response. | 345 # Make sure the status of test server is correct before sending response. |
349 if _CheckPortStatus(port, False): | 346 if _CheckPortAvailable(port): |
350 self._SendResponse(200, 'OK', {}, 'killed') | 347 self._SendResponse(200, 'OK', {}, 'killed') |
351 logging.info('Test server on port %d is killed', port) | 348 logging.info('Test server on port %d is killed', port) |
352 else: | 349 else: |
353 self._SendResponse(500, 'Test Server Error.', {}, '') | 350 self._SendResponse(500, 'Test Server Error.', {}, '') |
354 logging.info('Encounter problem during killing a test server.') | 351 logging.info('Encounter problem during killing a test server.') |
355 self.server.test_server_instance = None | 352 self.server.test_server_instance = None |
356 | 353 |
357 def do_POST(self): | 354 def do_POST(self): |
358 parsed_path = urlparse.urlparse(self.path) | 355 parsed_path = urlparse.urlparse(self.path) |
359 action = parsed_path.path | 356 action = parsed_path.path |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 | 413 |
417 def CleanupState(self): | 414 def CleanupState(self): |
418 """Cleans up the spawning server state. | 415 """Cleans up the spawning server state. |
419 | 416 |
420 This should be called if the test server spawner is reused, | 417 This should be called if the test server spawner is reused, |
421 to avoid sharing the test server instance. | 418 to avoid sharing the test server instance. |
422 """ | 419 """ |
423 if self.server.test_server_instance: | 420 if self.server.test_server_instance: |
424 self.server.test_server_instance.Stop() | 421 self.server.test_server_instance.Stop() |
425 self.server.test_server_instance = None | 422 self.server.test_server_instance = None |
OLD | NEW |