Show More
@@ -371,14 +371,13 b' def log(*msg):' | |||||
371 |
|
371 | |||
372 | Arguments are strings to print. |
|
372 | Arguments are strings to print. | |
373 | """ |
|
373 | """ | |
374 | iolock.acquire() |
|
374 | with iolock: | |
375 | if verbose: |
|
375 | if verbose: | |
376 | print(verbose, end=' ') |
|
376 | print(verbose, end=' ') | |
377 | for m in msg: |
|
377 | for m in msg: | |
378 | print(m, end=' ') |
|
378 | print(m, end=' ') | |
379 | print() |
|
379 | print() | |
380 | sys.stdout.flush() |
|
380 | sys.stdout.flush() | |
381 | iolock.release() |
|
|||
382 |
|
381 | |||
383 | def terminate(proc): |
|
382 | def terminate(proc): | |
384 | """Terminate subprocess (with fallback for Python versions < 2.6)""" |
|
383 | """Terminate subprocess (with fallback for Python versions < 2.6)""" | |
@@ -1209,18 +1208,16 b' class TestResult(unittest._TextTestResul' | |||||
1209 | if self._options.first: |
|
1208 | if self._options.first: | |
1210 | self.stop() |
|
1209 | self.stop() | |
1211 | else: |
|
1210 | else: | |
1212 |
iolock |
|
1211 | with iolock: | |
1213 | if not self._options.nodiff: |
|
1212 | if not self._options.nodiff: | |
1214 | self.stream.write('\nERROR: %s output changed\n' % test) |
|
1213 | self.stream.write('\nERROR: %s output changed\n' % test) | |
1215 |
|
1214 | |||
1216 | self.stream.write('!') |
|
1215 | self.stream.write('!') | |
1217 | self.stream.flush() |
|
1216 | self.stream.flush() | |
1218 | iolock.release() |
|
|||
1219 |
|
1217 | |||
1220 | def addSuccess(self, test): |
|
1218 | def addSuccess(self, test): | |
1221 |
iolock |
|
1219 | with iolock: | |
1222 | super(TestResult, self).addSuccess(test) |
|
1220 | super(TestResult, self).addSuccess(test) | |
1223 | iolock.release() |
|
|||
1224 | self.successes.append(test) |
|
1221 | self.successes.append(test) | |
1225 |
|
1222 | |||
1226 | def addError(self, test, err): |
|
1223 | def addError(self, test, err): | |
@@ -1231,26 +1228,24 b' class TestResult(unittest._TextTestResul' | |||||
1231 | # Polyfill. |
|
1228 | # Polyfill. | |
1232 | def addSkip(self, test, reason): |
|
1229 | def addSkip(self, test, reason): | |
1233 | self.skipped.append((test, reason)) |
|
1230 | self.skipped.append((test, reason)) | |
1234 |
iolock |
|
1231 | with iolock: | |
1235 | if self.showAll: |
|
1232 | if self.showAll: | |
1236 | self.stream.writeln('skipped %s' % reason) |
|
1233 | self.stream.writeln('skipped %s' % reason) | |
1237 | else: |
|
1234 | else: | |
1238 | self.stream.write('s') |
|
1235 | self.stream.write('s') | |
1239 | self.stream.flush() |
|
1236 | self.stream.flush() | |
1240 | iolock.release() |
|
|||
1241 |
|
1237 | |||
1242 | def addIgnore(self, test, reason): |
|
1238 | def addIgnore(self, test, reason): | |
1243 | self.ignored.append((test, reason)) |
|
1239 | self.ignored.append((test, reason)) | |
1244 |
iolock |
|
1240 | with iolock: | |
1245 | if self.showAll: |
|
1241 | if self.showAll: | |
1246 | self.stream.writeln('ignored %s' % reason) |
|
1242 | self.stream.writeln('ignored %s' % reason) | |
1247 | else: |
|
|||
1248 | if reason != 'not retesting' and reason != "doesn't match keyword": |
|
|||
1249 | self.stream.write('i') |
|
|||
1250 | else: |
|
1243 | else: | |
1251 | self.testsRun += 1 |
|
1244 | if reason not in ('not retesting', "doesn't match keyword"): | |
1252 |
self.stream. |
|
1245 | self.stream.write('i') | |
1253 | iolock.release() |
|
1246 | else: | |
|
1247 | self.testsRun += 1 | |||
|
1248 | self.stream.flush() | |||
1254 |
|
1249 | |||
1255 | def addWarn(self, test, reason): |
|
1250 | def addWarn(self, test, reason): | |
1256 | self.warned.append((test, reason)) |
|
1251 | self.warned.append((test, reason)) | |
@@ -1258,13 +1253,12 b' class TestResult(unittest._TextTestResul' | |||||
1258 | if self._options.first: |
|
1253 | if self._options.first: | |
1259 | self.stop() |
|
1254 | self.stop() | |
1260 |
|
1255 | |||
1261 |
iolock |
|
1256 | with iolock: | |
1262 | if self.showAll: |
|
1257 | if self.showAll: | |
1263 | self.stream.writeln('warned %s' % reason) |
|
1258 | self.stream.writeln('warned %s' % reason) | |
1264 | else: |
|
1259 | else: | |
1265 | self.stream.write('~') |
|
1260 | self.stream.write('~') | |
1266 | self.stream.flush() |
|
1261 | self.stream.flush() | |
1267 | iolock.release() |
|
|||
1268 |
|
1262 | |||
1269 | def addOutputMismatch(self, test, ret, got, expected): |
|
1263 | def addOutputMismatch(self, test, ret, got, expected): | |
1270 | """Record a mismatch in test output for a particular test.""" |
|
1264 | """Record a mismatch in test output for a particular test.""" | |
@@ -1278,38 +1272,37 b' class TestResult(unittest._TextTestResul' | |||||
1278 | failed = False |
|
1272 | failed = False | |
1279 | lines = [] |
|
1273 | lines = [] | |
1280 |
|
1274 | |||
1281 |
iolock |
|
1275 | with iolock: | |
1282 | if self._options.nodiff: |
|
1276 | if self._options.nodiff: | |
1283 | pass |
|
1277 | pass | |
1284 | elif self._options.view: |
|
1278 | elif self._options.view: | |
1285 | os.system("%s %s %s" % |
|
1279 | os.system("%s %s %s" % | |
1286 | (self._options.view, test.refpath, test.errpath)) |
|
1280 | (self._options.view, test.refpath, test.errpath)) | |
1287 | else: |
|
|||
1288 | servefail, lines = getdiff(expected, got, |
|
|||
1289 | test.refpath, test.errpath) |
|
|||
1290 | if servefail: |
|
|||
1291 | self.addFailure( |
|
|||
1292 | test, |
|
|||
1293 | 'server failed to start (HGPORT=%s)' % test._startport) |
|
|||
1294 | else: |
|
1281 | else: | |
1295 | self.stream.write('\n') |
|
1282 | servefail, lines = getdiff(expected, got, | |
1296 | for line in lines: |
|
1283 | test.refpath, test.errpath) | |
1297 | self.stream.write(line) |
|
1284 | if servefail: | |
1298 |
self. |
|
1285 | self.addFailure( | |
|
1286 | test, | |||
|
1287 | 'server failed to start (HGPORT=%s)' % test._startport) | |||
|
1288 | else: | |||
|
1289 | self.stream.write('\n') | |||
|
1290 | for line in lines: | |||
|
1291 | self.stream.write(line) | |||
|
1292 | self.stream.flush() | |||
1299 |
|
1293 | |||
1300 | # handle interactive prompt without releasing iolock |
|
1294 | # handle interactive prompt without releasing iolock | |
1301 | if self._options.interactive: |
|
1295 | if self._options.interactive: | |
1302 | self.stream.write('Accept this change? [n] ') |
|
1296 | self.stream.write('Accept this change? [n] ') | |
1303 | answer = sys.stdin.readline().strip() |
|
1297 | answer = sys.stdin.readline().strip() | |
1304 | if answer.lower() in ('y', 'yes'): |
|
1298 | if answer.lower() in ('y', 'yes'): | |
1305 | if test.name.endswith('.t'): |
|
1299 | if test.name.endswith('.t'): | |
1306 | rename(test.errpath, test.path) |
|
1300 | rename(test.errpath, test.path) | |
1307 | else: |
|
1301 | else: | |
1308 | rename(test.errpath, '%s.out' % test.path) |
|
1302 | rename(test.errpath, '%s.out' % test.path) | |
1309 | accepted = True |
|
1303 | accepted = True | |
1310 | if not accepted and not failed: |
|
1304 | if not accepted and not failed: | |
1311 | self.faildata[test.name] = ''.join(lines) |
|
1305 | self.faildata[test.name] = ''.join(lines) | |
1312 | iolock.release() |
|
|||
1313 |
|
1306 | |||
1314 | return accepted |
|
1307 | return accepted | |
1315 |
|
1308 | |||
@@ -1336,10 +1329,9 b' class TestResult(unittest._TextTestResul' | |||||
1336 | )) |
|
1329 | )) | |
1337 |
|
1330 | |||
1338 | if interrupted: |
|
1331 | if interrupted: | |
1339 |
iolock |
|
1332 | with iolock: | |
1340 | self.stream.writeln('INTERRUPTED: %s (after %d seconds)' % ( |
|
1333 | self.stream.writeln('INTERRUPTED: %s (after %d seconds)' % ( | |
1341 | test.name, self.times[-1][3])) |
|
1334 | test.name, self.times[-1][3])) | |
1342 | iolock.release() |
|
|||
1343 |
|
1335 | |||
1344 | class TestSuite(unittest.TestSuite): |
|
1336 | class TestSuite(unittest.TestSuite): | |
1345 | """Custom unittest TestSuite that knows how to execute Mercurial tests.""" |
|
1337 | """Custom unittest TestSuite that knows how to execute Mercurial tests.""" | |
@@ -1502,91 +1494,91 b' class TextTestRunner(unittest.TextTestRu' | |||||
1502 | skipped = len(result.skipped) |
|
1494 | skipped = len(result.skipped) | |
1503 | ignored = len(result.ignored) |
|
1495 | ignored = len(result.ignored) | |
1504 |
|
1496 | |||
1505 |
iolock |
|
1497 | with iolock: | |
1506 | self.stream.writeln('') |
|
1498 | self.stream.writeln('') | |
1507 |
|
1499 | |||
1508 | if not self._runner.options.noskips: |
|
1500 | if not self._runner.options.noskips: | |
1509 | for test, msg in result.skipped: |
|
1501 | for test, msg in result.skipped: | |
1510 | self.stream.writeln('Skipped %s: %s' % (test.name, msg)) |
|
1502 | self.stream.writeln('Skipped %s: %s' % (test.name, msg)) | |
1511 | for test, msg in result.warned: |
|
1503 | for test, msg in result.warned: | |
1512 | self.stream.writeln('Warned %s: %s' % (test.name, msg)) |
|
1504 | self.stream.writeln('Warned %s: %s' % (test.name, msg)) | |
1513 | for test, msg in result.failures: |
|
1505 | for test, msg in result.failures: | |
1514 | self.stream.writeln('Failed %s: %s' % (test.name, msg)) |
|
1506 | self.stream.writeln('Failed %s: %s' % (test.name, msg)) | |
1515 | for test, msg in result.errors: |
|
1507 | for test, msg in result.errors: | |
1516 | self.stream.writeln('Errored %s: %s' % (test.name, msg)) |
|
1508 | self.stream.writeln('Errored %s: %s' % (test.name, msg)) | |
1517 |
|
1509 | |||
1518 | if self._runner.options.xunit: |
|
1510 | if self._runner.options.xunit: | |
1519 | xuf = open(self._runner.options.xunit, 'wb') |
|
1511 | xuf = open(self._runner.options.xunit, 'wb') | |
1520 | try: |
|
1512 | try: | |
1521 | timesd = dict((t[0], t[3]) for t in result.times) |
|
1513 | timesd = dict((t[0], t[3]) for t in result.times) | |
1522 | doc = minidom.Document() |
|
1514 | doc = minidom.Document() | |
1523 | s = doc.createElement('testsuite') |
|
1515 | s = doc.createElement('testsuite') | |
1524 | s.setAttribute('name', 'run-tests') |
|
1516 | s.setAttribute('name', 'run-tests') | |
1525 | s.setAttribute('tests', str(result.testsRun)) |
|
1517 | s.setAttribute('tests', str(result.testsRun)) | |
1526 | s.setAttribute('errors', "0") # TODO |
|
1518 | s.setAttribute('errors', "0") # TODO | |
1527 | s.setAttribute('failures', str(failed)) |
|
1519 | s.setAttribute('failures', str(failed)) | |
1528 | s.setAttribute('skipped', str(skipped + ignored)) |
|
1520 | s.setAttribute('skipped', str(skipped + ignored)) | |
1529 | doc.appendChild(s) |
|
1521 | doc.appendChild(s) | |
1530 | for tc in result.successes: |
|
1522 | for tc in result.successes: | |
1531 | t = doc.createElement('testcase') |
|
1523 | t = doc.createElement('testcase') | |
1532 | t.setAttribute('name', tc.name) |
|
1524 | t.setAttribute('name', tc.name) | |
1533 | t.setAttribute('time', '%.3f' % timesd[tc.name]) |
|
1525 | t.setAttribute('time', '%.3f' % timesd[tc.name]) | |
1534 | s.appendChild(t) |
|
1526 | s.appendChild(t) | |
1535 | for tc, err in sorted(result.faildata.iteritems()): |
|
1527 | for tc, err in sorted(result.faildata.iteritems()): | |
1536 | t = doc.createElement('testcase') |
|
1528 | t = doc.createElement('testcase') | |
1537 | t.setAttribute('name', tc) |
|
1529 | t.setAttribute('name', tc) | |
1538 | t.setAttribute('time', '%.3f' % timesd[tc]) |
|
1530 | t.setAttribute('time', '%.3f' % timesd[tc]) | |
1539 |
# createCDATASection expects a unicode or it will |
|
1531 | # createCDATASection expects a unicode or it will | |
1540 |
# using default conversion rules, which will |
|
1532 | # convert using default conversion rules, which will | |
1541 | # string isn't ASCII. |
|
1533 | # fail if string isn't ASCII. | |
1542 | err = cdatasafe(err).decode('utf-8', 'replace') |
|
1534 | err = cdatasafe(err).decode('utf-8', 'replace') | |
1543 | cd = doc.createCDATASection(err) |
|
1535 | cd = doc.createCDATASection(err) | |
1544 | t.appendChild(cd) |
|
1536 | t.appendChild(cd) | |
1545 | s.appendChild(t) |
|
1537 | s.appendChild(t) | |
1546 | xuf.write(doc.toprettyxml(indent=' ', encoding='utf-8')) |
|
1538 | xuf.write(doc.toprettyxml(indent=' ', encoding='utf-8')) | |
1547 | finally: |
|
1539 | finally: | |
1548 | xuf.close() |
|
1540 | xuf.close() | |
1549 |
|
1541 | |||
1550 | if self._runner.options.json: |
|
1542 | if self._runner.options.json: | |
1551 | if json is None: |
|
1543 | if json is None: | |
1552 | raise ImportError("json module not installed") |
|
1544 | raise ImportError("json module not installed") | |
1553 | jsonpath = os.path.join(self._runner._testdir, 'report.json') |
|
1545 | jsonpath = os.path.join(self._runner._testdir, 'report.json') | |
1554 | fp = open(jsonpath, 'w') |
|
1546 | fp = open(jsonpath, 'w') | |
1555 | try: |
|
1547 | try: | |
1556 | timesd = {} |
|
1548 | timesd = {} | |
1557 | for tdata in result.times: |
|
1549 | for tdata in result.times: | |
1558 | test = tdata[0] |
|
1550 | test = tdata[0] | |
1559 | timesd[test] = tdata[1:] |
|
1551 | timesd[test] = tdata[1:] | |
1560 |
|
1552 | |||
1561 | outcome = {} |
|
1553 | outcome = {} | |
1562 |
groups = [('success', ((tc, None) |
|
1554 | groups = [('success', ((tc, None) | |
1563 |
|
|
1555 | for tc in result.successes)), | |
1564 |
(' |
|
1556 | ('failure', result.failures), | |
1565 | for res, testcases in groups: |
|
1557 | ('skip', result.skipped)] | |
1566 |
for |
|
1558 | for res, testcases in groups: | |
1567 |
|
|
1559 | for tc, __ in testcases: | |
1568 | 'time': ('%0.3f' % timesd[tc.name][2]), |
|
1560 | tres = {'result': res, | |
1569 |
|
|
1561 | 'time': ('%0.3f' % timesd[tc.name][2]), | |
1570 |
|
|
1562 | 'cuser': ('%0.3f' % timesd[tc.name][0]), | |
1571 | outcome[tc.name] = testresult |
|
1563 | 'csys': ('%0.3f' % timesd[tc.name][1])} | |
|
1564 | outcome[tc.name] = tres | |||
1572 |
|
1565 | |||
1573 | jsonout = json.dumps(outcome, sort_keys=True, indent=4) |
|
1566 | jsonout = json.dumps(outcome, sort_keys=True, indent=4) | |
1574 | fp.writelines(("testreport =", jsonout)) |
|
1567 | fp.writelines(("testreport =", jsonout)) | |
1575 | finally: |
|
1568 | finally: | |
1576 | fp.close() |
|
1569 | fp.close() | |
1577 |
|
1570 | |||
1578 | self._runner._checkhglib('Tested') |
|
1571 | self._runner._checkhglib('Tested') | |
1579 |
|
1572 | |||
1580 | self.stream.writeln('# Ran %d tests, %d skipped, %d warned, %d failed.' |
|
1573 | self.stream.writeln( | |
1581 | % (result.testsRun, |
|
1574 | '# Ran %d tests, %d skipped, %d warned, %d failed.' | |
1582 | skipped + ignored, warned, failed)) |
|
1575 | % (result.testsRun, | |
1583 | if failed: |
|
1576 | skipped + ignored, warned, failed)) | |
1584 | self.stream.writeln('python hash seed: %s' % |
|
1577 | if failed: | |
1585 | os.environ['PYTHONHASHSEED']) |
|
1578 | self.stream.writeln('python hash seed: %s' % | |
1586 | if self._runner.options.time: |
|
1579 | os.environ['PYTHONHASHSEED']) | |
1587 |
self. |
|
1580 | if self._runner.options.time: | |
1588 |
|
1581 | self.printtimes(result.times) | ||
1589 | iolock.release() |
|
|||
1590 |
|
1582 | |||
1591 | return result |
|
1583 | return result | |
1592 |
|
1584 |
General Comments 0
You need to be logged in to leave comments.
Login now