| Index: Tools/Scripts/webkitpy/layout_tests/port/driver.py
|
| diff --git a/Tools/Scripts/webkitpy/layout_tests/port/driver.py b/Tools/Scripts/webkitpy/layout_tests/port/driver.py
|
| index e7a439d04baa9cbc547e81bcd3f8a5360751853a..fd44a53e7f034f5a436922c8cea7e97bc8760213 100644
|
| --- a/Tools/Scripts/webkitpy/layout_tests/port/driver.py
|
| +++ b/Tools/Scripts/webkitpy/layout_tests/port/driver.py
|
| @@ -60,7 +60,7 @@ class DriverOutput(object):
|
|
|
| def __init__(self, text, image, image_hash, audio, crash=False,
|
| test_time=0, measurements=None, timeout=False, error='', crashed_process_name='??',
|
| - crashed_pid=None, crash_log=None, pid=None):
|
| + crashed_pid=None, crash_log=None, leak=False, leak_log=None, pid=None):
|
| # FIXME: Args could be renamed to better clarify what they do.
|
| self.text = text
|
| self.image = image # May be empty-string if the test crashes.
|
| @@ -71,6 +71,8 @@ class DriverOutput(object):
|
| self.crashed_process_name = crashed_process_name
|
| self.crashed_pid = crashed_pid
|
| self.crash_log = crash_log
|
| + self.leak = leak
|
| + self.leak_log = leak_log
|
| self.test_time = test_time
|
| self.measurements = measurements
|
| self.timeout = timeout
|
| @@ -102,17 +104,22 @@ class Driver(object):
|
| self._no_timeout = no_timeout
|
|
|
| self._driver_tempdir = None
|
| - # WebKitTestRunner can report back subprocess crashes by printing
|
| + # content_shell can report back subprocess crashes by printing
|
| # "#CRASHED - PROCESSNAME". Since those can happen at any time
|
| # and ServerProcess won't be aware of them (since the actual tool
|
| # didn't crash, just a subprocess) we record the crashed subprocess name here.
|
| self._crashed_process_name = None
|
| self._crashed_pid = None
|
|
|
| - # WebKitTestRunner can report back subprocesses that became unresponsive
|
| + # content_shell can report back subprocesses that became unresponsive
|
| # This could mean they crashed.
|
| self._subprocess_was_unresponsive = False
|
|
|
| + # content_shell can report back subprocess DOM-object leaks by printing
|
| + # "#LEAK". This leak detection is enabled only when the flag
|
| + # --enable-leak-detection is passed to content_shell.
|
| + self._leaked = False
|
| +
|
| # stderr reading is scoped on a per-test (not per-block) basis, so we store the accumulated
|
| # stderr output, as well as if we've seen #EOF on this driver instance.
|
| # FIXME: We should probably remove _read_first_block and _read_optional_image_block and
|
| @@ -158,8 +165,9 @@ class Driver(object):
|
| crashed = self.has_crashed()
|
| timed_out = self._server_process.timed_out
|
| pid = self._server_process.pid()
|
| + leaked = self._leaked
|
|
|
| - if stop_when_done or crashed or timed_out:
|
| + if stop_when_done or crashed or timed_out or leaked:
|
| # We call stop() even if we crashed or timed out in order to get any remaining stdout/stderr output.
|
| # In the timeout case, we kill the hung process as well.
|
| out, err = self._server_process.stop(self._port.driver_stop_timeout() if stop_when_done else 0.0)
|
| @@ -170,6 +178,7 @@ class Driver(object):
|
| self._server_process = None
|
|
|
| crash_log = None
|
| + leak_log = None
|
| if crashed:
|
| self.error_from_test, crash_log = self._get_crash_log(text, self.error_from_test, newer_than=start_time)
|
|
|
| @@ -184,16 +193,23 @@ class Driver(object):
|
| # Print stdout and stderr to the placeholder crash log; we want as much context as possible.
|
| if self.error_from_test:
|
| crash_log += '\nstdout:\n%s\nstderr:\n%s\n' % (text, self.error_from_test)
|
| + elif leaked:
|
| + self.error_from_test, leak_log = self._get_leak_log(text, self.error_from_test, newer_than=start_time)
|
|
|
| return DriverOutput(text, image, actual_image_hash, audio,
|
| crash=crashed, test_time=time.time() - test_begin_time, measurements=self._measurements,
|
| timeout=timed_out, error=self.error_from_test,
|
| crashed_process_name=self._crashed_process_name,
|
| - crashed_pid=self._crashed_pid, crash_log=crash_log, pid=pid)
|
| + crashed_pid=self._crashed_pid, crash_log=crash_log,
|
| + leak=leaked, leak_log=leak_log,
|
| + pid=pid)
|
|
|
| def _get_crash_log(self, stdout, stderr, newer_than):
|
| return self._port._get_crash_log(self._crashed_process_name, self._crashed_pid, stdout, stderr, newer_than)
|
|
|
| + def _get_leak_log(self, stdout, stderr, newer_than):
|
| + return self._port._get_leak_log(self._crashed_process_name, self._crashed_pid, stdout, stderr, newer_than)
|
| +
|
| # FIXME: Seems this could just be inlined into callers.
|
| @classmethod
|
| def _command_wrapper(cls, wrapper_option):
|
| @@ -268,6 +284,7 @@ class Driver(object):
|
| environment = self._setup_environ_for_driver(environment)
|
| self._crashed_process_name = None
|
| self._crashed_pid = None
|
| + self._leaked = False
|
| cmd_line = self.cmd_line(pixel_tests, per_test_args)
|
| self._server_process = self._port._server_process_constructor(self._port, server_name, cmd_line, environment, logging=self._port.get_option("driver_logging"))
|
| self._server_process.start()
|
| @@ -320,6 +337,8 @@ class Driver(object):
|
| cmd.append('--no-timeout')
|
| cmd.extend(self._port.get_option('additional_drt_flag', []))
|
| cmd.extend(self._port.additional_drt_flag())
|
| + if self._port.get_option('enable_leak_detection'):
|
| + cmd.append('--enable-leak-detection')
|
| cmd.extend(per_test_args)
|
| cmd.append('-')
|
| return cmd
|
| @@ -348,6 +367,11 @@ class Driver(object):
|
| return True
|
| return self.has_crashed()
|
|
|
| + def _check_for_leak(self, error_line):
|
| + if error_line.startswith("#LEAK - "):
|
| + self._leaked = True
|
| + return self._leaked
|
| +
|
| def _command_from_driver_input(self, driver_input):
|
| # FIXME: performance tests pass in full URLs instead of test names.
|
| if driver_input.test_name.startswith('http://') or driver_input.test_name.startswith('https://') or driver_input.test_name == ('about:blank'):
|
| @@ -461,6 +485,7 @@ class Driver(object):
|
| if err_line:
|
| if self._check_for_driver_crash(err_line):
|
| break
|
| + self._check_for_leak(err_line)
|
| self.error_from_test += err_line
|
|
|
| block.decode_content()
|
|
|