comparison tests/run-tests.py @ 21763:84cd5ee787ed

run-tests: hold iolock across diff/prompt when interactive Otherwise diff may get separated from the corresponding prompt by other threads. This required moving the interactive prompting from one helper method to another.
author Matt Mackall <mpm@selenic.com>
date Wed, 18 Jun 2014 20:51:49 -0500
parents 7e14d026c4c4
children 792ebd7dc5f6
comparison
equal deleted inserted replaced
21762:0c6cdbb697d9 21763:84cd5ee787ed
541 for line in out: 541 for line in out:
542 f.write(line) 542 f.write(line)
543 f.close() 543 f.close()
544 544
545 # The result object handles diff calculation for us. 545 # The result object handles diff calculation for us.
546 self._result.addOutputMismatch(self, ret, out, self._refout) 546 if self._result.addOutputMismatch(self, ret, out, self._refout):
547 # change was accepted, skip failing
548 return
547 549
548 if ret: 550 if ret:
549 msg = 'output changed and ' + describe(ret) 551 msg = 'output changed and ' + describe(ret)
550 else: 552 else:
551 msg = 'output changed' 553 msg = 'output changed'
1082 self.stop() 1084 self.stop()
1083 else: 1085 else:
1084 if not self._options.nodiff: 1086 if not self._options.nodiff:
1085 self.stream.write('\nERROR: %s output changed\n' % test) 1087 self.stream.write('\nERROR: %s output changed\n' % test)
1086 1088
1087 if self._options.interactive:
1088 iolock.acquire()
1089 self.stream.write('Accept this change? [n] ')
1090 answer = sys.stdin.readline().strip()
1091 iolock.release()
1092 if answer.lower() in ('y', 'yes'):
1093 if test.name.endswith('.t'):
1094 rename(test.errpath, test.path)
1095 else:
1096 rename(test.errpath, '%s.out' % test.path)
1097 self.failures.pop()
1098 return 1
1099
1100 self.stream.write('!') 1089 self.stream.write('!')
1101 1090
1102 def addError(self, *args, **kwargs): 1091 def addError(self, *args, **kwargs):
1103 super(TestResult, self).addError(*args, **kwargs) 1092 super(TestResult, self).addError(*args, **kwargs)
1104 1093
1138 self.stream.flush() 1127 self.stream.flush()
1139 1128
1140 def addOutputMismatch(self, test, ret, got, expected): 1129 def addOutputMismatch(self, test, ret, got, expected):
1141 """Record a mismatch in test output for a particular test.""" 1130 """Record a mismatch in test output for a particular test."""
1142 1131
1132 accepted = False
1133
1134 iolock.acquire()
1143 if self._options.nodiff: 1135 if self._options.nodiff:
1144 return 1136 pass
1145 1137 elif self._options.view:
1146 if self._options.view:
1147 os.system("%s %s %s" % (self._view, test.refpath, test.errpath)) 1138 os.system("%s %s %s" % (self._view, test.refpath, test.errpath))
1148 else: 1139 else:
1149 failed, lines = getdiff(expected, got, 1140 failed, lines = getdiff(expected, got,
1150 test.refpath, test.errpath) 1141 test.refpath, test.errpath)
1151 if failed: 1142 if failed:
1154 self.stream.write('\n') 1145 self.stream.write('\n')
1155 for line in lines: 1146 for line in lines:
1156 self.stream.write(line) 1147 self.stream.write(line)
1157 self.stream.flush() 1148 self.stream.flush()
1158 1149
1159 if ret or not self._options.interactive or \ 1150 # handle interactive prompt without releasing iolock
1160 not os.path.exists(test.errpath): 1151 if self._options.interactive:
1161 return 1152 self.stream.write('Accept this change? [n] ')
1153 answer = sys.stdin.readline().strip()
1154 if answer.lower() in ('y', 'yes'):
1155 if test.name.endswith('.t'):
1156 rename(test.errpath, test.path)
1157 else:
1158 rename(test.errpath, '%s.out' % test.path)
1159 accepted = True
1160
1161 iolock.release()
1162
1163 return accepted
1162 1164
1163 def startTest(self, test): 1165 def startTest(self, test):
1164 super(TestResult, self).startTest(test) 1166 super(TestResult, self).startTest(test)
1165 1167
1166 self._started[test.name] = time.time() 1168 self._started[test.name] = time.time()