Changeset 391 for python/trunk/Lib/test/regrtest.py
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/test/regrtest.py
r10 r391 1 1 #! /usr/bin/env python 2 2 3 """Regression test. 4 5 This will find all modules whose name is "test_*" in the test 6 directory, and run them. Various command line options provide 7 additional facilities. 8 9 Command line options: 10 11 -v: verbose -- run tests in verbose mode with output to stdout 12 -w: verbose2 -- re-run failed tests in verbose mode 13 -q: quiet -- don't print anything except if a test fails 14 -x: exclude -- arguments are tests to *exclude* 15 -s: single -- run only a single test (see below) 16 -S: slow -- print the slowest 10 tests 17 -r: random -- randomize test execution order 18 -f: fromfile -- read names of tests to run from a file (see below) 19 -l: findleaks -- if GC is available detect tests that leak memory 20 -u: use -- specify which special resource intensive tests to run 21 -h: help -- print this text and exit 22 -t: threshold -- call gc.set_threshold(N) 23 -T: coverage -- turn on code coverage using the trace module 24 -D: coverdir -- Directory where coverage files are put 25 -N: nocoverdir -- Put coverage files alongside modules 26 -L: runleaks -- run the leaks(1) command just before exit 27 -R: huntrleaks -- search for reference leaks (needs debug build, v. slow) 28 -M: memlimit -- run very large memory-consuming tests 29 30 If non-option arguments are present, they are names for tests to run, 31 unless -x is given, in which case they are names for tests not to run. 32 If no test names are given, all tests are run. 33 34 -T turns on code coverage tracing with the trace module. 35 36 -D specifies the directory where coverage files are put. 37 38 -N Put coverage files alongside modules. 39 40 -s means to run only a single test and exit. This is useful when 41 doing memory analysis on the Python interpreter (which tend to consume 42 too many resources to run the full regression test non-stop). The 43 file /tmp/pynexttest is read to find the next test to run. If this 44 file is missing, the first test_*.py file in testdir or on the command 45 line is used. (actually tempfile.gettempdir() is used instead of 46 /tmp). 3 """ 4 Usage: 5 6 python -m test.regrtest [options] [test_name1 [test_name2 ...]] 7 python path/to/Lib/test/regrtest.py [options] [test_name1 [test_name2 ...]] 8 9 10 If no arguments or options are provided, finds all files matching 11 the pattern "test_*" in the Lib/test subdirectory and runs 12 them in alphabetical order (but see -M and -u, below, for exceptions). 13 14 For more rigorous testing, it is useful to use the following 15 command line: 16 17 python -E -tt -Wd -3 -m test.regrtest [options] [test_name1 ...] 18 19 20 Options: 21 22 -h/--help -- print this text and exit 23 24 Verbosity 25 26 -v/--verbose -- run tests in verbose mode with output to stdout 27 -w/--verbose2 -- re-run failed tests in verbose mode 28 -W/--verbose3 -- re-run failed tests in verbose mode immediately 29 -q/--quiet -- no output unless one or more tests fail 30 -S/--slow -- print the slowest 10 tests 31 --header -- print header with interpreter info 32 33 Selecting tests 34 35 -r/--randomize -- randomize test execution order (see below) 36 --randseed -- pass a random seed to reproduce a previous random run 37 -f/--fromfile -- read names of tests to run from a file (see below) 38 -x/--exclude -- arguments are tests to *exclude* 39 -s/--single -- single step through a set of tests (see below) 40 -u/--use RES1,RES2,... 41 -- specify which special resource intensive tests to run 42 -M/--memlimit LIMIT 43 -- run very large memory-consuming tests 44 45 Special runs 46 47 -l/--findleaks -- if GC is available detect tests that leak memory 48 -L/--runleaks -- run the leaks(1) command just before exit 49 -R/--huntrleaks RUNCOUNTS 50 -- search for reference leaks (needs debug build, v. slow) 51 -j/--multiprocess PROCESSES 52 -- run PROCESSES processes at once 53 -T/--coverage -- turn on code coverage tracing using the trace module 54 -D/--coverdir DIRECTORY 55 -- Directory where coverage files are put 56 -N/--nocoverdir -- Put coverage files alongside modules 57 -t/--threshold THRESHOLD 58 -- call gc.set_threshold(THRESHOLD) 59 -F/--forever -- run the specified tests in a loop, until an error happens 60 61 62 Additional Option Details: 63 64 -r randomizes test execution order. You can use --randseed=int to provide a 65 int seed value for the randomizer; this is useful for reproducing troublesome 66 test orders. 67 68 -s On the first invocation of regrtest using -s, the first test file found 69 or the first test file given on the command line is run, and the name of 70 the next test is recorded in a file named pynexttest. If run from the 71 Python build directory, pynexttest is located in the 'build' subdirectory, 72 otherwise it is located in tempfile.gettempdir(). On subsequent runs, 73 the test in pynexttest is run, and the next test is written to pynexttest. 74 When the last test has been run, pynexttest is deleted. In this way it 75 is possible to single step through the test files. This is useful when 76 doing memory analysis on the Python interpreter, which process tends to 77 consume too many resources to run the full regression test non-stop. 47 78 48 79 -f reads the names of tests from the file given as f's argument, one … … 61 92 of times further it is run and 'fname' is the name of the file the 62 93 reports are written to. These parameters all have defaults (5, 4 and 63 "reflog.txt" respectively), so the minimal invocation is '-R ::'.94 "reflog.txt" respectively), and the minimal invocation is '-R :'. 64 95 65 96 -M runs tests that require an exorbitant amount of memory. These tests … … 92 123 state and output modes. 93 124 94 lib2to3 - Run the tests for 2to3 (They take a while.)95 96 125 largefile - It is okay to run some test that may create huge 97 126 files. These tests can take a long time and may … … 107 136 verifies compliance with standards. 108 137 109 compiler - Test the compiler package by compiling all the source 110 in the standard library and test suite. This takes 111 a long time. Enabling this resource also allows 112 test_tokenize to verify round-trip lexing on every 113 file in the test library. 138 cpu - Used for certain CPU-heavy tests. 114 139 115 140 subprocess Run all tests for the subprocess module. 116 141 117 142 urlfetch - It is okay to download files required on testing. 143 144 gui - Run tests that require a running GUI. 145 146 xpickle - Test pickle and cPickle against Python 2.4, 2.5 and 2.6 to 147 test backwards compatibility. These tests take a long time 148 to run. 118 149 119 150 To enable all resources except one, use '-uall,-<resource>'. For … … 122 153 """ 123 154 124 import cStringIO155 import StringIO 125 156 import getopt 157 import json 126 158 import os 127 159 import random 128 160 import re 161 import shutil 129 162 import sys 130 163 import time 131 164 import traceback 132 165 import warnings 133 134 # I see no other way to suppress these warnings; 135 # putting them in test_grammar.py has no effect: 136 warnings.filterwarnings("ignore", "hex/oct constants", FutureWarning, 137 ".*test.test_grammar$") 138 if sys.maxint > 0x7fffffff: 139 # Also suppress them in <string>, because for 64-bit platforms, 140 # that's where test_grammar.py hides them. 141 warnings.filterwarnings("ignore", "hex/oct constants", FutureWarning, 142 "<string>") 143 144 # Ignore ImportWarnings that only occur in the source tree, 145 # (because of modules with the same name as source-directories in Modules/) 146 for mod in ("ctypes", "gzip", "zipfile", "tarfile", "encodings.zlib_codec", 147 "test.test_zipimport", "test.test_zlib", "test.test_zipfile", 148 "test.test_codecs", "test.string_tests"): 149 warnings.filterwarnings(module=".*%s$" % (mod,), 150 action="ignore", category=ImportWarning) 166 import unittest 167 import tempfile 168 import imp 169 import platform 170 import sysconfig 171 172 173 # Some times __path__ and __file__ are not absolute (e.g. while running from 174 # Lib/) and, if we change the CWD to run the tests in a temporary dir, some 175 # imports might fail. This affects only the modules imported before os.chdir(). 176 # These modules are searched first in sys.path[0] (so '' -- the CWD) and if 177 # they are found in the CWD their __file__ and __path__ will be relative (this 178 # happens before the chdir). All the modules imported after the chdir, are 179 # not found in the CWD, and since the other paths in sys.path[1:] are absolute 180 # (site.py absolutize them), the __file__ and __path__ will be absolute too. 181 # Therefore it is necessary to absolutize manually the __file__ and __path__ of 182 # the packages to prevent later imports to fail when the CWD is different. 183 for module in sys.modules.itervalues(): 184 if hasattr(module, '__path__'): 185 module.__path__ = [os.path.abspath(path) for path in module.__path__] 186 if hasattr(module, '__file__'): 187 module.__file__ = os.path.abspath(module.__file__) 188 151 189 152 190 # MacOSX (a.k.a. Darwin) has a default stack size that is too small … … 166 204 resource.setrlimit(resource.RLIMIT_STACK, (newsoft, hard)) 167 205 206 # Test result constants. 207 PASSED = 1 208 FAILED = 0 209 ENV_CHANGED = -1 210 SKIPPED = -2 211 RESOURCE_DENIED = -3 212 INTERRUPTED = -4 213 168 214 from test import test_support 169 215 170 216 RESOURCE_NAMES = ('audio', 'curses', 'largefile', 'network', 'bsddb', 171 'decimal', 'compiler', 'subprocess', 'urlfetch') 217 'decimal', 'cpu', 'subprocess', 'urlfetch', 'gui', 218 'xpickle') 219 220 TEMPDIR = os.path.abspath(tempfile.gettempdir()) 172 221 173 222 … … 181 230 exclude=False, single=False, randomize=False, fromfile=None, 182 231 findleaks=False, use_resources=None, trace=False, coverdir='coverage', 183 runleaks=False, huntrleaks=False, verbose2=False, print_slow=False): 232 runleaks=False, huntrleaks=False, verbose2=False, print_slow=False, 233 random_seed=None, use_mp=None, verbose3=False, forever=False, 234 header=False): 184 235 """Execute a test suite. 185 236 … … 199 250 200 251 The other default arguments (verbose, quiet, exclude, 201 single, randomize, findleaks, use_resources, trace, coverdir, and 202 print_slow) allow programmers calling main() directly to set the 203 values that would normally be set by flags on the command line. 252 single, randomize, findleaks, use_resources, trace, coverdir, 253 print_slow, and random_seed) allow programmers calling main() 254 directly to set the values that would normally be set by flags 255 on the command line. 204 256 """ 205 257 206 258 test_support.record_original_stdout(sys.stdout) 207 259 try: 208 opts, args = getopt.getopt(sys.argv[1:], 'hvqxsSrf:lu:t:TD:NLR:wM:', 209 ['help', 'verbose', 'quiet', 'exclude', 210 'single', 'slow', 'random', 'fromfile', 211 'findleaks', 'use=', 'threshold=', 'trace', 212 'coverdir=', 'nocoverdir', 'runleaks', 213 'huntrleaks=', 'verbose2', 'memlimit=', 214 ]) 260 opts, args = getopt.getopt(sys.argv[1:], 'hvqxsSrf:lu:t:TD:NLR:FwWM:j:', 261 ['help', 'verbose', 'verbose2', 'verbose3', 'quiet', 262 'exclude', 'single', 'slow', 'randomize', 'fromfile=', 'findleaks', 263 'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir', 264 'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=', 265 'multiprocess=', 'slaveargs=', 'forever', 'header']) 215 266 except getopt.error, msg: 216 267 usage(2, msg) 217 268 218 269 # Defaults 270 if random_seed is None: 271 random_seed = random.randrange(10000000) 219 272 if use_resources is None: 220 273 use_resources = [] … … 226 279 elif o in ('-w', '--verbose2'): 227 280 verbose2 = True 281 elif o in ('-W', '--verbose3'): 282 verbose3 = True 228 283 elif o in ('-q', '--quiet'): 229 284 quiet = True; … … 237 292 elif o in ('-r', '--randomize'): 238 293 randomize = True 294 elif o == '--randseed': 295 random_seed = int(a) 239 296 elif o in ('-f', '--fromfile'): 240 297 fromfile = a … … 254 311 elif o in ('-R', '--huntrleaks'): 255 312 huntrleaks = a.split(':') 256 if len(huntrleaks) != 3:313 if len(huntrleaks) not in (2, 3): 257 314 print a, huntrleaks 258 usage(2, '-R takes threecolon-separated arguments')259 if len(huntrleaks[0]) == 0:315 usage(2, '-R takes 2 or 3 colon-separated arguments') 316 if not huntrleaks[0]: 260 317 huntrleaks[0] = 5 261 318 else: 262 319 huntrleaks[0] = int(huntrleaks[0]) 263 if len(huntrleaks[1]) == 0:320 if not huntrleaks[1]: 264 321 huntrleaks[1] = 4 265 322 else: 266 323 huntrleaks[1] = int(huntrleaks[1]) 267 if len(huntrleaks [2]) == 0:268 huntrleaks[2 ] = "reflog.txt"324 if len(huntrleaks) == 2 or not huntrleaks[2]: 325 huntrleaks[2:] = ["reflog.txt"] 269 326 elif o in ('-M', '--memlimit'): 270 327 test_support.set_memlimit(a) … … 286 343 elif r not in use_resources: 287 344 use_resources.append(r) 345 elif o in ('-F', '--forever'): 346 forever = True 347 elif o in ('-j', '--multiprocess'): 348 use_mp = int(a) 349 elif o == '--header': 350 header = True 351 elif o == '--slaveargs': 352 args, kwargs = json.loads(a) 353 try: 354 result = runtest(*args, **kwargs) 355 except BaseException, e: 356 result = INTERRUPTED, e.__class__.__name__ 357 print # Force a newline (just in case) 358 print json.dumps(result) 359 sys.exit(0) 288 360 else: 289 print >>sys.stderr, ("No handler for option { 0}. Please "361 print >>sys.stderr, ("No handler for option {}. Please " 290 362 "report this as a bug at http://bugs.python.org.").format(o) 291 363 sys.exit(1) 292 364 if single and fromfile: 293 365 usage(2, "-s and -f don't go together!") 366 if use_mp and trace: 367 usage(2, "-T and -j don't go together!") 368 if use_mp and findleaks: 369 usage(2, "-l and -j don't go together!") 294 370 295 371 good = [] … … 297 373 skipped = [] 298 374 resource_denieds = [] 375 environment_changed = [] 376 interrupted = False 299 377 300 378 if findleaks: … … 312 390 313 391 if single: 314 from tempfile import gettempdir 315 filename = os.path.join(gettempdir(), 'pynexttest') 392 filename = os.path.join(TEMPDIR, 'pynexttest') 316 393 try: 317 394 fp = open(filename, 'r') 318 next = fp.read().strip()319 tests = [next ]395 next_test = fp.read().strip() 396 tests = [next_test] 320 397 fp.close() 321 398 except IOError: … … 324 401 if fromfile: 325 402 tests = [] 326 fp = open( fromfile)403 fp = open(os.path.join(test_support.SAVEDCWD, fromfile)) 327 404 for line in fp: 328 405 guts = line.split() # assuming no test has whitespace in its name … … 332 409 333 410 # Strip .py extensions. 334 if args: 335 args = map(removepy, args) 336 if tests: 337 tests = map(removepy, tests) 411 removepy(args) 412 removepy(tests) 338 413 339 414 stdtests = STDTESTS[:] 340 nottests = NOTTESTS [:]415 nottests = NOTTESTS.copy() 341 416 if exclude: 342 417 for arg in args: 343 418 if arg in stdtests: 344 419 stdtests.remove(arg) 345 nottests[:0] = args420 nottests.add(arg) 346 421 args = [] 347 tests = tests or args or findtests(testdir, stdtests, nottests) 422 423 # For a partial run, we do not need to clutter the output. 424 if verbose or header or not (quiet or single or tests or args): 425 # Print basic platform information 426 print "==", platform.python_implementation(), \ 427 " ".join(sys.version.split()) 428 print "== ", platform.platform(aliased=True), \ 429 "%s-endian" % sys.byteorder 430 print "== ", os.getcwd() 431 print "Testing with flags:", sys.flags 432 433 alltests = findtests(testdir, stdtests, nottests) 434 selected = tests or args or alltests 348 435 if single: 349 tests = tests[:1] 436 selected = selected[:1] 437 try: 438 next_single_test = alltests[alltests.index(selected[0])+1] 439 except IndexError: 440 next_single_test = None 350 441 if randomize: 351 random.shuffle(tests) 442 random.seed(random_seed) 443 print "Using random seed", random_seed 444 random.shuffle(selected) 352 445 if trace: 353 446 import trace 354 447 tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix], 355 448 trace=False, count=True) 449 356 450 test_times = [] 357 test_support.verbose = verbose # Tell tests to be moderately quiet358 451 test_support.use_resources = use_resources 359 452 save_modules = sys.modules.keys() 360 for test in tests: 361 if not quiet: 362 print test 363 sys.stdout.flush() 364 if trace: 365 # If we're tracing code coverage, then we don't exit with status 366 # if on a false return value from main. 367 tracer.runctx('runtest(test, verbose, quiet,' 368 ' test_times, testdir)', 369 globals=globals(), locals=vars()) 370 else: 453 454 def accumulate_result(test, result): 455 ok, test_time = result 456 test_times.append((test_time, test)) 457 if ok == PASSED: 458 good.append(test) 459 elif ok == FAILED: 460 bad.append(test) 461 elif ok == ENV_CHANGED: 462 bad.append(test) 463 environment_changed.append(test) 464 elif ok == SKIPPED: 465 skipped.append(test) 466 elif ok == RESOURCE_DENIED: 467 skipped.append(test) 468 resource_denieds.append(test) 469 470 if forever: 471 def test_forever(tests=list(selected)): 472 while True: 473 for test in tests: 474 yield test 475 if bad: 476 return 477 tests = test_forever() 478 else: 479 tests = iter(selected) 480 481 if use_mp: 482 try: 483 from threading import Thread 484 except ImportError: 485 print "Multiprocess option requires thread support" 486 sys.exit(2) 487 from Queue import Queue 488 from subprocess import Popen, PIPE 489 debug_output_pat = re.compile(r"\[\d+ refs\]$") 490 output = Queue() 491 def tests_and_args(): 492 for test in tests: 493 args_tuple = ( 494 (test, verbose, quiet), 495 dict(huntrleaks=huntrleaks, use_resources=use_resources) 496 ) 497 yield (test, args_tuple) 498 pending = tests_and_args() 499 opt_args = test_support.args_from_interpreter_flags() 500 base_cmd = [sys.executable] + opt_args + ['-m', 'test.regrtest'] 501 def work(): 502 # A worker thread. 371 503 try: 372 ok = runtest(test, verbose, quiet, test_times, 373 testdir, huntrleaks) 374 except KeyboardInterrupt: 375 # print a newline separate from the ^C 376 print 377 break 378 except: 504 while True: 505 try: 506 test, args_tuple = next(pending) 507 except StopIteration: 508 output.put((None, None, None, None)) 509 return 510 # -E is needed by some tests, e.g. test_import 511 popen = Popen(base_cmd + ['--slaveargs', json.dumps(args_tuple)], 512 stdout=PIPE, stderr=PIPE, 513 universal_newlines=True, 514 close_fds=(os.name != 'nt')) 515 stdout, stderr = popen.communicate() 516 # Strip last refcount output line if it exists, since it 517 # comes from the shutdown of the interpreter in the subcommand. 518 stderr = debug_output_pat.sub("", stderr) 519 stdout, _, result = stdout.strip().rpartition("\n") 520 if not result: 521 output.put((None, None, None, None)) 522 return 523 result = json.loads(result) 524 if not quiet: 525 stdout = test+'\n'+stdout 526 output.put((test, stdout.rstrip(), stderr.rstrip(), result)) 527 except BaseException: 528 output.put((None, None, None, None)) 379 529 raise 380 if ok > 0: 381 good.append(test) 382 elif ok == 0: 383 bad.append(test) 530 workers = [Thread(target=work) for i in range(use_mp)] 531 for worker in workers: 532 worker.start() 533 finished = 0 534 try: 535 while finished < use_mp: 536 test, stdout, stderr, result = output.get() 537 if test is None: 538 finished += 1 539 continue 540 if stdout: 541 print stdout 542 if stderr: 543 print >>sys.stderr, stderr 544 sys.stdout.flush() 545 sys.stderr.flush() 546 if result[0] == INTERRUPTED: 547 assert result[1] == 'KeyboardInterrupt' 548 raise KeyboardInterrupt # What else? 549 accumulate_result(test, result) 550 except KeyboardInterrupt: 551 interrupted = True 552 pending.close() 553 for worker in workers: 554 worker.join() 555 else: 556 for test in tests: 557 if not quiet: 558 print test 559 sys.stdout.flush() 560 if trace: 561 # If we're tracing code coverage, then we don't exit with status 562 # if on a false return value from main. 563 tracer.runctx('runtest(test, verbose, quiet)', 564 globals=globals(), locals=vars()) 384 565 else: 385 skipped.append(test) 386 if ok == -2: 387 resource_denieds.append(test) 388 if findleaks: 389 gc.collect() 390 if gc.garbage: 391 print "Warning: test created", len(gc.garbage), 392 print "uncollectable object(s)." 393 # move the uncollectable objects somewhere so we don't see 394 # them again 395 found_garbage.extend(gc.garbage) 396 del gc.garbage[:] 397 # Unload the newly imported modules (best effort finalization) 398 for module in sys.modules.keys(): 399 if module not in save_modules and module.startswith("test."): 400 test_support.unload(module) 401 402 # The lists won't be sorted if running with -r 403 good.sort() 404 bad.sort() 405 skipped.sort() 406 566 try: 567 result = runtest(test, verbose, quiet, huntrleaks) 568 accumulate_result(test, result) 569 if verbose3 and result[0] == FAILED: 570 print "Re-running test %r in verbose mode" % test 571 runtest(test, True, quiet, huntrleaks) 572 except KeyboardInterrupt: 573 interrupted = True 574 break 575 except: 576 raise 577 if findleaks: 578 gc.collect() 579 if gc.garbage: 580 print "Warning: test created", len(gc.garbage), 581 print "uncollectable object(s)." 582 # move the uncollectable objects somewhere so we don't see 583 # them again 584 found_garbage.extend(gc.garbage) 585 del gc.garbage[:] 586 # Unload the newly imported modules (best effort finalization) 587 for module in sys.modules.keys(): 588 if module not in save_modules and module.startswith("test."): 589 test_support.unload(module) 590 591 if interrupted: 592 # print a newline after ^C 593 print 594 print "Test suite interrupted by signal SIGINT." 595 omitted = set(selected) - set(good) - set(bad) - set(skipped) 596 print count(len(omitted), "test"), "omitted:" 597 printlist(omitted) 407 598 if good and not quiet: 408 if not bad and not skipped and len(good) > 1:599 if not bad and not skipped and not interrupted and len(good) > 1: 409 600 print "All", 410 601 print count(len(good), "test"), "OK." … … 415 606 print "%s: %.1fs" % (test, time) 416 607 if bad: 417 print count(len(bad), "test"), "failed:" 418 printlist(bad) 608 bad = set(bad) - set(environment_changed) 609 if bad: 610 print count(len(bad), "test"), "failed:" 611 printlist(bad) 612 if environment_changed: 613 print "{} altered the execution environment:".format( 614 count(len(environment_changed), "test")) 615 printlist(environment_changed) 419 616 if skipped and not quiet: 420 617 print count(len(skipped), "test"), "skipped:" … … 442 639 try: 443 640 test_support.verbose = True 444 ok = runtest(test, True, quiet, test_times, testdir, 445 huntrleaks) 641 ok = runtest(test, True, quiet, huntrleaks) 446 642 except KeyboardInterrupt: 447 643 # print a newline separate from the ^C … … 452 648 453 649 if single: 454 alltests = findtests(testdir, stdtests, nottests) 455 for i in range(len(alltests)): 456 if tests[0] == alltests[i]: 457 if i == len(alltests) - 1: 458 os.unlink(filename) 459 else: 460 fp = open(filename, 'w') 461 fp.write(alltests[i+1] + '\n') 462 fp.close() 463 break 650 if next_single_test: 651 with open(filename, 'w') as fp: 652 fp.write(next_single_test + '\n') 464 653 else: 465 654 os.unlink(filename) … … 472 661 os.system("leaks %d" % os.getpid()) 473 662 474 sys.exit(len(bad) > 0 )663 sys.exit(len(bad) > 0 or interrupted) 475 664 476 665 … … 485 674 'test_doctest', 486 675 'test_doctest2', 487 488 489 NOTTESTS = [676 ] 677 678 NOTTESTS = { 490 679 'test_support', 491 680 'test_future1', 492 681 'test_future2', 493 ] 682 } 494 683 495 684 def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): 496 685 """Return a list of all applicable test modules.""" 497 if not testdir: testdir = findtestdir()686 testdir = findtestdir(testdir) 498 687 names = os.listdir(testdir) 499 688 tests = [] 689 others = set(stdtests) | nottests 500 690 for name in names: 501 if name[:5] == "test_" and name[-3:] == os.extsep+"py": 502 modname = name[:-3] 503 if modname not in stdtests and modname not in nottests: 504 tests.append(modname) 505 tests.sort() 506 return stdtests + tests 507 508 def runtest(test, verbose, quiet, test_times, 509 testdir=None, huntrleaks=False): 691 modname, ext = os.path.splitext(name) 692 if modname[:5] == "test_" and ext == ".py" and modname not in others: 693 tests.append(modname) 694 return stdtests + sorted(tests) 695 696 def runtest(test, verbose, quiet, 697 huntrleaks=False, use_resources=None): 510 698 """Run a single test. 511 699 … … 514 702 quiet -- if true, don't print 'skipped' messages (probably redundant) 515 703 test_times -- a list of (time, test_name) pairs 516 testdir -- test directory517 704 huntrleaks -- run multiple times to test for leaks; requires a debug 518 705 build; a triple corresponding to -R's three arguments 519 Return: 520 -2 test skipped because resource denied 521 -1 test skipped for some other reason 522 0 test failed 523 1 test passed 706 Returns one of the test result constants: 707 INTERRUPTED KeyboardInterrupt when run under -j 708 RESOURCE_DENIED test skipped because resource denied 709 SKIPPED test skipped for some other reason 710 ENV_CHANGED test failed because it changed the execution environment 711 FAILED test failed 712 PASSED test passed 524 713 """ 525 714 715 test_support.verbose = verbose # Tell tests to be moderately quiet 716 if use_resources is not None: 717 test_support.use_resources = use_resources 526 718 try: 527 return runtest_inner(test, verbose, quiet, test_times, 528 testdir, huntrleaks) 719 return runtest_inner(test, verbose, quiet, huntrleaks) 529 720 finally: 530 721 cleanup_test_droppings(test, verbose) 531 722 532 def runtest_inner(test, verbose, quiet, test_times, 533 testdir=None, huntrleaks=False): 723 724 # Unit tests are supposed to leave the execution environment unchanged 725 # once they complete. But sometimes tests have bugs, especially when 726 # tests fail, and the changes to environment go on to mess up other 727 # tests. This can cause issues with buildbot stability, since tests 728 # are run in random order and so problems may appear to come and go. 729 # There are a few things we can save and restore to mitigate this, and 730 # the following context manager handles this task. 731 732 class saved_test_environment: 733 """Save bits of the test environment and restore them at block exit. 734 735 with saved_test_environment(testname, verbose, quiet): 736 #stuff 737 738 Unless quiet is True, a warning is printed to stderr if any of 739 the saved items was changed by the test. The attribute 'changed' 740 is initially False, but is set to True if a change is detected. 741 742 If verbose is more than 1, the before and after state of changed 743 items is also printed. 744 """ 745 746 changed = False 747 748 def __init__(self, testname, verbose=0, quiet=False): 749 self.testname = testname 750 self.verbose = verbose 751 self.quiet = quiet 752 753 # To add things to save and restore, add a name XXX to the resources list 754 # and add corresponding get_XXX/restore_XXX functions. get_XXX should 755 # return the value to be saved and compared against a second call to the 756 # get function when test execution completes. restore_XXX should accept 757 # the saved value and restore the resource using it. It will be called if 758 # and only if a change in the value is detected. 759 # 760 # Note: XXX will have any '.' replaced with '_' characters when determining 761 # the corresponding method names. 762 763 resources = ('sys.argv', 'cwd', 'sys.stdin', 'sys.stdout', 'sys.stderr', 764 'os.environ', 'sys.path', 'asyncore.socket_map', 765 'test_support.TESTFN', 766 ) 767 768 def get_sys_argv(self): 769 return id(sys.argv), sys.argv, sys.argv[:] 770 def restore_sys_argv(self, saved_argv): 771 sys.argv = saved_argv[1] 772 sys.argv[:] = saved_argv[2] 773 774 def get_cwd(self): 775 return os.getcwd() 776 def restore_cwd(self, saved_cwd): 777 os.chdir(saved_cwd) 778 779 def get_sys_stdout(self): 780 return sys.stdout 781 def restore_sys_stdout(self, saved_stdout): 782 sys.stdout = saved_stdout 783 784 def get_sys_stderr(self): 785 return sys.stderr 786 def restore_sys_stderr(self, saved_stderr): 787 sys.stderr = saved_stderr 788 789 def get_sys_stdin(self): 790 return sys.stdin 791 def restore_sys_stdin(self, saved_stdin): 792 sys.stdin = saved_stdin 793 794 def get_os_environ(self): 795 return id(os.environ), os.environ, dict(os.environ) 796 def restore_os_environ(self, saved_environ): 797 os.environ = saved_environ[1] 798 os.environ.clear() 799 os.environ.update(saved_environ[2]) 800 801 def get_sys_path(self): 802 return id(sys.path), sys.path, sys.path[:] 803 def restore_sys_path(self, saved_path): 804 sys.path = saved_path[1] 805 sys.path[:] = saved_path[2] 806 807 def get_asyncore_socket_map(self): 808 asyncore = sys.modules.get('asyncore') 809 # XXX Making a copy keeps objects alive until __exit__ gets called. 810 return asyncore and asyncore.socket_map.copy() or {} 811 def restore_asyncore_socket_map(self, saved_map): 812 asyncore = sys.modules.get('asyncore') 813 if asyncore is not None: 814 asyncore.close_all(ignore_all=True) 815 asyncore.socket_map.update(saved_map) 816 817 def get_test_support_TESTFN(self): 818 if os.path.isfile(test_support.TESTFN): 819 result = 'f' 820 elif os.path.isdir(test_support.TESTFN): 821 result = 'd' 822 else: 823 result = None 824 return result 825 def restore_test_support_TESTFN(self, saved_value): 826 if saved_value is None: 827 if os.path.isfile(test_support.TESTFN): 828 os.unlink(test_support.TESTFN) 829 elif os.path.isdir(test_support.TESTFN): 830 shutil.rmtree(test_support.TESTFN) 831 832 def resource_info(self): 833 for name in self.resources: 834 method_suffix = name.replace('.', '_') 835 get_name = 'get_' + method_suffix 836 restore_name = 'restore_' + method_suffix 837 yield name, getattr(self, get_name), getattr(self, restore_name) 838 839 def __enter__(self): 840 self.saved_values = dict((name, get()) for name, get, restore 841 in self.resource_info()) 842 return self 843 844 def __exit__(self, exc_type, exc_val, exc_tb): 845 saved_values = self.saved_values 846 del self.saved_values 847 for name, get, restore in self.resource_info(): 848 current = get() 849 original = saved_values.pop(name) 850 # Check for changes to the resource's value 851 if current != original: 852 self.changed = True 853 restore(original) 854 if not self.quiet: 855 print >>sys.stderr, ( 856 "Warning -- {} was modified by {}".format( 857 name, self.testname)) 858 if self.verbose > 1: 859 print >>sys.stderr, ( 860 " Before: {}\n After: {} ".format( 861 original, current)) 862 # XXX (ncoghlan): for most resources (e.g. sys.path) identity 863 # matters at least as much as value. For others (e.g. cwd), 864 # identity is irrelevant. Should we add a mechanism to check 865 # for substitution in the cases where it matters? 866 return False 867 868 869 def runtest_inner(test, verbose, quiet, huntrleaks=False): 534 870 test_support.unload(test) 535 if not testdir:536 testdir = findtestdir()537 871 if verbose: 538 872 capture_stdout = None 539 873 else: 540 capture_stdout = cStringIO.StringIO() 541 874 capture_stdout = StringIO.StringIO() 875 876 test_time = 0.0 877 refleak = False # True if the test leaked references. 542 878 try: 543 879 save_stdout = sys.stdout … … 550 886 # Always import it from the test package 551 887 abstest = 'test.' + test 552 start_time = time.time() 553 the_package = __import__(abstest, globals(), locals(), []) 554 the_module = getattr(the_package, test) 555 # Old tests run to completion simply as a side-effect of 556 # being imported. For tests based on unittest or doctest, 557 # explicitly invoke their test_main() function (if it exists). 558 indirect_test = getattr(the_module, "test_main", None) 559 if indirect_test is not None: 560 indirect_test() 561 if huntrleaks: 562 dash_R(the_module, test, indirect_test, huntrleaks) 563 test_time = time.time() - start_time 564 test_times.append((test_time, test)) 888 with saved_test_environment(test, verbose, quiet) as environment: 889 start_time = time.time() 890 the_package = __import__(abstest, globals(), locals(), []) 891 the_module = getattr(the_package, test) 892 # Old tests run to completion simply as a side-effect of 893 # being imported. For tests based on unittest or doctest, 894 # explicitly invoke their test_main() function (if it exists). 895 indirect_test = getattr(the_module, "test_main", None) 896 if indirect_test is not None: 897 indirect_test() 898 if huntrleaks: 899 refleak = dash_R(the_module, test, indirect_test, 900 huntrleaks) 901 test_time = time.time() - start_time 565 902 finally: 566 903 sys.stdout = save_stdout … … 569 906 print test, "skipped --", msg 570 907 sys.stdout.flush() 571 return -2572 except (ImportError, test_support.TestSkipped), msg:908 return RESOURCE_DENIED, test_time 909 except unittest.SkipTest, msg: 573 910 if not quiet: 574 911 print test, "skipped --", msg 575 912 sys.stdout.flush() 576 return -1913 return SKIPPED, test_time 577 914 except KeyboardInterrupt: 578 915 raise 579 916 except test_support.TestFailed, msg: 580 print "test", test, "failed --", msg581 sys.std out.flush()582 return 0917 print >>sys.stderr, "test", test, "failed --", msg 918 sys.stderr.flush() 919 return FAILED, test_time 583 920 except: 584 921 type, value = sys.exc_info()[:2] 585 print "test", test, "crashed --", str(type) + ":", value586 sys.std out.flush()922 print >>sys.stderr, "test", test, "crashed --", str(type) + ":", value 923 sys.stderr.flush() 587 924 if verbose: 588 traceback.print_exc(file=sys.std out)589 sys.std out.flush()590 return 0925 traceback.print_exc(file=sys.stderr) 926 sys.stderr.flush() 927 return FAILED, test_time 591 928 else: 929 if refleak: 930 return FAILED, test_time 931 if environment.changed: 932 return ENV_CHANGED, test_time 592 933 # Except in verbose mode, tests should not print anything 593 934 if verbose or huntrleaks: 594 return 1935 return PASSED, test_time 595 936 output = capture_stdout.getvalue() 596 937 if not output: 597 return 1938 return PASSED, test_time 598 939 print "test", test, "produced unexpected output:" 599 940 print "*" * 70 … … 601 942 print "*" * 70 602 943 sys.stdout.flush() 603 return 0944 return FAILED, test_time 604 945 605 946 def cleanup_test_droppings(testname, verbose): 606 import shutil 947 import stat 948 import gc 949 950 # First kill any dangling references to open files etc. 951 gc.collect() 607 952 608 953 # Try to clean up junk commonly left behind. While tests shouldn't leave … … 629 974 print "%r left behind %s %r" % (testname, kind, name) 630 975 try: 976 # if we have chmod, fix possible permissions problems 977 # that might prevent cleanup 978 if (hasattr(os, 'chmod')): 979 os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) 631 980 nuker(name) 632 981 except Exception, msg: … … 635 984 636 985 def dash_R(the_module, test, indirect_test, huntrleaks): 986 """Run a test multiple times, looking for reference leaks. 987 988 Returns: 989 False if the test didn't leak references; True if we detected refleaks. 990 """ 637 991 # This code is hackish and inelegant, but it seems to do the job. 638 import copy_reg, _abcoll, io992 import copy_reg, _abcoll, _pyio 639 993 640 994 if not hasattr(sys, 'gettotalrefcount'): … … 646 1000 ps = copy_reg.dispatch_table.copy() 647 1001 pic = sys.path_importer_cache.copy() 1002 try: 1003 import zipimport 1004 except ImportError: 1005 zdc = None # Run unmodified on platforms without zipimport support 1006 else: 1007 zdc = zipimport._zip_directory_cache.copy() 648 1008 abcs = {} 649 modules = _abcoll, io1009 modules = _abcoll, _pyio 650 1010 for abc in [getattr(mod, a) for mod in modules for a in mod.__all__]: 651 1011 # XXX isinstance(abc, ABCMeta) leads to infinite recursion … … 660 1020 else: 661 1021 def run_the_test(): 662 reload(the_module)1022 imp.reload(the_module) 663 1023 664 1024 deltas = [] 665 1025 nwarmup, ntracked, fname = huntrleaks 1026 fname = os.path.join(test_support.SAVEDCWD, fname) 666 1027 repcount = nwarmup + ntracked 667 1028 print >> sys.stderr, "beginning", repcount, "repetitions" 668 1029 print >> sys.stderr, ("1234567890"*(repcount//10 + 1))[:repcount] 669 dash_R_cleanup(fs, ps, pic, abcs)1030 dash_R_cleanup(fs, ps, pic, zdc, abcs) 670 1031 for i in range(repcount): 671 rc = sys.gettotalrefcount()1032 rc_before = sys.gettotalrefcount() 672 1033 run_the_test() 673 1034 sys.stderr.write('.') 674 dash_R_cleanup(fs, ps, pic, abcs) 1035 dash_R_cleanup(fs, ps, pic, zdc, abcs) 1036 rc_after = sys.gettotalrefcount() 675 1037 if i >= nwarmup: 676 deltas.append( sys.gettotalrefcount() - rc - 2)1038 deltas.append(rc_after - rc_before) 677 1039 print >> sys.stderr 678 1040 if any(deltas): 679 1041 msg = '%s leaked %s references, sum=%s' % (test, deltas, sum(deltas)) 680 1042 print >> sys.stderr, msg 681 refrep = open(fname, "a") 682 print >> refrep, msg 683 refrep.close() 684 685 def dash_R_cleanup(fs, ps, pic, abcs): 1043 with open(fname, "a") as refrep: 1044 print >> refrep, msg 1045 refrep.flush() 1046 return True 1047 return False 1048 1049 def dash_R_cleanup(fs, ps, pic, zdc, abcs): 686 1050 import gc, copy_reg 687 1051 import _strptime, linecache … … 702 1066 sys.path_importer_cache.clear() 703 1067 sys.path_importer_cache.update(pic) 1068 try: 1069 import zipimport 1070 except ImportError: 1071 pass # Run unmodified on platforms without zipimport support 1072 else: 1073 zipimport._zip_directory_cache.clear() 1074 zipimport._zip_directory_cache.update(zdc) 704 1075 705 1076 # clear type cache … … 725 1096 struct._clearcache() 726 1097 doctest.master = None 1098 try: 1099 import ctypes 1100 except ImportError: 1101 # Don't worry about resetting the cache if ctypes is not supported 1102 pass 1103 else: 1104 ctypes._reset_cache() 727 1105 728 1106 # Collect cyclic trash. 729 1107 gc.collect() 730 1108 731 def findtestdir(): 732 if __name__ == '__main__': 733 file = sys.argv[0] 734 else: 735 file = __file__ 736 testdir = os.path.dirname(file) or os.curdir 737 return testdir 738 739 def removepy(name): 740 if name.endswith(os.extsep + "py"): 741 name = name[:-3] 742 return name 1109 def findtestdir(path=None): 1110 return path or os.path.dirname(__file__) or os.curdir 1111 1112 def removepy(names): 1113 if not names: 1114 return 1115 for idx, name in enumerate(names): 1116 basename, ext = os.path.splitext(name) 1117 if ext == '.py': 1118 names[idx] = basename 743 1119 744 1120 def count(n, word): … … 758 1134 from textwrap import fill 759 1135 blanks = ' ' * indent 760 print fill(' '.join(map(str, x)), width, 1136 # Print the sorted list: 'x' may be a '--random' list or a set() 1137 print fill(' '.join(str(elt) for elt in sorted(x)), width, 761 1138 initial_indent=blanks, subsequent_indent=blanks) 762 1139 … … 768 1145 # The _ExpectedSkips constructor adds this to the set of expected 769 1146 # skips if not os.path.supports_unicode_filenames. 770 # test_socket_ssl771 # Controlled by test_socket_ssl.skip_expected. Requires the network772 # resource, and a socket module with ssl support.773 1147 # test_timeout 774 1148 # Controlled by test_timeout.skip_expected. Requires the network … … 821 1195 test_ossaudiodev 822 1196 """, 823 'mac':824 """825 test_atexit826 test_bsddb827 test_bsddb185828 test_bsddb3829 test_bz2830 test_commands831 test_crypt832 test_curses833 test_dbm834 test_dl835 test_fcntl836 test_fork1837 test_epoll838 test_grp839 test_ioctl840 test_largefile841 test_locale842 test_kqueue843 test_mmap844 test_openpty845 test_ossaudiodev846 test_poll847 test_popen848 test_popen2849 test_posix850 test_pty851 test_pwd852 test_resource853 test_signal854 test_sundry855 test_tarfile856 test_timing857 """,858 1197 'unixware7': 859 1198 """ … … 947 1286 test_curses 948 1287 test_epoll 1288 test_gdb 949 1289 test_gdbm 950 1290 test_largefile … … 1072 1412 test_pep277 1073 1413 test_pty 1074 test_socket_ssl1075 1414 test_socketserver 1076 1415 test_tcl 1416 test_tk 1417 test_ttk_guionly 1418 test_ttk_textonly 1077 1419 test_timeout 1078 1420 test_urllibnet … … 1092 1434 test_ossaudiodev 1093 1435 test_tcl 1436 test_tk 1437 test_ttk_guionly 1438 test_ttk_textonly 1094 1439 test_zipimport 1095 1440 test_zlib … … 1097 1442 'openbsd3': 1098 1443 """ 1444 test_ascii_formatd 1099 1445 test_bsddb 1100 1446 test_bsddb3 … … 1108 1454 test_pep277 1109 1455 test_tcl 1456 test_tk 1457 test_ttk_guionly 1458 test_ttk_textonly 1110 1459 test_multiprocessing 1111 1460 """, 1112 1461 'netbsd3': 1113 1462 """ 1463 test_ascii_formatd 1114 1464 test_bsddb 1115 1465 test_bsddb185 … … 1124 1474 test_pep277 1125 1475 test_tcl 1476 test_tk 1477 test_ttk_guionly 1478 test_ttk_textonly 1126 1479 test_multiprocessing 1127 1480 """, … … 1148 1501 self.expected.add('test_pep277') 1149 1502 1150 try:1151 from test import test_socket_ssl1152 except ImportError:1153 pass1154 else:1155 if test_socket_ssl.skip_expected:1156 self.expected.add('test_socket_ssl')1157 1158 1503 if test_timeout.skip_expected: 1159 1504 self.expected.add('test_timeout') … … 1162 1507 self.expected.add('test_imageop') 1163 1508 1164 if not sys.platform in ("mac", "darwin"):1509 if sys.platform != "darwin": 1165 1510 MAC_ONLY = ["test_macos", "test_macostools", "test_aepack", 1166 1511 "test_plistlib", "test_scriptpackages", … … 1177 1522 WIN_ONLY = ["test_unicode_file", "test_winreg", 1178 1523 "test_winsound", "test_startfile", 1179 "test_sqlite" ]1524 "test_sqlite", "test_msilib"] 1180 1525 for skip in WIN_ONLY: 1181 1526 self.expected.add(skip) … … 1210 1555 1211 1556 if __name__ == '__main__': 1212 # Remove regrtest.py's own directory from the module search path. This 1213 # prevents relative imports from working, and relative imports will screw 1214 # up the testing framework. E.g. if both test.test_support and 1215 # test_support are imported, they will not contain the same globals, and 1216 # much of the testing framework relies on the globals in the 1217 # test.test_support module. 1218 mydir = os.path.abspath(os.path.normpath(os.path.dirname(sys.argv[0]))) 1219 i = len(sys.path) 1220 while i >= 0: 1221 i -= 1 1222 if os.path.abspath(os.path.normpath(sys.path[i])) == mydir: 1223 del sys.path[i] 1224 main() 1557 # findtestdir() gets the dirname out of __file__, so we have to make it 1558 # absolute before changing the working directory. 1559 # For example __file__ may be relative when running trace or profile. 1560 # See issue #9323. 1561 __file__ = os.path.abspath(__file__) 1562 1563 # sanity check 1564 assert __file__ == os.path.abspath(sys.argv[0]) 1565 1566 # When tests are run from the Python build directory, it is best practice 1567 # to keep the test files in a subfolder. It eases the cleanup of leftover 1568 # files using command "make distclean". 1569 if sysconfig.is_python_build(): 1570 TEMPDIR = os.path.join(sysconfig.get_config_var('srcdir'), 'build') 1571 TEMPDIR = os.path.abspath(TEMPDIR) 1572 if not os.path.exists(TEMPDIR): 1573 os.mkdir(TEMPDIR) 1574 1575 # Define a writable temp dir that will be used as cwd while running 1576 # the tests. The name of the dir includes the pid to allow parallel 1577 # testing (see the -j option). 1578 TESTCWD = 'test_python_{}'.format(os.getpid()) 1579 1580 TESTCWD = os.path.join(TEMPDIR, TESTCWD) 1581 1582 # Run the tests in a context manager that temporary changes the CWD to a 1583 # temporary and writable directory. If it's not possible to create or 1584 # change the CWD, the original CWD will be used. The original CWD is 1585 # available from test_support.SAVEDCWD. 1586 with test_support.temp_cwd(TESTCWD, quiet=True): 1587 main()
Note:
See TracChangeset
for help on using the changeset viewer.