diff options
author | William Deegan <bill@baddogconsulting.com> | 2023-05-09 12:48:42 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-09 12:48:42 -0700 |
commit | 39285a666b3a2ca2c84c57a670a4a00833a2d814 (patch) | |
tree | 08379e7d0496dafab1aed2e5f7974044947da316 | |
parent | fcb92c4ff1503ac0cf920d26f771b8f47386f4dc (diff) | |
parent | faa271d1dd379d5fe46ca2742f5a83e54ea4f36c (diff) | |
download | scons-git-39285a666b3a2ca2c84c57a670a4a00833a2d814.tar.gz |
Merge pull request #4340 from mwichmann/test/runtest-pathlib
Use pathlib in runtest
-rw-r--r-- | CHANGES.txt | 2 | ||||
-rw-r--r-- | RELEASE.txt | 6 | ||||
-rwxr-xr-x | runtest.py | 126 | ||||
-rw-r--r-- | test/runtest/SCons.py | 17 | ||||
-rw-r--r-- | test/runtest/baseline/combined.py | 29 | ||||
-rw-r--r-- | test/runtest/baseline/fail.py | 27 | ||||
-rw-r--r-- | test/runtest/baseline/no_result.py | 38 | ||||
-rw-r--r-- | test/runtest/baseline/pass.py | 17 | ||||
-rw-r--r-- | test/runtest/faillog.py | 17 | ||||
-rw-r--r-- | test/runtest/no_faillog.py | 26 | ||||
-rw-r--r-- | test/runtest/pathseps.py | 78 | ||||
-rw-r--r-- | test/runtest/print_time.py | 28 | ||||
-rw-r--r-- | test/runtest/python.py | 25 | ||||
-rw-r--r-- | test/runtest/retry.py | 22 | ||||
-rw-r--r-- | test/runtest/simple/combined.py | 28 | ||||
-rw-r--r-- | test/runtest/simple/fail.py | 25 | ||||
-rw-r--r-- | test/runtest/simple/no_result.py | 31 | ||||
-rw-r--r-- | test/runtest/simple/pass.py | 18 | ||||
-rw-r--r-- | test/runtest/testargv.py | 42 | ||||
-rw-r--r-- | test/runtest/testlistfile.py | 24 | ||||
-rw-r--r-- | test/runtest/xml/output.py | 32 |
21 files changed, 364 insertions, 294 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index d4ad973a0..5ad76b8de 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -23,6 +23,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER calls dunder method __call__. Invoke instance directly." - Python 3.9 dropped the alias base64.decodestring, deprecated since 3.1. Only used in msvs.py. Use base64.decodebytes instead. + - SCons test runner now uses pathlib to normalize and compare paths + to test files. RELEASE 4.5.2 - Sun, 21 Mar 2023 14:08:29 -0700 diff --git a/RELEASE.txt b/RELEASE.txt index c2244f27b..bafda4777 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -64,7 +64,11 @@ DOCUMENTATION DEVELOPMENT ----------- -- List visible changes in the way SCons is developed +- SCons test runner now uses pathlib to normalize and compare paths + to test files, which allows test lists, exclude lists, and tests on + the command line to "not care" about the OS convention for pathname + separators. + Thanks to the following contributors listed below for their contributions to this release. ========================================================================================== diff --git a/runtest.py b/runtest.py index a2ece7ee9..46cdc7b81 100755 --- a/runtest.py +++ b/runtest.py @@ -14,22 +14,17 @@ This script adds SCons/ and testing/ directories to PYTHONPATH, performs test discovery and processes tests according to options. """ -# TODO: normalize requested and testlist/exclude paths for easier comparison. -# e.g.: "runtest foo/bar" on windows will produce paths like foo/bar\test.py -# this is hard to match with excludelists, and makes those both os.sep-specific -# and command-line-typing specific. - import argparse -import glob +import itertools import os -import stat import subprocess import sys import tempfile import threading import time from abc import ABC, abstractmethod -from pathlib import Path +from io import StringIO +from pathlib import Path, PurePath, PureWindowsPath from queue import Queue cwd = os.getcwd() @@ -39,7 +34,7 @@ scons = None catch_output = False suppress_output = False -script = os.path.basename(sys.argv[0]) +script = PurePath(sys.argv[0]).name usagestr = """\ %(script)s [OPTIONS] [TEST ...] """ % locals() @@ -388,11 +383,13 @@ else: class RuntestBase(ABC): """ Base class for tests """ - def __init__(self, path, num, spe=None): - self.path = path - self.num = num + _ids = itertools.count(1) # to geenerate test # automatically + + def __init__(self, path, spe=None): + self.path = str(path) + self.testno = next(self._ids) self.stdout = self.stderr = self.status = None - self.abspath = os.path.abspath(path) + self.abspath = path.absolute() self.command_args = [] self.command_str = "" self.test_time = self.total_time = 0 @@ -404,7 +401,7 @@ class RuntestBase(ABC): break @abstractmethod - def execute(self): + def execute(self, env): pass @@ -547,7 +544,7 @@ if sys.platform == 'win32': # Windows doesn't support "shebang" lines directly (the Python launcher # and Windows Store version do, but you have to get them launched first) # so to directly launch a script we depend on an assoc for .py to work. - # Some systems may have none, and in some cases IDE programs take over + # Some systems may have none, and in some cases IDE programs take over # the assoc. Detect this so the small number of tests affected can skip. try: python_assoc = get_template_command('.py') @@ -564,7 +561,7 @@ if '_JAVA_OPTIONS' in os.environ: # ---[ test discovery ]------------------------------------ -# This section figures which tests to run. +# This section figures out which tests to run. # # The initial testlist is made by reading from the testlistfile, # if supplied, or by looking at the test arguments, if supplied, @@ -587,10 +584,15 @@ if '_JAVA_OPTIONS' in os.environ: # Test exclusions, if specified, are then applied. -def scanlist(testlist): +def scanlist(testfile): """ Process a testlist file """ - tests = [t.strip() for t in testlist if not t.startswith('#')] - return [t for t in tests if t] + data = StringIO(testfile.read_text()) + tests = [t.strip() for t in data.readlines() if not t.startswith('#')] + # in order to allow scanned lists to work whether they use forward or + # backward slashes, first create the object as a PureWindowsPath which + # accepts either, then use that to make a Path object to use for + # comparisons like "file in scanned_list". + return [Path(PureWindowsPath(t)) for t in tests if t] def find_unit_tests(directory): @@ -602,7 +604,8 @@ def find_unit_tests(directory): continue for fname in filenames: if fname.endswith("Tests.py"): - result.append(os.path.join(dirpath, fname)) + result.append(Path(dirpath, fname)) + return sorted(result) @@ -617,79 +620,74 @@ def find_e2e_tests(directory): # Slurp in any tests in exclude lists excludes = [] if ".exclude_tests" in filenames: - p = Path(dirpath).joinpath(".exclude_tests") - # TODO simplify when Py3.5 dropped - if sys.version_info.major == 3 and sys.version_info.minor < 6: - excludefile = p.resolve() - else: - excludefile = p.resolve(strict=True) - with excludefile.open() as f: - excludes = scanlist(f) + excludefile = Path(dirpath, ".exclude_tests").resolve() + excludes = scanlist(excludefile) for fname in filenames: - if fname.endswith(".py") and fname not in excludes: - result.append(os.path.join(dirpath, fname)) + if fname.endswith(".py") and Path(fname) not in excludes: + result.append(Path(dirpath, fname)) return sorted(result) # initial selection: +# if we have a testlist file read that, else hunt for tests. unittests = [] endtests = [] if args.testlistfile: - with args.testlistfile.open() as f: - tests = scanlist(f) + tests = scanlist(args.testlistfile) else: testpaths = [] - if args.all: - testpaths = ['SCons', 'test'] - elif args.testlist: - testpaths = args.testlist - - for tp in testpaths: - # Clean up path so it can match startswith's below - # remove leading ./ or .\ - if tp.startswith('.') and tp[1] in (os.sep, os.altsep): - tp = tp[2:] - - for path in glob.glob(tp): - if os.path.isdir(path): - if path.startswith(('SCons', 'testing')): + if args.all: # -a flag + testpaths = [Path('SCons'), Path('test')] + elif args.testlist: # paths given on cmdline + testpaths = [Path(PureWindowsPath(t)) for t in args.testlist] + + for path in testpaths: + # Clean up path removing leading ./ or .\ + name = str(path) + if name.startswith('.') and name[1] in (os.sep, os.altsep): + path = path.with_name(tn[2:]) + + if path.exists(): + if path.is_dir(): + if path.parts[0] == "SCons" or path.parts[0] == "testing": unittests.extend(find_unit_tests(path)) - elif path.startswith('test'): + elif path.parts[0] == 'test': endtests.extend(find_e2e_tests(path)) + # else: TODO: what if user pointed to a dir outside scons tree? else: - if path.endswith("Tests.py"): + if path.match("*Tests.py"): unittests.append(path) - elif path.endswith(".py"): + elif path.match("*.py"): endtests.append(path) - tests = sorted(unittests + endtests) + tests = sorted(unittests + endtests) # Remove exclusions: if args.e2e_only: - tests = [t for t in tests if not t.endswith("Tests.py")] + tests = [t for t in tests if not t.match("*Tests.py")] if args.unit_only: - tests = [t for t in tests if t.endswith("Tests.py")] + tests = [t for t in tests if t.match("*Tests.py")] if args.excludelistfile: - with args.excludelistfile.open() as f: - excludetests = scanlist(f) + excludetests = scanlist(args.excludelistfile) tests = [t for t in tests if t not in excludetests] +# did we end up with any tests? if not tests: sys.stderr.write(parser.format_usage() + """ -error: no tests were found. - Tests can be specified on the command line, read from a file with - the -f/--file option, or discovered with -a/--all to run all tests. +error: no tests matching the specification were found. + See "Test selection options" in the help for details on + how to specify and/or exclude tests. """) sys.exit(1) # ---[ test processing ]----------------------------------- -tests = [Test(t, n + 1) for n, t in enumerate(tests)] +tests = [Test(t) for t in tests] if args.list_only: for t in tests: - sys.stdout.write(t.path + "\n") + print(t.path) sys.exit(0) if not args.python: @@ -702,7 +700,7 @@ os.environ["python_executable"] = args.python if args.print_times: def print_time(fmt, tm): - sys.stdout.write(fmt % tm) + print(fmt % tm) else: @@ -739,7 +737,7 @@ def log_result(t, io_lock=None): print(t.stdout) if t.stderr: print(t.stderr) - print_time("Test execution time: %.1f seconds\n", t.test_time) + print_time("Test execution time: %.1f seconds", t.test_time) finally: if io_lock: io_lock.release() @@ -778,8 +776,8 @@ def run_test(t, io_lock=None, run_async=True): if args.printcommand: if args.print_progress: t.headline += "%d/%d (%.2f%s) %s\n" % ( - t.num, total_num_tests, - float(t.num) * 100.0 / float(total_num_tests), + t.testno, total_num_tests, + float(t.testno) * 100.0 / float(total_num_tests), "%", t.command_str, ) @@ -843,7 +841,7 @@ else: # --- all tests are complete by the time we get here --- if tests: tests[0].total_time = time_func() - total_start_time - print_time("Total execution time for all tests: %.1f seconds\n", tests[0].total_time) + print_time("Total execution time for all tests: %.1f seconds", tests[0].total_time) passed = [t for t in tests if t.status == 0] fail = [t for t in tests if t.status == 1] diff --git a/test/runtest/SCons.py b/test/runtest/SCons.py index 20c4c6418..fc4c3e06c 100644 --- a/test/runtest/SCons.py +++ b/test/runtest/SCons.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Verify that we find tests under the SCons/ tree only if they end @@ -46,17 +45,17 @@ test.write_passing_test(['SCons', 'passTests.py']) test.write_passing_test(['SCons', 'suite', 'pass.py']) test.write_passing_test(['SCons', 'suite', 'passTests.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(src_passTests_py)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {src_passTests_py} PASSING TEST STDOUT -%(pythonstring)s%(pythonflags)s %(src_suite_passTests_py)s +{pythonstring}{pythonflags} {src_suite_passTests_py} PASSING TEST STDOUT -""" % locals() +""" expect_stderr = """\ PASSING TEST STDERR PASSING TEST STDERR -""" % locals() +""" test.run(arguments='-k SCons', stdout=expect_stdout, stderr=expect_stderr) diff --git a/test/runtest/baseline/combined.py b/test/runtest/baseline/combined.py index 228d42d1a..00ce85bdf 100644 --- a/test/runtest/baseline/combined.py +++ b/test/runtest/baseline/combined.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test a combination of a passing test, failing test, and no-result @@ -42,27 +41,24 @@ test_pass_py = os.path.join('test', 'pass.py') test = TestRuntest.TestRuntest() test.subdir('test') - test.write_failing_test(['test', 'fail.py']) - test.write_no_result_test(['test', 'no_result.py']) - test.write_passing_test(['test', 'pass.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(test_fail_py)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_fail_py} FAILING TEST STDOUT -%(pythonstring)s%(pythonflags)s %(test_no_result_py)s +{pythonstring}{pythonflags} {test_no_result_py} NO RESULT TEST STDOUT -%(pythonstring)s%(pythonflags)s %(test_pass_py)s +{pythonstring}{pythonflags} {test_pass_py} PASSING TEST STDOUT Failed the following test: -\t%(test_fail_py)s +\t{test_fail_py} NO RESULT from the following test: -\t%(test_no_result_py)s -""" % locals() +\t{test_no_result_py} +""" expect_stderr = """\ FAILING TEST STDERR @@ -70,10 +66,7 @@ NO RESULT TEST STDERR PASSING TEST STDERR """ -test.run(arguments='-k -b . test', - status=1, - stdout=expect_stdout, - stderr=expect_stderr) +test.run(arguments='-k -b . test', status=1, stdout=expect_stdout, stderr=expect_stderr) test.pass_test() diff --git a/test/runtest/baseline/fail.py b/test/runtest/baseline/fail.py index e2aff4a22..2268dce84 100644 --- a/test/runtest/baseline/fail.py +++ b/test/runtest/baseline/fail.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,38 +22,39 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test how we handle a failing test specified on the command line. """ +import os + import TestRuntest pythonstring = TestRuntest.pythonstring pythonflags = TestRuntest.pythonflags +test_fail_py = os.path.join('test', 'fail.py') test = TestRuntest.TestRuntest() test.subdir('test') - test.write_failing_test(['test', 'fail.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s test/fail.py +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_fail_py} FAILING TEST STDOUT -""" % locals() +""" expect_stderr = """\ FAILING TEST STDERR """ -test.run(arguments='-k -b . test/fail.py', - status=1, - stdout=expect_stdout, - stderr=expect_stderr) +test.run( + arguments='-k -b . test/fail.py', + status=1, + stdout=expect_stdout, + stderr=expect_stderr, +) test.pass_test() diff --git a/test/runtest/baseline/no_result.py b/test/runtest/baseline/no_result.py index d00f5364f..ce6f20cbb 100644 --- a/test/runtest/baseline/no_result.py +++ b/test/runtest/baseline/no_result.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,43 +22,45 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test how we handle a no-results test specified on the command line. """ +import os + import TestRuntest pythonstring = TestRuntest.pythonstring pythonflags = TestRuntest.pythonflags +test_no_result_py = os.path.join('test', 'no_result.py') test = TestRuntest.TestRuntest() - test.subdir('test') - test.write_no_result_test(['test', 'no_result.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s test/no_result.py +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_no_result_py} NO RESULT TEST STDOUT -""" % locals() +""" expect_stderr = """\ NO RESULT TEST STDERR """ -test.run(arguments='--no-ignore-skips -k -b . test/no_result.py', - status=2, - stdout=expect_stdout, - stderr=expect_stderr) +test.run( + arguments='--no-ignore-skips -k -b . test/no_result.py', + status=2, + stdout=expect_stdout, + stderr=expect_stderr, +) -test.run(arguments='-k -b . test/no_result.py', - status=0, - stdout=expect_stdout, - stderr=expect_stderr) +test.run( + arguments='-k -b . test/no_result.py', + status=0, + stdout=expect_stdout, + stderr=expect_stderr, +) test.pass_test() diff --git a/test/runtest/baseline/pass.py b/test/runtest/baseline/pass.py index 481fc9791..c31a6d6a8 100644 --- a/test/runtest/baseline/pass.py +++ b/test/runtest/baseline/pass.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test how we handle a passing test specified on the command line. @@ -42,18 +41,16 @@ test.subdir('test') test.write_passing_test(['test', 'pass.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(test_pass_py)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_pass_py} PASSING TEST STDOUT -""" % locals() +""" expect_stderr = """\ PASSING TEST STDERR """ -test.run(arguments='-k -b . test', - stdout=expect_stdout, - stderr=expect_stderr) +test.run(arguments='-k -b . test', stdout=expect_stdout, stderr=expect_stderr) test.pass_test() diff --git a/test/runtest/faillog.py b/test/runtest/faillog.py index e2ca67e63..f23b90bc7 100644 --- a/test/runtest/faillog.py +++ b/test/runtest/faillog.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test a list of tests in failed_tests.log to run with the --retry option @@ -42,15 +41,15 @@ test.subdir('test') test.write_failing_test(test_fail_py) test.write_passing_test(test_pass_py) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(test_fail_py)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_fail_py} FAILING TEST STDOUT -%(pythonstring)s%(pythonflags)s %(test_pass_py)s +{pythonstring}{pythonflags} {test_pass_py} PASSING TEST STDOUT Failed the following test: -\t%(test_fail_py)s -""" % locals() +\t{test_fail_py} +""" expect_stderr = """\ FAILING TEST STDERR diff --git a/test/runtest/no_faillog.py b/test/runtest/no_faillog.py index db17c8edf..174ab48c9 100644 --- a/test/runtest/no_faillog.py +++ b/test/runtest/no_faillog.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test a list of tests in failed_tests.log to run with the --retry option @@ -42,19 +41,22 @@ test.subdir('test') test.write_failing_test(test_fail_py) test.write_passing_test(test_pass_py) -test.write('failed_tests.log', """\ -%(test_fail_py)s -""" % locals()) +test.write( + 'failed_tests.log', + f"""\ +{test_fail_py} +""", +) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(test_fail_py)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_fail_py} FAILING TEST STDOUT -%(pythonstring)s%(pythonflags)s %(test_pass_py)s +{pythonstring}{pythonflags} {test_pass_py} PASSING TEST STDOUT Failed the following test: -\t%(test_fail_py)s -""" % locals() +\t{test_fail_py} +""" expect_stderr = """\ FAILING TEST STDERR diff --git a/test/runtest/pathseps.py b/test/runtest/pathseps.py new file mode 100644 index 000000000..10d86b22e --- /dev/null +++ b/test/runtest/pathseps.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Make sure different path separators don't break things. +Backslashes should be okay on POSIX, forwards slashes on win32, +and combinations should cause no problems. +""" + +import os.path + +import TestRuntest + +# the "expected" paths are generated os-native +test_one_py = os.path.join('test', 'subdir', 'test1.py') +test_two_py = os.path.join('test', 'subdir', 'test2.py') +test_three_py = os.path.join('test', 'subdir', 'test3.py') +test_four_py = os.path.join('test', 'subdir', 'test4.py') + +test = TestRuntest.TestRuntest() +# create files for discovery +testdir = "test/subdir".split("/") +test.subdir(testdir[0], testdir) +test.write_passing_test(testdir + ['test1.py']) +test.write_passing_test(testdir + ['test2.py']) +test.write_passing_test(testdir + ['test3.py']) +test.write_passing_test(testdir + ['test4.py']) + +# discover tests using testlist file with various combinations of slashes +test.write( + 'testlist.txt', + r""" +test/subdir/test1.py +test\subdir/test2.py +test/subdir\test3.py +test\subdir\test4.py +""", +) + +# expect the discovered files to all be os-native +expect_stdout = f"""\ +{test_one_py} +{test_two_py} +{test_three_py} +{test_four_py} +""" + +test.run(arguments="-k -l -f testlist.txt", stdout=expect_stdout, stderr=None) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/runtest/print_time.py b/test/runtest/print_time.py index 834d2ae45..3d49a9702 100644 --- a/test/runtest/print_time.py +++ b/test/runtest/print_time.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test a combination of a passing test, failing test, and no-result @@ -41,30 +40,30 @@ test_fail_py = re.escape(os.path.join('test', 'fail.py')) test_no_result_py = re.escape(os.path.join('test', 'no_result.py')) test_pass_py = re.escape(os.path.join('test', 'pass.py')) -test = TestRuntest.TestRuntest(match = TestCmd.match_re) +test = TestRuntest.TestRuntest(match=TestCmd.match_re) test.subdir('test') test.write_failing_test(['test', 'fail.py']) test.write_no_result_test(['test', 'no_result.py']) test.write_passing_test(['test', 'pass.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(test_fail_py)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_fail_py} FAILING TEST STDOUT Test execution time: \\d+.\\d seconds -%(pythonstring)s%(pythonflags)s %(test_no_result_py)s +{pythonstring}{pythonflags} {test_no_result_py} NO RESULT TEST STDOUT Test execution time: \\d+.\\d seconds -%(pythonstring)s%(pythonflags)s %(test_pass_py)s +{pythonstring}{pythonflags} {test_pass_py} PASSING TEST STDOUT Test execution time: \\d+.\\d seconds Total execution time for all tests: \\d+.\\d seconds Failed the following test: -\t%(test_fail_py)s +\t{test_fail_py} NO RESULT from the following test: -\t%(test_no_result_py)s -""" % locals() +\t{test_no_result_py} +""" expect_stderr = """\ FAILING TEST STDERR @@ -72,10 +71,7 @@ NO RESULT TEST STDERR PASSING TEST STDERR """ -test.run(arguments='-k -t test', - status=1, - stdout=expect_stdout, - stderr=expect_stderr) +test.run(arguments='-k -t test', status=1, stdout=expect_stdout, stderr=expect_stderr) test.pass_test() diff --git a/test/runtest/python.py b/test/runtest/python.py index abd4f0cba..dbb24ca1a 100644 --- a/test/runtest/python.py +++ b/test/runtest/python.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test that the -P option lets us specify a Python version to use. @@ -46,26 +45,26 @@ head, dir = os.path.split(head) # python version then in use, which could be different pythonflags = TestRuntest.pythonflags -# We have to normalize the python path here, because some installations don't like -# getting called with "/bin/../bin/python" as first argument, e.g. Fedora 17 Desktop. +# We have to normalize the python path here, because some installations +# don't like getting called with "/bin/../bin/python" as first argument, +# e.g. Fedora 17 Desktop. mypython = os.path.normpath(os.path.join(head, dir, os.path.pardir, dir, python)) test.subdir('test') - test.write_passing_test(['test', 'pass.py']) -expect_stdout = """\ -%(mypython)s%(pythonflags)s %(test_pass_py)s +expect_stdout = f"""\ +{mypython}{pythonflags} {test_pass_py} PASSING TEST STDOUT -""" % locals() +""" expect_stderr = """\ PASSING TEST STDERR """ -test.run(arguments=['-k','-P', mypython, 'test'], - stdout=expect_stdout, - stderr=expect_stderr) +test.run( + arguments=['-k', '-P', mypython, 'test'], stdout=expect_stdout, stderr=expect_stderr +) test.pass_test() diff --git a/test/runtest/retry.py b/test/runtest/retry.py index 4280152db..0c5beb694 100644 --- a/test/runtest/retry.py +++ b/test/runtest/retry.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test a list of tests in failed_tests.log to run with the --retry option @@ -45,14 +44,17 @@ test.write_failing_test(['test', 'fail.py']) test.write_no_result_test(['test', 'no_result.py']) test.write_passing_test(['test', 'pass.py']) -test.write('failed_tests.log', """\ -%(test_fail_py)s -""" % locals()) +test.write( + 'failed_tests.log', + f"""\ +{test_fail_py} +""", +) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(test_fail_py)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_fail_py} FAILING TEST STDOUT -""" % locals() +""" expect_stderr = """\ FAILING TEST STDERR diff --git a/test/runtest/simple/combined.py b/test/runtest/simple/combined.py index a54e57c12..e594c5048 100644 --- a/test/runtest/simple/combined.py +++ b/test/runtest/simple/combined.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test a combination of a passing test, failing test, and no-result @@ -45,20 +44,20 @@ test.write_failing_test(test_fail_py) test.write_no_result_test(test_no_result_py) test.write_passing_test(test_pass_py) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(test_fail_py)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_fail_py} FAILING TEST STDOUT -%(pythonstring)s%(pythonflags)s %(test_no_result_py)s +{pythonstring}{pythonflags} {test_no_result_py} NO RESULT TEST STDOUT -%(pythonstring)s%(pythonflags)s %(test_pass_py)s +{pythonstring}{pythonflags} {test_pass_py} PASSING TEST STDOUT Failed the following test: -\t%(test_fail_py)s +\t{test_fail_py} NO RESULT from the following test: -\t%(test_no_result_py)s -""" % locals() +\t{test_no_result_py} +""" expect_stderr = """\ FAILING TEST STDERR @@ -66,12 +65,7 @@ NO RESULT TEST STDERR PASSING TEST STDERR """ -test.run( - arguments='-k test', - status=1, - stdout=expect_stdout, - stderr=expect_stderr -) +test.run(arguments='-k test', status=1, stdout=expect_stdout, stderr=expect_stderr) test.must_exist('failed_tests.log') test.must_contain('failed_tests.log', test_fail_py) diff --git a/test/runtest/simple/fail.py b/test/runtest/simple/fail.py index f26f00e9a..5e1979a1b 100644 --- a/test/runtest/simple/fail.py +++ b/test/runtest/simple/fail.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,38 +22,35 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test how we handle a failing test specified on the command line. """ +import os + import TestRuntest pythonstring = TestRuntest.pythonstring pythonflags = TestRuntest.pythonflags +test_fail_py = os.path.join('test', 'fail.py') test = TestRuntest.TestRuntest() - test.subdir('test') - test.write_failing_test(['test', 'fail.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s test/fail.py +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_fail_py} FAILING TEST STDOUT -""" % locals() +""" expect_stderr = """\ FAILING TEST STDERR """ -test.run(arguments='-k test/fail.py', - status=1, - stdout=expect_stdout, - stderr=expect_stderr) +test.run( + arguments='-k test/fail.py', status=1, stdout=expect_stdout, stderr=expect_stderr +) test.pass_test() diff --git a/test/runtest/simple/no_result.py b/test/runtest/simple/no_result.py index 33f28e4a9..beb82b01c 100644 --- a/test/runtest/simple/no_result.py +++ b/test/runtest/simple/no_result.py @@ -27,35 +27,40 @@ Test how we handle a no-results test specified on the command line. """ +import os + import TestRuntest pythonstring = TestRuntest.pythonstring pythonflags = TestRuntest.pythonflags +test_no_result_py = os.path.join('test', 'no_result.py') test = TestRuntest.TestRuntest() - test.subdir('test') - test.write_no_result_test(['test', 'no_result.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s test/no_result.py +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_no_result_py} NO RESULT TEST STDOUT -""" % locals() +""" expect_stderr = """\ NO RESULT TEST STDERR """ -test.run(arguments='--no-ignore-skips -k test/no_result.py', - status=2, - stdout=expect_stdout, - stderr=expect_stderr) +test.run( + arguments='--no-ignore-skips -k test/no_result.py', + status=2, + stdout=expect_stdout, + stderr=expect_stderr, +) -test.run(arguments='-k test/no_result.py', - status=0, - stdout=expect_stdout, - stderr=expect_stderr) +test.run( + arguments='-k test/no_result.py', + status=0, + stdout=expect_stdout, + stderr=expect_stderr, +) test.pass_test() diff --git a/test/runtest/simple/pass.py b/test/runtest/simple/pass.py index 7ceb9a054..408ef4c28 100644 --- a/test/runtest/simple/pass.py +++ b/test/runtest/simple/pass.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,29 +22,27 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test how we handle a passing test specified on the command line. """ +import os + import TestRuntest pythonstring = TestRuntest.pythonstring pythonflags = TestRuntest.pythonflags +test_pass_py = os.path.join('test', 'pass.py') test = TestRuntest.TestRuntest() - test.subdir('test') - test.write_passing_test(['test', 'pass.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s test/pass.py +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_pass_py} PASSING TEST STDOUT -""" % locals() +""" expect_stderr = """\ PASSING TEST STDERR diff --git a/test/runtest/testargv.py b/test/runtest/testargv.py index 22e57e83b..20dcdc848 100644 --- a/test/runtest/testargv.py +++ b/test/runtest/testargv.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test subdir args for runtest.py, for example: @@ -38,34 +37,35 @@ import TestRuntest test = TestRuntest.TestRuntest() test.subdir('test', ['test', 'subdir']) -files = {} -files['pythonstring'] = TestRuntest.pythonstring -files['pythonflags'] = TestRuntest.pythonflags +pythonstring = TestRuntest.pythonstring +pythonflags = TestRuntest.pythonflags -files['one'] = os.path.join('test/subdir', 'test_one.py') -files['two'] = os.path.join('test/subdir', 'two.py') -files['three'] = os.path.join('test', 'test_three.py') +one = os.path.join('test', 'subdir', 'test_one.py') +two = os.path.join('test', 'subdir', 'two.py') +three = os.path.join('test', 'test_three.py') -test.write_passing_test(files['one']) -test.write_passing_test(files['two']) -test.write_passing_test(files['three']) +test.write_passing_test(['test', 'subdir', 'test_one.py']) +test.write_passing_test(['test', 'subdir', 'two.py']) +test.write_passing_test(['test', 'test_three.py']) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(one)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {one} PASSING TEST STDOUT -%(pythonstring)s%(pythonflags)s %(two)s +{pythonstring}{pythonflags} {two} PASSING TEST STDOUT -""" % files +""" expect_stderr = """\ PASSING TEST STDERR PASSING TEST STDERR """ -test.run(arguments = '--no-progress test/subdir', - status = 0, - stdout = expect_stdout, - stderr = expect_stderr) +test.run( + arguments='--no-progress test/subdir', + status=0, + stdout=expect_stdout, + stderr=expect_stderr, +) test.pass_test() diff --git a/test/runtest/testlistfile.py b/test/runtest/testlistfile.py index 5c956b8e3..e5d85b8dc 100644 --- a/test/runtest/testlistfile.py +++ b/test/runtest/testlistfile.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test a list of tests to run in a file specified with the -f option. @@ -46,15 +45,18 @@ test.write_failing_test(['test', 'fail.py']) test.write_no_result_test(['test', 'no_result.py']) test.write_passing_test(['test', 'pass.py']) -test.write('t.txt', """\ -#%(test_fail_py)s -%(test_pass_py)s -""" % locals()) +test.write( + 't.txt', + f"""\ +#{test_fail_py} +{test_pass_py} +""", +) -expect_stdout = """\ -%(pythonstring)s%(pythonflags)s %(test_pass_py)s +expect_stdout = f"""\ +{pythonstring}{pythonflags} {test_pass_py} PASSING TEST STDOUT -""" % locals() +""" expect_stderr = """\ PASSING TEST STDERR diff --git a/test/runtest/xml/output.py b/test/runtest/xml/output.py index cd20dbdf9..66ec6562b 100644 --- a/test/runtest/xml/output.py +++ b/test/runtest/xml/output.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test writing XML output to a file. @@ -34,8 +33,7 @@ import re import TestCmd import TestRuntest -test = TestRuntest.TestRuntest(match = TestCmd.match_re, - diff = TestCmd.diff_re) +test = TestRuntest.TestRuntest(match=TestCmd.match_re, diff=TestCmd.diff_re) pythonstring = re.escape(TestRuntest.pythonstring) pythonflags = TestRuntest.pythonflags @@ -44,22 +42,18 @@ test_no_result_py = re.escape(os.path.join('test', 'no_result.py')) test_pass_py = re.escape(os.path.join('test', 'pass.py')) test.subdir('test') - test.write_fake_scons_source_tree() - test.write_failing_test(['test', 'fail.py']) - test.write_no_result_test(['test', 'no_result.py']) - test.write_passing_test(['test', 'pass.py']) -test.run(arguments = '--xml xml.out test', status=1) +test.run(arguments='--xml xml.out test', status=1) -expect = """\ +expect = f"""\ <results> <test> - <file_name>%(test_fail_py)s</file_name> - <command_line>%(pythonstring)s%(pythonflags)s %(test_fail_py)s</command_line> + <file_name>{test_fail_py}</file_name> + <command_line>{pythonstring}{pythonflags} {test_fail_py}</command_line> <exit_status>1</exit_status> <stdout>FAILING TEST STDOUT </stdout> @@ -68,8 +62,8 @@ expect = """\ <time>\\d+\\.\\d</time> </test> <test> - <file_name>%(test_no_result_py)s</file_name> - <command_line>%(pythonstring)s%(pythonflags)s %(test_no_result_py)s</command_line> + <file_name>{test_no_result_py}</file_name> + <command_line>{pythonstring}{pythonflags} {test_no_result_py}</command_line> <exit_status>2</exit_status> <stdout>NO RESULT TEST STDOUT </stdout> @@ -78,8 +72,8 @@ expect = """\ <time>\\d+\\.\\d</time> </test> <test> - <file_name>%(test_pass_py)s</file_name> - <command_line>%(pythonstring)s%(pythonflags)s %(test_pass_py)s</command_line> + <file_name>{test_pass_py}</file_name> + <command_line>{pythonstring}{pythonflags} {test_pass_py}</command_line> <exit_status>0</exit_status> <stdout>PASSING TEST STDOUT </stdout> @@ -89,7 +83,7 @@ expect = """\ </test> <time>\\d+\\.\\d</time> </results> -""" % locals() +""" # Just strip carriage returns so the regular expression matching works. contents = test.read('xml.out') |