summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorklarlund <klarlund@01de4be4-8c4a-0410-9132-4925637da917>2008-05-31 00:38:48 +0000
committerklarlund <klarlund@01de4be4-8c4a-0410-9132-4925637da917>2008-05-31 00:38:48 +0000
commit1a6d0aba13bf3f365b15e173b363edf893eed879 (patch)
tree54f180ce92fc53927aaf5f6e350b99c1aa3ab31b
parentfe96c8cf1833b0a432cd8705bc27c7dbf42508e6 (diff)
downloaddistcc-1a6d0aba13bf3f365b15e173b363edf893eed879.tar.gz
Tidy-up testing framework to overcome recently introduced bug.
Testing on cygwine revealed that as tests were being issued the temporary testing directory would suffer from longer and longer prefixes until a 'filename too long' error would stop the party. This is result of an earlier attempt to avoid too much printing to stdout during tests, spefically during recursive test invocations. The problem is that the teardown mechanism of the comfychair enviroment is not expressed -- by any name at all (it could be 'teardown' for example). So, I added a name --- but because there's no expectation that the TestCase class defined there has its teardown method called from derived classes --- I chose the name CleanUps, which corresponds to the private variable. I also made an abstraction for running a test. This new Comfychair.runtest function can the conveniently by called to carry out a subtest. With this CL, 'make pump-maintainer-check' now works on cygwin. git-svn-id: http://distcc.googlecode.com/svn/trunk@434 01de4be4-8c4a-0410-9132-4925637da917
-rwxr-xr-xtest/comfychair.py122
-rwxr-xr-xtest/testdistcc.py17
2 files changed, 88 insertions, 51 deletions
diff --git a/test/comfychair.py b/test/comfychair.py
index 0528bb3..75e5c99 100755
--- a/test/comfychair.py
+++ b/test/comfychair.py
@@ -97,6 +97,25 @@ class TestCase:
"""Queue a cleanup to be run when the test is complete."""
self._cleanups.append(c)
+ def apply_cleanups(self, debugger):
+ """Apply cleanup functions and return error code.
+
+ Returns:
+ 0 on success; 2 if a KeyboardInterrupt occurs; 1 if any other exception
+ occurs.
+ """
+ while self._cleanups:
+ try:
+ apply(self._cleanups.pop())
+ except KeyboardInterrupt:
+ print "interrupted during cleanups"
+ _report_error(self, debugger)
+ return 2
+ except:
+ print "error during cleanups"
+ _report_error(self, debugger)
+ return 1
+ return 0
def fail(self, reason = ""):
"""Say the test failed."""
@@ -299,6 +318,64 @@ def _report_error(case, debugger):
debugger(tb)
+def runtest(testcase_class, ret, verbose=0, debugger=None, subtest=0):
+ """Instantiate test class, run it, and catch and report exceptions.
+
+ Inputs:
+ testcase_class a class derived from TestCase
+ ret return status, an integer
+ verbose an integer (used as boolean)
+ debugger debugger object to be applied to errors
+ subtest an integer (used as boolean)
+ Returns:
+ a new return status
+ Raises:
+ KeyboardInterrupt
+
+ If subtest is true, then the ordinary information about the
+ test progress is not printed.
+ """
+ if not subtest:
+ print "%-30s" % _test_name(testcase_class),
+ def failure_print(message):
+ print message
+ else:
+ def failure_print(message):
+ print '[%s %s]' % (_test_name(testcase_class), message)
+
+ # flush now so that long running tests are easier to follow
+ sys.stdout.flush()
+
+ obj = None
+ try:
+ try:
+ # run test and sometimes show result
+ obj = testcase_class()
+ obj.setup()
+ obj.runtest()
+ if not subtest:
+ print "OK"
+ except KeyboardInterrupt:
+ failure_print("INTERRUPT")
+ if obj:
+ _report_error(obj, debugger)
+ raise
+ except NotRunError, msg:
+ failure_print("NOTRUN, %s" % msg.value)
+ except:
+ failure_print("FAIL")
+ if obj:
+ _report_error(obj, debugger)
+ return 1
+ finally:
+ if obj:
+ ret = obj.apply_cleanups(debugger) or ret
+ # Display log file if we're verbose
+ if ret == 0 and verbose:
+ obj.explain_failure()
+ return ret
+
+
def runtests(test_list, verbose = 0, debugger = None):
"""Run a series of tests.
@@ -312,46 +389,13 @@ def runtests(test_list, verbose = 0, debugger = None):
"""
import traceback
ret = 0
- for test_class in test_list:
- print "%-30s" % _test_name(test_class),
- # flush now so that long running tests are easier to follow
- sys.stdout.flush()
-
- obj = None
+ for testcase_class in test_list:
try:
- try: # run test and show result
- obj = test_class()
- obj.setup()
- obj.runtest()
- print "OK"
- except KeyboardInterrupt:
- print "INTERRUPT"
- _report_error(obj, debugger)
- ret = 2
- break
- except NotRunError, msg:
- print "NOTRUN, %s" % msg.value
- except:
- print "FAIL"
- _report_error(obj, debugger)
- ret = 1
- finally:
- while obj and obj._cleanups:
- try:
- apply(obj._cleanups.pop())
- except KeyboardInterrupt:
- print "interrupted during teardown"
- _report_error(obj, debugger)
- ret = 2
- break
- except:
- print "error during teardown"
- _report_error(obj, debugger)
- ret = 1
- # Display log file if we're verbose
- if ret == 0 and verbose:
- obj.explain_failure()
-
+ ret = runtest(testcase_class, ret, verbose=verbose,
+ debugger=debugger)
+ except KeyboardInterrupt:
+ ret = 2
+ break
return ret
diff --git a/test/testdistcc.py b/test/testdistcc.py
index 871be8a..711584c 100755
--- a/test/testdistcc.py
+++ b/test/testdistcc.py
@@ -610,18 +610,11 @@ int main(char **argv) {};
glob_result = glob.glob(dep_glob)
dotd_result.extend(glob_result)
- # We explicit call setup(), runtest(), and teardown() to run the
- # test, rather than just comfychair.runtests([TempCompile_Case]),
- # because we don't want to see 10 test results for
- # 'TempCompile_Case' in the output; we just want a single
- # output line for 'DotD_Case'.
- case = TempCompile_Case()
- case.setup()
- try:
- case.runtest()
- finally:
- case.teardown()
-
+ ret = comfychair.runtest(TempCompile_Case, 0, subtest=1)
+ if ret:
+ raise AssertionError(
+ "Case (args:%s, dep_glob:%s, how_many:%s, target:%s)"
+ % (args, dep_glob, how_many, target))
self.assert_equal(len(dotd_result), how_many)
if how_many == 1:
expected_dep_file = dotd_result[0]