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)