| 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 |