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

Side by Side Diff: Tools/Scripts/webkitpy/layout_tests/servers/server_base.py

Issue 546133003: Reformat webkitpy.layout_tests w/ format-webkitpy. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 3 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
OLDNEW
1 # Copyright (C) 2011 Google Inc. All rights reserved. 1 # Copyright (C) 2011 Google Inc. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are 4 # modification, are permitted provided that the following conditions are
5 # met: 5 # met:
6 # 6 #
7 # * Redistributions of source code must retain the above copyright 7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer. 8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above 9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer 10 # copyright notice, this list of conditions and the following disclaimer
(...skipping 25 matching lines...) Expand all
36 36
37 37
38 _log = logging.getLogger(__name__) 38 _log = logging.getLogger(__name__)
39 39
40 40
41 class ServerError(Exception): 41 class ServerError(Exception):
42 pass 42 pass
43 43
44 44
45 class ServerBase(object): 45 class ServerBase(object):
46
46 """A skeleton class for starting and stopping servers used by the layout tes ts.""" 47 """A skeleton class for starting and stopping servers used by the layout tes ts."""
47 48
48 def __init__(self, port_obj, output_dir): 49 def __init__(self, port_obj, output_dir):
49 self._port_obj = port_obj 50 self._port_obj = port_obj
50 self._executive = port_obj._executive 51 self._executive = port_obj._executive
51 self._filesystem = port_obj._filesystem 52 self._filesystem = port_obj._filesystem
52 self._platform = port_obj.host.platform 53 self._platform = port_obj.host.platform
53 self._output_dir = output_dir 54 self._output_dir = output_dir
54 55
55 # We need a non-checkout-dependent place to put lock files, etc. We 56 # We need a non-checkout-dependent place to put lock files, etc. We
56 # don't use the Python default on the Mac because it defaults to a 57 # don't use the Python default on the Mac because it defaults to a
57 # randomly-generated directory under /var/folders and no one would ever 58 # randomly-generated directory under /var/folders and no one would ever
58 # look there. 59 # look there.
59 tmpdir = tempfile.gettempdir() 60 tmpdir = tempfile.gettempdir()
60 if self._platform.is_mac(): 61 if self._platform.is_mac():
61 tmpdir = '/tmp' 62 tmpdir = '/tmp'
62 63
63 self._runtime_path = self._filesystem.join(tmpdir, "WebKit") 64 self._runtime_path = self._filesystem.join(tmpdir, 'WebKit')
64 self._filesystem.maybe_make_directory(self._runtime_path) 65 self._filesystem.maybe_make_directory(self._runtime_path)
65 66
66 # Subclasses must override these fields. 67 # Subclasses must override these fields.
67 self._name = '<virtual>' 68 self._name = '<virtual>'
68 self._log_prefixes = tuple() 69 self._log_prefixes = tuple()
69 self._mappings = {} 70 self._mappings = {}
70 self._pid_file = None 71 self._pid_file = None
71 self._start_cmd = None 72 self._start_cmd = None
72 73
73 # Subclasses may override these fields. 74 # Subclasses may override these fields.
(...skipping 21 matching lines...) Expand all
95 self._remove_pid_file() 96 self._remove_pid_file()
96 self._pid = None 97 self._pid = None
97 98
98 self._remove_stale_logs() 99 self._remove_stale_logs()
99 self._prepare_config() 100 self._prepare_config()
100 self._check_that_all_ports_are_available() 101 self._check_that_all_ports_are_available()
101 102
102 self._pid = self._spawn_process() 103 self._pid = self._spawn_process()
103 104
104 if self._wait_for_action(self._is_server_running_on_all_ports): 105 if self._wait_for_action(self._is_server_running_on_all_ports):
105 _log.debug("%s successfully started (pid = %d)" % (self._name, self. _pid)) 106 _log.debug('%s successfully started (pid = %d)' % (self._name, self. _pid))
106 else: 107 else:
107 self._log_errors_from_subprocess() 108 self._log_errors_from_subprocess()
108 self._stop_running_server() 109 self._stop_running_server()
109 raise ServerError('Failed to start %s server' % self._name) 110 raise ServerError('Failed to start %s server' % self._name)
110 111
111 def stop(self): 112 def stop(self):
112 """Stops the server. Stopping a server that isn't started is harmless."" " 113 """Stops the server. Stopping a server that isn't started is harmless."" "
113 actual_pid = None 114 actual_pid = None
114 try: 115 try:
115 if self._filesystem.exists(self._pid_file): 116 if self._filesystem.exists(self._pid_file):
116 try: 117 try:
117 actual_pid = int(self._filesystem.read_text_file(self._pid_f ile)) 118 actual_pid = int(self._filesystem.read_text_file(self._pid_f ile))
118 except (ValueError, UnicodeDecodeError): 119 except (ValueError, UnicodeDecodeError):
119 # These could be raised if the pid file is corrupt. 120 # These could be raised if the pid file is corrupt.
120 pass 121 pass
121 if not self._pid: 122 if not self._pid:
122 self._pid = actual_pid 123 self._pid = actual_pid
123 124
124 if not self._pid: 125 if not self._pid:
125 return 126 return
126 127
127 if not actual_pid: 128 if not actual_pid:
128 _log.warning('Failed to stop %s: pid file is missing' % self._na me) 129 _log.warning('Failed to stop %s: pid file is missing' % self._na me)
129 return 130 return
130 if self._pid != actual_pid: 131 if self._pid != actual_pid:
131 _log.warning('Failed to stop %s: pid file contains %d, not %d' % 132 _log.warning('Failed to stop %s: pid file contains %d, not %d' %
132 (self._name, actual_pid, self._pid)) 133 (self._name, actual_pid, self._pid))
133 # Try to kill the existing pid, anyway, in case it got orphaned. 134 # Try to kill the existing pid, anyway, in case it got orphaned.
134 self._executive.kill_process(self._pid) 135 self._executive.kill_process(self._pid)
135 self._pid = None 136 self._pid = None
136 return 137 return
137 138
138 _log.debug("Attempting to shut down %s server at pid %d" % (self._na me, self._pid)) 139 _log.debug('Attempting to shut down %s server at pid %d' % (self._na me, self._pid))
139 self._stop_running_server() 140 self._stop_running_server()
140 _log.debug("%s server at pid %d stopped" % (self._name, self._pid)) 141 _log.debug('%s server at pid %d stopped' % (self._name, self._pid))
141 self._pid = None 142 self._pid = None
142 finally: 143 finally:
143 # Make sure we delete the pid file no matter what happens. 144 # Make sure we delete the pid file no matter what happens.
144 self._remove_pid_file() 145 self._remove_pid_file()
145 146
146 def _prepare_config(self): 147 def _prepare_config(self):
147 """This routine can be overridden by subclasses to do any sort 148 """This routine can be overridden by subclasses to do any sort
148 of initialization required prior to starting the server that may fail."" " 149 of initialization required prior to starting the server that may fail."" "
149 pass 150 pass
150 151
151 def _remove_stale_logs(self): 152 def _remove_stale_logs(self):
152 """This routine can be overridden by subclasses to try and remove logs 153 """This routine can be overridden by subclasses to try and remove logs
153 left over from a prior run. This routine should log warnings if the 154 left over from a prior run. This routine should log warnings if the
154 files cannot be deleted, but should not fail unless failure to 155 files cannot be deleted, but should not fail unless failure to
155 delete the logs will actually cause start() to fail.""" 156 delete the logs will actually cause start() to fail."""
156 # Sometimes logs are open in other processes but they should clear event ually. 157 # Sometimes logs are open in other processes but they should clear event ually.
157 for log_prefix in self._log_prefixes: 158 for log_prefix in self._log_prefixes:
158 try: 159 try:
159 self._remove_log_files(self._output_dir, log_prefix) 160 self._remove_log_files(self._output_dir, log_prefix)
160 except OSError, e: 161 except OSError as e:
161 _log.warning('Failed to remove old %s %s files' % (self._name, l og_prefix)) 162 _log.warning('Failed to remove old %s %s files' % (self._name, l og_prefix))
162 163
163 def _spawn_process(self): 164 def _spawn_process(self):
164 _log.debug('Starting %s server, cmd="%s"' % (self._name, self._start_cmd )) 165 _log.debug('Starting %s server, cmd="%s"' % (self._name, self._start_cmd ))
165 process = self._executive.popen(self._start_cmd, env=self._env, stdout=s elf._stdout, stderr=self._stderr) 166 process = self._executive.popen(self._start_cmd, env=self._env, stdout=s elf._stdout, stderr=self._stderr)
166 pid = process.pid 167 pid = process.pid
167 self._filesystem.write_text_file(self._pid_file, str(pid)) 168 self._filesystem.write_text_file(self._pid_file, str(pid))
168 return pid 169 return pid
169 170
170 def _stop_running_server(self): 171 def _stop_running_server(self):
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 else: 223 else:
223 _log.error('%s no error log' % self._name) 224 _log.error('%s no error log' % self._name)
224 225
225 def _wait_for_action(self, action, wait_secs=20.0, sleep_secs=1.0): 226 def _wait_for_action(self, action, wait_secs=20.0, sleep_secs=1.0):
226 """Repeat the action for wait_sec or until it succeeds, sleeping for sle ep_secs 227 """Repeat the action for wait_sec or until it succeeds, sleeping for sle ep_secs
227 in between each attempt. Returns whether it succeeded.""" 228 in between each attempt. Returns whether it succeeded."""
228 start_time = time.time() 229 start_time = time.time()
229 while time.time() - start_time < wait_secs: 230 while time.time() - start_time < wait_secs:
230 if action(): 231 if action():
231 return True 232 return True
232 _log.debug("Waiting for action: %s" % action) 233 _log.debug('Waiting for action: %s' % action)
233 time.sleep(sleep_secs) 234 time.sleep(sleep_secs)
234 235
235 return False 236 return False
236 237
237 def _is_server_running_on_all_ports(self): 238 def _is_server_running_on_all_ports(self):
238 """Returns whether the server is running on all the desired ports.""" 239 """Returns whether the server is running on all the desired ports."""
239 240
240 # TODO(dpranke): crbug/378444 maybe pid is unreliable on win? 241 # TODO(dpranke): crbug/378444 maybe pid is unreliable on win?
241 if not self._platform.is_win() and not self._executive.check_running_pid (self._pid): 242 if not self._platform.is_win() and not self._executive.check_running_pid (self._pid):
242 _log.debug("Server isn't running at all") 243 _log.debug("Server isn't running at all")
243 self._log_errors_from_subprocess() 244 self._log_errors_from_subprocess()
244 raise ServerError("Server exited") 245 raise ServerError('Server exited')
245 246
246 for mapping in self._mappings: 247 for mapping in self._mappings:
247 s = socket.socket() 248 s = socket.socket()
248 port = mapping['port'] 249 port = mapping['port']
249 try: 250 try:
250 s.connect(('localhost', port)) 251 s.connect(('localhost', port))
251 _log.debug("Server running on %d" % port) 252 _log.debug('Server running on %d' % port)
252 except IOError, e: 253 except IOError as e:
253 if e.errno not in (errno.ECONNREFUSED, errno.ECONNRESET): 254 if e.errno not in (errno.ECONNREFUSED, errno.ECONNRESET):
254 raise 255 raise
255 _log.debug("Server NOT running on %d: %s" % (port, e)) 256 _log.debug('Server NOT running on %d: %s' % (port, e))
256 return False 257 return False
257 finally: 258 finally:
258 s.close() 259 s.close()
259 return True 260 return True
260 261
261 def _check_that_all_ports_are_available(self): 262 def _check_that_all_ports_are_available(self):
262 for mapping in self._mappings: 263 for mapping in self._mappings:
263 s = socket.socket() 264 s = socket.socket()
264 if not self._platform.is_win(): 265 if not self._platform.is_win():
265 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 266 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
266 port = mapping['port'] 267 port = mapping['port']
267 try: 268 try:
268 s.bind(('localhost', port)) 269 s.bind(('localhost', port))
269 except IOError, e: 270 except IOError as e:
270 if e.errno in (errno.EALREADY, errno.EADDRINUSE): 271 if e.errno in (errno.EALREADY, errno.EADDRINUSE):
271 raise ServerError('Port %d is already in use.' % port) 272 raise ServerError('Port %d is already in use.' % port)
272 elif self._platform.is_win() and e.errno in (errno.WSAEACCES,): # pylint: disable=E1101 273 elif self._platform.is_win() and e.errno in (errno.WSAEACCES,): # pylint: disable=E1101
273 raise ServerError('Port %d is already in use.' % port) 274 raise ServerError('Port %d is already in use.' % port)
274 else: 275 else:
275 raise 276 raise
276 finally: 277 finally:
277 s.close() 278 s.close()
278 _log.debug('all ports are available') 279 _log.debug('all ports are available')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698