mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
Issue #16799: Switched from getopt to argparse style in regrtest's argument
parsing. Added more tests for regrtest's argument parsing.
This commit is contained in:
parent
48e6a8c88a
commit
64f7c4e4ca
3 changed files with 498 additions and 358 deletions
|
@ -233,18 +233,20 @@ def _create_parser():
|
||||||
# We add help explicitly to control what argument group it renders under.
|
# We add help explicitly to control what argument group it renders under.
|
||||||
group.add_argument('-h', '--help', action='help',
|
group.add_argument('-h', '--help', action='help',
|
||||||
help='show this help message and exit')
|
help='show this help message and exit')
|
||||||
group.add_argument('--timeout', metavar='TIMEOUT',
|
group.add_argument('--timeout', metavar='TIMEOUT', type=float,
|
||||||
help='dump the traceback and exit if a test takes '
|
help='dump the traceback and exit if a test takes '
|
||||||
'more than TIMEOUT seconds; disabled if TIMEOUT '
|
'more than TIMEOUT seconds; disabled if TIMEOUT '
|
||||||
'is negative or equals to zero')
|
'is negative or equals to zero')
|
||||||
group.add_argument('--wait', action='store_true', help='wait for user '
|
group.add_argument('--wait', action='store_true',
|
||||||
'input, e.g., allow a debugger to be attached')
|
help='wait for user input, e.g., allow a debugger '
|
||||||
|
'to be attached')
|
||||||
group.add_argument('--slaveargs', metavar='ARGS')
|
group.add_argument('--slaveargs', metavar='ARGS')
|
||||||
group.add_argument('-S', '--start', metavar='START', help='the name of '
|
group.add_argument('-S', '--start', metavar='START',
|
||||||
'the test at which to start.' + more_details)
|
help='the name of the test at which to start.' +
|
||||||
|
more_details)
|
||||||
|
|
||||||
group = parser.add_argument_group('Verbosity')
|
group = parser.add_argument_group('Verbosity')
|
||||||
group.add_argument('-v', '--verbose', action='store_true',
|
group.add_argument('-v', '--verbose', action='count',
|
||||||
help='run tests in verbose mode with output to stdout')
|
help='run tests in verbose mode with output to stdout')
|
||||||
group.add_argument('-w', '--verbose2', action='store_true',
|
group.add_argument('-w', '--verbose2', action='store_true',
|
||||||
help='re-run failed tests in verbose mode')
|
help='re-run failed tests in verbose mode')
|
||||||
|
@ -254,7 +256,7 @@ def _create_parser():
|
||||||
help='print traceback for failed tests')
|
help='print traceback for failed tests')
|
||||||
group.add_argument('-q', '--quiet', action='store_true',
|
group.add_argument('-q', '--quiet', action='store_true',
|
||||||
help='no output unless one or more tests fail')
|
help='no output unless one or more tests fail')
|
||||||
group.add_argument('-o', '--slow', action='store_true',
|
group.add_argument('-o', '--slow', action='store_true', dest='print_slow',
|
||||||
help='print the slowest 10 tests')
|
help='print the slowest 10 tests')
|
||||||
group.add_argument('--header', action='store_true',
|
group.add_argument('--header', action='store_true',
|
||||||
help='print header with interpreter info')
|
help='print header with interpreter info')
|
||||||
|
@ -262,45 +264,60 @@ def _create_parser():
|
||||||
group = parser.add_argument_group('Selecting tests')
|
group = parser.add_argument_group('Selecting tests')
|
||||||
group.add_argument('-r', '--randomize', action='store_true',
|
group.add_argument('-r', '--randomize', action='store_true',
|
||||||
help='randomize test execution order.' + more_details)
|
help='randomize test execution order.' + more_details)
|
||||||
group.add_argument('--randseed', metavar='SEED', help='pass a random seed '
|
group.add_argument('--randseed', metavar='SEED',
|
||||||
'to reproduce a previous random run')
|
dest='random_seed', type=int,
|
||||||
group.add_argument('-f', '--fromfile', metavar='FILE', help='read names '
|
help='pass a random seed to reproduce a previous '
|
||||||
'of tests to run from a file.' + more_details)
|
'random run')
|
||||||
|
group.add_argument('-f', '--fromfile', metavar='FILE',
|
||||||
|
help='read names of tests to run from a file.' +
|
||||||
|
more_details)
|
||||||
group.add_argument('-x', '--exclude', action='store_true',
|
group.add_argument('-x', '--exclude', action='store_true',
|
||||||
help='arguments are tests to *exclude*')
|
help='arguments are tests to *exclude*')
|
||||||
group.add_argument('-s', '--single', action='store_true', help='single '
|
group.add_argument('-s', '--single', action='store_true',
|
||||||
'step through a set of tests.' + more_details)
|
help='single step through a set of tests.' +
|
||||||
group.add_argument('-m', '--match', metavar='PAT', help='match test cases '
|
more_details)
|
||||||
'and methods with glob pattern PAT')
|
group.add_argument('-m', '--match', metavar='PAT',
|
||||||
group.add_argument('-G', '--failfast', action='store_true', help='fail as '
|
dest='match_tests',
|
||||||
'soon as a test fails (only with -v or -W)')
|
help='match test cases and methods with glob pattern PAT')
|
||||||
group.add_argument('-u', '--use', metavar='RES1,RES2,...', help='specify '
|
group.add_argument('-G', '--failfast', action='store_true',
|
||||||
'which special resource intensive tests to run.' +
|
help='fail as soon as a test fails (only with -v or -W)')
|
||||||
|
group.add_argument('-u', '--use', metavar='RES1,RES2,...',
|
||||||
|
action='append', type=resources_list,
|
||||||
|
help='specify which special resource intensive tests '
|
||||||
|
'to run.' + more_details)
|
||||||
|
group.add_argument('-M', '--memlimit', metavar='LIMIT',
|
||||||
|
help='run very large memory-consuming tests.' +
|
||||||
more_details)
|
more_details)
|
||||||
group.add_argument('-M', '--memlimit', metavar='LIMIT', help='run very '
|
|
||||||
'large memory-consuming tests.' + more_details)
|
|
||||||
group.add_argument('--testdir', metavar='DIR',
|
group.add_argument('--testdir', metavar='DIR',
|
||||||
|
type=relative_filename,
|
||||||
help='execute test files in the specified directory '
|
help='execute test files in the specified directory '
|
||||||
'(instead of the Python stdlib test suite)')
|
'(instead of the Python stdlib test suite)')
|
||||||
|
|
||||||
group = parser.add_argument_group('Special runs')
|
group = parser.add_argument_group('Special runs')
|
||||||
group.add_argument('-l', '--findleaks', action='store_true', help='if GC '
|
group.add_argument('-l', '--findleaks', action='store_true',
|
||||||
'is available detect tests that leak memory')
|
help='if GC is available detect tests that leak memory')
|
||||||
group.add_argument('-L', '--runleaks', action='store_true',
|
group.add_argument('-L', '--runleaks', action='store_true',
|
||||||
help='run the leaks(1) command just before exit.' +
|
help='run the leaks(1) command just before exit.' +
|
||||||
more_details)
|
more_details)
|
||||||
group.add_argument('-R', '--huntrleaks', metavar='RUNCOUNTS',
|
group.add_argument('-R', '--huntrleaks', metavar='RUNCOUNTS',
|
||||||
|
type=huntrleaks,
|
||||||
help='search for reference leaks (needs debug build, '
|
help='search for reference leaks (needs debug build, '
|
||||||
'very slow).' + more_details)
|
'very slow).' + more_details)
|
||||||
group.add_argument('-j', '--multiprocess', metavar='PROCESSES',
|
group.add_argument('-j', '--multiprocess', metavar='PROCESSES',
|
||||||
|
dest='use_mp', type=int,
|
||||||
help='run PROCESSES processes at once')
|
help='run PROCESSES processes at once')
|
||||||
group.add_argument('-T', '--coverage', action='store_true', help='turn on '
|
group.add_argument('-T', '--coverage', action='store_true',
|
||||||
'code coverage tracing using the trace module')
|
dest='trace',
|
||||||
|
help='turn on code coverage tracing using the trace '
|
||||||
|
'module')
|
||||||
group.add_argument('-D', '--coverdir', metavar='DIR',
|
group.add_argument('-D', '--coverdir', metavar='DIR',
|
||||||
|
type=relative_filename,
|
||||||
help='directory where coverage files are put')
|
help='directory where coverage files are put')
|
||||||
group.add_argument('-N', '--nocoverdir', action='store_true',
|
group.add_argument('-N', '--nocoverdir',
|
||||||
|
action='store_const', const=None, dest='coverdir',
|
||||||
help='put coverage files alongside modules')
|
help='put coverage files alongside modules')
|
||||||
group.add_argument('-t', '--threshold', metavar='THRESHOLD',
|
group.add_argument('-t', '--threshold', metavar='THRESHOLD',
|
||||||
|
type=int,
|
||||||
help='call gc.set_threshold(THRESHOLD)')
|
help='call gc.set_threshold(THRESHOLD)')
|
||||||
group.add_argument('-n', '--nowindows', action='store_true',
|
group.add_argument('-n', '--nowindows', action='store_true',
|
||||||
help='suppress error message boxes on Windows')
|
help='suppress error message boxes on Windows')
|
||||||
|
@ -313,43 +330,103 @@ def _create_parser():
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
# TODO: remove this function as described in issue #16799, for example.
|
def relative_filename(string):
|
||||||
# We use this function since regrtest.main() was originally written to use
|
# CWD is replaced with a temporary dir before calling main(), so we
|
||||||
# getopt for parsing.
|
# join it with the saved CWD so it ends up where the user expects.
|
||||||
def _convert_namespace_to_getopt(ns):
|
return os.path.join(support.SAVEDCWD, string)
|
||||||
"""Convert an argparse.Namespace object to a getopt-style opts list.
|
|
||||||
|
|
||||||
The return value of this function mimics the first element of
|
def huntrleaks(string):
|
||||||
getopt.getopt()'s (opts, args) return value. In addition, the (option,
|
args = string.split(':')
|
||||||
value) pairs in the opts list are sorted by option and use the long
|
if len(args) not in (2, 3):
|
||||||
option string. The args part of (opts, args) can be mimicked by the
|
raise argparse.ArgumentTypeError(
|
||||||
args attribute of the Namespace object we are using in regrtest.
|
'needs 2 or 3 colon-separated arguments')
|
||||||
"""
|
nwarmup = int(args[0]) if args[0] else 5
|
||||||
opts = []
|
ntracked = int(args[1]) if args[1] else 4
|
||||||
args_dict = vars(ns)
|
fname = args[2] if len(args) > 2 and args[2] else 'reflog.txt'
|
||||||
for key in sorted(args_dict.keys()):
|
return nwarmup, ntracked, fname
|
||||||
if key == 'args':
|
|
||||||
|
def resources_list(string):
|
||||||
|
u = [x.lower() for x in string.split(',')]
|
||||||
|
for r in u:
|
||||||
|
if r == 'all' or r == 'none':
|
||||||
continue
|
continue
|
||||||
val = args_dict[key]
|
if r[0] == '-':
|
||||||
# Don't continue if val equals '' because this means an option
|
r = r[1:]
|
||||||
# accepting a value was provided the empty string. Such values should
|
if r not in RESOURCE_NAMES:
|
||||||
# show up in the returned opts list.
|
raise argparse.ArgumentTypeError('invalid resource: ' + r)
|
||||||
if val is None or val is False:
|
return u
|
||||||
continue
|
|
||||||
if val is True:
|
|
||||||
# Then an option with action store_true was passed. getopt
|
|
||||||
# includes these with value '' in the opts list.
|
|
||||||
val = ''
|
|
||||||
opts.append(('--' + key, val))
|
|
||||||
return opts
|
|
||||||
|
|
||||||
|
def _parse_args(args, **kwargs):
|
||||||
def main(tests=None, testdir=None, verbose=0, quiet=False,
|
# Defaults
|
||||||
|
ns = argparse.Namespace(testdir=None, verbose=0, quiet=False,
|
||||||
exclude=False, single=False, randomize=False, fromfile=None,
|
exclude=False, single=False, randomize=False, fromfile=None,
|
||||||
findleaks=False, use_resources=None, trace=False, coverdir='coverage',
|
findleaks=False, use_resources=None, trace=False, coverdir='coverage',
|
||||||
runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,
|
runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,
|
||||||
random_seed=None, use_mp=None, verbose3=False, forever=False,
|
random_seed=None, use_mp=None, verbose3=False, forever=False,
|
||||||
header=False, failfast=False, match_tests=None):
|
header=False, failfast=False, match_tests=None)
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
if not hasattr(ns, k):
|
||||||
|
raise TypeError('%r is an invalid keyword argument '
|
||||||
|
'for this function' % k)
|
||||||
|
setattr(ns, k, v)
|
||||||
|
if ns.use_resources is None:
|
||||||
|
ns.use_resources = []
|
||||||
|
|
||||||
|
parser = _create_parser()
|
||||||
|
parser.parse_args(args=args, namespace=ns)
|
||||||
|
|
||||||
|
if ns.single and ns.fromfile:
|
||||||
|
parser.error("-s and -f don't go together!")
|
||||||
|
if ns.use_mp and ns.trace:
|
||||||
|
parser.error("-T and -j don't go together!")
|
||||||
|
if ns.use_mp and ns.findleaks:
|
||||||
|
parser.error("-l and -j don't go together!")
|
||||||
|
if ns.use_mp and ns.memlimit:
|
||||||
|
parser.error("-M and -j don't go together!")
|
||||||
|
if ns.failfast and not (ns.verbose or ns.verbose3):
|
||||||
|
parser.error("-G/--failfast needs either -v or -W")
|
||||||
|
|
||||||
|
if ns.quiet:
|
||||||
|
ns.verbose = 0
|
||||||
|
if ns.timeout is not None:
|
||||||
|
if hasattr(faulthandler, 'dump_traceback_later'):
|
||||||
|
if ns.timeout <= 0:
|
||||||
|
ns.timeout = None
|
||||||
|
else:
|
||||||
|
print("Warning: The timeout option requires "
|
||||||
|
"faulthandler.dump_traceback_later")
|
||||||
|
ns.timeout = None
|
||||||
|
if ns.use_mp is not None:
|
||||||
|
if ns.use_mp <= 0:
|
||||||
|
# Use all cores + extras for tests that like to sleep
|
||||||
|
ns.use_mp = 2 + (os.cpu_count() or 1)
|
||||||
|
if ns.use_mp == 1:
|
||||||
|
ns.use_mp = None
|
||||||
|
if ns.use:
|
||||||
|
for a in ns.use:
|
||||||
|
for r in a:
|
||||||
|
if r == 'all':
|
||||||
|
ns.use_resources[:] = RESOURCE_NAMES
|
||||||
|
continue
|
||||||
|
if r == 'none':
|
||||||
|
del ns.use_resources[:]
|
||||||
|
continue
|
||||||
|
remove = False
|
||||||
|
if r[0] == '-':
|
||||||
|
remove = True
|
||||||
|
r = r[1:]
|
||||||
|
if remove:
|
||||||
|
if r in ns.use_resources:
|
||||||
|
ns.use_resources.remove(r)
|
||||||
|
elif r not in ns.use_resources:
|
||||||
|
ns.use_resources.append(r)
|
||||||
|
if ns.random_seed is not None:
|
||||||
|
ns.randomize = True
|
||||||
|
|
||||||
|
return ns
|
||||||
|
|
||||||
|
|
||||||
|
def main(tests=None, **kwargs):
|
||||||
"""Execute a test suite.
|
"""Execute a test suite.
|
||||||
|
|
||||||
This also parses command-line options and modifies its behavior
|
This also parses command-line options and modifies its behavior
|
||||||
|
@ -372,7 +449,6 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
directly to set the values that would normally be set by flags
|
directly to set the values that would normally be set by flags
|
||||||
on the command line.
|
on the command line.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Display the Python traceback on fatal errors (e.g. segfault)
|
# Display the Python traceback on fatal errors (e.g. segfault)
|
||||||
faulthandler.enable(all_threads=True)
|
faulthandler.enable(all_threads=True)
|
||||||
|
|
||||||
|
@ -389,107 +465,18 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
|
|
||||||
support.record_original_stdout(sys.stdout)
|
support.record_original_stdout(sys.stdout)
|
||||||
|
|
||||||
parser = _create_parser()
|
ns = _parse_args(sys.argv[1:], **kwargs)
|
||||||
ns = parser.parse_args()
|
|
||||||
opts = _convert_namespace_to_getopt(ns)
|
|
||||||
args = ns.args
|
|
||||||
usage = parser.error
|
|
||||||
|
|
||||||
# Defaults
|
if ns.huntrleaks:
|
||||||
if random_seed is None:
|
|
||||||
random_seed = random.randrange(10000000)
|
|
||||||
if use_resources is None:
|
|
||||||
use_resources = []
|
|
||||||
debug = False
|
|
||||||
start = None
|
|
||||||
timeout = None
|
|
||||||
for o, a in opts:
|
|
||||||
if o in ('-v', '--verbose'):
|
|
||||||
verbose += 1
|
|
||||||
elif o in ('-w', '--verbose2'):
|
|
||||||
verbose2 = True
|
|
||||||
elif o in ('-d', '--debug'):
|
|
||||||
debug = True
|
|
||||||
elif o in ('-W', '--verbose3'):
|
|
||||||
verbose3 = True
|
|
||||||
elif o in ('-G', '--failfast'):
|
|
||||||
failfast = True
|
|
||||||
elif o in ('-q', '--quiet'):
|
|
||||||
quiet = True;
|
|
||||||
verbose = 0
|
|
||||||
elif o in ('-x', '--exclude'):
|
|
||||||
exclude = True
|
|
||||||
elif o in ('-S', '--start'):
|
|
||||||
start = a
|
|
||||||
elif o in ('-s', '--single'):
|
|
||||||
single = True
|
|
||||||
elif o in ('-o', '--slow'):
|
|
||||||
print_slow = True
|
|
||||||
elif o in ('-r', '--randomize'):
|
|
||||||
randomize = True
|
|
||||||
elif o == '--randseed':
|
|
||||||
randomize = True
|
|
||||||
random_seed = int(a)
|
|
||||||
elif o in ('-f', '--fromfile'):
|
|
||||||
fromfile = a
|
|
||||||
elif o in ('-m', '--match'):
|
|
||||||
match_tests = a
|
|
||||||
elif o in ('-l', '--findleaks'):
|
|
||||||
findleaks = True
|
|
||||||
elif o in ('-L', '--runleaks'):
|
|
||||||
runleaks = True
|
|
||||||
elif o in ('-t', '--threshold'):
|
|
||||||
import gc
|
|
||||||
gc.set_threshold(int(a))
|
|
||||||
elif o in ('-T', '--coverage'):
|
|
||||||
trace = True
|
|
||||||
elif o in ('-D', '--coverdir'):
|
|
||||||
# CWD is replaced with a temporary dir before calling main(), so we
|
|
||||||
# need join it with the saved CWD so it goes where the user expects.
|
|
||||||
coverdir = os.path.join(support.SAVEDCWD, a)
|
|
||||||
elif o in ('-N', '--nocoverdir'):
|
|
||||||
coverdir = None
|
|
||||||
elif o in ('-R', '--huntrleaks'):
|
|
||||||
huntrleaks = a.split(':')
|
|
||||||
if len(huntrleaks) not in (2, 3):
|
|
||||||
print(a, huntrleaks)
|
|
||||||
usage('-R takes 2 or 3 colon-separated arguments')
|
|
||||||
if not huntrleaks[0]:
|
|
||||||
huntrleaks[0] = 5
|
|
||||||
else:
|
|
||||||
huntrleaks[0] = int(huntrleaks[0])
|
|
||||||
if not huntrleaks[1]:
|
|
||||||
huntrleaks[1] = 4
|
|
||||||
else:
|
|
||||||
huntrleaks[1] = int(huntrleaks[1])
|
|
||||||
if len(huntrleaks) == 2 or not huntrleaks[2]:
|
|
||||||
huntrleaks[2:] = ["reflog.txt"]
|
|
||||||
# Avoid false positives due to various caches
|
# Avoid false positives due to various caches
|
||||||
# filling slowly with random data:
|
# filling slowly with random data:
|
||||||
warm_caches()
|
warm_caches()
|
||||||
elif o in ('-M', '--memlimit'):
|
if ns.memlimit is not None:
|
||||||
support.set_memlimit(a)
|
support.set_memlimit(ns.memlimit)
|
||||||
elif o in ('-u', '--use'):
|
if ns.threshold is not None:
|
||||||
u = [x.lower() for x in a.split(',')]
|
import gc
|
||||||
for r in u:
|
gc.set_threshold(ns.threshold)
|
||||||
if r == 'all':
|
if ns.nowindows:
|
||||||
use_resources[:] = RESOURCE_NAMES
|
|
||||||
continue
|
|
||||||
if r == 'none':
|
|
||||||
del use_resources[:]
|
|
||||||
continue
|
|
||||||
remove = False
|
|
||||||
if r[0] == '-':
|
|
||||||
remove = True
|
|
||||||
r = r[1:]
|
|
||||||
if r not in RESOURCE_NAMES:
|
|
||||||
usage('Invalid -u/--use option: ' + a)
|
|
||||||
if remove:
|
|
||||||
if r in use_resources:
|
|
||||||
use_resources.remove(r)
|
|
||||||
elif r not in use_resources:
|
|
||||||
use_resources.append(r)
|
|
||||||
elif o in ('-n', '--nowindows'):
|
|
||||||
import msvcrt
|
import msvcrt
|
||||||
msvcrt.SetErrorMode(msvcrt.SEM_FAILCRITICALERRORS|
|
msvcrt.SetErrorMode(msvcrt.SEM_FAILCRITICALERRORS|
|
||||||
msvcrt.SEM_NOALIGNMENTFAULTEXCEPT|
|
msvcrt.SEM_NOALIGNMENTFAULTEXCEPT|
|
||||||
|
@ -504,19 +491,11 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
for m in [msvcrt.CRT_WARN, msvcrt.CRT_ERROR, msvcrt.CRT_ASSERT]:
|
for m in [msvcrt.CRT_WARN, msvcrt.CRT_ERROR, msvcrt.CRT_ASSERT]:
|
||||||
msvcrt.CrtSetReportMode(m, msvcrt.CRTDBG_MODE_FILE)
|
msvcrt.CrtSetReportMode(m, msvcrt.CRTDBG_MODE_FILE)
|
||||||
msvcrt.CrtSetReportFile(m, msvcrt.CRTDBG_FILE_STDERR)
|
msvcrt.CrtSetReportFile(m, msvcrt.CRTDBG_FILE_STDERR)
|
||||||
elif o in ('-F', '--forever'):
|
if ns.wait:
|
||||||
forever = True
|
input("Press any key to continue...")
|
||||||
elif o in ('-j', '--multiprocess'):
|
|
||||||
use_mp = int(a)
|
if ns.slaveargs is not None:
|
||||||
if use_mp <= 0:
|
args, kwargs = json.loads(ns.slaveargs)
|
||||||
# Use all cores + extras for tests that like to sleep
|
|
||||||
use_mp = 2 + (os.cpu_count() or 1)
|
|
||||||
if use_mp == 1:
|
|
||||||
use_mp = None
|
|
||||||
elif o == '--header':
|
|
||||||
header = True
|
|
||||||
elif o == '--slaveargs':
|
|
||||||
args, kwargs = json.loads(a)
|
|
||||||
try:
|
try:
|
||||||
result = runtest(*args, **kwargs)
|
result = runtest(*args, **kwargs)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
@ -528,35 +507,6 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
print() # Force a newline (just in case)
|
print() # Force a newline (just in case)
|
||||||
print(json.dumps(result))
|
print(json.dumps(result))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
elif o == '--testdir':
|
|
||||||
# CWD is replaced with a temporary dir before calling main(), so we
|
|
||||||
# join it with the saved CWD so it ends up where the user expects.
|
|
||||||
testdir = os.path.join(support.SAVEDCWD, a)
|
|
||||||
elif o == '--timeout':
|
|
||||||
if hasattr(faulthandler, 'dump_traceback_later'):
|
|
||||||
timeout = float(a)
|
|
||||||
if timeout <= 0:
|
|
||||||
timeout = None
|
|
||||||
else:
|
|
||||||
print("Warning: The timeout option requires "
|
|
||||||
"faulthandler.dump_traceback_later")
|
|
||||||
timeout = None
|
|
||||||
elif o == '--wait':
|
|
||||||
input("Press any key to continue...")
|
|
||||||
else:
|
|
||||||
print(("No handler for option {}. Please report this as a bug "
|
|
||||||
"at http://bugs.python.org.").format(o), file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
if single and fromfile:
|
|
||||||
usage("-s and -f don't go together!")
|
|
||||||
if use_mp and trace:
|
|
||||||
usage("-T and -j don't go together!")
|
|
||||||
if use_mp and findleaks:
|
|
||||||
usage("-l and -j don't go together!")
|
|
||||||
if use_mp and support.max_memuse:
|
|
||||||
usage("-M and -j don't go together!")
|
|
||||||
if failfast and not (verbose or verbose3):
|
|
||||||
usage("-G/--failfast needs either -v or -W")
|
|
||||||
|
|
||||||
good = []
|
good = []
|
||||||
bad = []
|
bad = []
|
||||||
|
@ -565,12 +515,12 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
environment_changed = []
|
environment_changed = []
|
||||||
interrupted = False
|
interrupted = False
|
||||||
|
|
||||||
if findleaks:
|
if ns.findleaks:
|
||||||
try:
|
try:
|
||||||
import gc
|
import gc
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print('No GC available, disabling findleaks.')
|
print('No GC available, disabling findleaks.')
|
||||||
findleaks = False
|
ns.findleaks = False
|
||||||
else:
|
else:
|
||||||
# Uncomment the line below to report garbage that is not
|
# Uncomment the line below to report garbage that is not
|
||||||
# freeable by reference counting alone. By default only
|
# freeable by reference counting alone. By default only
|
||||||
|
@ -578,42 +528,40 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
#gc.set_debug(gc.DEBUG_SAVEALL)
|
#gc.set_debug(gc.DEBUG_SAVEALL)
|
||||||
found_garbage = []
|
found_garbage = []
|
||||||
|
|
||||||
if single:
|
if ns.single:
|
||||||
filename = os.path.join(TEMPDIR, 'pynexttest')
|
filename = os.path.join(TEMPDIR, 'pynexttest')
|
||||||
try:
|
try:
|
||||||
fp = open(filename, 'r')
|
with open(filename, 'r') as fp:
|
||||||
next_test = fp.read().strip()
|
next_test = fp.read().strip()
|
||||||
tests = [next_test]
|
tests = [next_test]
|
||||||
fp.close()
|
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if fromfile:
|
if ns.fromfile:
|
||||||
tests = []
|
tests = []
|
||||||
fp = open(os.path.join(support.SAVEDCWD, fromfile))
|
with open(os.path.join(support.SAVEDCWD, ns.fromfile)) as fp:
|
||||||
count_pat = re.compile(r'\[\s*\d+/\s*\d+\]')
|
count_pat = re.compile(r'\[\s*\d+/\s*\d+\]')
|
||||||
for line in fp:
|
for line in fp:
|
||||||
line = count_pat.sub('', line)
|
line = count_pat.sub('', line)
|
||||||
guts = line.split() # assuming no test has whitespace in its name
|
guts = line.split() # assuming no test has whitespace in its name
|
||||||
if guts and not guts[0].startswith('#'):
|
if guts and not guts[0].startswith('#'):
|
||||||
tests.extend(guts)
|
tests.extend(guts)
|
||||||
fp.close()
|
|
||||||
|
|
||||||
# Strip .py extensions.
|
# Strip .py extensions.
|
||||||
removepy(args)
|
removepy(ns.args)
|
||||||
removepy(tests)
|
removepy(tests)
|
||||||
|
|
||||||
stdtests = STDTESTS[:]
|
stdtests = STDTESTS[:]
|
||||||
nottests = NOTTESTS.copy()
|
nottests = NOTTESTS.copy()
|
||||||
if exclude:
|
if ns.exclude:
|
||||||
for arg in args:
|
for arg in ns.args:
|
||||||
if arg in stdtests:
|
if arg in stdtests:
|
||||||
stdtests.remove(arg)
|
stdtests.remove(arg)
|
||||||
nottests.add(arg)
|
nottests.add(arg)
|
||||||
args = []
|
ns.args = []
|
||||||
|
|
||||||
# For a partial run, we do not need to clutter the output.
|
# For a partial run, we do not need to clutter the output.
|
||||||
if verbose or header or not (quiet or single or tests or args):
|
if ns.verbose or ns.header or not (ns.quiet or ns.single or tests or ns.args):
|
||||||
# Print basic platform information
|
# Print basic platform information
|
||||||
print("==", platform.python_implementation(), *sys.version.split())
|
print("==", platform.python_implementation(), *sys.version.split())
|
||||||
print("== ", platform.platform(aliased=True),
|
print("== ", platform.platform(aliased=True),
|
||||||
|
@ -623,37 +571,39 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
|
|
||||||
# if testdir is set, then we are not running the python tests suite, so
|
# if testdir is set, then we are not running the python tests suite, so
|
||||||
# don't add default tests to be executed or skipped (pass empty values)
|
# don't add default tests to be executed or skipped (pass empty values)
|
||||||
if testdir:
|
if ns.testdir:
|
||||||
alltests = findtests(testdir, list(), set())
|
alltests = findtests(ns.testdir, list(), set())
|
||||||
else:
|
else:
|
||||||
alltests = findtests(testdir, stdtests, nottests)
|
alltests = findtests(ns.testdir, stdtests, nottests)
|
||||||
|
|
||||||
selected = tests or args or alltests
|
selected = tests or ns.args or alltests
|
||||||
if single:
|
if ns.single:
|
||||||
selected = selected[:1]
|
selected = selected[:1]
|
||||||
try:
|
try:
|
||||||
next_single_test = alltests[alltests.index(selected[0])+1]
|
next_single_test = alltests[alltests.index(selected[0])+1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
next_single_test = None
|
next_single_test = None
|
||||||
# Remove all the selected tests that precede start if it's set.
|
# Remove all the selected tests that precede start if it's set.
|
||||||
if start:
|
if ns.start:
|
||||||
try:
|
try:
|
||||||
del selected[:selected.index(start)]
|
del selected[:selected.index(ns.start)]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Couldn't find starting test (%s), using all tests" % start)
|
print("Couldn't find starting test (%s), using all tests" % ns.start)
|
||||||
if randomize:
|
if ns.randomize:
|
||||||
random.seed(random_seed)
|
if ns.random_seed is None:
|
||||||
print("Using random seed", random_seed)
|
ns.random_seed = random.randrange(10000000)
|
||||||
|
random.seed(ns.random_seed)
|
||||||
|
print("Using random seed", ns.random_seed)
|
||||||
random.shuffle(selected)
|
random.shuffle(selected)
|
||||||
if trace:
|
if ns.trace:
|
||||||
import trace, tempfile
|
import trace, tempfile
|
||||||
tracer = trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,
|
tracer = trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,
|
||||||
tempfile.gettempdir()],
|
tempfile.gettempdir()],
|
||||||
trace=False, count=True)
|
trace=False, count=True)
|
||||||
|
|
||||||
test_times = []
|
test_times = []
|
||||||
support.verbose = verbose # Tell tests to be moderately quiet
|
support.verbose = ns.verbose # Tell tests to be moderately quiet
|
||||||
support.use_resources = use_resources
|
support.use_resources = ns.use_resources
|
||||||
save_modules = sys.modules.keys()
|
save_modules = sys.modules.keys()
|
||||||
|
|
||||||
def accumulate_result(test, result):
|
def accumulate_result(test, result):
|
||||||
|
@ -671,7 +621,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
skipped.append(test)
|
skipped.append(test)
|
||||||
resource_denieds.append(test)
|
resource_denieds.append(test)
|
||||||
|
|
||||||
if forever:
|
if ns.forever:
|
||||||
def test_forever(tests=list(selected)):
|
def test_forever(tests=list(selected)):
|
||||||
while True:
|
while True:
|
||||||
for test in tests:
|
for test in tests:
|
||||||
|
@ -686,7 +636,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
test_count = '/{}'.format(len(selected))
|
test_count = '/{}'.format(len(selected))
|
||||||
test_count_width = len(test_count) - 1
|
test_count_width = len(test_count) - 1
|
||||||
|
|
||||||
if use_mp:
|
if ns.use_mp:
|
||||||
try:
|
try:
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -710,11 +660,12 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
output.put((None, None, None, None))
|
output.put((None, None, None, None))
|
||||||
return
|
return
|
||||||
args_tuple = (
|
args_tuple = (
|
||||||
(test, verbose, quiet),
|
(test, ns.verbose, ns.quiet),
|
||||||
dict(huntrleaks=huntrleaks, use_resources=use_resources,
|
dict(huntrleaks=ns.huntrleaks,
|
||||||
debug=debug, output_on_failure=verbose3,
|
use_resources=ns.use_resources,
|
||||||
timeout=timeout, failfast=failfast,
|
debug=ns.debug, output_on_failure=ns.verbose3,
|
||||||
match_tests=match_tests)
|
timeout=ns.timeout, failfast=ns.failfast,
|
||||||
|
match_tests=ns.match_tests)
|
||||||
)
|
)
|
||||||
# -E is needed by some tests, e.g. test_import
|
# -E is needed by some tests, e.g. test_import
|
||||||
# Running the child from the same working directory ensures
|
# Running the child from the same working directory ensures
|
||||||
|
@ -743,19 +694,19 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
except BaseException:
|
except BaseException:
|
||||||
output.put((None, None, None, None))
|
output.put((None, None, None, None))
|
||||||
raise
|
raise
|
||||||
workers = [Thread(target=work) for i in range(use_mp)]
|
workers = [Thread(target=work) for i in range(ns.use_mp)]
|
||||||
for worker in workers:
|
for worker in workers:
|
||||||
worker.start()
|
worker.start()
|
||||||
finished = 0
|
finished = 0
|
||||||
test_index = 1
|
test_index = 1
|
||||||
try:
|
try:
|
||||||
while finished < use_mp:
|
while finished < ns.use_mp:
|
||||||
test, stdout, stderr, result = output.get()
|
test, stdout, stderr, result = output.get()
|
||||||
if test is None:
|
if test is None:
|
||||||
finished += 1
|
finished += 1
|
||||||
continue
|
continue
|
||||||
accumulate_result(test, result)
|
accumulate_result(test, result)
|
||||||
if not quiet:
|
if not ns.quiet:
|
||||||
fmt = "[{1:{0}}{2}/{3}] {4}" if bad else "[{1:{0}}{2}] {4}"
|
fmt = "[{1:{0}}{2}/{3}] {4}" if bad else "[{1:{0}}{2}] {4}"
|
||||||
print(fmt.format(
|
print(fmt.format(
|
||||||
test_count_width, test_index, test_count,
|
test_count_width, test_index, test_count,
|
||||||
|
@ -778,29 +729,30 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
worker.join()
|
worker.join()
|
||||||
else:
|
else:
|
||||||
for test_index, test in enumerate(tests, 1):
|
for test_index, test in enumerate(tests, 1):
|
||||||
if not quiet:
|
if not ns.quiet:
|
||||||
fmt = "[{1:{0}}{2}/{3}] {4}" if bad else "[{1:{0}}{2}] {4}"
|
fmt = "[{1:{0}}{2}/{3}] {4}" if bad else "[{1:{0}}{2}] {4}"
|
||||||
print(fmt.format(
|
print(fmt.format(
|
||||||
test_count_width, test_index, test_count, len(bad), test))
|
test_count_width, test_index, test_count, len(bad), test))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
if trace:
|
if ns.trace:
|
||||||
# If we're tracing code coverage, then we don't exit with status
|
# If we're tracing code coverage, then we don't exit with status
|
||||||
# if on a false return value from main.
|
# if on a false return value from main.
|
||||||
tracer.runctx('runtest(test, verbose, quiet, timeout=timeout)',
|
tracer.runctx('runtest(test, ns.verbose, ns.quiet, timeout=ns.timeout)',
|
||||||
globals=globals(), locals=vars())
|
globals=globals(), locals=vars())
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
result = runtest(test, verbose, quiet, huntrleaks, debug,
|
result = runtest(test, ns.verbose, ns.quiet,
|
||||||
output_on_failure=verbose3,
|
ns.huntrleaks, ns.debug,
|
||||||
timeout=timeout, failfast=failfast,
|
output_on_failure=ns.verbose3,
|
||||||
match_tests=match_tests)
|
timeout=ns.timeout, failfast=ns.failfast,
|
||||||
|
match_tests=ns.match_tests)
|
||||||
accumulate_result(test, result)
|
accumulate_result(test, result)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
interrupted = True
|
interrupted = True
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
raise
|
raise
|
||||||
if findleaks:
|
if ns.findleaks:
|
||||||
gc.collect()
|
gc.collect()
|
||||||
if gc.garbage:
|
if gc.garbage:
|
||||||
print("Warning: test created", len(gc.garbage), end=' ')
|
print("Warning: test created", len(gc.garbage), end=' ')
|
||||||
|
@ -821,11 +773,11 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
omitted = set(selected) - set(good) - set(bad) - set(skipped)
|
omitted = set(selected) - set(good) - set(bad) - set(skipped)
|
||||||
print(count(len(omitted), "test"), "omitted:")
|
print(count(len(omitted), "test"), "omitted:")
|
||||||
printlist(omitted)
|
printlist(omitted)
|
||||||
if good and not quiet:
|
if good and not ns.quiet:
|
||||||
if not bad and not skipped and not interrupted and len(good) > 1:
|
if not bad and not skipped and not interrupted and len(good) > 1:
|
||||||
print("All", end=' ')
|
print("All", end=' ')
|
||||||
print(count(len(good), "test"), "OK.")
|
print(count(len(good), "test"), "OK.")
|
||||||
if print_slow:
|
if ns.print_slow:
|
||||||
test_times.sort(reverse=True)
|
test_times.sort(reverse=True)
|
||||||
print("10 slowest tests:")
|
print("10 slowest tests:")
|
||||||
for time, test in test_times[:10]:
|
for time, test in test_times[:10]:
|
||||||
|
@ -839,18 +791,19 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
print("{} altered the execution environment:".format(
|
print("{} altered the execution environment:".format(
|
||||||
count(len(environment_changed), "test")))
|
count(len(environment_changed), "test")))
|
||||||
printlist(environment_changed)
|
printlist(environment_changed)
|
||||||
if skipped and not quiet:
|
if skipped and not ns.quiet:
|
||||||
print(count(len(skipped), "test"), "skipped:")
|
print(count(len(skipped), "test"), "skipped:")
|
||||||
printlist(skipped)
|
printlist(skipped)
|
||||||
|
|
||||||
if verbose2 and bad:
|
if ns.verbose2 and bad:
|
||||||
print("Re-running failed tests in verbose mode")
|
print("Re-running failed tests in verbose mode")
|
||||||
for test in bad:
|
for test in bad:
|
||||||
print("Re-running test %r in verbose mode" % test)
|
print("Re-running test %r in verbose mode" % test)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
try:
|
try:
|
||||||
verbose = True
|
ns.verbose = True
|
||||||
ok = runtest(test, True, quiet, huntrleaks, debug, timeout=timeout)
|
ok = runtest(test, True, ns.quiet, ns.huntrleaks, ns.debug,
|
||||||
|
timeout=ns.timeout)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
# print a newline separate from the ^C
|
# print a newline separate from the ^C
|
||||||
print()
|
print()
|
||||||
|
@ -858,18 +811,18 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
except:
|
except:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
if single:
|
if ns.single:
|
||||||
if next_single_test:
|
if next_single_test:
|
||||||
with open(filename, 'w') as fp:
|
with open(filename, 'w') as fp:
|
||||||
fp.write(next_single_test + '\n')
|
fp.write(next_single_test + '\n')
|
||||||
else:
|
else:
|
||||||
os.unlink(filename)
|
os.unlink(filename)
|
||||||
|
|
||||||
if trace:
|
if ns.trace:
|
||||||
r = tracer.results()
|
r = tracer.results()
|
||||||
r.write_results(show_missing=True, summary=True, coverdir=coverdir)
|
r.write_results(show_missing=True, summary=True, coverdir=ns.coverdir)
|
||||||
|
|
||||||
if runleaks:
|
if ns.runleaks:
|
||||||
os.system("leaks %d" % os.getpid())
|
os.system("leaks %d" % os.getpid())
|
||||||
|
|
||||||
sys.exit(len(bad) > 0 or interrupted)
|
sys.exit(len(bad) > 0 or interrupted)
|
||||||
|
|
|
@ -4,97 +4,281 @@ Tests of regrtest.py.
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import getopt
|
import getopt
|
||||||
|
import os.path
|
||||||
import unittest
|
import unittest
|
||||||
from test import regrtest, support
|
from test import regrtest, support
|
||||||
|
|
||||||
def old_parse_args(args):
|
|
||||||
"""Parse arguments as regrtest did strictly prior to 3.4.
|
|
||||||
|
|
||||||
Raises getopt.GetoptError on bad arguments.
|
|
||||||
"""
|
|
||||||
return getopt.getopt(args, 'hvqxsoS:rf:lu:t:TD:NLR:FdwWM:nj:Gm:',
|
|
||||||
['help', 'verbose', 'verbose2', 'verbose3', 'quiet',
|
|
||||||
'exclude', 'single', 'slow', 'randomize', 'fromfile=', 'findleaks',
|
|
||||||
'use=', 'threshold=', 'coverdir=', 'nocoverdir',
|
|
||||||
'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=',
|
|
||||||
'multiprocess=', 'coverage', 'slaveargs=', 'forever', 'debug',
|
|
||||||
'start=', 'nowindows', 'header', 'testdir=', 'timeout=', 'wait',
|
|
||||||
'failfast', 'match='])
|
|
||||||
|
|
||||||
class ParseArgsTestCase(unittest.TestCase):
|
class ParseArgsTestCase(unittest.TestCase):
|
||||||
|
|
||||||
"""Test that regrtest's parsing code matches the prior getopt behavior."""
|
"""Test regrtest's argument parsing."""
|
||||||
|
|
||||||
def _parse_args(self, args):
|
def checkError(self, args, msg):
|
||||||
# This is the same logic as that used in regrtest.main()
|
with support.captured_stderr() as err, self.assertRaises(SystemExit):
|
||||||
parser = regrtest._create_parser()
|
regrtest._parse_args(args)
|
||||||
ns = parser.parse_args(args=args)
|
self.assertIn(msg, err.getvalue())
|
||||||
opts = regrtest._convert_namespace_to_getopt(ns)
|
|
||||||
return opts, ns.args
|
|
||||||
|
|
||||||
def _check_args(self, args, expected=None):
|
def test_help(self):
|
||||||
"""
|
for opt in '-h', '--help':
|
||||||
The expected parameter is for cases when the behavior of the new
|
with self.subTest(opt=opt):
|
||||||
parse_args differs from the old (but deliberately so).
|
with support.captured_stdout() as out, \
|
||||||
"""
|
self.assertRaises(SystemExit):
|
||||||
if expected is None:
|
regrtest._parse_args([opt])
|
||||||
try:
|
self.assertIn('Run Python regression tests.', out.getvalue())
|
||||||
expected = old_parse_args(args)
|
|
||||||
except getopt.GetoptError:
|
|
||||||
# Suppress usage string output when an argparse.ArgumentError
|
|
||||||
# error is raised.
|
|
||||||
with support.captured_stderr():
|
|
||||||
self.assertRaises(SystemExit, self._parse_args, args)
|
|
||||||
return
|
|
||||||
# The new parse_args() sorts by long option string.
|
|
||||||
expected[0].sort()
|
|
||||||
actual = self._parse_args(args)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
def test_unrecognized_argument(self):
|
def test_timeout(self):
|
||||||
self._check_args(['--xxx'])
|
ns = regrtest._parse_args(['--timeout', '4.2'])
|
||||||
|
self.assertEqual(ns.timeout, 4.2)
|
||||||
|
self.checkError(['--timeout'], 'expected one argument')
|
||||||
|
self.checkError(['--timeout', 'foo'], 'invalid float value')
|
||||||
|
|
||||||
def test_value_not_provided(self):
|
def test_wait(self):
|
||||||
self._check_args(['--start'])
|
ns = regrtest._parse_args(['--wait'])
|
||||||
|
self.assertTrue(ns.wait)
|
||||||
|
|
||||||
def test_short_option(self):
|
def test_slaveargs(self):
|
||||||
# getopt returns the short option whereas argparse returns the long.
|
ns = regrtest._parse_args(['--slaveargs', '[[], {}]'])
|
||||||
expected = ([('--quiet', '')], [])
|
self.assertEqual(ns.slaveargs, '[[], {}]')
|
||||||
self._check_args(['-q'], expected=expected)
|
self.checkError(['--slaveargs'], 'expected one argument')
|
||||||
|
|
||||||
def test_long_option(self):
|
def test_start(self):
|
||||||
self._check_args(['--quiet'])
|
for opt in '-S', '--start':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, 'foo'])
|
||||||
|
self.assertEqual(ns.start, 'foo')
|
||||||
|
self.checkError([opt], 'expected one argument')
|
||||||
|
|
||||||
def test_long_option__partial(self):
|
def test_verbose(self):
|
||||||
self._check_args(['--qui'])
|
ns = regrtest._parse_args(['-v'])
|
||||||
|
self.assertEqual(ns.verbose, 1)
|
||||||
|
ns = regrtest._parse_args(['-vvv'])
|
||||||
|
self.assertEqual(ns.verbose, 3)
|
||||||
|
ns = regrtest._parse_args(['--verbose'])
|
||||||
|
self.assertEqual(ns.verbose, 1)
|
||||||
|
ns = regrtest._parse_args(['--verbose'] * 3)
|
||||||
|
self.assertEqual(ns.verbose, 3)
|
||||||
|
ns = regrtest._parse_args([])
|
||||||
|
self.assertEqual(ns.verbose, 0)
|
||||||
|
|
||||||
def test_two_options(self):
|
def test_verbose2(self):
|
||||||
self._check_args(['--quiet', '--exclude'])
|
for opt in '-w', '--verbose2':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.verbose2)
|
||||||
|
|
||||||
def test_option_with_value(self):
|
def test_verbose3(self):
|
||||||
self._check_args(['--start', 'foo'])
|
for opt in '-W', '--verbose3':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.verbose3)
|
||||||
|
|
||||||
def test_option_with_empty_string_value(self):
|
def test_debug(self):
|
||||||
self._check_args(['--start', ''])
|
for opt in '-d', '--debug':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.debug)
|
||||||
|
|
||||||
def test_arg(self):
|
def test_quiet(self):
|
||||||
self._check_args(['foo'])
|
for opt in '-q', '--quiet':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.quiet)
|
||||||
|
self.assertEqual(ns.verbose, 0)
|
||||||
|
|
||||||
def test_option_and_arg(self):
|
def test_slow(self):
|
||||||
self._check_args(['--quiet', 'foo'])
|
for opt in '-o', '--slow':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.print_slow)
|
||||||
|
|
||||||
def test_fromfile(self):
|
def test_header(self):
|
||||||
self._check_args(['--fromfile', 'file'])
|
ns = regrtest._parse_args(['--header'])
|
||||||
|
self.assertTrue(ns.header)
|
||||||
def test_match(self):
|
|
||||||
self._check_args(['--match', 'pattern'])
|
|
||||||
|
|
||||||
def test_randomize(self):
|
def test_randomize(self):
|
||||||
self._check_args(['--randomize'])
|
for opt in '-r', '--randomize':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.randomize)
|
||||||
|
|
||||||
|
def test_randseed(self):
|
||||||
|
ns = regrtest._parse_args(['--randseed', '12345'])
|
||||||
|
self.assertEqual(ns.random_seed, 12345)
|
||||||
|
self.assertTrue(ns.randomize)
|
||||||
|
self.checkError(['--randseed'], 'expected one argument')
|
||||||
|
self.checkError(['--randseed', 'foo'], 'invalid int value')
|
||||||
|
|
||||||
|
def test_fromfile(self):
|
||||||
|
for opt in '-f', '--fromfile':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, 'foo'])
|
||||||
|
self.assertEqual(ns.fromfile, 'foo')
|
||||||
|
self.checkError([opt], 'expected one argument')
|
||||||
|
self.checkError([opt, 'foo', '-s'], "don't go together")
|
||||||
|
|
||||||
|
def test_exclude(self):
|
||||||
|
for opt in '-x', '--exclude':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.exclude)
|
||||||
|
|
||||||
|
def test_single(self):
|
||||||
|
for opt in '-s', '--single':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.single)
|
||||||
|
self.checkError([opt, '-f', 'foo'], "don't go together")
|
||||||
|
|
||||||
|
def test_match(self):
|
||||||
|
for opt in '-m', '--match':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, 'pattern'])
|
||||||
|
self.assertEqual(ns.match_tests, 'pattern')
|
||||||
|
self.checkError([opt], 'expected one argument')
|
||||||
|
|
||||||
|
def test_failfast(self):
|
||||||
|
for opt in '-G', '--failfast':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, '-v'])
|
||||||
|
self.assertTrue(ns.failfast)
|
||||||
|
ns = regrtest._parse_args([opt, '-W'])
|
||||||
|
self.assertTrue(ns.failfast)
|
||||||
|
self.checkError([opt], '-G/--failfast needs either -v or -W')
|
||||||
|
|
||||||
|
def test_use(self):
|
||||||
|
for opt in '-u', '--use':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, 'gui,network'])
|
||||||
|
self.assertEqual(ns.use_resources, ['gui', 'network'])
|
||||||
|
ns = regrtest._parse_args([opt, 'gui,none,network'])
|
||||||
|
self.assertEqual(ns.use_resources, ['network'])
|
||||||
|
expected = list(regrtest.RESOURCE_NAMES)
|
||||||
|
expected.remove('gui')
|
||||||
|
ns = regrtest._parse_args([opt, 'all,-gui'])
|
||||||
|
self.assertEqual(ns.use_resources, expected)
|
||||||
|
self.checkError([opt], 'expected one argument')
|
||||||
|
self.checkError([opt, 'foo'], 'invalid resource')
|
||||||
|
|
||||||
|
def test_memlimit(self):
|
||||||
|
for opt in '-M', '--memlimit':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, '4G'])
|
||||||
|
self.assertEqual(ns.memlimit, '4G')
|
||||||
|
self.checkError([opt], 'expected one argument')
|
||||||
|
|
||||||
|
def test_testdir(self):
|
||||||
|
ns = regrtest._parse_args(['--testdir', 'foo'])
|
||||||
|
self.assertEqual(ns.testdir, os.path.join(support.SAVEDCWD, 'foo'))
|
||||||
|
self.checkError(['--testdir'], 'expected one argument')
|
||||||
|
|
||||||
|
def test_findleaks(self):
|
||||||
|
for opt in '-l', '--findleaks':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.findleaks)
|
||||||
|
|
||||||
|
def test_findleaks(self):
|
||||||
|
for opt in '-L', '--runleaks':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.runleaks)
|
||||||
|
|
||||||
|
def test_findleaks(self):
|
||||||
|
for opt in '-R', '--huntrleaks':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, ':'])
|
||||||
|
self.assertEqual(ns.huntrleaks, (5, 4, 'reflog.txt'))
|
||||||
|
ns = regrtest._parse_args([opt, '6:'])
|
||||||
|
self.assertEqual(ns.huntrleaks, (6, 4, 'reflog.txt'))
|
||||||
|
ns = regrtest._parse_args([opt, ':3'])
|
||||||
|
self.assertEqual(ns.huntrleaks, (5, 3, 'reflog.txt'))
|
||||||
|
ns = regrtest._parse_args([opt, '6:3:leaks.log'])
|
||||||
|
self.assertEqual(ns.huntrleaks, (6, 3, 'leaks.log'))
|
||||||
|
self.checkError([opt], 'expected one argument')
|
||||||
|
self.checkError([opt, '6'],
|
||||||
|
'needs 2 or 3 colon-separated arguments')
|
||||||
|
self.checkError([opt, 'foo:'], 'invalid huntrleaks value')
|
||||||
|
self.checkError([opt, '6:foo'], 'invalid huntrleaks value')
|
||||||
|
|
||||||
|
def test_multiprocess(self):
|
||||||
|
for opt in '-j', '--multiprocess':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, '2'])
|
||||||
|
self.assertEqual(ns.use_mp, 2)
|
||||||
|
self.checkError([opt], 'expected one argument')
|
||||||
|
self.checkError([opt, 'foo'], 'invalid int value')
|
||||||
|
self.checkError([opt, '2', '-T'], "don't go together")
|
||||||
|
self.checkError([opt, '2', '-l'], "don't go together")
|
||||||
|
self.checkError([opt, '2', '-M', '4G'], "don't go together")
|
||||||
|
|
||||||
|
def test_findleaks(self):
|
||||||
|
for opt in '-T', '--coverage':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.trace)
|
||||||
|
|
||||||
|
def test_coverdir(self):
|
||||||
|
for opt in '-D', '--coverdir':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, 'foo'])
|
||||||
|
self.assertEqual(ns.coverdir,
|
||||||
|
os.path.join(support.SAVEDCWD, 'foo'))
|
||||||
|
self.checkError([opt], 'expected one argument')
|
||||||
|
|
||||||
|
def test_nocoverdir(self):
|
||||||
|
for opt in '-N', '--nocoverdir':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertIsNone(ns.coverdir)
|
||||||
|
|
||||||
|
def test_threshold(self):
|
||||||
|
for opt in '-t', '--threshold':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt, '1000'])
|
||||||
|
self.assertEqual(ns.threshold, 1000)
|
||||||
|
self.checkError([opt], 'expected one argument')
|
||||||
|
self.checkError([opt, 'foo'], 'invalid int value')
|
||||||
|
|
||||||
|
def test_nowindows(self):
|
||||||
|
for opt in '-n', '--nowindows':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.nowindows)
|
||||||
|
|
||||||
|
def test_forever(self):
|
||||||
|
for opt in '-F', '--forever':
|
||||||
|
with self.subTest(opt=opt):
|
||||||
|
ns = regrtest._parse_args([opt])
|
||||||
|
self.assertTrue(ns.forever)
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_unrecognized_argument(self):
|
||||||
support.run_unittest(__name__)
|
self.checkError(['--xxx'], 'usage:')
|
||||||
|
|
||||||
|
def test_long_option__partial(self):
|
||||||
|
ns = regrtest._parse_args(['--qui'])
|
||||||
|
self.assertTrue(ns.quiet)
|
||||||
|
self.assertEqual(ns.verbose, 0)
|
||||||
|
|
||||||
|
def test_two_options(self):
|
||||||
|
ns = regrtest._parse_args(['--quiet', '--exclude'])
|
||||||
|
self.assertTrue(ns.quiet)
|
||||||
|
self.assertEqual(ns.verbose, 0)
|
||||||
|
self.assertTrue(ns.exclude)
|
||||||
|
|
||||||
|
def test_option_with_empty_string_value(self):
|
||||||
|
ns = regrtest._parse_args(['--start', ''])
|
||||||
|
self.assertEqual(ns.start, '')
|
||||||
|
|
||||||
|
def test_arg(self):
|
||||||
|
ns = regrtest._parse_args(['foo'])
|
||||||
|
self.assertEqual(ns.args, ['foo'])
|
||||||
|
|
||||||
|
def test_option_and_arg(self):
|
||||||
|
ns = regrtest._parse_args(['--quiet', 'foo'])
|
||||||
|
self.assertTrue(ns.quiet)
|
||||||
|
self.assertEqual(ns.verbose, 0)
|
||||||
|
self.assertEqual(ns.args, ['foo'])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test_main()
|
unittest.main()
|
||||||
|
|
|
@ -153,6 +153,9 @@ Library
|
||||||
Tests
|
Tests
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- Issue #16799: Switched from getopt to argparse style in regrtest's argument
|
||||||
|
parsing. Added more tests for regrtest's argument parsing.
|
||||||
|
|
||||||
- Issue #18792: Use "127.0.0.1" or "::1" instead of "localhost" as much as
|
- Issue #18792: Use "127.0.0.1" or "::1" instead of "localhost" as much as
|
||||||
possible, since "localhost" goes through a DNS lookup under recent Windows
|
possible, since "localhost" goes through a DNS lookup under recent Windows
|
||||||
versions.
|
versions.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue