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

Side by Side Diff: Tools/Scripts/webkitpy/layout_tests/port/driver.py

Issue 219083002: Bug fix: Get the leak log not from error strings but from the line (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 8 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 | « Tools/Scripts/webkitpy/layout_tests/port/base.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 # We call stop() even if we crashed or timed out in order to get any remaining stdout/stderr output. 171 # We call stop() even if we crashed or timed out in order to get any remaining stdout/stderr output.
172 # In the timeout case, we kill the hung process as well. 172 # In the timeout case, we kill the hung process as well.
173 out, err = self._server_process.stop(self._port.driver_stop_timeout( ) if stop_when_done else 0.0) 173 out, err = self._server_process.stop(self._port.driver_stop_timeout( ) if stop_when_done else 0.0)
174 if out: 174 if out:
175 text += out 175 text += out
176 if err: 176 if err:
177 self.error_from_test += err 177 self.error_from_test += err
178 self._server_process = None 178 self._server_process = None
179 179
180 crash_log = None 180 crash_log = None
181 leak_log = None
182 if crashed: 181 if crashed:
183 self.error_from_test, crash_log = self._get_crash_log(text, self.err or_from_test, newer_than=start_time) 182 self.error_from_test, crash_log = self._get_crash_log(text, self.err or_from_test, newer_than=start_time)
184 183
185 # If we don't find a crash log use a placeholder error message inste ad. 184 # If we don't find a crash log use a placeholder error message inste ad.
186 if not crash_log: 185 if not crash_log:
187 pid_str = str(self._crashed_pid) if self._crashed_pid else "unkn own pid" 186 pid_str = str(self._crashed_pid) if self._crashed_pid else "unkn own pid"
188 crash_log = 'No crash log found for %s:%s.\n' % (self._crashed_p rocess_name, pid_str) 187 crash_log = 'No crash log found for %s:%s.\n' % (self._crashed_p rocess_name, pid_str)
189 # If we were unresponsive append a message informing there may n ot have been a crash. 188 # If we were unresponsive append a message informing there may n ot have been a crash.
190 if self._subprocess_was_unresponsive: 189 if self._subprocess_was_unresponsive:
191 crash_log += 'Process failed to become responsive before tim ing out.\n' 190 crash_log += 'Process failed to become responsive before tim ing out.\n'
192 191
193 # Print stdout and stderr to the placeholder crash log; we want as much context as possible. 192 # Print stdout and stderr to the placeholder crash log; we want as much context as possible.
194 if self.error_from_test: 193 if self.error_from_test:
195 crash_log += '\nstdout:\n%s\nstderr:\n%s\n' % (text, self.er ror_from_test) 194 crash_log += '\nstdout:\n%s\nstderr:\n%s\n' % (text, self.er ror_from_test)
196 elif leaked:
197 self.error_from_test, leak_log = self._get_leak_log(text, self.error _from_test, newer_than=start_time)
198 195
199 return DriverOutput(text, image, actual_image_hash, audio, 196 return DriverOutput(text, image, actual_image_hash, audio,
200 crash=crashed, test_time=time.time() - test_begin_time, measurements =self._measurements, 197 crash=crashed, test_time=time.time() - test_begin_time, measurements =self._measurements,
201 timeout=timed_out, error=self.error_from_test, 198 timeout=timed_out, error=self.error_from_test,
202 crashed_process_name=self._crashed_process_name, 199 crashed_process_name=self._crashed_process_name,
203 crashed_pid=self._crashed_pid, crash_log=crash_log, 200 crashed_pid=self._crashed_pid, crash_log=crash_log,
204 leak=leaked, leak_log=leak_log, 201 leak=leaked, leak_log=self._leak_log,
205 pid=pid) 202 pid=pid)
206 203
207 def _get_crash_log(self, stdout, stderr, newer_than): 204 def _get_crash_log(self, stdout, stderr, newer_than):
208 return self._port._get_crash_log(self._crashed_process_name, self._crash ed_pid, stdout, stderr, newer_than) 205 return self._port._get_crash_log(self._crashed_process_name, self._crash ed_pid, stdout, stderr, newer_than)
209 206
210 def _get_leak_log(self, stdout, stderr, newer_than):
211 return self._port._get_leak_log(self._crashed_process_name, self._crashe d_pid, stdout, stderr, newer_than)
212
213 # FIXME: Seems this could just be inlined into callers. 207 # FIXME: Seems this could just be inlined into callers.
214 @classmethod 208 @classmethod
215 def _command_wrapper(cls, wrapper_option): 209 def _command_wrapper(cls, wrapper_option):
216 # Hook for injecting valgrind or other runtime instrumentation, 210 # Hook for injecting valgrind or other runtime instrumentation,
217 # used by e.g. tools/valgrind/valgrind_tests.py. 211 # used by e.g. tools/valgrind/valgrind_tests.py.
218 return shlex.split(wrapper_option) if wrapper_option else [] 212 return shlex.split(wrapper_option) if wrapper_option else []
219 213
220 HTTP_DIR = "http/tests/" 214 HTTP_DIR = "http/tests/"
221 HTTP_LOCAL_DIR = "http/tests/local/" 215 HTTP_LOCAL_DIR = "http/tests/local/"
222 216
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 272
279 def _start(self, pixel_tests, per_test_args, wait_for_ready=True): 273 def _start(self, pixel_tests, per_test_args, wait_for_ready=True):
280 self.stop() 274 self.stop()
281 self._driver_tempdir = self._port._filesystem.mkdtemp(prefix='%s-' % sel f._port.driver_name()) 275 self._driver_tempdir = self._port._filesystem.mkdtemp(prefix='%s-' % sel f._port.driver_name())
282 server_name = self._port.driver_name() 276 server_name = self._port.driver_name()
283 environment = self._port.setup_environ_for_server(server_name) 277 environment = self._port.setup_environ_for_server(server_name)
284 environment = self._setup_environ_for_driver(environment) 278 environment = self._setup_environ_for_driver(environment)
285 self._crashed_process_name = None 279 self._crashed_process_name = None
286 self._crashed_pid = None 280 self._crashed_pid = None
287 self._leaked = False 281 self._leaked = False
282 self._leak_log = None
288 cmd_line = self.cmd_line(pixel_tests, per_test_args) 283 cmd_line = self.cmd_line(pixel_tests, per_test_args)
289 self._server_process = self._port._server_process_constructor(self._port , server_name, cmd_line, environment, logging=self._port.get_option("driver_logg ing")) 284 self._server_process = self._port._server_process_constructor(self._port , server_name, cmd_line, environment, logging=self._port.get_option("driver_logg ing"))
290 self._server_process.start() 285 self._server_process.start()
291 self._current_cmd_line = cmd_line 286 self._current_cmd_line = cmd_line
292 287
293 if wait_for_ready: 288 if wait_for_ready:
294 deadline = time.time() + DRIVER_START_TIMEOUT_SECS 289 deadline = time.time() + DRIVER_START_TIMEOUT_SECS
295 if not self._wait_for_server_process_output(self._server_process, de adline, '#READY'): 290 if not self._wait_for_server_process_output(self._server_process, de adline, '#READY'):
296 _log.error("content_shell took too long to startup.") 291 _log.error("content_shell took too long to startup.")
297 292
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 self._subprocess_was_unresponsive = True 358 self._subprocess_was_unresponsive = True
364 self._port.sample_process(self._crashed_process_name, self._cras hed_pid) 359 self._port.sample_process(self._crashed_process_name, self._cras hed_pid)
365 # We want to show this since it's not a regular crash and probab ly we don't have a crash log. 360 # We want to show this since it's not a regular crash and probab ly we don't have a crash log.
366 self.error_from_test += error_line 361 self.error_from_test += error_line
367 return True 362 return True
368 return self.has_crashed() 363 return self.has_crashed()
369 364
370 def _check_for_leak(self, error_line): 365 def _check_for_leak(self, error_line):
371 if error_line.startswith("#LEAK - "): 366 if error_line.startswith("#LEAK - "):
372 self._leaked = True 367 self._leaked = True
368 match = re.match('#LEAK - (\S+) pid (\d+) (.+)\n', error_line)
369 self._leak_log = match.group(3)
373 return self._leaked 370 return self._leaked
374 371
375 def _command_from_driver_input(self, driver_input): 372 def _command_from_driver_input(self, driver_input):
376 # FIXME: performance tests pass in full URLs instead of test names. 373 # FIXME: performance tests pass in full URLs instead of test names.
377 if driver_input.test_name.startswith('http://') or driver_input.test_nam e.startswith('https://') or driver_input.test_name == ('about:blank'): 374 if driver_input.test_name.startswith('http://') or driver_input.test_nam e.startswith('https://') or driver_input.test_name == ('about:blank'):
378 command = driver_input.test_name 375 command = driver_input.test_name
379 elif self.is_http_test(driver_input.test_name): 376 elif self.is_http_test(driver_input.test_name):
380 command = self.test_to_uri(driver_input.test_name) 377 command = self.test_to_uri(driver_input.test_name)
381 else: 378 else:
382 command = self._port.abspath_for_test(driver_input.test_name) 379 command = self._port.abspath_for_test(driver_input.test_name)
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 if content_length_before_header_check != block._content_length: 475 if content_length_before_header_check != block._content_length:
479 if block._content_length > 0: 476 if block._content_length > 0:
480 block.content = self._server_process.read_stdout(deadlin e, block._content_length) 477 block.content = self._server_process.read_stdout(deadlin e, block._content_length)
481 else: 478 else:
482 _log.error("Received content of type %s with Content-Len gth of 0! This indicates a bug in %s.", 479 _log.error("Received content of type %s with Content-Len gth of 0! This indicates a bug in %s.",
483 block.content_type, self._server_process.name ()) 480 block.content_type, self._server_process.name ())
484 481
485 if err_line: 482 if err_line:
486 if self._check_for_driver_crash(err_line): 483 if self._check_for_driver_crash(err_line):
487 break 484 break
488 self._check_for_leak(err_line) 485 if self._check_for_leak(err_line):
486 break
489 self.error_from_test += err_line 487 self.error_from_test += err_line
490 488
491 block.decode_content() 489 block.decode_content()
492 return block 490 return block
493 491
494 492
495 class ContentBlock(object): 493 class ContentBlock(object):
496 def __init__(self): 494 def __init__(self):
497 self.content_type = None 495 self.content_type = None
498 self.encoding = None 496 self.encoding = None
499 self.content_hash = None 497 self.content_hash = None
500 self._content_length = None 498 self._content_length = None
501 # Content is treated as binary data even though the text output is usual ly UTF-8. 499 # Content is treated as binary data even though the text output is usual ly UTF-8.
502 self.content = str() # FIXME: Should be bytearray() once we require Pyt hon 2.6. 500 self.content = str() # FIXME: Should be bytearray() once we require Pyt hon 2.6.
503 self.decoded_content = None 501 self.decoded_content = None
504 self.malloc = None 502 self.malloc = None
505 self.js_heap = None 503 self.js_heap = None
506 504
507 def decode_content(self): 505 def decode_content(self):
508 if self.encoding == 'base64' and self.content is not None: 506 if self.encoding == 'base64' and self.content is not None:
509 self.decoded_content = base64.b64decode(self.content) 507 self.decoded_content = base64.b64decode(self.content)
510 else: 508 else:
511 self.decoded_content = self.content 509 self.decoded_content = self.content
OLDNEW
« no previous file with comments | « Tools/Scripts/webkitpy/layout_tests/port/base.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698