Mercurial > hg
comparison tests/run-tests.py @ 35187:b4b0aed7bfaf
run-tests: convert to argparse
optparse has been deprecated since Python 3.2. Best to get on the new
boat before the old one sinks.
It looks like argparse formats its usage string differently than
optparse. Meh.
Differential Revision: https://phab.mercurial-scm.org/D1474
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Mon, 20 Nov 2017 20:41:43 -0800 |
parents | 6d5718e39657 |
children | d997b82152e8 |
comparison
equal
deleted
inserted
replaced
35186:aef2b98d9352 | 35187:b4b0aed7bfaf |
---|---|
43 # completes fairly quickly, includes both shell and Python scripts, and | 43 # completes fairly quickly, includes both shell and Python scripts, and |
44 # includes some scripts that run daemon processes.) | 44 # includes some scripts that run daemon processes.) |
45 | 45 |
46 from __future__ import absolute_import, print_function | 46 from __future__ import absolute_import, print_function |
47 | 47 |
48 import argparse | |
48 import difflib | 49 import difflib |
49 import distutils.version as version | 50 import distutils.version as version |
50 import errno | 51 import errno |
51 import json | 52 import json |
52 import optparse | |
53 import os | 53 import os |
54 import random | 54 import random |
55 import re | 55 import re |
56 import shutil | 56 import shutil |
57 import signal | 57 import signal |
294 raise | 294 raise |
295 return cases | 295 return cases |
296 | 296 |
297 def getparser(): | 297 def getparser(): |
298 """Obtain the OptionParser used by the CLI.""" | 298 """Obtain the OptionParser used by the CLI.""" |
299 parser = optparse.OptionParser("%prog [options] [tests]") | 299 parser = argparse.ArgumentParser(usage='%(prog)s [options] [tests]') |
300 | 300 |
301 # keep these sorted | 301 # keep these sorted |
302 parser.add_option("--blacklist", action="append", | 302 parser.add_argument("--blacklist", action="append", |
303 help="skip tests listed in the specified blacklist file") | 303 help="skip tests listed in the specified blacklist file") |
304 parser.add_option("--whitelist", action="append", | 304 parser.add_argument("--whitelist", action="append", |
305 help="always run tests listed in the specified whitelist file") | 305 help="always run tests listed in the specified whitelist file") |
306 parser.add_option("--test-list", action="append", | 306 parser.add_argument("--test-list", action="append", |
307 help="read tests to run from the specified file") | 307 help="read tests to run from the specified file") |
308 parser.add_option("--changed", type="string", | 308 parser.add_argument("--changed", |
309 help="run tests that are changed in parent rev or working directory") | 309 help="run tests that are changed in parent rev or working directory") |
310 parser.add_option("-C", "--annotate", action="store_true", | 310 parser.add_argument("-C", "--annotate", action="store_true", |
311 help="output files annotated with coverage") | 311 help="output files annotated with coverage") |
312 parser.add_option("-c", "--cover", action="store_true", | 312 parser.add_argument("-c", "--cover", action="store_true", |
313 help="print a test coverage report") | 313 help="print a test coverage report") |
314 parser.add_option("--color", choices=["always", "auto", "never"], | 314 parser.add_argument("--color", choices=["always", "auto", "never"], |
315 default=os.environ.get('HGRUNTESTSCOLOR', 'auto'), | 315 default=os.environ.get('HGRUNTESTSCOLOR', 'auto'), |
316 help="colorisation: always|auto|never (default: auto)") | 316 help="colorisation: always|auto|never (default: auto)") |
317 parser.add_option("-d", "--debug", action="store_true", | 317 parser.add_argument("-d", "--debug", action="store_true", |
318 help="debug mode: write output of test scripts to console" | 318 help="debug mode: write output of test scripts to console" |
319 " rather than capturing and diffing it (disables timeout)") | 319 " rather than capturing and diffing it (disables timeout)") |
320 parser.add_option("-f", "--first", action="store_true", | 320 parser.add_argument("-f", "--first", action="store_true", |
321 help="exit on the first test failure") | 321 help="exit on the first test failure") |
322 parser.add_option("-H", "--htmlcov", action="store_true", | 322 parser.add_argument("-H", "--htmlcov", action="store_true", |
323 help="create an HTML report of the coverage of the files") | 323 help="create an HTML report of the coverage of the files") |
324 parser.add_option("-i", "--interactive", action="store_true", | 324 parser.add_argument("-i", "--interactive", action="store_true", |
325 help="prompt to accept changed output") | 325 help="prompt to accept changed output") |
326 parser.add_option("-j", "--jobs", type="int", | 326 parser.add_argument("-j", "--jobs", type=int, |
327 help="number of jobs to run in parallel" | 327 help="number of jobs to run in parallel" |
328 " (default: $%s or %d)" % defaults['jobs']) | 328 " (default: $%s or %d)" % defaults['jobs']) |
329 parser.add_option("--keep-tmpdir", action="store_true", | 329 parser.add_argument("--keep-tmpdir", action="store_true", |
330 help="keep temporary directory after running tests") | 330 help="keep temporary directory after running tests") |
331 parser.add_option("-k", "--keywords", | 331 parser.add_argument("-k", "--keywords", |
332 help="run tests matching keywords") | 332 help="run tests matching keywords") |
333 parser.add_option("--list-tests", action="store_true", | 333 parser.add_argument("--list-tests", action="store_true", |
334 help="list tests instead of running them") | 334 help="list tests instead of running them") |
335 parser.add_option("-l", "--local", action="store_true", | 335 parser.add_argument("-l", "--local", action="store_true", |
336 help="shortcut for --with-hg=<testdir>/../hg, " | 336 help="shortcut for --with-hg=<testdir>/../hg, " |
337 "and --with-chg=<testdir>/../contrib/chg/chg if --chg is set") | 337 "and --with-chg=<testdir>/../contrib/chg/chg if --chg is set") |
338 parser.add_option("--loop", action="store_true", | 338 parser.add_argument("--loop", action="store_true", |
339 help="loop tests repeatedly") | 339 help="loop tests repeatedly") |
340 parser.add_option("--runs-per-test", type="int", dest="runs_per_test", | 340 parser.add_argument("--runs-per-test", type=int, dest="runs_per_test", |
341 help="run each test N times (default=1)", default=1) | 341 help="run each test N times (default=1)", default=1) |
342 parser.add_option("-n", "--nodiff", action="store_true", | 342 parser.add_argument("-n", "--nodiff", action="store_true", |
343 help="skip showing test changes") | 343 help="skip showing test changes") |
344 parser.add_option("--outputdir", type="string", | 344 parser.add_argument("--outputdir", |
345 help="directory to write error logs to (default=test directory)") | 345 help="directory to write error logs to (default=test directory)") |
346 parser.add_option("-p", "--port", type="int", | 346 parser.add_argument("-p", "--port", type=int, |
347 help="port on which servers should listen" | 347 help="port on which servers should listen" |
348 " (default: $%s or %d)" % defaults['port']) | 348 " (default: $%s or %d)" % defaults['port']) |
349 parser.add_option("--compiler", type="string", | 349 parser.add_argument("--compiler", |
350 help="compiler to build with") | 350 help="compiler to build with") |
351 parser.add_option("--pure", action="store_true", | 351 parser.add_argument("--pure", action="store_true", |
352 help="use pure Python code instead of C extensions") | 352 help="use pure Python code instead of C extensions") |
353 parser.add_option("-R", "--restart", action="store_true", | 353 parser.add_argument("-R", "--restart", action="store_true", |
354 help="restart at last error") | 354 help="restart at last error") |
355 parser.add_option("-r", "--retest", action="store_true", | 355 parser.add_argument("-r", "--retest", action="store_true", |
356 help="retest failed tests") | 356 help="retest failed tests") |
357 parser.add_option("-S", "--noskips", action="store_true", | 357 parser.add_argument("-S", "--noskips", action="store_true", |
358 help="don't report skip tests verbosely") | 358 help="don't report skip tests verbosely") |
359 parser.add_option("--shell", type="string", | 359 parser.add_argument("--shell", |
360 help="shell to use (default: $%s or %s)" % defaults['shell']) | 360 help="shell to use (default: $%s or %s)" % defaults['shell']) |
361 parser.add_option("-t", "--timeout", type="int", | 361 parser.add_argument("-t", "--timeout", type=int, |
362 help="kill errant tests after TIMEOUT seconds" | 362 help="kill errant tests after TIMEOUT seconds" |
363 " (default: $%s or %d)" % defaults['timeout']) | 363 " (default: $%s or %d)" % defaults['timeout']) |
364 parser.add_option("--slowtimeout", type="int", | 364 parser.add_argument("--slowtimeout", type=int, |
365 help="kill errant slow tests after SLOWTIMEOUT seconds" | 365 help="kill errant slow tests after SLOWTIMEOUT seconds" |
366 " (default: $%s or %d)" % defaults['slowtimeout']) | 366 " (default: $%s or %d)" % defaults['slowtimeout']) |
367 parser.add_option("--time", action="store_true", | 367 parser.add_argument("--time", action="store_true", |
368 help="time how long each test takes") | 368 help="time how long each test takes") |
369 parser.add_option("--json", action="store_true", | 369 parser.add_argument("--json", action="store_true", |
370 help="store test result data in 'report.json' file") | 370 help="store test result data in 'report.json' file") |
371 parser.add_option("--tmpdir", type="string", | 371 parser.add_argument("--tmpdir", |
372 help="run tests in the given temporary directory" | 372 help="run tests in the given temporary directory" |
373 " (implies --keep-tmpdir)") | 373 " (implies --keep-tmpdir)") |
374 parser.add_option("-v", "--verbose", action="store_true", | 374 parser.add_argument("-v", "--verbose", action="store_true", |
375 help="output verbose messages") | 375 help="output verbose messages") |
376 parser.add_option("--xunit", type="string", | 376 parser.add_argument("--xunit", |
377 help="record xunit results at specified path") | 377 help="record xunit results at specified path") |
378 parser.add_option("--view", type="string", | 378 parser.add_argument("--view", |
379 help="external diff viewer") | 379 help="external diff viewer") |
380 parser.add_option("--with-hg", type="string", | 380 parser.add_argument("--with-hg", |
381 metavar="HG", | 381 metavar="HG", |
382 help="test using specified hg script rather than a " | 382 help="test using specified hg script rather than a " |
383 "temporary installation") | 383 "temporary installation") |
384 parser.add_option("--chg", action="store_true", | 384 parser.add_argument("--chg", action="store_true", |
385 help="install and use chg wrapper in place of hg") | 385 help="install and use chg wrapper in place of hg") |
386 parser.add_option("--with-chg", metavar="CHG", | 386 parser.add_argument("--with-chg", metavar="CHG", |
387 help="use specified chg wrapper in place of hg") | 387 help="use specified chg wrapper in place of hg") |
388 parser.add_option("--ipv6", action="store_true", | 388 parser.add_argument("--ipv6", action="store_true", |
389 help="prefer IPv6 to IPv4 for network related tests") | 389 help="prefer IPv6 to IPv4 for network related tests") |
390 parser.add_option("-3", "--py3k-warnings", action="store_true", | 390 parser.add_argument("-3", "--py3k-warnings", action="store_true", |
391 help="enable Py3k warnings on Python 2.7+") | 391 help="enable Py3k warnings on Python 2.7+") |
392 # This option should be deleted once test-check-py3-compat.t and other | 392 # This option should be deleted once test-check-py3-compat.t and other |
393 # Python 3 tests run with Python 3. | 393 # Python 3 tests run with Python 3. |
394 parser.add_option("--with-python3", metavar="PYTHON3", | 394 parser.add_argument("--with-python3", metavar="PYTHON3", |
395 help="Python 3 interpreter (if running under Python 2)" | 395 help="Python 3 interpreter (if running under Python 2)" |
396 " (TEMPORARY)") | 396 " (TEMPORARY)") |
397 parser.add_option('--extra-config-opt', action="append", | 397 parser.add_argument('--extra-config-opt', action="append", |
398 help='set the given config opt in the test hgrc') | 398 help='set the given config opt in the test hgrc') |
399 parser.add_option('--random', action="store_true", | 399 parser.add_argument('--random', action="store_true", |
400 help='run tests in random order') | 400 help='run tests in random order') |
401 parser.add_option('--profile-runner', action='store_true', | 401 parser.add_argument('--profile-runner', action='store_true', |
402 help='run statprof on run-tests') | 402 help='run statprof on run-tests') |
403 parser.add_option('--allow-slow-tests', action='store_true', | 403 parser.add_argument('--allow-slow-tests', action='store_true', |
404 help='allow extremely slow tests') | 404 help='allow extremely slow tests') |
405 parser.add_option('--showchannels', action='store_true', | 405 parser.add_argument('--showchannels', action='store_true', |
406 help='show scheduling channels') | 406 help='show scheduling channels') |
407 parser.add_option('--known-good-rev', type="string", | 407 parser.add_argument('--known-good-rev', |
408 metavar="known_good_rev", | 408 metavar="known_good_rev", |
409 help=("Automatically bisect any failures using this " | 409 help=("Automatically bisect any failures using this " |
410 "revision as a known-good revision.")) | 410 "revision as a known-good revision.")) |
411 parser.add_option('--bisect-repo', type="string", | 411 parser.add_argument('--bisect-repo', |
412 metavar='bisect_repo', | 412 metavar='bisect_repo', |
413 help=("Path of a repo to bisect. Use together with " | 413 help=("Path of a repo to bisect. Use together with " |
414 "--known-good-rev")) | 414 "--known-good-rev")) |
415 | |
416 parser.add_argument('tests', metavar='TESTS', nargs='*', | |
417 help='Tests to run') | |
415 | 418 |
416 for option, (envvar, default) in defaults.items(): | 419 for option, (envvar, default) in defaults.items(): |
417 defaults[option] = type(default)(os.environ.get(envvar, default)) | 420 defaults[option] = type(default)(os.environ.get(envvar, default)) |
418 parser.set_defaults(**defaults) | 421 parser.set_defaults(**defaults) |
419 | 422 |
420 return parser | 423 return parser |
421 | 424 |
422 def parseargs(args, parser): | 425 def parseargs(args, parser): |
423 """Parse arguments with our OptionParser and validate results.""" | 426 """Parse arguments with our OptionParser and validate results.""" |
424 (options, args) = parser.parse_args(args) | 427 options = parser.parse_args(args) |
425 | 428 |
426 # jython is always pure | 429 # jython is always pure |
427 if 'java' in sys.platform or '__pypy__' in sys.modules: | 430 if 'java' in sys.platform or '__pypy__' in sys.modules: |
428 options.pure = True | 431 options.pure = True |
429 | 432 |
548 options.whitelisted = {} | 551 options.whitelisted = {} |
549 | 552 |
550 if options.showchannels: | 553 if options.showchannels: |
551 options.nodiff = True | 554 options.nodiff = True |
552 | 555 |
553 return (options, args) | 556 return options |
554 | 557 |
555 def rename(src, dst): | 558 def rename(src, dst): |
556 """Like os.rename(), trade atomicity and opened files friendliness | 559 """Like os.rename(), trade atomicity and opened files friendliness |
557 for existing destination support. | 560 for existing destination support. |
558 """ | 561 """ |
2296 def run(self, args, parser=None): | 2299 def run(self, args, parser=None): |
2297 """Run the test suite.""" | 2300 """Run the test suite.""" |
2298 oldmask = os.umask(0o22) | 2301 oldmask = os.umask(0o22) |
2299 try: | 2302 try: |
2300 parser = parser or getparser() | 2303 parser = parser or getparser() |
2301 options, args = parseargs(args, parser) | 2304 options = parseargs(args, parser) |
2302 # positional arguments are paths to test files to run, so | 2305 tests = [_bytespath(a) for a in options.tests] |
2303 # we make sure they're all bytestrings | |
2304 args = [_bytespath(a) for a in args] | |
2305 if options.test_list is not None: | 2306 if options.test_list is not None: |
2306 for listfile in options.test_list: | 2307 for listfile in options.test_list: |
2307 with open(listfile, 'rb') as f: | 2308 with open(listfile, 'rb') as f: |
2308 args.extend(t for t in f.read().splitlines() if t) | 2309 tests.extend(t for t in f.read().splitlines() if t) |
2309 self.options = options | 2310 self.options = options |
2310 | 2311 |
2311 self._checktools() | 2312 self._checktools() |
2312 testdescs = self.findtests(args) | 2313 testdescs = self.findtests(tests) |
2313 if options.profile_runner: | 2314 if options.profile_runner: |
2314 import statprof | 2315 import statprof |
2315 statprof.start() | 2316 statprof.start() |
2316 result = self._run(testdescs) | 2317 result = self._run(testdescs) |
2317 if options.profile_runner: | 2318 if options.profile_runner: |