From fa74ef4c5785453ebdd1aaa1380aa7a632336c5b Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Wed, 22 Jul 2015 23:57:00 +0300 Subject: [PATCH] Added timeout kwarg to tests. --- backends.py | 6 ++++-- interpreter.py | 8 ++++++-- manual tests/8 timeout/meson.build | 8 ++++++++ manual tests/8 timeout/sleepprog.c | 6 ++++++ meson_test.py | 13 +++++++++++-- 5 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 manual tests/8 timeout/meson.build create mode 100644 manual tests/8 timeout/sleepprog.c diff --git a/backends.py b/backends.py index 851ed51fe..1fe98b50e 100644 --- a/backends.py +++ b/backends.py @@ -20,7 +20,7 @@ from coredata import MesonException class TestSerialisation: def __init__(self, name, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env, - should_fail, valgrind_args): + should_fail, valgrind_args, timeout): self.name = name self.fname = fname self.is_cross = is_cross @@ -30,6 +30,7 @@ class TestSerialisation: self.env = env self.should_fail = should_fail self.valgrind_args = valgrind_args + self.timeout = timeout # This class contains the basic functionality that is needed by all backends. # Feel free to move stuff in and out of it as you see fit. @@ -251,7 +252,8 @@ class Backend(): else: exe_wrapper = None ts = TestSerialisation(t.get_name(), fname, is_cross, exe_wrapper, - t.is_parallel, t.cmd_args, t.env, t.should_fail, t.valgrind_args) + t.is_parallel, t.cmd_args, t.env, t.should_fail, t.valgrind_args, + t.timeout) arr.append(ts) pickle.dump(arr, datafile) diff --git a/interpreter.py b/interpreter.py index 2349696b3..ebfca1a72 100644 --- a/interpreter.py +++ b/interpreter.py @@ -475,7 +475,7 @@ class RunTargetHolder(InterpreterObject): self.held_object = build.RunTarget(name, command, args, subdir) class Test(InterpreterObject): - def __init__(self, name, exe, is_parallel, cmd_args, env, should_fail, valgrind_args): + def __init__(self, name, exe, is_parallel, cmd_args, env, should_fail, valgrind_args, timeout): InterpreterObject.__init__(self) self.name = name self.exe = exe @@ -484,6 +484,7 @@ class Test(InterpreterObject): self.env = env self.should_fail = should_fail self.valgrind_args = valgrind_args + self.timeout = timeout def get_exe(self): return self.exe @@ -1437,7 +1438,10 @@ class Interpreter(): should_fail = kwargs.get('should_fail', False) if not isinstance(should_fail, bool): raise InterpreterException('Keyword argument should_fail must be a boolean.') - t = Test(args[0], args[1].held_object, par, cmd_args, env, should_fail, valgrind_args) + timeout = kwargs.get('timeout', 30) + if not isinstance(timeout, int): + raise InterpreterException('Timeout must be an integer.') + t = Test(args[0], args[1].held_object, par, cmd_args, env, should_fail, valgrind_args, timeout) self.build.tests.append(t) mlog.debug('Adding test "', mlog.bold(args[0]), '".', sep='') diff --git a/manual tests/8 timeout/meson.build b/manual tests/8 timeout/meson.build new file mode 100644 index 000000000..8ba7d4b43 --- /dev/null +++ b/manual tests/8 timeout/meson.build @@ -0,0 +1,8 @@ +project('timeout', 'c') + +# This creates a test that times out. It is a manual test +# because currently there is no test suite for test that are expected +# to fail during unit test phase. + +exe = executable('sleepprog', 'sleepprog.c') +test('timeout', exe, timeout : 1) diff --git a/manual tests/8 timeout/sleepprog.c b/manual tests/8 timeout/sleepprog.c new file mode 100644 index 000000000..e3714828a --- /dev/null +++ b/manual tests/8 timeout/sleepprog.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + sleep(1000); + return 0; +} diff --git a/meson_test.py b/meson_test.py index 452ce7429..5dedd01f8 100755 --- a/meson_test.py +++ b/meson_test.py @@ -97,12 +97,21 @@ def run_single_test(wrap, test): child_env.update(test.env) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=child_env) - (stdo, stde) = p.communicate() + timed_out = False + try: + (stdo, stde) = p.communicate(timeout=test.timeout) + except subprocess.TimeoutExpired: + timed_out = True + p.kill() + (stdo, stde) = p.communicate() endtime = time.time() duration = endtime - starttime stdo = stdo.decode() stde = stde.decode() - if (not test.should_fail and p.returncode == 0) or \ + if timed_out: + res = 'TIMEOUT' + tests_failed = True + elif (not test.should_fail and p.returncode == 0) or \ (test.should_fail and p.returncode != 0): res = 'OK' else: