Mercurial > hg
comparison tests/run-tests.py @ 21523:9fb6f328576a
run-tests: move interactive test acceptance into TestResult
We shouldn't be performing interactive prompting during test execution.
The first step of this is to move the functionality into TestResult.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 22 Apr 2014 13:32:05 -0700 |
parents | eeaec308ad5f |
children | 32b9bbca2052 |
comparison
equal
deleted
inserted
replaced
21522:eeaec308ad5f | 21523:9fb6f328576a |
---|---|
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, keeptmpdir=False, | 341 def __init__(self, path, tmpdir, keeptmpdir=False, |
342 debug=False, | 342 debug=False, |
343 interactive=False, timeout=defaults['timeout'], | 343 timeout=defaults['timeout'], |
344 startport=defaults['port'], extraconfigopts=None, | 344 startport=defaults['port'], extraconfigopts=None, |
345 py3kwarnings=False, shell=None): | 345 py3kwarnings=False, shell=None): |
346 """Create a test from parameters. | 346 """Create a test from parameters. |
347 | 347 |
348 path is the full path to the file defining the test. | 348 path is the full path to the file defining the test. |
352 keeptmpdir determines whether to keep the test's temporary directory | 352 keeptmpdir determines whether to keep the test's temporary directory |
353 after execution. It defaults to removal (False). | 353 after execution. It defaults to removal (False). |
354 | 354 |
355 debug mode will make the test execute verbosely, with unfiltered | 355 debug mode will make the test execute verbosely, with unfiltered |
356 output. | 356 output. |
357 | |
358 interactive controls whether the test will run interactively. | |
359 | 357 |
360 timeout controls the maximum run time of the test. It is ignored when | 358 timeout controls the maximum run time of the test. It is ignored when |
361 debug is True. | 359 debug is True. |
362 | 360 |
363 startport controls the starting port number to use for this test. Each | 361 startport controls the starting port number to use for this test. Each |
380 self.errpath = os.path.join(self._testdir, '%s.err' % self.name) | 378 self.errpath = os.path.join(self._testdir, '%s.err' % self.name) |
381 | 379 |
382 self._threadtmp = tmpdir | 380 self._threadtmp = tmpdir |
383 self._keeptmpdir = keeptmpdir | 381 self._keeptmpdir = keeptmpdir |
384 self._debug = debug | 382 self._debug = debug |
385 self._interactive = interactive | |
386 self._timeout = timeout | 383 self._timeout = timeout |
387 self._startport = startport | 384 self._startport = startport |
388 self._extraconfigopts = extraconfigopts or [] | 385 self._extraconfigopts = extraconfigopts or [] |
389 self._py3kwarnings = py3kwarnings | 386 self._py3kwarnings = py3kwarnings |
390 self._shell = shell | 387 self._shell = shell |
518 | 515 |
519 if not missing: | 516 if not missing: |
520 missing = ['irrelevant'] | 517 missing = ['irrelevant'] |
521 | 518 |
522 if failed: | 519 if failed: |
523 self.fail('hg have failed checking for %s' % failed[-1], ret) | 520 self.fail('hg have failed checking for %s' % failed[-1]) |
524 else: | 521 else: |
525 self._skipped = True | 522 self._skipped = True |
526 raise SkipTest(missing[-1]) | 523 raise SkipTest(missing[-1]) |
527 elif ret == 'timeout': | 524 elif ret == 'timeout': |
528 self.fail('timed out', ret) | 525 self.fail('timed out') |
529 elif ret is False: | 526 elif ret is False: |
530 raise WarnTest('no result code from test') | 527 raise WarnTest('no result code from test') |
531 elif out != self._refout: | 528 elif out != self._refout: |
532 # The result object handles diff calculation for us. | 529 # The result object handles diff calculation for us. |
533 self._result.addOutputMismatch(self, out, self._refout) | 530 self._result.addOutputMismatch(self, ret, out, self._refout) |
534 | 531 |
535 if ret: | 532 if ret: |
536 msg = 'output changed and ' + describe(ret) | 533 msg = 'output changed and ' + describe(ret) |
537 else: | 534 else: |
538 msg = 'output changed' | 535 msg = 'output changed' |
542 f = open(self.errpath, 'wb') | 539 f = open(self.errpath, 'wb') |
543 for line in out: | 540 for line in out: |
544 f.write(line) | 541 f.write(line) |
545 f.close() | 542 f.close() |
546 | 543 |
547 self.fail(msg, ret) | 544 self.fail(msg) |
548 elif ret: | 545 elif ret: |
549 self.fail(describe(ret), ret) | 546 self.fail(describe(ret)) |
550 | 547 |
551 def tearDown(self): | 548 def tearDown(self): |
552 """Tasks to perform after run().""" | 549 """Tasks to perform after run().""" |
553 for entry in self._daemonpids: | 550 for entry in self._daemonpids: |
554 killdaemons(entry) | 551 killdaemons(entry) |
643 assert '=' in key, ('extra config opt %s must ' | 640 assert '=' in key, ('extra config opt %s must ' |
644 'have an = for assignment' % opt) | 641 'have an = for assignment' % opt) |
645 hgrc.write('[%s]\n%s\n' % (section, key)) | 642 hgrc.write('[%s]\n%s\n' % (section, key)) |
646 hgrc.close() | 643 hgrc.close() |
647 | 644 |
648 def fail(self, msg, ret): | 645 def fail(self, msg): |
649 if (not ret and self._interactive and | |
650 os.path.exists(self.errpath)): | |
651 iolock.acquire() | |
652 print 'Accept this change? [n] ', | |
653 answer = sys.stdin.readline().strip() | |
654 iolock.release() | |
655 if answer.lower() in ('y', 'yes'): | |
656 if self.name.endswith('.t'): | |
657 rename(self.errpath, self.path) | |
658 else: | |
659 rename(self.errpath, '%s.out' % self.path) | |
660 | |
661 return '.', self.name, '' | |
662 | |
663 # unittest differentiates between errored and failed. | 646 # unittest differentiates between errored and failed. |
664 # Failed is denoted by AssertionError (by default at least). | 647 # Failed is denoted by AssertionError (by default at least). |
665 raise AssertionError(msg) | 648 raise AssertionError(msg) |
666 | 649 |
667 class PythonTest(Test): | 650 class PythonTest(Test): |
1117 self.stream.writeln('warned %s' % reason) | 1100 self.stream.writeln('warned %s' % reason) |
1118 else: | 1101 else: |
1119 self.stream.write('~') | 1102 self.stream.write('~') |
1120 self.stream.flush() | 1103 self.stream.flush() |
1121 | 1104 |
1122 def addOutputMismatch(self, test, got, expected): | 1105 def addOutputMismatch(self, test, ret, got, expected): |
1123 """Record a mismatch in test output for a particular test.""" | 1106 """Record a mismatch in test output for a particular test.""" |
1124 | 1107 |
1125 if self._options.nodiff: | 1108 if self._options.nodiff: |
1126 return | 1109 return |
1127 | 1110 |
1135 else: | 1118 else: |
1136 self.stream.write('\n') | 1119 self.stream.write('\n') |
1137 for line in lines: | 1120 for line in lines: |
1138 self.stream.write(line) | 1121 self.stream.write(line) |
1139 self.stream.flush() | 1122 self.stream.flush() |
1123 | |
1124 if ret or not self._options.interactive or \ | |
1125 not os.path.exists(test.errpath): | |
1126 return | |
1127 | |
1128 iolock.acquire() | |
1129 print 'Accept this change? [n] ', | |
1130 answer = sys.stdin.readline().strip() | |
1131 iolock.release() | |
1132 if answer.lower() in ('y', 'yes'): | |
1133 if test.name.endswith('.t'): | |
1134 rename(test.errpath, test.path) | |
1135 else: | |
1136 rename(test.errpath, '%s.out' % test.path) | |
1140 | 1137 |
1141 def startTest(self, test): | 1138 def startTest(self, test): |
1142 super(TestResult, self).startTest(test) | 1139 super(TestResult, self).startTest(test) |
1143 | 1140 |
1144 self._started[test.name] = time.time() | 1141 self._started[test.name] = time.time() |
1522 tmpdir = os.path.join(self.hgtmp, 'child%d' % count) | 1519 tmpdir = os.path.join(self.hgtmp, 'child%d' % count) |
1523 | 1520 |
1524 return testcls(refpath, tmpdir, | 1521 return testcls(refpath, tmpdir, |
1525 keeptmpdir=self.options.keep_tmpdir, | 1522 keeptmpdir=self.options.keep_tmpdir, |
1526 debug=self.options.debug, | 1523 debug=self.options.debug, |
1527 interactive=self.options.interactive, | |
1528 timeout=self.options.timeout, | 1524 timeout=self.options.timeout, |
1529 startport=self.options.port + count * 3, | 1525 startport=self.options.port + count * 3, |
1530 extraconfigopts=self.options.extra_config_opt, | 1526 extraconfigopts=self.options.extra_config_opt, |
1531 py3kwarnings=self.options.py3k_warnings, | 1527 py3kwarnings=self.options.py3k_warnings, |
1532 shell=self.options.shell) | 1528 shell=self.options.shell) |