diff -r 5d43154d68a8 Lib/test/__main__.py --- a/Lib/test/__main__.py Sun Jul 08 21:03:01 2012 +0200 +++ b/Lib/test/__main__.py Sun Jul 08 22:32:47 2012 -0700 @@ -1,13 +1,3 @@ -from test import regrtest, support +from test import regrtest - -TEMPDIR, TESTCWD = regrtest._make_temp_dir_for_build(regrtest.TEMPDIR) -regrtest.TEMPDIR = TEMPDIR -regrtest.TESTCWD = TESTCWD - -# Run the tests in a context manager that temporary changes the CWD to a -# temporary and writable directory. If it's not possible to create or -# change the CWD, the original CWD will be used. The original CWD is -# available from support.SAVEDCWD. -with support.temp_cwd(TESTCWD, quiet=True): - regrtest.main() +regrtest.main_with_temp_cwd() diff -r 5d43154d68a8 Lib/test/regrtest.py --- a/Lib/test/regrtest.py Sun Jul 08 21:03:01 2012 +0200 +++ b/Lib/test/regrtest.py Sun Jul 08 22:32:47 2012 -0700 @@ -229,6 +229,10 @@ newsoft = min(hard, max(soft, 1024*2048)) resource.setrlimit(resource.RLIMIT_STACK, (newsoft, hard)) +# A command option used internally to ensure that temp_cwd directories are +# created in the same build folder when tests are run in multiprocess mode. +_OPTION_CWD_PARENT_DIR = 'cwdparentdir' + # Test result constants. PASSED = 1 FAILED = 0 @@ -250,6 +254,72 @@ print("Use --help for usage", file=sys.stderr) sys.exit(2) +def parse_cwd_parent_dir_option(): + """Preparse args, and return the --cwdparentdir option value. + + Returns None on error or if not specified. + + """ + try: + opts, args = parse_args() + except Exception as err: + return + for opt, val in opts: + if opt == '--' + _OPTION_CWD_PARENT_DIR: + return val + return + +def parse_args(): + opts, args = getopt.getopt(sys.argv[1:], 'hvqxsoS:rf:lu:t:TD:NLR:FdwWM:nj:Gm:', + ['help', 'verbose', 'verbose2', 'verbose3', 'quiet', + 'exclude', 'single', 'slow', 'random', 'fromfile', 'findleaks', + 'use=', 'threshold=', 'coverdir=', 'nocoverdir', + 'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=', + 'multiprocess=', 'coverage', 'slaveargs=', 'forever', 'debug', + 'start=', 'nowindows', 'header', 'testdir=', 'timeout=', 'wait', + 'failfast', 'match', _OPTION_CWD_PARENT_DIR + '=']) + return opts, args + +def _make_temp_dir_for_build(): + """Create and return a build directory. + + """ + temp_dir = os.path.join(sysconfig.get_config_var('srcdir'), 'build') + temp_dir = os.path.abspath(temp_dir) + try: + os.mkdir(temp_dir) + except FileExistsError: + pass + return temp_dir + +def main_with_temp_cwd(cwd_parent_dir=None): + """Execute a test suite in a temporary working directory. + + """ + global TEMPDIR, TESTCWD + + if cwd_parent_dir is None: + # When tests are run from the Python build directory, it is best + # practice to keep the test files in a subfolder. This simplifies + # the cleanup of leftover files using command "make distclean". + if sysconfig.is_python_build(): + TEMPDIR = _make_temp_dir_for_build() + else: + TEMPDIR = cwd_parent_dir + + # Define a writable temp dir that will be used as cwd while running + # the tests. The name of the dir includes the pid to allow parallel + # testing (see the -j option). + TESTCWD = 'test_python_{}'.format(os.getpid()) + + TESTCWD = os.path.join(TEMPDIR, TESTCWD) + + # Run the tests in a context manager that temporarily changes the CWD to + # a temporary and writable directory. If it's not possible to create or + # change the CWD, the original CWD will be used. The original CWD is + # available from support.SAVEDCWD. + with support.temp_cwd(TESTCWD, quiet=True): + main() def main(tests=None, testdir=None, verbose=0, quiet=False, exclude=False, single=False, randomize=False, fromfile=None, @@ -296,14 +366,7 @@ support.record_original_stdout(sys.stdout) try: - opts, args = getopt.getopt(sys.argv[1:], 'hvqxsoS:rf:lu:t:TD:NLR:FdwWM:nj:Gm:', - ['help', 'verbose', 'verbose2', 'verbose3', 'quiet', - 'exclude', 'single', 'slow', 'random', 'fromfile', 'findleaks', - 'use=', 'threshold=', 'coverdir=', 'nocoverdir', - 'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=', - 'multiprocess=', 'coverage', 'slaveargs=', 'forever', 'debug', - 'start=', 'nowindows', 'header', 'testdir=', 'timeout=', 'wait', - 'failfast', 'match']) + opts, args = parse_args() except getopt.error as msg: usage(msg) @@ -443,6 +506,9 @@ print() # Force a newline (just in case) print(json.dumps(result)) sys.exit(0) + elif o == '--' + _OPTION_CWD_PARENT_DIR: + # This option is incorporated prior to calling main(). + pass elif o == '--testdir': # CWD is replaced with a temporary dir before calling main(), so we # join it with the saved CWD so it ends up where the user expects. @@ -623,7 +689,8 @@ yield (test, args_tuple) pending = tests_and_args() opt_args = support.args_from_interpreter_flags() - base_cmd = [sys.executable] + opt_args + ['-m', 'test.regrtest'] + base_cmd = ([sys.executable] + opt_args + + ['-m', 'test.regrtest', '--' + _OPTION_CWD_PARENT_DIR, TEMPDIR]) def work(): # A worker thread. try: @@ -1735,26 +1802,6 @@ assert self.isvalid() return self.expected -def _make_temp_dir_for_build(TEMPDIR): - # When tests are run from the Python build directory, it is best practice - # to keep the test files in a subfolder. It eases the cleanup of leftover - # files using command "make distclean". - if sysconfig.is_python_build(): - TEMPDIR = os.path.join(sysconfig.get_config_var('srcdir'), 'build') - TEMPDIR = os.path.abspath(TEMPDIR) - try: - os.mkdir(TEMPDIR) - except FileExistsError: - pass - - # Define a writable temp dir that will be used as cwd while running - # the tests. The name of the dir includes the pid to allow parallel - # testing (see the -j option). - TESTCWD = 'test_python_{}'.format(os.getpid()) - - TESTCWD = os.path.join(TEMPDIR, TESTCWD) - return TEMPDIR, TESTCWD - if __name__ == '__main__': # Remove regrtest.py's own directory from the module search path. Despite # the elimination of implicit relative imports, this is still needed to @@ -1777,11 +1824,6 @@ # sanity check assert __file__ == os.path.abspath(sys.argv[0]) - TEMPDIR, TESTCWD = _make_temp_dir_for_build(TEMPDIR) + cwd_parent_dir = parse_cwd_parent_dir_option() - # Run the tests in a context manager that temporary changes the CWD to a - # temporary and writable directory. If it's not possible to create or - # change the CWD, the original CWD will be used. The original CWD is - # available from support.SAVEDCWD. - with support.temp_cwd(TESTCWD, quiet=True): - main() + main_with_temp_cwd(cwd_parent_dir=cwd_parent_dir) diff -r 5d43154d68a8 Misc/ACKS --- a/Misc/ACKS Sun Jul 08 21:03:01 2012 +0200 +++ b/Misc/ACKS Sun Jul 08 22:32:47 2012 -0700 @@ -505,6 +505,7 @@ Drew Jenkins Flemming Kjær Jensen MunSic Jeong +Chris Jerdonek Jim Jewett Orjan Johansen Fredrik Johansson diff -r 5d43154d68a8 Misc/NEWS --- a/Misc/NEWS Sun Jul 08 21:03:01 2012 +0200 +++ b/Misc/NEWS Sun Jul 08 22:32:47 2012 -0700 @@ -104,6 +104,9 @@ - Issue #15284: Skip {send,recv}msg tests in test_socket when IPv6 is not enabled. Patch by Brian Brazil. +- Issue #15300: Ensure the temporary test working directories are in the same + folder when running tests in multiprocess mode. Patch by Chris Jerdonek. + - Issue #15277: Fix a resource leak in support.py when IPv6 is disabled. Patch by Brian Brazil.