Log Message
[GTK] run-gtk-tests: Use a timeout per test instead of a global timeout https://bugs.webkit.org/show_bug.cgi?id=84695
Reviewed by Philippe Normand. It also adds a command line option to be able to pass a custom timeout value, instead of hard-coding it. The default timeout is 10 seconds if no other value is passed to the script. * Scripts/run-gtk-tests: (TestTimeout): Exception raised when a test times out. (TestRunner._get_child_pid_from_test_output): Helper function to get the pid of the running test from gtester output. (TestRunner._kill_process): Helper funtion ot kill a process ignoring exceptions if the process is already died. (TestRunner._run_test_command): Run the test command raising TestTimeout exception if the test doesn't finish before the given timeout in seconds. (TestRunner._run_test_command.alarm_handler): Alarm handler that raises TestTimeout exception. (TestRunner._run_test_glib): Use _run_test_command() to run the test. (TestRunner._run_test_google): Ditto. (TestRunner.run_tests): Add current test to the list of timed out test if TestTimeout exception is raised. Show the list of timed out test at the end.
Modified Paths
Diff
Modified: trunk/Tools/ChangeLog (115312 => 115313)
--- trunk/Tools/ChangeLog 2012-04-26 14:30:17 UTC (rev 115312)
+++ trunk/Tools/ChangeLog 2012-04-26 14:45:10 UTC (rev 115313)
@@ -1,3 +1,31 @@
+2012-04-26 Carlos Garcia Campos <cgar...@igalia.com>
+
+ [GTK] run-gtk-tests: Use a timeout per test instead of a global timeout
+ https://bugs.webkit.org/show_bug.cgi?id=84695
+
+ Reviewed by Philippe Normand.
+
+ It also adds a command line option to be able to pass a custom
+ timeout value, instead of hard-coding it. The default timeout is 10
+ seconds if no other value is passed to the script.
+
+ * Scripts/run-gtk-tests:
+ (TestTimeout): Exception raised when a test times out.
+ (TestRunner._get_child_pid_from_test_output): Helper function to
+ get the pid of the running test from gtester output.
+ (TestRunner._kill_process): Helper funtion ot kill a process
+ ignoring exceptions if the process is already died.
+ (TestRunner._run_test_command): Run the test command raising
+ TestTimeout exception if the test doesn't finish before the given
+ timeout in seconds.
+ (TestRunner._run_test_command.alarm_handler): Alarm handler that
+ raises TestTimeout exception.
+ (TestRunner._run_test_glib): Use _run_test_command() to run the test.
+ (TestRunner._run_test_google): Ditto.
+ (TestRunner.run_tests): Add current test to the list of timed out
+ test if TestTimeout exception is raised. Show the list of timed
+ out test at the end.
+
2012-04-26 Sudarsana Nagineni <sudarsana.nagin...@linux.intel.com>
[EFL] [DRT] LayoutTestController needs implementation of addOriginAccessWhitelistEntry and removeOriginAccessWhitelistEntry
Modified: trunk/Tools/Scripts/run-gtk-tests (115312 => 115313)
--- trunk/Tools/Scripts/run-gtk-tests 2012-04-26 14:30:17 UTC (rev 115312)
+++ trunk/Tools/Scripts/run-gtk-tests 2012-04-26 14:45:10 UTC (rev 115313)
@@ -20,12 +20,11 @@
import subprocess
import os
import sys
-import time
import optparse
+import re
+from signal import alarm, signal, SIGALRM, SIGKILL
from gi.repository import Gio, GLib
-TIMEOUT=180 # seconds
-
class SkippedTest:
def __init__(self, test, reason, bug=None, test_cases=[]):
self.test = test
@@ -42,6 +41,9 @@
skipped_test_str += "(https://bugs.webkit.org/show_bug.cgi?id=%d)" % self.bug
return skipped_test_str
+class TestTimeout(Exception):
+ pass
+
class TestRunner:
TEST_DIRS = [ "unittests", "WebKit2APITests", "TestWebKitAPI/WTF" ]
@@ -242,6 +244,46 @@
# Run only skipped tests.
return skipped is not None
+ def _get_child_pid_from_test_output(self, output):
+ if not output:
+ return -1
+ match = re.search(r'\(pid=(?P<child_pid>[0-9]+)\)', output)
+ if not match:
+ return -1
+ return int(match.group('child_pid'))
+
+ def _kill_process(self, pid):
+ try:
+ os.kill(pid, SIGKILL)
+ except OSError:
+ # Process already died.
+ pass
+
+ def _run_test_command(self, command, timeout=-1):
+ def alarm_handler(signum, frame):
+ raise TestTimeout
+
+ p = self._create_process(command, stdout=subprocess.PIPE, env=self._test_env)
+ if timeout > 0:
+ signal(SIGALRM, alarm_handler)
+ alarm(timeout)
+
+ stdout = ""
+ try:
+ stdout = p.communicate()[0]
+ if timeout > 0:
+ alarm(0)
+ sys.stdout.write(stdout)
+ sys.stdout.flush()
+ except TestTimeout:
+ self._kill_process(p.pid)
+ child_pid = self._get_child_pid_from_test_output(stdout)
+ if child_pid > 0:
+ self._kill_process(child_pid)
+ raise
+
+ return not p.returncode
+
def _run_test_glib(self, test):
tester_command = ['gtester']
if self._options.verbose:
@@ -250,7 +292,7 @@
tester_command.extend(['-s', test_case])
tester_command.append(test)
- return not self._create_process(tester_command, env=self._test_env).wait()
+ return self._run_test_command(tester_command, self._options.timeout)
def _run_test_google(self, test):
tester_command = [test, "--gtest_throw_on_failure"]
@@ -258,7 +300,7 @@
if skipped_tests_cases:
tester_command.append("--gtest_filter=-%s" % ":".join(skipped_tests_cases))
- return not self._create_process(tester_command, env=self._test_env).wait()
+ return self._run_test_command(tester_command, self._options.timeout)
def _run_test(self, test):
if "unittests" in test or "WebKit2APITests" in test:
@@ -283,17 +325,19 @@
self._tests = [test for test in self._tests if self._should_run_test(test)]
failed_tests = []
+ timed_out_tests = []
try:
- start_time = time.time()
for test in self._tests:
- if not self._run_test(test):
- failed_tests.append(test)
-
- if time.time() - start_time >= TIMEOUT:
- sys.stdout.write("Tests timed out after %d seconds\n" % TIMEOUT)
+ success = True
+ try:
+ success = self._run_test(test)
+ except TestTimeout:
+ sys.stdout.write("TEST: %s: TIMEOUT\n" % test)
sys.stdout.flush()
- return 1
+ timed_out_tests.append(test)
+ if not success:
+ failed_tests.append(test)
finally:
self._tear_down_testing_environment()
@@ -302,6 +346,11 @@
sys.stdout.write("Tests failed: %s\n" % ", ".join(names))
sys.stdout.flush()
+ if timed_out_tests:
+ names = [test.replace(self._programs_path, '', 1) for test in timed_out_tests]
+ sys.stdout.write("Tests that timed out: %s\n" % ", ".join(names))
+ sys.stdout.flush()
+
if self._skipped_tests and self._options.skipped_action == 'skip':
sys.stdout.write("Tests skipped:\n%s\n" % "\n".join([str(skipped) for skipped in self._skipped_tests]))
sys.stdout.flush()
@@ -325,6 +374,9 @@
choices=['skip', 'ignore', 'only'], default='skip',
metavar='skip|ignore|only',
help='Specifies how to treat the skipped tests')
+ option_parser.add_option('-t', '--timeout',
+ action='', type='int', dest='timeout', default=10,
+ help='Time in seconds until a test times out')
options, args = option_parser.parse_args()
sys.exit(TestRunner(options, args).run_tests())
_______________________________________________ webkit-changes mailing list webkit-changes@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes