Mercurial > hg
comparison tests/run-tests.py @ 27396:64c584070fc7
run-tests: show scheduling with --showchannels
This gives one line of output per second with one column per -j level
that allows analyzing test scheduling problems. First 24 seconds of
output at -j 30 looks like this:
0 .
1 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = s.
2 c c o c r l g r s s = c p = c h c a h c g c h c b c c l l c ss
3 h o b o e a e u u u c o a h o e o c g o l h g h u o = a o = s
4 e n s n b r n n b b m t g n l n l w n o e w e n n e r g i .
5 c t o = a g d - r r = m c w v p v . e v g c e c d v x g . m
6 k r l r s e o t e e b a h e e . e . b e . k b k l e t e . p
7 - i e e e f c e p p u n b b r . r . - r . - - - e r e f . o .
8 p b t v - i . s o o n d o d t . t . c t . c s = 2 t n i . r
9 y - e s c l . t - . d - m i - . - . o - . o y r - - s l . t
10 3 p - e h e . s s . l t b r s . s . m s . d m e f s i e . .
11 - e c t e s . . v . e e . . v . v . m v . e r n o v o s . .
12 c r h . c - . . n . 2 m . . n . n . a n . . e a r n n . . .
13 o f e . k u . . . . - p . . - . - . n - . . v m m - . . . .
14 m . c . - p . . . . e l . . s . m . d s . . . e a e . . . .
15 p . k . r d . . . . x a . . i . o . s o . . . - t n . . . .
16 a . h . e a . . . . c t . . n . v . . u . . . m . c . . . .
17 t . e . s t . . . . h e . . k . e . . r . . . e . o . . . .
18 . . a . t e . . . . a . . . . . . . . c . . . r . d . . . .
19 . . d . o . . . . . n . . . . . . . . e . . . g . i . . . .
20 . . s . r . . . . . g . . . . . . . . . . . . e . n . . . .
21 . . . . e . . . . . e . . . . . . . . . . . . 2 . g . . . .
22 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24 . . . . . . . . . . . . . . . . . . . . . . . . . = . . . . ^C
Test names read off vertically, beginning with '='. Idle time (not
shown) appears as blank space.
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 07 Dec 2015 16:16:06 -0600 |
parents | b4d7743e174a |
children | 80b53082a353 |
comparison
equal
deleted
inserted
replaced
27395:0622d6e134fb | 27396:64c584070fc7 |
---|---|
265 help='run tests in random order') | 265 help='run tests in random order') |
266 parser.add_option('--profile-runner', action='store_true', | 266 parser.add_option('--profile-runner', action='store_true', |
267 help='run statprof on run-tests') | 267 help='run statprof on run-tests') |
268 parser.add_option('--allow-slow-tests', action='store_true', | 268 parser.add_option('--allow-slow-tests', action='store_true', |
269 help='allow extremely slow tests') | 269 help='allow extremely slow tests') |
270 parser.add_option('--showchannels', action='store_true', | |
271 help='show scheduling channels') | |
270 | 272 |
271 for option, (envvar, default) in defaults.items(): | 273 for option, (envvar, default) in defaults.items(): |
272 defaults[option] = type(default)(os.environ.get(envvar, default)) | 274 defaults[option] = type(default)(os.environ.get(envvar, default)) |
273 parser.set_defaults(**defaults) | 275 parser.set_defaults(**defaults) |
274 | 276 |
344 options.blacklist = parselistfiles(options.blacklist, 'blacklist') | 346 options.blacklist = parselistfiles(options.blacklist, 'blacklist') |
345 if options.whitelist: | 347 if options.whitelist: |
346 options.whitelisted = parselistfiles(options.whitelist, 'whitelist') | 348 options.whitelisted = parselistfiles(options.whitelist, 'whitelist') |
347 else: | 349 else: |
348 options.whitelisted = {} | 350 options.whitelisted = {} |
351 | |
352 if options.showchannels: | |
353 options.nodiff = True | |
349 | 354 |
350 return (options, args) | 355 return (options, args) |
351 | 356 |
352 def rename(src, dst): | 357 def rename(src, dst): |
353 """Like os.rename(), trade atomicity and opened files friendliness | 358 """Like os.rename(), trade atomicity and opened files friendliness |
1416 class TestSuite(unittest.TestSuite): | 1421 class TestSuite(unittest.TestSuite): |
1417 """Custom unittest TestSuite that knows how to execute Mercurial tests.""" | 1422 """Custom unittest TestSuite that knows how to execute Mercurial tests.""" |
1418 | 1423 |
1419 def __init__(self, testdir, jobs=1, whitelist=None, blacklist=None, | 1424 def __init__(self, testdir, jobs=1, whitelist=None, blacklist=None, |
1420 retest=False, keywords=None, loop=False, runs_per_test=1, | 1425 retest=False, keywords=None, loop=False, runs_per_test=1, |
1421 loadtest=None, | 1426 loadtest=None, showchannels=False, |
1422 *args, **kwargs): | 1427 *args, **kwargs): |
1423 """Create a new instance that can run tests with a configuration. | 1428 """Create a new instance that can run tests with a configuration. |
1424 | 1429 |
1425 testdir specifies the directory where tests are executed from. This | 1430 testdir specifies the directory where tests are executed from. This |
1426 is typically the ``tests`` directory from Mercurial's source | 1431 is typically the ``tests`` directory from Mercurial's source |
1453 self._retest = retest | 1458 self._retest = retest |
1454 self._keywords = keywords | 1459 self._keywords = keywords |
1455 self._loop = loop | 1460 self._loop = loop |
1456 self._runs_per_test = runs_per_test | 1461 self._runs_per_test = runs_per_test |
1457 self._loadtest = loadtest | 1462 self._loadtest = loadtest |
1463 self._showchannels = showchannels | |
1458 | 1464 |
1459 def run(self, result): | 1465 def run(self, result): |
1460 # We have a number of filters that need to be applied. We do this | 1466 # We have a number of filters that need to be applied. We do this |
1461 # here instead of inside Test because it makes the running logic for | 1467 # here instead of inside Test because it makes the running logic for |
1462 # Test simpler. | 1468 # Test simpler. |
1499 | 1505 |
1500 runtests = list(tests) | 1506 runtests = list(tests) |
1501 done = queue.Queue() | 1507 done = queue.Queue() |
1502 running = 0 | 1508 running = 0 |
1503 | 1509 |
1510 channels = [""] * self._jobs | |
1511 | |
1504 def job(test, result): | 1512 def job(test, result): |
1513 for n, v in enumerate(channels): | |
1514 if not v: | |
1515 channel = n | |
1516 break | |
1517 channels[channel] = "=" + test.name[5:].split(".")[0] | |
1505 try: | 1518 try: |
1506 test(result) | 1519 test(result) |
1507 done.put(None) | 1520 done.put(None) |
1508 except KeyboardInterrupt: | 1521 except KeyboardInterrupt: |
1509 pass | 1522 pass |
1510 except: # re-raises | 1523 except: # re-raises |
1511 done.put(('!', test, 'run-test raised an error, see traceback')) | 1524 done.put(('!', test, 'run-test raised an error, see traceback')) |
1512 raise | 1525 raise |
1526 channels[channel] = '' | |
1527 | |
1528 def stat(): | |
1529 count = 0 | |
1530 while channels: | |
1531 d = '\n%03s ' % count | |
1532 for n, v in enumerate(channels): | |
1533 if v: | |
1534 d += v[0] | |
1535 channels[n] = v[1:] or '.' | |
1536 else: | |
1537 d += ' ' | |
1538 d += ' ' | |
1539 with iolock: | |
1540 sys.stdout.write(d + ' ') | |
1541 sys.stdout.flush() | |
1542 for x in xrange(10): | |
1543 if channels: | |
1544 time.sleep(.1) | |
1545 count += 1 | |
1513 | 1546 |
1514 stoppedearly = False | 1547 stoppedearly = False |
1548 | |
1549 if self._showchannels: | |
1550 statthread = threading.Thread(target=stat, name="stat") | |
1551 statthread.start() | |
1515 | 1552 |
1516 try: | 1553 try: |
1517 while tests or running: | 1554 while tests or running: |
1518 if not done.empty() or running == self._jobs or not tests: | 1555 if not done.empty() or running == self._jobs or not tests: |
1519 try: | 1556 try: |
1550 except queue.Empty: | 1587 except queue.Empty: |
1551 continue | 1588 continue |
1552 except KeyboardInterrupt: | 1589 except KeyboardInterrupt: |
1553 for test in runtests: | 1590 for test in runtests: |
1554 test.abort() | 1591 test.abort() |
1592 | |
1593 channels = [] | |
1555 | 1594 |
1556 return result | 1595 return result |
1557 | 1596 |
1558 class TextTestRunner(unittest.TextTestRunner): | 1597 class TextTestRunner(unittest.TextTestRunner): |
1559 """Custom unittest test runner that uses appropriate settings.""" | 1598 """Custom unittest test runner that uses appropriate settings.""" |
1940 blacklist=self.options.blacklist, | 1979 blacklist=self.options.blacklist, |
1941 retest=self.options.retest, | 1980 retest=self.options.retest, |
1942 keywords=kws, | 1981 keywords=kws, |
1943 loop=self.options.loop, | 1982 loop=self.options.loop, |
1944 runs_per_test=self.options.runs_per_test, | 1983 runs_per_test=self.options.runs_per_test, |
1984 showchannels=self.options.showchannels, | |
1945 tests=tests, loadtest=self._gettest) | 1985 tests=tests, loadtest=self._gettest) |
1946 verbosity = 1 | 1986 verbosity = 1 |
1947 if self.options.verbose: | 1987 if self.options.verbose: |
1948 verbosity = 2 | 1988 verbosity = 2 |
1949 runner = TextTestRunner(self, verbosity=verbosity) | 1989 runner = TextTestRunner(self, verbosity=verbosity) |