Show More
@@ -338,7 +338,7 b' class Test(unittest.TestCase):' | |||||
338 | # Status code reserved for skipped tests (used by hghave). |
|
338 | # Status code reserved for skipped tests (used by hghave). | |
339 | SKIPPED_STATUS = 80 |
|
339 | SKIPPED_STATUS = 80 | |
340 |
|
340 | |||
341 |
def __init__(self, path, tmpdir, |
|
341 | def __init__(self, path, tmpdir, keeptmpdir=False, | |
342 | debug=False, nodiff=False, diffviewer=None, |
|
342 | debug=False, nodiff=False, diffviewer=None, | |
343 | interactive=False, timeout=defaults['timeout'], |
|
343 | interactive=False, timeout=defaults['timeout'], | |
344 | startport=defaults['port'], extraconfigopts=None, |
|
344 | startport=defaults['port'], extraconfigopts=None, | |
@@ -349,9 +349,6 b' class Test(unittest.TestCase):' | |||||
349 |
|
349 | |||
350 | tmpdir is the main temporary directory to use for this test. |
|
350 | tmpdir is the main temporary directory to use for this test. | |
351 |
|
351 | |||
352 | abort is a flag that turns to True if test execution should be aborted. |
|
|||
353 | It is consulted periodically during the execution of tests. |
|
|||
354 |
|
||||
355 | keeptmpdir determines whether to keep the test's temporary directory |
|
352 | keeptmpdir determines whether to keep the test's temporary directory | |
356 | after execution. It defaults to removal (False). |
|
353 | after execution. It defaults to removal (False). | |
357 |
|
354 | |||
@@ -388,7 +385,6 b' class Test(unittest.TestCase):' | |||||
388 | self.errpath = os.path.join(self._testdir, '%s.err' % self.name) |
|
385 | self.errpath = os.path.join(self._testdir, '%s.err' % self.name) | |
389 |
|
386 | |||
390 | self._threadtmp = tmpdir |
|
387 | self._threadtmp = tmpdir | |
391 | self._abort = abort |
|
|||
392 | self._keeptmpdir = keeptmpdir |
|
388 | self._keeptmpdir = keeptmpdir | |
393 | self._debug = debug |
|
389 | self._debug = debug | |
394 | self._nodiff = nodiff |
|
390 | self._nodiff = nodiff | |
@@ -399,8 +395,9 b' class Test(unittest.TestCase):' | |||||
399 | self._extraconfigopts = extraconfigopts or [] |
|
395 | self._extraconfigopts = extraconfigopts or [] | |
400 | self._py3kwarnings = py3kwarnings |
|
396 | self._py3kwarnings = py3kwarnings | |
401 | self._shell = shell |
|
397 | self._shell = shell | |
|
398 | ||||
|
399 | self._aborted = False | |||
402 | self._daemonpids = [] |
|
400 | self._daemonpids = [] | |
403 |
|
||||
404 | self._finished = None |
|
401 | self._finished = None | |
405 | self._ret = None |
|
402 | self._ret = None | |
406 | self._out = None |
|
403 | self._out = None | |
@@ -447,12 +444,11 b' class Test(unittest.TestCase):' | |||||
447 |
|
444 | |||
448 | def run(self, result): |
|
445 | def run(self, result): | |
449 | result.startTest(self) |
|
446 | result.startTest(self) | |
450 | interrupted = False |
|
|||
451 | try: |
|
447 | try: | |
452 | try: |
|
448 | try: | |
453 | self.setUp() |
|
449 | self.setUp() | |
454 | except (KeyboardInterrupt, SystemExit): |
|
450 | except (KeyboardInterrupt, SystemExit): | |
455 |
|
|
451 | self._aborted = True | |
456 | raise |
|
452 | raise | |
457 | except Exception: |
|
453 | except Exception: | |
458 | result.addError(self, sys.exc_info()) |
|
454 | result.addError(self, sys.exc_info()) | |
@@ -462,7 +458,7 b' class Test(unittest.TestCase):' | |||||
462 | try: |
|
458 | try: | |
463 | self.runTest() |
|
459 | self.runTest() | |
464 | except KeyboardInterrupt: |
|
460 | except KeyboardInterrupt: | |
465 |
|
|
461 | self._aborted = True | |
466 | raise |
|
462 | raise | |
467 | except SkipTest, e: |
|
463 | except SkipTest, e: | |
468 | result.addSkip(self, str(e)) |
|
464 | result.addSkip(self, str(e)) | |
@@ -484,7 +480,7 b' class Test(unittest.TestCase):' | |||||
484 | try: |
|
480 | try: | |
485 | self.tearDown() |
|
481 | self.tearDown() | |
486 | except (KeyboardInterrupt, SystemExit): |
|
482 | except (KeyboardInterrupt, SystemExit): | |
487 |
|
|
483 | self._aborted = True | |
488 | raise |
|
484 | raise | |
489 | except Exception: |
|
485 | except Exception: | |
490 | result.addError(self, sys.exc_info()) |
|
486 | result.addError(self, sys.exc_info()) | |
@@ -493,7 +489,7 b' class Test(unittest.TestCase):' | |||||
493 | if success: |
|
489 | if success: | |
494 | result.addSuccess(self) |
|
490 | result.addSuccess(self) | |
495 | finally: |
|
491 | finally: | |
496 |
result.stopTest(self, interrupted= |
|
492 | result.stopTest(self, interrupted=self._aborted) | |
497 |
|
493 | |||
498 | def runTest(self): |
|
494 | def runTest(self): | |
499 | """Run this test instance. |
|
495 | """Run this test instance. | |
@@ -589,6 +585,10 b' class Test(unittest.TestCase):' | |||||
589 | # This should be implemented in child classes to run tests. |
|
585 | # This should be implemented in child classes to run tests. | |
590 | raise SkipTest('unknown test type') |
|
586 | raise SkipTest('unknown test type') | |
591 |
|
587 | |||
|
588 | def abort(self): | |||
|
589 | """Terminate execution of this test.""" | |||
|
590 | self._aborted = True | |||
|
591 | ||||
592 | def _getreplacements(self): |
|
592 | def _getreplacements(self): | |
593 | r = [ |
|
593 | r = [ | |
594 | (r':%s\b' % self._startport, ':$HGPORT'), |
|
594 | (r':%s\b' % self._startport, ':$HGPORT'), | |
@@ -698,8 +698,12 b' class PythonTest(Test):' | |||||
698 | vlog("# Running", cmd) |
|
698 | vlog("# Running", cmd) | |
699 | if os.name == 'nt': |
|
699 | if os.name == 'nt': | |
700 | replacements.append((r'\r\n', '\n')) |
|
700 | replacements.append((r'\r\n', '\n')) | |
701 |
re |
|
701 | result = run(cmd, self._testtmp, replacements, env, | |
702 | debug=self._debug, timeout=self._timeout) |
|
702 | debug=self._debug, timeout=self._timeout) | |
|
703 | if self._aborted: | |||
|
704 | raise KeyboardInterrupt() | |||
|
705 | ||||
|
706 | return result | |||
703 |
|
707 | |||
704 | class TTest(Test): |
|
708 | class TTest(Test): | |
705 | """A "t test" is a test backed by a .t file.""" |
|
709 | """A "t test" is a test backed by a .t file.""" | |
@@ -734,8 +738,11 b' class TTest(Test):' | |||||
734 | vlog("# Running", cmd) |
|
738 | vlog("# Running", cmd) | |
735 |
|
739 | |||
736 | exitcode, output = run(cmd, self._testtmp, replacements, env, |
|
740 | exitcode, output = run(cmd, self._testtmp, replacements, env, | |
737 |
|
|
741 | debug=self._debug, timeout=self._timeout) | |
738 | timeout=self._timeout) |
|
742 | ||
|
743 | if self._aborted: | |||
|
744 | raise KeyboardInterrupt() | |||
|
745 | ||||
739 | # Do not merge output if skipped. Return hghave message instead. |
|
746 | # Do not merge output if skipped. Return hghave message instead. | |
740 | # Similarly, with --debug, output is None. |
|
747 | # Similarly, with --debug, output is None. | |
741 | if exitcode == self.SKIPPED_STATUS or output is None: |
|
748 | if exitcode == self.SKIPPED_STATUS or output is None: | |
@@ -1012,7 +1019,7 b' class TTest(Test):' | |||||
1012 |
|
1019 | |||
1013 |
|
1020 | |||
1014 | wifexited = getattr(os, "WIFEXITED", lambda x: False) |
|
1021 | wifexited = getattr(os, "WIFEXITED", lambda x: False) | |
1015 |
def run(cmd, wd, replacements, env, |
|
1022 | def run(cmd, wd, replacements, env, debug=False, timeout=None): | |
1016 | """Run command in a sub-process, capturing the output (stdout and stderr). |
|
1023 | """Run command in a sub-process, capturing the output (stdout and stderr). | |
1017 | Return a tuple (exitcode, output). output is None in debug mode.""" |
|
1024 | Return a tuple (exitcode, output). output is None in debug mode.""" | |
1018 | if debug: |
|
1025 | if debug: | |
@@ -1049,9 +1056,6 b' def run(cmd, wd, replacements, env, abor' | |||||
1049 | if ret: |
|
1056 | if ret: | |
1050 | killdaemons(env['DAEMON_PIDS']) |
|
1057 | killdaemons(env['DAEMON_PIDS']) | |
1051 |
|
1058 | |||
1052 | if abort[0]: |
|
|||
1053 | raise KeyboardInterrupt() |
|
|||
1054 |
|
||||
1055 | for s, r in replacements: |
|
1059 | for s, r in replacements: | |
1056 | output = re.sub(s, r, output) |
|
1060 | output = re.sub(s, r, output) | |
1057 | return ret, output.splitlines(True) |
|
1061 | return ret, output.splitlines(True) | |
@@ -1196,6 +1200,7 b' class TestSuite(unittest.TestSuite):' | |||||
1196 |
|
1200 | |||
1197 | tests.append(test) |
|
1201 | tests.append(test) | |
1198 |
|
1202 | |||
|
1203 | runtests = list(tests) | |||
1199 | jobs = self._runner.options.jobs |
|
1204 | jobs = self._runner.options.jobs | |
1200 | done = queue.Queue() |
|
1205 | done = queue.Queue() | |
1201 | running = 0 |
|
1206 | running = 0 | |
@@ -1229,7 +1234,8 b' class TestSuite(unittest.TestSuite):' | |||||
1229 | t.start() |
|
1234 | t.start() | |
1230 | running += 1 |
|
1235 | running += 1 | |
1231 | except KeyboardInterrupt: |
|
1236 | except KeyboardInterrupt: | |
1232 | self._runner.abort[0] = True |
|
1237 | for test in runtests: | |
|
1238 | test.abort() | |||
1233 |
|
1239 | |||
1234 | return result |
|
1240 | return result | |
1235 |
|
1241 | |||
@@ -1315,7 +1321,6 b' class TestRunner(object):' | |||||
1315 | self.tmpbinddir = None |
|
1321 | self.tmpbinddir = None | |
1316 | self.pythondir = None |
|
1322 | self.pythondir = None | |
1317 | self.coveragefile = None |
|
1323 | self.coveragefile = None | |
1318 | self.abort = [False] |
|
|||
1319 | self._createdfiles = [] |
|
1324 | self._createdfiles = [] | |
1320 | self._hgpath = None |
|
1325 | self._hgpath = None | |
1321 |
|
1326 | |||
@@ -1518,7 +1523,7 b' class TestRunner(object):' | |||||
1518 | refpath = os.path.join(self.testdir, test) |
|
1523 | refpath = os.path.join(self.testdir, test) | |
1519 | tmpdir = os.path.join(self.hgtmp, 'child%d' % count) |
|
1524 | tmpdir = os.path.join(self.hgtmp, 'child%d' % count) | |
1520 |
|
1525 | |||
1521 |
return testcls(refpath, tmpdir, |
|
1526 | return testcls(refpath, tmpdir, | |
1522 | keeptmpdir=self.options.keep_tmpdir, |
|
1527 | keeptmpdir=self.options.keep_tmpdir, | |
1523 | debug=self.options.debug, |
|
1528 | debug=self.options.debug, | |
1524 | nodiff = self.options.nodiff, |
|
1529 | nodiff = self.options.nodiff, |
General Comments 0
You need to be logged in to leave comments.
Login now