Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Side by Side Diff: trunk/src/build/android/pylib/chrome_test_server_spawner.py

Issue 19576005: Revert 212020 "Move Python setup/tear down logic into Forwarder ..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « trunk/src/build/android/pylib/base/shard.py ('k') | trunk/src/build/android/pylib/forwarder.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 10
11 import BaseHTTPServer 11 import BaseHTTPServer
12 import json 12 import json
13 import logging 13 import logging
14 import os 14 import os
15 import select 15 import select
16 import struct 16 import struct
17 import subprocess 17 import subprocess
18 import sys 18 import sys
19 import threading 19 import threading
20 import time 20 import time
21 import urlparse 21 import urlparse
22 22
23 import constants 23 import constants
24 import ports 24 import ports
25 25
26 from pylib.forwarder import Forwarder
27 26
28 # Path that are needed to import necessary modules when launching a testserver. 27 # Path that are needed to import necessary modules when launching a testserver.
29 os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + (':%s:%s:%s:%s:%s' 28 os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + (':%s:%s:%s:%s:%s'
30 % (os.path.join(constants.DIR_SOURCE_ROOT, 'third_party'), 29 % (os.path.join(constants.DIR_SOURCE_ROOT, 'third_party'),
31 os.path.join(constants.DIR_SOURCE_ROOT, 'third_party', 'tlslite'), 30 os.path.join(constants.DIR_SOURCE_ROOT, 'third_party', 'tlslite'),
32 os.path.join(constants.DIR_SOURCE_ROOT, 'third_party', 'pyftpdlib', 31 os.path.join(constants.DIR_SOURCE_ROOT, 'third_party', 'pyftpdlib',
33 'src'), 32 'src'),
34 os.path.join(constants.DIR_SOURCE_ROOT, 'net', 'tools', 'testserver'), 33 os.path.join(constants.DIR_SOURCE_ROOT, 'net', 'tools', 'testserver'),
35 os.path.join(constants.DIR_SOURCE_ROOT, 'sync', 'tools', 'testserver'))) 34 os.path.join(constants.DIR_SOURCE_ROOT, 'sync', 'tools', 'testserver')))
36 35
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 raise NotImplementedError('Unknown server type: %s' % server_type) 92 raise NotImplementedError('Unknown server type: %s' % server_type)
94 if server_type == 'udpecho': 93 if server_type == 'udpecho':
95 raise Exception('Please do not run UDP echo tests because we do not have ' 94 raise Exception('Please do not run UDP echo tests because we do not have '
96 'a UDP forwarder tool.') 95 'a UDP forwarder tool.')
97 return SERVER_TYPES[server_type] 96 return SERVER_TYPES[server_type]
98 97
99 98
100 class TestServerThread(threading.Thread): 99 class TestServerThread(threading.Thread):
101 """A thread to run the test server in a separate process.""" 100 """A thread to run the test server in a separate process."""
102 101
103 def __init__(self, ready_event, arguments, adb, tool, build_type): 102 def __init__(self, ready_event, arguments, adb, tool, forwarder, build_type):
104 """Initialize TestServerThread with the following argument. 103 """Initialize TestServerThread with the following argument.
105 104
106 Args: 105 Args:
107 ready_event: event which will be set when the test server is ready. 106 ready_event: event which will be set when the test server is ready.
108 arguments: dictionary of arguments to run the test server. 107 arguments: dictionary of arguments to run the test server.
109 adb: instance of AndroidCommands. 108 adb: instance of AndroidCommands.
110 tool: instance of runtime error detection tool. 109 tool: instance of runtime error detection tool.
110 forwarder: instance of Forwarder.
111 build_type: 'Release' or 'Debug'. 111 build_type: 'Release' or 'Debug'.
112 """ 112 """
113 threading.Thread.__init__(self) 113 threading.Thread.__init__(self)
114 self.wait_event = threading.Event() 114 self.wait_event = threading.Event()
115 self.stop_flag = False 115 self.stop_flag = False
116 self.ready_event = ready_event 116 self.ready_event = ready_event
117 self.ready_event.clear() 117 self.ready_event.clear()
118 self.arguments = arguments 118 self.arguments = arguments
119 self.adb = adb 119 self.adb = adb
120 self.tool = tool 120 self.tool = tool
121 self.test_server_process = None 121 self.test_server_process = None
122 self.is_ready = False 122 self.is_ready = False
123 self.host_port = self.arguments['port'] 123 self.host_port = self.arguments['port']
124 assert isinstance(self.host_port, int) 124 assert isinstance(self.host_port, int)
125 self._test_server_forwarder = forwarder
125 # The forwarder device port now is dynamically allocated. 126 # The forwarder device port now is dynamically allocated.
126 self.forwarder_device_port = 0 127 self.forwarder_device_port = 0
127 # Anonymous pipe in order to get port info from test server. 128 # Anonymous pipe in order to get port info from test server.
128 self.pipe_in = None 129 self.pipe_in = None
129 self.pipe_out = None 130 self.pipe_out = None
130 self.command_line = [] 131 self.command_line = []
131 self.build_type = build_type 132 self.build_type = build_type
132 133
133 def _WaitToStartAndGetPortFromTestServer(self): 134 def _WaitToStartAndGetPortFromTestServer(self):
134 """Waits for the Python test server to start and gets the port it is using. 135 """Waits for the Python test server to start and gets the port it is using.
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 command = [os.path.join(command, 'net', 'tools', 'testserver', 233 command = [os.path.join(command, 'net', 'tools', 'testserver',
233 'testserver.py')] + self.command_line 234 'testserver.py')] + self.command_line
234 logging.info('Running: %s', command) 235 logging.info('Running: %s', command)
235 self.process = subprocess.Popen(command) 236 self.process = subprocess.Popen(command)
236 if self.process: 237 if self.process:
237 if self.pipe_out: 238 if self.pipe_out:
238 self.is_ready = self._WaitToStartAndGetPortFromTestServer() 239 self.is_ready = self._WaitToStartAndGetPortFromTestServer()
239 else: 240 else:
240 self.is_ready = _CheckPortStatus(self.host_port, True) 241 self.is_ready = _CheckPortStatus(self.host_port, True)
241 if self.is_ready: 242 if self.is_ready:
242 Forwarder.Map([(0, self.host_port)], self.adb, self.build_type, self.tool) 243 self._test_server_forwarder.Run([(0, self.host_port)], self.tool)
243 # Check whether the forwarder is ready on the device. 244 # Check whether the forwarder is ready on the device.
244 self.is_ready = False 245 self.is_ready = False
245 device_port = Forwarder.DevicePortForHostPort(self.host_port) 246 device_port = self._test_server_forwarder.DevicePortForHostPort(
247 self.host_port)
246 if device_port and _CheckDevicePortStatus(self.adb, device_port): 248 if device_port and _CheckDevicePortStatus(self.adb, device_port):
247 self.is_ready = True 249 self.is_ready = True
248 self.forwarder_device_port = device_port 250 self.forwarder_device_port = device_port
249 # Wake up the request handler thread. 251 # Wake up the request handler thread.
250 self.ready_event.set() 252 self.ready_event.set()
251 # Keep thread running until Stop() gets called. 253 # Keep thread running until Stop() gets called.
252 _WaitUntil(lambda: self.stop_flag, max_attempts=sys.maxint) 254 _WaitUntil(lambda: self.stop_flag, max_attempts=sys.maxint)
253 if self.process.poll() is None: 255 if self.process.poll() is None:
254 self.process.kill() 256 self.process.kill()
255 Forwarder.UnmapDevicePort(self.forwarder_device_port, self.adb) 257 self._test_server_forwarder.UnmapDevicePort(self.forwarder_device_port)
256 self.process = None 258 self.process = None
257 self.is_ready = False 259 self.is_ready = False
258 if self.pipe_out: 260 if self.pipe_out:
259 os.close(self.pipe_in) 261 os.close(self.pipe_in)
260 os.close(self.pipe_out) 262 os.close(self.pipe_out)
261 self.pipe_in = None 263 self.pipe_in = None
262 self.pipe_out = None 264 self.pipe_out = None
263 logging.info('Test-server has died.') 265 logging.info('Test-server has died.')
264 self.wait_event.set() 266 self.wait_event.set()
265 267
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 logging.info(content_length) 317 logging.info(content_length)
316 test_server_argument_json = self.rfile.read(content_length) 318 test_server_argument_json = self.rfile.read(content_length)
317 logging.info(test_server_argument_json) 319 logging.info(test_server_argument_json)
318 assert not self.server.test_server_instance 320 assert not self.server.test_server_instance
319 ready_event = threading.Event() 321 ready_event = threading.Event()
320 self.server.test_server_instance = TestServerThread( 322 self.server.test_server_instance = TestServerThread(
321 ready_event, 323 ready_event,
322 json.loads(test_server_argument_json), 324 json.loads(test_server_argument_json),
323 self.server.adb, 325 self.server.adb,
324 self.server.tool, 326 self.server.tool,
327 self.server.forwarder,
325 self.server.build_type) 328 self.server.build_type)
326 self.server.test_server_instance.setDaemon(True) 329 self.server.test_server_instance.setDaemon(True)
327 self.server.test_server_instance.start() 330 self.server.test_server_instance.start()
328 ready_event.wait() 331 ready_event.wait()
329 if self.server.test_server_instance.is_ready: 332 if self.server.test_server_instance.is_ready:
330 self._SendResponse(200, 'OK', {}, json.dumps( 333 self._SendResponse(200, 'OK', {}, json.dumps(
331 {'port': self.server.test_server_instance.forwarder_device_port, 334 {'port': self.server.test_server_instance.forwarder_device_port,
332 'message': 'started'})) 335 'message': 'started'}))
333 logging.info('Test server is running on port: %d.', 336 logging.info('Test server is running on port: %d.',
334 self.server.test_server_instance.host_port) 337 self.server.test_server_instance.host_port)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 self._SendResponse(200, 'OK', {}, 'ready') 385 self._SendResponse(200, 'OK', {}, 'ready')
383 logging.info('Handled ping request and sent response.') 386 logging.info('Handled ping request and sent response.')
384 else: 387 else:
385 self._SendResponse(400, 'Unknown request', {}, '') 388 self._SendResponse(400, 'Unknown request', {}, '')
386 logging.info('Encounter unknown request: %s.', action) 389 logging.info('Encounter unknown request: %s.', action)
387 390
388 391
389 class SpawningServer(object): 392 class SpawningServer(object):
390 """The class used to start/stop a http server.""" 393 """The class used to start/stop a http server."""
391 394
392 def __init__(self, test_server_spawner_port, adb, tool, build_type): 395 def __init__(self, test_server_spawner_port, adb, tool, forwarder,
396 build_type):
393 logging.info('Creating new spawner on port: %d.', test_server_spawner_port) 397 logging.info('Creating new spawner on port: %d.', test_server_spawner_port)
394 self.server = BaseHTTPServer.HTTPServer(('', test_server_spawner_port), 398 self.server = BaseHTTPServer.HTTPServer(('', test_server_spawner_port),
395 SpawningServerRequestHandler) 399 SpawningServerRequestHandler)
396 self.server.adb = adb 400 self.server.adb = adb
397 self.server.tool = tool 401 self.server.tool = tool
402 self.server.forwarder = forwarder
398 self.server.test_server_instance = None 403 self.server.test_server_instance = None
399 self.server.build_type = build_type 404 self.server.build_type = build_type
400 405
401 def _Listen(self): 406 def _Listen(self):
402 logging.info('Starting test server spawner') 407 logging.info('Starting test server spawner')
403 self.server.serve_forever() 408 self.server.serve_forever()
404 409
405 def Start(self): 410 def Start(self):
406 """Starts the test server spawner.""" 411 """Starts the test server spawner."""
407 listener_thread = threading.Thread(target=self._Listen) 412 listener_thread = threading.Thread(target=self._Listen)
(...skipping 10 matching lines...) Expand all
418 423
419 def CleanupState(self): 424 def CleanupState(self):
420 """Cleans up the spawning server state. 425 """Cleans up the spawning server state.
421 426
422 This should be called if the test server spawner is reused, 427 This should be called if the test server spawner is reused,
423 to avoid sharing the test server instance. 428 to avoid sharing the test server instance.
424 """ 429 """
425 if self.server.test_server_instance: 430 if self.server.test_server_instance:
426 self.server.test_server_instance.Stop() 431 self.server.test_server_instance.Stop()
427 self.server.test_server_instance = None 432 self.server.test_server_instance = None
OLDNEW
« no previous file with comments | « trunk/src/build/android/pylib/base/shard.py ('k') | trunk/src/build/android/pylib/forwarder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698