Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/test/regrtest.py

    r10 r391  
    11#! /usr/bin/env python
    22
    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"""
     4Usage:
     5
     6python -m test.regrtest [options] [test_name1 [test_name2 ...]]
     7python path/to/Lib/test/regrtest.py [options] [test_name1 [test_name2 ...]]
     8
     9
     10If no arguments or options are provided, finds all files matching
     11the pattern "test_*" in the Lib/test subdirectory and runs
     12them in alphabetical order (but see -M and -u, below, for exceptions).
     13
     14For more rigorous testing, it is useful to use the following
     15command line:
     16
     17python -E -tt -Wd -3 -m test.regrtest [options] [test_name1 ...]
     18
     19
     20Options:
     21
     22-h/--help       -- print this text and exit
     23
     24Verbosity
     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
     33Selecting 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
     45Special 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
     62Additional Option Details:
     63
     64-r randomizes test execution order. You can use --randseed=int to provide a
     65int seed value for the randomizer; this is useful for reproducing troublesome
     66test orders.
     67
     68-s On the first invocation of regrtest using -s, the first test file found
     69or the first test file given on the command line is run, and the name of
     70the next test is recorded in a file named pynexttest.  If run from the
     71Python build directory, pynexttest is located in the 'build' subdirectory,
     72otherwise it is located in tempfile.gettempdir().  On subsequent runs,
     73the test in pynexttest is run, and the next test is written to pynexttest.
     74When the last test has been run, pynexttest is deleted.  In this way it
     75is possible to single step through the test files.  This is useful when
     76doing memory analysis on the Python interpreter, which process tends to
     77consume too many resources to run the full regression test non-stop.
    4778
    4879-f reads the names of tests from the file given as f's argument, one
     
    6192of times further it is run and 'fname' is the name of the file the
    6293reports 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 :'.
    6495
    6596-M runs tests that require an exorbitant amount of memory. These tests
     
    92123                state and output modes.
    93124
    94     lib2to3 -   Run the tests for 2to3 (They take a while.)
    95 
    96125    largefile - It is okay to run some test that may create huge
    97126                files.  These tests can take a long time and may
     
    107136                verifies compliance with standards.
    108137
    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.
    114139
    115140    subprocess  Run all tests for the subprocess module.
    116141
    117142    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.
    118149
    119150To enable all resources except one, use '-uall,-<resource>'.  For
     
    122153"""
    123154
    124 import cStringIO
     155import StringIO
    125156import getopt
     157import json
    126158import os
    127159import random
    128160import re
     161import shutil
    129162import sys
    130163import time
    131164import traceback
    132165import 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)
     166import unittest
     167import tempfile
     168import imp
     169import platform
     170import 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.
     183for 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
    151189
    152190# MacOSX (a.k.a. Darwin) has a default stack size that is too small
     
    166204        resource.setrlimit(resource.RLIMIT_STACK, (newsoft, hard))
    167205
     206# Test result constants.
     207PASSED = 1
     208FAILED = 0
     209ENV_CHANGED = -1
     210SKIPPED = -2
     211RESOURCE_DENIED = -3
     212INTERRUPTED = -4
     213
    168214from test import test_support
    169215
    170216RESOURCE_NAMES = ('audio', 'curses', 'largefile', 'network', 'bsddb',
    171                   'decimal', 'compiler', 'subprocess', 'urlfetch')
     217                  'decimal', 'cpu', 'subprocess', 'urlfetch', 'gui',
     218                  'xpickle')
     219
     220TEMPDIR = os.path.abspath(tempfile.gettempdir())
    172221
    173222
     
    181230         exclude=False, single=False, randomize=False, fromfile=None,
    182231         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):
    184235    """Execute a test suite.
    185236
     
    199250
    200251    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.
    204256    """
    205257
    206258    test_support.record_original_stdout(sys.stdout)
    207259    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'])
    215266    except getopt.error, msg:
    216267        usage(2, msg)
    217268
    218269    # Defaults
     270    if random_seed is None:
     271        random_seed = random.randrange(10000000)
    219272    if use_resources is None:
    220273        use_resources = []
     
    226279        elif o in ('-w', '--verbose2'):
    227280            verbose2 = True
     281        elif o in ('-W', '--verbose3'):
     282            verbose3 = True
    228283        elif o in ('-q', '--quiet'):
    229284            quiet = True;
     
    237292        elif o in ('-r', '--randomize'):
    238293            randomize = True
     294        elif o == '--randseed':
     295            random_seed = int(a)
    239296        elif o in ('-f', '--fromfile'):
    240297            fromfile = a
     
    254311        elif o in ('-R', '--huntrleaks'):
    255312            huntrleaks = a.split(':')
    256             if len(huntrleaks) != 3:
     313            if len(huntrleaks) not in (2, 3):
    257314                print a, huntrleaks
    258                 usage(2, '-R takes three colon-separated arguments')
    259             if len(huntrleaks[0]) == 0:
     315                usage(2, '-R takes 2 or 3 colon-separated arguments')
     316            if not huntrleaks[0]:
    260317                huntrleaks[0] = 5
    261318            else:
    262319                huntrleaks[0] = int(huntrleaks[0])
    263             if len(huntrleaks[1]) == 0:
     320            if not huntrleaks[1]:
    264321                huntrleaks[1] = 4
    265322            else:
    266323                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"]
    269326        elif o in ('-M', '--memlimit'):
    270327            test_support.set_memlimit(a)
     
    286343                elif r not in use_resources:
    287344                    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)
    288360        else:
    289             print >>sys.stderr, ("No handler for option {0}.  Please "
     361            print >>sys.stderr, ("No handler for option {}.  Please "
    290362                "report this as a bug at http://bugs.python.org.").format(o)
    291363            sys.exit(1)
    292364    if single and fromfile:
    293365        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!")
    294370
    295371    good = []
     
    297373    skipped = []
    298374    resource_denieds = []
     375    environment_changed = []
     376    interrupted = False
    299377
    300378    if findleaks:
     
    312390
    313391    if single:
    314         from tempfile import gettempdir
    315         filename = os.path.join(gettempdir(), 'pynexttest')
     392        filename = os.path.join(TEMPDIR, 'pynexttest')
    316393        try:
    317394            fp = open(filename, 'r')
    318             next = fp.read().strip()
    319             tests = [next]
     395            next_test = fp.read().strip()
     396            tests = [next_test]
    320397            fp.close()
    321398        except IOError:
     
    324401    if fromfile:
    325402        tests = []
    326         fp = open(fromfile)
     403        fp = open(os.path.join(test_support.SAVEDCWD, fromfile))
    327404        for line in fp:
    328405            guts = line.split() # assuming no test has whitespace in its name
     
    332409
    333410    # 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)
    338413
    339414    stdtests = STDTESTS[:]
    340     nottests = NOTTESTS[:]
     415    nottests = NOTTESTS.copy()
    341416    if exclude:
    342417        for arg in args:
    343418            if arg in stdtests:
    344419                stdtests.remove(arg)
    345         nottests[:0] = args
     420            nottests.add(arg)
    346421        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
    348435    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
    350441    if randomize:
    351         random.shuffle(tests)
     442        random.seed(random_seed)
     443        print "Using random seed", random_seed
     444        random.shuffle(selected)
    352445    if trace:
    353446        import trace
    354447        tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix],
    355448                             trace=False, count=True)
     449
    356450    test_times = []
    357     test_support.verbose = verbose      # Tell tests to be moderately quiet
    358451    test_support.use_resources = use_resources
    359452    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.
    371503            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))
    379529                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())
    384565            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)
    407598    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:
    409600            print "All",
    410601        print count(len(good), "test"), "OK."
     
    415606            print "%s: %.1fs" % (test, time)
    416607    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)
    419616    if skipped and not quiet:
    420617        print count(len(skipped), "test"), "skipped:"
     
    442639            try:
    443640                test_support.verbose = True
    444                 ok = runtest(test, True, quiet, test_times, testdir,
    445                              huntrleaks)
     641                ok = runtest(test, True, quiet, huntrleaks)
    446642            except KeyboardInterrupt:
    447643                # print a newline separate from the ^C
     
    452648
    453649    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')
    464653        else:
    465654            os.unlink(filename)
     
    472661        os.system("leaks %d" % os.getpid())
    473662
    474     sys.exit(len(bad) > 0)
     663    sys.exit(len(bad) > 0 or interrupted)
    475664
    476665
     
    485674    'test_doctest',
    486675    'test_doctest2',
    487    ]
    488 
    489 NOTTESTS = [
     676]
     677
     678NOTTESTS = {
    490679    'test_support',
    491680    'test_future1',
    492681    'test_future2',
    493     ]
     682}
    494683
    495684def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
    496685    """Return a list of all applicable test modules."""
    497     if not testdir: testdir = findtestdir()
     686    testdir = findtestdir(testdir)
    498687    names = os.listdir(testdir)
    499688    tests = []
     689    others = set(stdtests) | nottests
    500690    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
     696def runtest(test, verbose, quiet,
     697            huntrleaks=False, use_resources=None):
    510698    """Run a single test.
    511699
     
    514702    quiet -- if true, don't print 'skipped' messages (probably redundant)
    515703    test_times -- a list of (time, test_name) pairs
    516     testdir -- test directory
    517704    huntrleaks -- run multiple times to test for leaks; requires a debug
    518705                  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
    524713    """
    525714
     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
    526718    try:
    527         return runtest_inner(test, verbose, quiet, test_times,
    528                              testdir, huntrleaks)
     719        return runtest_inner(test, verbose, quiet, huntrleaks)
    529720    finally:
    530721        cleanup_test_droppings(test, verbose)
    531722
    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
     732class 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
     869def runtest_inner(test, verbose, quiet, huntrleaks=False):
    534870    test_support.unload(test)
    535     if not testdir:
    536         testdir = findtestdir()
    537871    if verbose:
    538872        capture_stdout = None
    539873    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.
    542878    try:
    543879        save_stdout = sys.stdout
     
    550886                # Always import it from the test package
    551887                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
    565902        finally:
    566903            sys.stdout = save_stdout
     
    569906            print test, "skipped --", msg
    570907            sys.stdout.flush()
    571         return -2
    572     except (ImportError, test_support.TestSkipped), msg:
     908        return RESOURCE_DENIED, test_time
     909    except unittest.SkipTest, msg:
    573910        if not quiet:
    574911            print test, "skipped --", msg
    575912            sys.stdout.flush()
    576         return -1
     913        return SKIPPED, test_time
    577914    except KeyboardInterrupt:
    578915        raise
    579916    except test_support.TestFailed, msg:
    580         print "test", test, "failed --", msg
    581         sys.stdout.flush()
    582         return 0
     917        print >>sys.stderr, "test", test, "failed --", msg
     918        sys.stderr.flush()
     919        return FAILED, test_time
    583920    except:
    584921        type, value = sys.exc_info()[:2]
    585         print "test", test, "crashed --", str(type) + ":", value
    586         sys.stdout.flush()
     922        print >>sys.stderr, "test", test, "crashed --", str(type) + ":", value
     923        sys.stderr.flush()
    587924        if verbose:
    588             traceback.print_exc(file=sys.stdout)
    589             sys.stdout.flush()
    590         return 0
     925            traceback.print_exc(file=sys.stderr)
     926            sys.stderr.flush()
     927        return FAILED, test_time
    591928    else:
     929        if refleak:
     930            return FAILED, test_time
     931        if environment.changed:
     932            return ENV_CHANGED, test_time
    592933        # Except in verbose mode, tests should not print anything
    593934        if verbose or huntrleaks:
    594             return 1
     935            return PASSED, test_time
    595936        output = capture_stdout.getvalue()
    596937        if not output:
    597             return 1
     938            return PASSED, test_time
    598939        print "test", test, "produced unexpected output:"
    599940        print "*" * 70
     
    601942        print "*" * 70
    602943        sys.stdout.flush()
    603         return 0
     944        return FAILED, test_time
    604945
    605946def 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()
    607952
    608953    # Try to clean up junk commonly left behind.  While tests shouldn't leave
     
    629974            print "%r left behind %s %r" % (testname, kind, name)
    630975        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)
    631980            nuker(name)
    632981        except Exception, msg:
     
    635984
    636985def 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    """
    637991    # This code is hackish and inelegant, but it seems to do the job.
    638     import copy_reg, _abcoll, io
     992    import copy_reg, _abcoll, _pyio
    639993
    640994    if not hasattr(sys, 'gettotalrefcount'):
     
    6461000    ps = copy_reg.dispatch_table.copy()
    6471001    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()
    6481008    abcs = {}
    649     modules = _abcoll, io
     1009    modules = _abcoll, _pyio
    6501010    for abc in [getattr(mod, a) for mod in modules for a in mod.__all__]:
    6511011        # XXX isinstance(abc, ABCMeta) leads to infinite recursion
     
    6601020    else:
    6611021        def run_the_test():
    662             reload(the_module)
     1022            imp.reload(the_module)
    6631023
    6641024    deltas = []
    6651025    nwarmup, ntracked, fname = huntrleaks
     1026    fname = os.path.join(test_support.SAVEDCWD, fname)
    6661027    repcount = nwarmup + ntracked
    6671028    print >> sys.stderr, "beginning", repcount, "repetitions"
    6681029    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)
    6701031    for i in range(repcount):
    671         rc = sys.gettotalrefcount()
     1032        rc_before = sys.gettotalrefcount()
    6721033        run_the_test()
    6731034        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()
    6751037        if i >= nwarmup:
    676             deltas.append(sys.gettotalrefcount() - rc - 2)
     1038            deltas.append(rc_after - rc_before)
    6771039    print >> sys.stderr
    6781040    if any(deltas):
    6791041        msg = '%s leaked %s references, sum=%s' % (test, deltas, sum(deltas))
    6801042        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
     1049def dash_R_cleanup(fs, ps, pic, zdc, abcs):
    6861050    import gc, copy_reg
    6871051    import _strptime, linecache
     
    7021066    sys.path_importer_cache.clear()
    7031067    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)
    7041075
    7051076    # clear type cache
     
    7251096    struct._clearcache()
    7261097    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()
    7271105
    7281106    # Collect cyclic trash.
    7291107    gc.collect()
    7301108
    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
     1109def findtestdir(path=None):
     1110    return path or os.path.dirname(__file__) or os.curdir
     1111
     1112def 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
    7431119
    7441120def count(n, word):
     
    7581134    from textwrap import fill
    7591135    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,
    7611138               initial_indent=blanks, subsequent_indent=blanks)
    7621139
     
    7681145#         The _ExpectedSkips constructor adds this to the set of expected
    7691146#         skips if not os.path.supports_unicode_filenames.
    770 #     test_socket_ssl
    771 #         Controlled by test_socket_ssl.skip_expected.  Requires the network
    772 #         resource, and a socket module with ssl support.
    7731147#     test_timeout
    7741148#         Controlled by test_timeout.skip_expected.  Requires the network
     
    8211195        test_ossaudiodev
    8221196        """,
    823    'mac':
    824         """
    825         test_atexit
    826         test_bsddb
    827         test_bsddb185
    828         test_bsddb3
    829         test_bz2
    830         test_commands
    831         test_crypt
    832         test_curses
    833         test_dbm
    834         test_dl
    835         test_fcntl
    836         test_fork1
    837         test_epoll
    838         test_grp
    839         test_ioctl
    840         test_largefile
    841         test_locale
    842         test_kqueue
    843         test_mmap
    844         test_openpty
    845         test_ossaudiodev
    846         test_poll
    847         test_popen
    848         test_popen2
    849         test_posix
    850         test_pty
    851         test_pwd
    852         test_resource
    853         test_signal
    854         test_sundry
    855         test_tarfile
    856         test_timing
    857         """,
    8581197    'unixware7':
    8591198        """
     
    9471286        test_curses
    9481287        test_epoll
     1288        test_gdb
    9491289        test_gdbm
    9501290        test_largefile
     
    10721412        test_pep277
    10731413        test_pty
    1074         test_socket_ssl
    10751414        test_socketserver
    10761415        test_tcl
     1416        test_tk
     1417        test_ttk_guionly
     1418        test_ttk_textonly
    10771419        test_timeout
    10781420        test_urllibnet
     
    10921434        test_ossaudiodev
    10931435        test_tcl
     1436        test_tk
     1437        test_ttk_guionly
     1438        test_ttk_textonly
    10941439        test_zipimport
    10951440        test_zlib
     
    10971442    'openbsd3':
    10981443        """
     1444        test_ascii_formatd
    10991445        test_bsddb
    11001446        test_bsddb3
     
    11081454        test_pep277
    11091455        test_tcl
     1456        test_tk
     1457        test_ttk_guionly
     1458        test_ttk_textonly
    11101459        test_multiprocessing
    11111460        """,
    11121461    'netbsd3':
    11131462        """
     1463        test_ascii_formatd
    11141464        test_bsddb
    11151465        test_bsddb185
     
    11241474        test_pep277
    11251475        test_tcl
     1476        test_tk
     1477        test_ttk_guionly
     1478        test_ttk_textonly
    11261479        test_multiprocessing
    11271480        """,
     
    11481501                self.expected.add('test_pep277')
    11491502
    1150             try:
    1151                 from test import test_socket_ssl
    1152             except ImportError:
    1153                 pass
    1154             else:
    1155                 if test_socket_ssl.skip_expected:
    1156                     self.expected.add('test_socket_ssl')
    1157 
    11581503            if test_timeout.skip_expected:
    11591504                self.expected.add('test_timeout')
     
    11621507                self.expected.add('test_imageop')
    11631508
    1164             if not sys.platform in ("mac", "darwin"):
     1509            if sys.platform != "darwin":
    11651510                MAC_ONLY = ["test_macos", "test_macostools", "test_aepack",
    11661511                            "test_plistlib", "test_scriptpackages",
     
    11771522                WIN_ONLY = ["test_unicode_file", "test_winreg",
    11781523                            "test_winsound", "test_startfile",
    1179                             "test_sqlite"]
     1524                            "test_sqlite", "test_msilib"]
    11801525                for skip in WIN_ONLY:
    11811526                    self.expected.add(skip)
     
    12101555
    12111556if __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.