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

Side by Side Diff: Tools/Scripts/webkitpy/layout_tests/port/driver.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 28 matching lines...) Expand all
39 from webkitpy.common.system.profiler import ProfilerFactory 39 from webkitpy.common.system.profiler import ProfilerFactory
40 40
41 41
42 _log = logging.getLogger(__name__) 42 _log = logging.getLogger(__name__)
43 43
44 44
45 DRIVER_START_TIMEOUT_SECS = 30 45 DRIVER_START_TIMEOUT_SECS = 30
46 46
47 47
48 class DriverInput(object): 48 class DriverInput(object):
49
49 def __init__(self, test_name, timeout, image_hash, should_run_pixel_test, ar gs): 50 def __init__(self, test_name, timeout, image_hash, should_run_pixel_test, ar gs):
50 self.test_name = test_name 51 self.test_name = test_name
51 self.timeout = timeout # in ms 52 self.timeout = timeout # in ms
52 self.image_hash = image_hash 53 self.image_hash = image_hash
53 self.should_run_pixel_test = should_run_pixel_test 54 self.should_run_pixel_test = should_run_pixel_test
54 self.args = args 55 self.args = args
55 56
56 57
57 class DriverOutput(object): 58 class DriverOutput(object):
59
58 """Groups information about a output from driver for easy passing 60 """Groups information about a output from driver for easy passing
59 and post-processing of data.""" 61 and post-processing of data."""
60 62
61 def __init__(self, text, image, image_hash, audio, crash=False, 63 def __init__(self, text, image, image_hash, audio, crash=False,
62 test_time=0, measurements=None, timeout=False, error='', crashed_pro cess_name='??', 64 test_time=0, measurements=None, timeout=False, error='', crashe d_process_name='??',
63 crashed_pid=None, crash_log=None, leak=False, leak_log=None, pid=Non e): 65 crashed_pid=None, crash_log=None, leak=False, leak_log=None, pi d=None):
64 # FIXME: Args could be renamed to better clarify what they do. 66 # FIXME: Args could be renamed to better clarify what they do.
65 self.text = text 67 self.text = text
66 self.image = image # May be empty-string if the test crashes. 68 self.image = image # May be empty-string if the test crashes.
67 self.image_hash = image_hash 69 self.image_hash = image_hash
68 self.image_diff = None # image_diff gets filled in after construction. 70 self.image_diff = None # image_diff gets filled in after construction.
69 self.audio = audio # Binary format is port-dependent. 71 self.audio = audio # Binary format is port-dependent.
70 self.crash = crash 72 self.crash = crash
71 self.crashed_process_name = crashed_process_name 73 self.crashed_process_name = crashed_process_name
72 self.crashed_pid = crashed_pid 74 self.crashed_pid = crashed_pid
73 self.crash_log = crash_log 75 self.crash_log = crash_log
74 self.leak = leak 76 self.leak = leak
75 self.leak_log = leak_log 77 self.leak_log = leak_log
76 self.test_time = test_time 78 self.test_time = test_time
77 self.measurements = measurements 79 self.measurements = measurements
78 self.timeout = timeout 80 self.timeout = timeout
79 self.error = error # stderr output 81 self.error = error # stderr output
80 self.pid = pid 82 self.pid = pid
81 83
82 def has_stderr(self): 84 def has_stderr(self):
83 return bool(self.error) 85 return bool(self.error)
84 86
85 87
86 class DeviceFailure(Exception): 88 class DeviceFailure(Exception):
87 pass 89 pass
88 90
89 91
90 class Driver(object): 92 class Driver(object):
93
91 """object for running test(s) using content_shell or other driver.""" 94 """object for running test(s) using content_shell or other driver."""
92 95
93 def __init__(self, port, worker_number, pixel_tests, no_timeout=False): 96 def __init__(self, port, worker_number, pixel_tests, no_timeout=False):
94 """Initialize a Driver to subsequently run tests. 97 """Initialize a Driver to subsequently run tests.
95 98
96 Typically this routine will spawn content_shell in a config 99 Typically this routine will spawn content_shell in a config
97 ready for subsequent input. 100 ready for subsequent input.
98 101
99 port - reference back to the port object. 102 port - reference back to the port object.
100 worker_number - identifier for a particular worker/driver instance 103 worker_number - identifier for a particular worker/driver instance
(...skipping 22 matching lines...) Expand all
123 # stderr reading is scoped on a per-test (not per-block) basis, so we st ore the accumulated 126 # stderr reading is scoped on a per-test (not per-block) basis, so we st ore the accumulated
124 # stderr output, as well as if we've seen #EOF on this driver instance. 127 # stderr output, as well as if we've seen #EOF on this driver instance.
125 # FIXME: We should probably remove _read_first_block and _read_optional_ image_block and 128 # FIXME: We should probably remove _read_first_block and _read_optional_ image_block and
126 # instead scope these locally in run_test. 129 # instead scope these locally in run_test.
127 self.error_from_test = str() 130 self.error_from_test = str()
128 self.err_seen_eof = False 131 self.err_seen_eof = False
129 self._server_process = None 132 self._server_process = None
130 self._current_cmd_line = None 133 self._current_cmd_line = None
131 134
132 self._measurements = {} 135 self._measurements = {}
133 if self._port.get_option("profile"): 136 if self._port.get_option('profile'):
134 profiler_name = self._port.get_option("profiler") 137 profiler_name = self._port.get_option('profiler')
135 self._profiler = ProfilerFactory.create_profiler(self._port.host, 138 self._profiler = ProfilerFactory.create_profiler(self._port.host,
136 self._port._path_to_driver(), self._port.results_directory(), pr ofiler_name) 139 self._port._path_to _driver(), self._port.results_directory(), profiler_name)
137 else: 140 else:
138 self._profiler = None 141 self._profiler = None
139 142
140 def __del__(self): 143 def __del__(self):
141 self.stop() 144 self.stop()
142 145
143 def run_test(self, driver_input, stop_when_done): 146 def run_test(self, driver_input, stop_when_done):
144 """Run a single test and return the results. 147 """Run a single test and return the results.
145 148
146 Note that it is okay if a test times out or crashes and leaves 149 Note that it is okay if a test times out or crashes and leaves
(...skipping 17 matching lines...) Expand all
164 image, actual_image_hash = self._read_optional_image_block(deadline) # The second (optional) block is image data. 167 image, actual_image_hash = self._read_optional_image_block(deadline) # The second (optional) block is image data.
165 168
166 crashed = self.has_crashed() 169 crashed = self.has_crashed()
167 timed_out = self._server_process.timed_out 170 timed_out = self._server_process.timed_out
168 pid = self._server_process.pid() 171 pid = self._server_process.pid()
169 leaked = self._leaked 172 leaked = self._leaked
170 173
171 if not crashed: 174 if not crashed:
172 sanitizer = self._port._output_contains_sanitizer_messages(self.erro r_from_test) 175 sanitizer = self._port._output_contains_sanitizer_messages(self.erro r_from_test)
173 if sanitizer: 176 if sanitizer:
174 self.error_from_test = 'OUTPUT CONTAINS "' + sanitizer + '", so we are treating this test as if it crashed, even though it did not.\n\n' + self. error_from_test 177 self.error_from_test = 'OUTPUT CONTAINS "' + sanitizer + \
178 '", so we are treating this test as if it crashed, even thou gh it did not.\n\n' + self.error_from_test
175 crashed = True 179 crashed = True
176 self._crashed_process_name = "unknown process name" 180 self._crashed_process_name = 'unknown process name'
177 self._crashed_pid = 0 181 self._crashed_pid = 0
178 182
179 if stop_when_done or crashed or timed_out or leaked: 183 if stop_when_done or crashed or timed_out or leaked:
180 # We call stop() even if we crashed or timed out in order to get any remaining stdout/stderr output. 184 # We call stop() even if we crashed or timed out in order to get any remaining stdout/stderr output.
181 # In the timeout case, we kill the hung process as well. 185 # In the timeout case, we kill the hung process as well.
182 out, err = self._server_process.stop(self._port.driver_stop_timeout( ) if stop_when_done else 0.0) 186 out, err = self._server_process.stop(self._port.driver_stop_timeout( ) if stop_when_done else 0.0)
183 if out: 187 if out:
184 text += out 188 text += out
185 if err: 189 if err:
186 self.error_from_test += err 190 self.error_from_test += err
187 self._server_process = None 191 self._server_process = None
188 192
189 crash_log = None 193 crash_log = None
190 if crashed: 194 if crashed:
191 self.error_from_test, crash_log = self._get_crash_log(text, self.err or_from_test, newer_than=start_time) 195 self.error_from_test, crash_log = self._get_crash_log(text, self.err or_from_test, newer_than=start_time)
192 196
193 # If we don't find a crash log use a placeholder error message inste ad. 197 # If we don't find a crash log use a placeholder error message inste ad.
194 if not crash_log: 198 if not crash_log:
195 pid_str = str(self._crashed_pid) if self._crashed_pid else "unkn own pid" 199 pid_str = str(self._crashed_pid) if self._crashed_pid else 'unkn own pid'
196 crash_log = 'No crash log found for %s:%s.\n' % (self._crashed_p rocess_name, pid_str) 200 crash_log = 'No crash log found for %s:%s.\n' % (self._crashed_p rocess_name, pid_str)
197 # If we were unresponsive append a message informing there may n ot have been a crash. 201 # If we were unresponsive append a message informing there may n ot have been a crash.
198 if self._subprocess_was_unresponsive: 202 if self._subprocess_was_unresponsive:
199 crash_log += 'Process failed to become responsive before tim ing out.\n' 203 crash_log += 'Process failed to become responsive before tim ing out.\n'
200 204
201 # Print stdout and stderr to the placeholder crash log; we want as much context as possible. 205 # Print stdout and stderr to the placeholder crash log; we want as much context as possible.
202 if self.error_from_test: 206 if self.error_from_test:
203 crash_log += '\nstdout:\n%s\nstderr:\n%s\n' % (text, self.er ror_from_test) 207 crash_log += '\nstdout:\n%s\nstderr:\n%s\n' % (text, self.er ror_from_test)
204 208
205 return DriverOutput(text, image, actual_image_hash, audio, 209 return DriverOutput(text, image, actual_image_hash, audio,
206 crash=crashed, test_time=time.time() - test_begin_time, measurements =self._measurements, 210 crash=crashed, test_time=time.time() - test_begin_ti me, measurements=self._measurements,
207 timeout=timed_out, error=self.error_from_test, 211 timeout=timed_out, error=self.error_from_test,
208 crashed_process_name=self._crashed_process_name, 212 crashed_process_name=self._crashed_process_name,
209 crashed_pid=self._crashed_pid, crash_log=crash_log, 213 crashed_pid=self._crashed_pid, crash_log=crash_log,
210 leak=leaked, leak_log=self._leak_log, 214 leak=leaked, leak_log=self._leak_log,
211 pid=pid) 215 pid=pid)
212 216
213 def _get_crash_log(self, stdout, stderr, newer_than): 217 def _get_crash_log(self, stdout, stderr, newer_than):
214 return self._port._get_crash_log(self._crashed_process_name, self._crash ed_pid, stdout, stderr, newer_than) 218 return self._port._get_crash_log(self._crashed_process_name, self._crash ed_pid, stdout, stderr, newer_than)
215 219
216 # FIXME: Seems this could just be inlined into callers. 220 # FIXME: Seems this could just be inlined into callers.
217 @classmethod 221 @classmethod
218 def _command_wrapper(cls, wrapper_option): 222 def _command_wrapper(cls, wrapper_option):
219 # Hook for injecting valgrind or other runtime instrumentation, 223 # Hook for injecting valgrind or other runtime instrumentation,
220 # used by e.g. tools/valgrind/valgrind_tests.py. 224 # used by e.g. tools/valgrind/valgrind_tests.py.
221 return shlex.split(wrapper_option) if wrapper_option else [] 225 return shlex.split(wrapper_option) if wrapper_option else []
222 226
223 HTTP_DIR = "http/tests/" 227 HTTP_DIR = 'http/tests/'
224 HTTP_LOCAL_DIR = "http/tests/local/" 228 HTTP_LOCAL_DIR = 'http/tests/local/'
225 229
226 def is_http_test(self, test_name): 230 def is_http_test(self, test_name):
227 return test_name.startswith(self.HTTP_DIR) and not test_name.startswith( self.HTTP_LOCAL_DIR) 231 return test_name.startswith(self.HTTP_DIR) and not test_name.startswith( self.HTTP_LOCAL_DIR)
228 232
229 def test_to_uri(self, test_name): 233 def test_to_uri(self, test_name):
230 """Convert a test name to a URI. 234 """Convert a test name to a URI.
231 235
232 Tests which have an 'https' directory in their paths (e.g. 236 Tests which have an 'https' directory in their paths (e.g.
233 '/http/tests/security/mixedContent/https/test1.html') will be loaded 237 '/http/tests/security/mixedContent/https/test1.html') will be loaded
234 over HTTPS; all other tests over HTTP. 238 over HTTPS; all other tests over HTTP.
235 """ 239 """
236 if not self.is_http_test(test_name): 240 if not self.is_http_test(test_name):
237 return path.abspath_to_uri(self._port.host.platform, self._port.absp ath_for_test(test_name)) 241 return path.abspath_to_uri(self._port.host.platform, self._port.absp ath_for_test(test_name))
238 242
239 relative_path = test_name[len(self.HTTP_DIR):] 243 relative_path = test_name[len(self.HTTP_DIR):]
240 244
241 if "/https/" in test_name: 245 if '/https/' in test_name:
242 return "https://127.0.0.1:8443/" + relative_path 246 return 'https://127.0.0.1:8443/' + relative_path
243 return "http://127.0.0.1:8000/" + relative_path 247 return 'http://127.0.0.1:8000/' + relative_path
244 248
245 def uri_to_test(self, uri): 249 def uri_to_test(self, uri):
246 """Return the base layout test name for a given URI. 250 """Return the base layout test name for a given URI.
247 251
248 This returns the test name for a given URI, e.g., if you passed in 252 This returns the test name for a given URI, e.g., if you passed in
249 "file:///src/LayoutTests/fast/html/keygen.html" it would return 253 "file:///src/LayoutTests/fast/html/keygen.html" it would return
250 "fast/html/keygen.html". 254 "fast/html/keygen.html".
251 255
252 """ 256 """
253 if uri.startswith("file:///"): 257 if uri.startswith('file:///'):
254 prefix = path.abspath_to_uri(self._port.host.platform, self._port.la yout_tests_dir()) 258 prefix = path.abspath_to_uri(self._port.host.platform, self._port.la yout_tests_dir())
255 if not prefix.endswith('/'): 259 if not prefix.endswith('/'):
256 prefix += '/' 260 prefix += '/'
257 return uri[len(prefix):] 261 return uri[len(prefix):]
258 if uri.startswith("http://"): 262 if uri.startswith('http://'):
259 return uri.replace('http://127.0.0.1:8000/', self.HTTP_DIR) 263 return uri.replace('http://127.0.0.1:8000/', self.HTTP_DIR)
260 if uri.startswith("https://"): 264 if uri.startswith('https://'):
261 return uri.replace('https://127.0.0.1:8443/', self.HTTP_DIR) 265 return uri.replace('https://127.0.0.1:8443/', self.HTTP_DIR)
262 raise NotImplementedError('unknown url type: %s' % uri) 266 raise NotImplementedError('unknown url type: %s' % uri)
263 267
264 def has_crashed(self): 268 def has_crashed(self):
265 if self._server_process is None: 269 if self._server_process is None:
266 return False 270 return False
267 if self._crashed_process_name: 271 if self._crashed_process_name:
268 return True 272 return True
269 if self._server_process.has_crashed(): 273 if self._server_process.has_crashed():
270 self._crashed_process_name = self._server_process.name() 274 self._crashed_process_name = self._server_process.name()
(...skipping 16 matching lines...) Expand all
287 self.stop() 291 self.stop()
288 self._driver_tempdir = self._port._filesystem.mkdtemp(prefix='%s-' % sel f._port.driver_name()) 292 self._driver_tempdir = self._port._filesystem.mkdtemp(prefix='%s-' % sel f._port.driver_name())
289 server_name = self._port.driver_name() 293 server_name = self._port.driver_name()
290 environment = self._port.setup_environ_for_server(server_name) 294 environment = self._port.setup_environ_for_server(server_name)
291 environment = self._setup_environ_for_driver(environment) 295 environment = self._setup_environ_for_driver(environment)
292 self._crashed_process_name = None 296 self._crashed_process_name = None
293 self._crashed_pid = None 297 self._crashed_pid = None
294 self._leaked = False 298 self._leaked = False
295 self._leak_log = None 299 self._leak_log = None
296 cmd_line = self.cmd_line(pixel_tests, per_test_args) 300 cmd_line = self.cmd_line(pixel_tests, per_test_args)
297 self._server_process = self._port._server_process_constructor(self._port , server_name, cmd_line, environment, logging=self._port.get_option("driver_logg ing")) 301 self._server_process = self._port._server_process_constructor(
302 self._port,
303 server_name,
304 cmd_line,
305 environment,
306 logging=self._port.get_option('driver_logging'))
298 self._server_process.start() 307 self._server_process.start()
299 self._current_cmd_line = cmd_line 308 self._current_cmd_line = cmd_line
300 309
301 if wait_for_ready: 310 if wait_for_ready:
302 deadline = time.time() + DRIVER_START_TIMEOUT_SECS 311 deadline = time.time() + DRIVER_START_TIMEOUT_SECS
303 if not self._wait_for_server_process_output(self._server_process, de adline, '#READY'): 312 if not self._wait_for_server_process_output(self._server_process, de adline, '#READY'):
304 _log.error("content_shell took too long to startup.") 313 _log.error('content_shell took too long to startup.')
305 314
306 def _wait_for_server_process_output(self, server_process, deadline, text): 315 def _wait_for_server_process_output(self, server_process, deadline, text):
307 output = '' 316 output = ''
308 line = server_process.read_stdout_line(deadline) 317 line = server_process.read_stdout_line(deadline)
309 while not server_process.timed_out and not server_process.has_crashed() and not text in line.rstrip(): 318 while not server_process.timed_out and not server_process.has_crashed() and not text in line.rstrip():
310 output += line 319 output += line
311 line = server_process.read_stdout_line(deadline) 320 line = server_process.read_stdout_line(deadline)
312 321
313 if server_process.timed_out or server_process.has_crashed(): 322 if server_process.timed_out or server_process.has_crashed():
314 _log.error('Failed to start the %s process: \n%s' % (server_process. name(), output)) 323 _log.error('Failed to start the %s process: \n%s' % (server_process. name(), output))
(...skipping 30 matching lines...) Expand all
345 cmd.append('--no-timeout') 354 cmd.append('--no-timeout')
346 cmd.extend(self._port.get_option('additional_drt_flag', [])) 355 cmd.extend(self._port.get_option('additional_drt_flag', []))
347 cmd.extend(self._port.additional_drt_flag()) 356 cmd.extend(self._port.additional_drt_flag())
348 if self._port.get_option('enable_leak_detection'): 357 if self._port.get_option('enable_leak_detection'):
349 cmd.append('--enable-leak-detection') 358 cmd.append('--enable-leak-detection')
350 cmd.extend(per_test_args) 359 cmd.extend(per_test_args)
351 cmd.append('-') 360 cmd.append('-')
352 return cmd 361 return cmd
353 362
354 def _check_for_driver_crash(self, error_line): 363 def _check_for_driver_crash(self, error_line):
355 if error_line == "#CRASHED\n": 364 if error_line == '#CRASHED\n':
356 # This is used on Windows to report that the process has crashed 365 # This is used on Windows to report that the process has crashed
357 # See http://trac.webkit.org/changeset/65537. 366 # See http://trac.webkit.org/changeset/65537.
358 self._crashed_process_name = self._server_process.name() 367 self._crashed_process_name = self._server_process.name()
359 self._crashed_pid = self._server_process.pid() 368 self._crashed_pid = self._server_process.pid()
360 elif (error_line.startswith("#CRASHED - ") 369 elif (error_line.startswith('#CRASHED - ')
361 or error_line.startswith("#PROCESS UNRESPONSIVE - ")): 370 or error_line.startswith('#PROCESS UNRESPONSIVE - ')):
362 # WebKitTestRunner uses this to report that the WebProcess subproces s crashed. 371 # WebKitTestRunner uses this to report that the WebProcess subproces s crashed.
363 match = re.match('#(?:CRASHED|PROCESS UNRESPONSIVE) - (\S+)', error_ line) 372 match = re.match('#(?:CRASHED|PROCESS UNRESPONSIVE) - (\S+)', error_ line)
364 self._crashed_process_name = match.group(1) if match else 'WebProces s' 373 self._crashed_process_name = match.group(1) if match else 'WebProces s'
365 match = re.search('pid (\d+)', error_line) 374 match = re.search('pid (\d+)', error_line)
366 pid = int(match.group(1)) if match else None 375 pid = int(match.group(1)) if match else None
367 self._crashed_pid = pid 376 self._crashed_pid = pid
368 # FIXME: delete this after we're sure this code is working :) 377 # FIXME: delete this after we're sure this code is working :)
369 _log.debug('%s crash, pid = %s, error_line = %s' % (self._crashed_pr ocess_name, str(pid), error_line)) 378 _log.debug('%s crash, pid = %s, error_line = %s' % (self._crashed_pr ocess_name, str(pid), error_line))
370 if error_line.startswith("#PROCESS UNRESPONSIVE - "): 379 if error_line.startswith('#PROCESS UNRESPONSIVE - '):
371 self._subprocess_was_unresponsive = True 380 self._subprocess_was_unresponsive = True
372 self._port.sample_process(self._crashed_process_name, self._cras hed_pid) 381 self._port.sample_process(self._crashed_process_name, self._cras hed_pid)
373 # We want to show this since it's not a regular crash and probab ly we don't have a crash log. 382 # We want to show this since it's not a regular crash and probab ly we don't have a crash log.
374 self.error_from_test += error_line 383 self.error_from_test += error_line
375 return True 384 return True
376 return self.has_crashed() 385 return self.has_crashed()
377 386
378 def _check_for_leak(self, error_line): 387 def _check_for_leak(self, error_line):
379 if error_line.startswith("#LEAK - "): 388 if error_line.startswith('#LEAK - '):
380 self._leaked = True 389 self._leaked = True
381 match = re.match('#LEAK - (\S+) pid (\d+) (.+)\n', error_line) 390 match = re.match('#LEAK - (\S+) pid (\d+) (.+)\n', error_line)
382 self._leak_log = match.group(3) 391 self._leak_log = match.group(3)
383 return self._leaked 392 return self._leaked
384 393
385 def _command_from_driver_input(self, driver_input): 394 def _command_from_driver_input(self, driver_input):
386 # FIXME: performance tests pass in full URLs instead of test names. 395 # FIXME: performance tests pass in full URLs instead of test names.
387 if driver_input.test_name.startswith('http://') or driver_input.test_nam e.startswith('https://') or driver_input.test_name == ('about:blank'): 396 if driver_input.test_name.startswith(
397 'http://') or driver_input.test_name.startswith('https://') or d river_input.test_name == ('about:blank'):
388 command = driver_input.test_name 398 command = driver_input.test_name
389 elif self.is_http_test(driver_input.test_name): 399 elif self.is_http_test(driver_input.test_name):
390 command = self.test_to_uri(driver_input.test_name) 400 command = self.test_to_uri(driver_input.test_name)
391 else: 401 else:
392 command = self._port.abspath_for_test(driver_input.test_name) 402 command = self._port.abspath_for_test(driver_input.test_name)
393 if sys.platform == 'cygwin': 403 if sys.platform == 'cygwin':
394 command = path.cygpath(command) 404 command = path.cygpath(command)
395 405
396 assert not driver_input.image_hash or driver_input.should_run_pixel_test 406 assert not driver_input.image_hash or driver_input.should_run_pixel_test
397 407
398 # ' is the separator between arguments. 408 # ' is the separator between arguments.
399 if self._port.supports_per_test_timeout(): 409 if self._port.supports_per_test_timeout():
400 command += "'--timeout'%s" % driver_input.timeout 410 command += "'--timeout'%s" % driver_input.timeout
401 if driver_input.should_run_pixel_test: 411 if driver_input.should_run_pixel_test:
402 command += "'--pixel-test" 412 command += "'--pixel-test"
403 if driver_input.image_hash: 413 if driver_input.image_hash:
404 command += "'" + driver_input.image_hash 414 command += "'" + driver_input.image_hash
405 return command + "\n" 415 return command + '\n'
406 416
407 def _read_first_block(self, deadline): 417 def _read_first_block(self, deadline):
408 # returns (text_content, audio_content) 418 # returns (text_content, audio_content)
409 block = self._read_block(deadline) 419 block = self._read_block(deadline)
410 if block.malloc: 420 if block.malloc:
411 self._measurements['Malloc'] = float(block.malloc) 421 self._measurements['Malloc'] = float(block.malloc)
412 if block.js_heap: 422 if block.js_heap:
413 self._measurements['JSHeap'] = float(block.js_heap) 423 self._measurements['JSHeap'] = float(block.js_heap)
414 if block.content_type == 'audio/wav': 424 if block.content_type == 'audio/wav':
415 return (None, block.decoded_content) 425 return (None, block.decoded_content)
(...skipping 10 matching lines...) Expand all
426 if line.startswith(header_text) and getattr(block, header_attr) is None: 436 if line.startswith(header_text) and getattr(block, header_attr) is None:
427 value = line.split()[1] 437 value = line.split()[1]
428 if header_filter: 438 if header_filter:
429 value = header_filter(value) 439 value = header_filter(value)
430 setattr(block, header_attr, value) 440 setattr(block, header_attr, value)
431 return True 441 return True
432 return False 442 return False
433 443
434 def _process_stdout_line(self, block, line): 444 def _process_stdout_line(self, block, line):
435 if (self._read_header(block, line, 'Content-Type: ', 'content_type') 445 if (self._read_header(block, line, 'Content-Type: ', 'content_type')
436 or self._read_header(block, line, 'Content-Transfer-Encoding: ', 'en coding') 446 or self._read_header(block, line, 'Content-Transfer-Encoding: ', 'encoding')
437 or self._read_header(block, line, 'Content-Length: ', '_content_leng th', int) 447 or self._read_header(block, line, 'Content-Length: ', '_content_ length', int)
438 or self._read_header(block, line, 'ActualHash: ', 'content_hash') 448 or self._read_header(block, line, 'ActualHash: ', 'content_hash' )
439 or self._read_header(block, line, 'DumpMalloc: ', 'malloc') 449 or self._read_header(block, line, 'DumpMalloc: ', 'malloc')
440 or self._read_header(block, line, 'DumpJSHeap: ', 'js_heap') 450 or self._read_header(block, line, 'DumpJSHeap: ', 'js_heap')
441 or self._read_header(block, line, 'StdinPath', 'stdin_path')): 451 or self._read_header(block, line, 'StdinPath', 'stdin_path')):
442 return 452 return
443 # Note, we're not reading ExpectedHash: here, but we could. 453 # Note, we're not reading ExpectedHash: here, but we could.
444 # If the line wasn't a header, we just append it to the content. 454 # If the line wasn't a header, we just append it to the content.
445 block.content += line 455 block.content += line
446 456
447 def _strip_eof(self, line): 457 def _strip_eof(self, line):
448 if line and line.endswith("#EOF\n"): 458 if line and line.endswith('#EOF\n'):
449 return line[:-5], True 459 return line[:-5], True
450 if line and line.endswith("#EOF\r\n"): 460 if line and line.endswith('#EOF\r\n'):
451 _log.error("Got a CRLF-terminated #EOF - this is a driver bug.") 461 _log.error('Got a CRLF-terminated #EOF - this is a driver bug.')
452 return line[:-6], True 462 return line[:-6], True
453 return line, False 463 return line, False
454 464
455 def _read_block(self, deadline, wait_for_stderr_eof=False): 465 def _read_block(self, deadline, wait_for_stderr_eof=False):
456 block = ContentBlock() 466 block = ContentBlock()
457 out_seen_eof = False 467 out_seen_eof = False
458 468
459 while not self.has_crashed(): 469 while not self.has_crashed():
460 if out_seen_eof and (self.err_seen_eof or not wait_for_stderr_eof): 470 if out_seen_eof and (self.err_seen_eof or not wait_for_stderr_eof):
461 break 471 break
(...skipping 11 matching lines...) Expand all
473 break 483 break
474 484
475 if out_line: 485 if out_line:
476 assert not out_seen_eof 486 assert not out_seen_eof
477 out_line, out_seen_eof = self._strip_eof(out_line) 487 out_line, out_seen_eof = self._strip_eof(out_line)
478 if err_line: 488 if err_line:
479 assert not self.err_seen_eof 489 assert not self.err_seen_eof
480 err_line, self.err_seen_eof = self._strip_eof(err_line) 490 err_line, self.err_seen_eof = self._strip_eof(err_line)
481 491
482 if out_line: 492 if out_line:
483 if out_line[-1] != "\n": 493 if out_line[-1] != '\n':
484 _log.error("Last character read from DRT stdout line was not a newline! This indicates either a NRWT or DRT bug.") 494 _log.error(
495 'Last character read from DRT stdout line was not a newl ine! This indicates either a NRWT or DRT bug.')
485 content_length_before_header_check = block._content_length 496 content_length_before_header_check = block._content_length
486 self._process_stdout_line(block, out_line) 497 self._process_stdout_line(block, out_line)
487 # FIXME: Unlike HTTP, DRT dumps the content right after printing a Content-Length header. 498 # FIXME: Unlike HTTP, DRT dumps the content right after printing a Content-Length header.
488 # Don't wait until we're done with headers, just read the binary blob right now. 499 # Don't wait until we're done with headers, just read the binary blob right now.
489 if content_length_before_header_check != block._content_length: 500 if content_length_before_header_check != block._content_length:
490 if block._content_length > 0: 501 if block._content_length > 0:
491 block.content = self._server_process.read_stdout(deadlin e, block._content_length) 502 block.content = self._server_process.read_stdout(deadlin e, block._content_length)
492 else: 503 else:
493 _log.error("Received content of type %s with Content-Len gth of 0! This indicates a bug in %s.", 504 _log.error('Received content of type %s with Content-Len gth of 0! This indicates a bug in %s.',
494 block.content_type, self._server_process.name ()) 505 block.content_type, self._server_process.name ())
495 506
496 if err_line: 507 if err_line:
497 if self._check_for_driver_crash(err_line): 508 if self._check_for_driver_crash(err_line):
498 break 509 break
499 if self._check_for_leak(err_line): 510 if self._check_for_leak(err_line):
500 break 511 break
501 self.error_from_test += err_line 512 self.error_from_test += err_line
502 513
503 block.decode_content() 514 block.decode_content()
504 return block 515 return block
505 516
506 517
507 class ContentBlock(object): 518 class ContentBlock(object):
519
508 def __init__(self): 520 def __init__(self):
509 self.content_type = None 521 self.content_type = None
510 self.encoding = None 522 self.encoding = None
511 self.content_hash = None 523 self.content_hash = None
512 self._content_length = None 524 self._content_length = None
513 # Content is treated as binary data even though the text output is usual ly UTF-8. 525 # Content is treated as binary data even though the text output is usual ly UTF-8.
514 self.content = str() # FIXME: Should be bytearray() once we require Pyt hon 2.6. 526 self.content = str() # FIXME: Should be bytearray() once we require Pyt hon 2.6.
515 self.decoded_content = None 527 self.decoded_content = None
516 self.malloc = None 528 self.malloc = None
517 self.js_heap = None 529 self.js_heap = None
518 self.stdin_path = None 530 self.stdin_path = None
519 531
520 def decode_content(self): 532 def decode_content(self):
521 if self.encoding == 'base64' and self.content is not None: 533 if self.encoding == 'base64' and self.content is not None:
522 self.decoded_content = base64.b64decode(self.content) 534 self.decoded_content = base64.b64decode(self.content)
523 else: 535 else:
524 self.decoded_content = self.content 536 self.decoded_content = self.content
OLDNEW
« no previous file with comments | « Tools/Scripts/webkitpy/layout_tests/port/config.py ('k') | Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698