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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 Args: | 70 Args: |
71 port: the port number. | 71 port: the port number. |
72 expected_status: boolean of expected status. | 72 expected_status: boolean of expected status. |
73 | 73 |
74 Returns: | 74 Returns: |
75 Returns True if the status is expected. Otherwise returns False. | 75 Returns True if the status is expected. Otherwise returns False. |
76 """ | 76 """ |
77 return _WaitUntil(lambda: ports.IsHostPortUsed(port) == expected_status) | 77 return _WaitUntil(lambda: ports.IsHostPortUsed(port) == expected_status) |
78 | 78 |
79 | 79 |
80 def _CheckDevicePortStatus(adb, port): | 80 def _CheckDevicePortStatus(device, port): |
81 """Returns whether the provided port is used.""" | 81 """Returns whether the provided port is used.""" |
82 return _WaitUntil(lambda: ports.IsDevicePortUsed(adb, port)) | 82 return _WaitUntil(lambda: ports.IsDevicePortUsed(device, port)) |
83 | 83 |
84 | 84 |
85 def _GetServerTypeCommandLine(server_type): | 85 def _GetServerTypeCommandLine(server_type): |
86 """Returns the command-line by the given server type. | 86 """Returns the command-line by the given server type. |
87 | 87 |
88 Args: | 88 Args: |
89 server_type: the server type to be used (e.g. 'http'). | 89 server_type: the server type to be used (e.g. 'http'). |
90 | 90 |
91 Returns: | 91 Returns: |
92 A string containing the command-line argument. | 92 A string containing the command-line argument. |
93 """ | 93 """ |
94 if server_type not in SERVER_TYPES: | 94 if server_type not in SERVER_TYPES: |
95 raise NotImplementedError('Unknown server type: %s' % server_type) | 95 raise NotImplementedError('Unknown server type: %s' % server_type) |
96 if server_type == 'udpecho': | 96 if server_type == 'udpecho': |
97 raise Exception('Please do not run UDP echo tests because we do not have ' | 97 raise Exception('Please do not run UDP echo tests because we do not have ' |
98 'a UDP forwarder tool.') | 98 'a UDP forwarder tool.') |
99 return SERVER_TYPES[server_type] | 99 return SERVER_TYPES[server_type] |
100 | 100 |
101 | 101 |
102 class TestServerThread(threading.Thread): | 102 class TestServerThread(threading.Thread): |
103 """A thread to run the test server in a separate process.""" | 103 """A thread to run the test server in a separate process.""" |
104 | 104 |
105 def __init__(self, ready_event, arguments, adb, tool): | 105 def __init__(self, ready_event, arguments, device, tool): |
106 """Initialize TestServerThread with the following argument. | 106 """Initialize TestServerThread with the following argument. |
107 | 107 |
108 Args: | 108 Args: |
109 ready_event: event which will be set when the test server is ready. | 109 ready_event: event which will be set when the test server is ready. |
110 arguments: dictionary of arguments to run the test server. | 110 arguments: dictionary of arguments to run the test server. |
111 adb: instance of AndroidCommands. | 111 device: An instance of DeviceUtils. |
112 tool: instance of runtime error detection tool. | 112 tool: instance of runtime error detection tool. |
113 """ | 113 """ |
114 threading.Thread.__init__(self) | 114 threading.Thread.__init__(self) |
115 self.wait_event = threading.Event() | 115 self.wait_event = threading.Event() |
116 self.stop_flag = False | 116 self.stop_flag = False |
117 self.ready_event = ready_event | 117 self.ready_event = ready_event |
118 self.ready_event.clear() | 118 self.ready_event.clear() |
119 self.arguments = arguments | 119 self.arguments = arguments |
120 self.adb = adb | 120 self.device = device |
121 self.tool = tool | 121 self.tool = tool |
122 self.test_server_process = None | 122 self.test_server_process = None |
123 self.is_ready = False | 123 self.is_ready = False |
124 self.host_port = self.arguments['port'] | 124 self.host_port = self.arguments['port'] |
125 assert isinstance(self.host_port, int) | 125 assert isinstance(self.host_port, int) |
126 # The forwarder device port now is dynamically allocated. | 126 # The forwarder device port now is dynamically allocated. |
127 self.forwarder_device_port = 0 | 127 self.forwarder_device_port = 0 |
128 # Anonymous pipe in order to get port info from test server. | 128 # Anonymous pipe in order to get port info from test server. |
129 self.pipe_in = None | 129 self.pipe_in = None |
130 self.pipe_out = None | 130 self.pipe_out = None |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 'testserver.py')] + self.command_line | 245 'testserver.py')] + self.command_line |
246 logging.info('Running: %s', command) | 246 logging.info('Running: %s', command) |
247 self.process = subprocess.Popen( | 247 self.process = subprocess.Popen( |
248 command, preexec_fn=self._CloseUnnecessaryFDsForTestServerProcess) | 248 command, preexec_fn=self._CloseUnnecessaryFDsForTestServerProcess) |
249 if self.process: | 249 if self.process: |
250 if self.pipe_out: | 250 if self.pipe_out: |
251 self.is_ready = self._WaitToStartAndGetPortFromTestServer() | 251 self.is_ready = self._WaitToStartAndGetPortFromTestServer() |
252 else: | 252 else: |
253 self.is_ready = _CheckPortStatus(self.host_port, True) | 253 self.is_ready = _CheckPortStatus(self.host_port, True) |
254 if self.is_ready: | 254 if self.is_ready: |
255 Forwarder.Map([(0, self.host_port)], self.adb, self.tool) | 255 Forwarder.Map([(0, self.host_port)], self.device, self.tool) |
256 # Check whether the forwarder is ready on the device. | 256 # Check whether the forwarder is ready on the device. |
257 self.is_ready = False | 257 self.is_ready = False |
258 device_port = Forwarder.DevicePortForHostPort(self.host_port) | 258 device_port = Forwarder.DevicePortForHostPort(self.host_port) |
259 if device_port and _CheckDevicePortStatus(self.adb, device_port): | 259 if device_port and _CheckDevicePortStatus(self.device, device_port): |
260 self.is_ready = True | 260 self.is_ready = True |
261 self.forwarder_device_port = device_port | 261 self.forwarder_device_port = device_port |
262 # Wake up the request handler thread. | 262 # Wake up the request handler thread. |
263 self.ready_event.set() | 263 self.ready_event.set() |
264 # Keep thread running until Stop() gets called. | 264 # Keep thread running until Stop() gets called. |
265 _WaitUntil(lambda: self.stop_flag, max_attempts=sys.maxint) | 265 _WaitUntil(lambda: self.stop_flag, max_attempts=sys.maxint) |
266 if self.process.poll() is None: | 266 if self.process.poll() is None: |
267 self.process.kill() | 267 self.process.kill() |
268 Forwarder.UnmapDevicePort(self.forwarder_device_port, self.adb) | 268 Forwarder.UnmapDevicePort(self.forwarder_device_port, self.device) |
269 self.process = None | 269 self.process = None |
270 self.is_ready = False | 270 self.is_ready = False |
271 if self.pipe_out: | 271 if self.pipe_out: |
272 os.close(self.pipe_in) | 272 os.close(self.pipe_in) |
273 os.close(self.pipe_out) | 273 os.close(self.pipe_out) |
274 self.pipe_in = None | 274 self.pipe_in = None |
275 self.pipe_out = None | 275 self.pipe_out = None |
276 logging.info('Test-server has died.') | 276 logging.info('Test-server has died.') |
277 self.wait_event.set() | 277 self.wait_event.set() |
278 | 278 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 except: | 326 except: |
327 raise Exception('Bad content-length for start request.') | 327 raise Exception('Bad content-length for start request.') |
328 logging.info(content_length) | 328 logging.info(content_length) |
329 test_server_argument_json = self.rfile.read(content_length) | 329 test_server_argument_json = self.rfile.read(content_length) |
330 logging.info(test_server_argument_json) | 330 logging.info(test_server_argument_json) |
331 assert not self.server.test_server_instance | 331 assert not self.server.test_server_instance |
332 ready_event = threading.Event() | 332 ready_event = threading.Event() |
333 self.server.test_server_instance = TestServerThread( | 333 self.server.test_server_instance = TestServerThread( |
334 ready_event, | 334 ready_event, |
335 json.loads(test_server_argument_json), | 335 json.loads(test_server_argument_json), |
336 self.server.adb, | 336 self.server.device, |
337 self.server.tool) | 337 self.server.tool) |
338 self.server.test_server_instance.setDaemon(True) | 338 self.server.test_server_instance.setDaemon(True) |
339 self.server.test_server_instance.start() | 339 self.server.test_server_instance.start() |
340 ready_event.wait() | 340 ready_event.wait() |
341 if self.server.test_server_instance.is_ready: | 341 if self.server.test_server_instance.is_ready: |
342 self._SendResponse(200, 'OK', {}, json.dumps( | 342 self._SendResponse(200, 'OK', {}, json.dumps( |
343 {'port': self.server.test_server_instance.forwarder_device_port, | 343 {'port': self.server.test_server_instance.forwarder_device_port, |
344 'message': 'started'})) | 344 'message': 'started'})) |
345 logging.info('Test server is running on port: %d.', | 345 logging.info('Test server is running on port: %d.', |
346 self.server.test_server_instance.host_port) | 346 self.server.test_server_instance.host_port) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 self._SendResponse(200, 'OK', {}, 'ready') | 394 self._SendResponse(200, 'OK', {}, 'ready') |
395 logging.info('Handled ping request and sent response.') | 395 logging.info('Handled ping request and sent response.') |
396 else: | 396 else: |
397 self._SendResponse(400, 'Unknown request', {}, '') | 397 self._SendResponse(400, 'Unknown request', {}, '') |
398 logging.info('Encounter unknown request: %s.', action) | 398 logging.info('Encounter unknown request: %s.', action) |
399 | 399 |
400 | 400 |
401 class SpawningServer(object): | 401 class SpawningServer(object): |
402 """The class used to start/stop a http server.""" | 402 """The class used to start/stop a http server.""" |
403 | 403 |
404 def __init__(self, test_server_spawner_port, adb, tool): | 404 def __init__(self, test_server_spawner_port, device, tool): |
405 logging.info('Creating new spawner on port: %d.', test_server_spawner_port) | 405 logging.info('Creating new spawner on port: %d.', test_server_spawner_port) |
406 self.server = BaseHTTPServer.HTTPServer(('', test_server_spawner_port), | 406 self.server = BaseHTTPServer.HTTPServer(('', test_server_spawner_port), |
407 SpawningServerRequestHandler) | 407 SpawningServerRequestHandler) |
408 self.server.adb = adb | 408 self.server.device = device |
409 self.server.tool = tool | 409 self.server.tool = tool |
410 self.server.test_server_instance = None | 410 self.server.test_server_instance = None |
411 self.server.build_type = constants.GetBuildType() | 411 self.server.build_type = constants.GetBuildType() |
412 | 412 |
413 def _Listen(self): | 413 def _Listen(self): |
414 logging.info('Starting test server spawner') | 414 logging.info('Starting test server spawner') |
415 self.server.serve_forever() | 415 self.server.serve_forever() |
416 | 416 |
417 def Start(self): | 417 def Start(self): |
418 """Starts the test server spawner.""" | 418 """Starts the test server spawner.""" |
(...skipping 11 matching lines...) Expand all Loading... |
430 | 430 |
431 def CleanupState(self): | 431 def CleanupState(self): |
432 """Cleans up the spawning server state. | 432 """Cleans up the spawning server state. |
433 | 433 |
434 This should be called if the test server spawner is reused, | 434 This should be called if the test server spawner is reused, |
435 to avoid sharing the test server instance. | 435 to avoid sharing the test server instance. |
436 """ | 436 """ |
437 if self.server.test_server_instance: | 437 if self.server.test_server_instance: |
438 self.server.test_server_instance.Stop() | 438 self.server.test_server_instance.Stop() |
439 self.server.test_server_instance = None | 439 self.server.test_server_instance = None |
OLD | NEW |