diff --git a/CHANGES.txt b/CHANGES.txt index 30822523c0..ed6905ba7f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -196,6 +196,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Update the User Guide Command() example which now shows a target name being created from '${SOURCE.base}.out' to use a valid special attribute and to explain what's being done in the example. + - Test framework reformatted using settings from pyproject.toml. + Includes code embedded in docstrings. From Adam Scott: - Changed Ninja's TEMPLATE rule pool to use `install_pool` instead of diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py index 4863a13c82..8e799b995d 100644 --- a/testing/framework/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -307,6 +307,7 @@ import hashlib import os import re + try: import psutil except ImportError: @@ -319,7 +320,6 @@ import subprocess import sys import tempfile -import threading import time import traceback from collections import UserList, UserString @@ -338,8 +338,6 @@ NEED_HELPER = os.environ.get('SCONS_NO_DIRECT_SCRIPT') - - # sentinel for cases where None won't do _Null = object() @@ -379,6 +377,7 @@ def to_str(s): def is_String(e): return isinstance(e, (str, UserString)) + testprefix = 'testcmd.' if os.name in ('posix', 'nt'): testprefix += f"{os.getpid()}." @@ -486,7 +485,7 @@ def fail_test( sys.exit(1) -def no_result(self=None, condition: bool=True, function=None, skip: int=0) -> None: +def no_result(self=None, condition: bool = True, function=None, skip: int = 0) -> None: """Causes a test to exit with a no result. In testing parlance NO RESULT means the test could not be completed @@ -528,7 +527,7 @@ def no_result(self=None, condition: bool=True, function=None, skip: int=0) -> No sys.exit(2) -def pass_test(self=None, condition: bool=True, function=None) -> None: +def pass_test(self=None, condition: bool = True, function=None) -> None: """Causes a test to exit with a pass. Reports that the test PASSED and exits with a status of 0, unless @@ -623,7 +622,7 @@ def match_re(lines=None, res=None): print(f"match_re: expected {len(res)} lines, found {len(lines)}") return None for i, (line, regex) in enumerate(zip(lines, res)): - s = fr"^{regex}$" + s = rf"^{regex}$" try: expr = re.compile(s) except re.error as e: @@ -653,7 +652,7 @@ def match_re_dotall(lines=None, res=None): lines = "\n".join(lines) if not isinstance(res, str): res = "\n".join(res) - s = fr"^{res}$" + s = rf"^{res}$" try: expr = re.compile(s, re.DOTALL) except re.error as e: @@ -662,8 +661,16 @@ def match_re_dotall(lines=None, res=None): return expr.match(lines) -def simple_diff(a, b, fromfile: str='', tofile: str='', - fromfiledate: str='', tofiledate: str='', n: int=0, lineterm: str=''): +def simple_diff( + a, + b, + fromfile: str = '', + tofile: str = '', + fromfiledate: str = '', + tofiledate: str = '', + n: int = 0, + lineterm: str = '', +): r"""Compare two sequences of lines; generate the delta as a simple diff. Similar to difflib.context_diff and difflib.unified_diff but @@ -712,8 +719,16 @@ def comma(x1, x2): yield f"> {l}" -def diff_re(a, b, fromfile: str='', tofile: str='', - fromfiledate: str='', tofiledate: str='', n: int=3, lineterm: str='\n'): +def diff_re( + a, + b, + fromfile: str = '', + tofile: str = '', + fromfiledate: str = '', + tofiledate: str = '', + n: int = 3, + lineterm: str = '\n', +): """Compare a and b (lists of strings) where a are regular expressions. A simple "diff" of two sets of lines when the expected lines @@ -732,7 +747,7 @@ def diff_re(a, b, fromfile: str='', tofile: str='', elif diff > 0: b = b + [''] * diff for i, (aline, bline) in enumerate(zip(a, b)): - s = fr"^{aline}$" + s = rf"^{aline}$" try: expr = re.compile(s) except re.error as e: @@ -747,6 +762,7 @@ def diff_re(a, b, fromfile: str='', tofile: str='', if os.name == 'posix': + def escape(arg): """escape shell special characters""" slash = '\\' @@ -766,6 +782,7 @@ def escape(arg): arg = f"\"{arg}\"" return arg + if os.name == 'java': python = os.path.join(sys.prefix, 'jython') else: @@ -773,7 +790,6 @@ def escape(arg): _python_ = escape(python) if sys.platform == 'win32': - default_sleep_seconds = 2 def where_is(file, path=None, pathext=None): @@ -786,7 +802,7 @@ def where_is(file, path=None, pathext=None): if is_String(pathext): pathext = pathext.split(os.pathsep) for ext in pathext: - if ext.casefold() == file[-len(ext):].casefold(): + if ext.casefold() == file[-len(ext) :].casefold(): pathext = [''] break for dir in path: @@ -837,7 +853,8 @@ def ReadFile(hFile, bufSize, ol=None): lpBuffer = ctypes.create_string_buffer(bufSize) bytesRead = DWORD() bErr = ctypes.windll.kernel32.ReadFile( - hFile, lpBuffer, bufSize, ctypes.byref(bytesRead), ol) + hFile, lpBuffer, bufSize, ctypes.byref(bytesRead), ol + ) if not bErr: raise ctypes.WinError() return (0, ctypes.string_at(lpBuffer, bytesRead.value)) @@ -846,7 +863,8 @@ def WriteFile(hFile, data, ol=None): assert ol is None bytesWritten = DWORD() bErr = ctypes.windll.kernel32.WriteFile( - hFile, data, len(data), ctypes.byref(bytesWritten), ol) + hFile, data, len(data), ctypes.byref(bytesWritten), ol + ) if not bErr: raise ctypes.WinError() return (0, bytesWritten.value) @@ -855,10 +873,12 @@ def PeekNamedPipe(hPipe, size): assert size == 0 bytesAvail = DWORD() bErr = ctypes.windll.kernel32.PeekNamedPipe( - hPipe, None, size, None, ctypes.byref(bytesAvail), None) + hPipe, None, size, None, ctypes.byref(bytesAvail), None + ) if not bErr: raise ctypes.WinError() return ("", bytesAvail.value, None) + import msvcrt else: import select @@ -882,7 +902,7 @@ def recv(self, maxsize=None): def recv_err(self, maxsize=None): return self._recv('stderr', maxsize) - def send_recv(self, input: str='', maxsize=None): + def send_recv(self, input: str = '', maxsize=None): return self.send(input), self.recv(maxsize), self.recv_err(maxsize) def get_conn_maxsize(self, which, maxsize): @@ -897,6 +917,7 @@ def _close(self, which) -> None: setattr(self, which, None) if sys.platform == 'win32': # and subprocess.mswindows: + def send(self, input): input = to_bytes(input) if not self.stdin: @@ -938,6 +959,7 @@ def _recv(self, which, maxsize): return read else: + def send(self, input): if not self.stdin: return None @@ -946,8 +968,7 @@ def send(self, input): return 0 try: - written = os.write(self.stdin.fileno(), - bytearray(input, 'utf-8')) + written = os.write(self.stdin.fileno(), bytearray(input, 'utf-8')) except OSError as why: if why.args[0] == errno.EPIPE: # broken pipe return self._close('stdin') @@ -987,7 +1008,7 @@ def _recv(self, which, maxsize): disconnect_message = "Other end disconnected!" -def recv_some(p, t: float=.1, e: int=1, tr: int=5, stderr: int=0): +def recv_some(p, t: float = 0.1, e: int = 1, tr: int = 5, stderr: int = 0): if tr < 1: tr = 1 x = time.time() + t @@ -1100,7 +1121,6 @@ def __init__( except KeyError: self.fixture_dirs = [] - def __del__(self) -> None: self.cleanup() @@ -1200,7 +1220,7 @@ def command_args(self, program=None, interpreter=None, arguments=None): return cmd def description_set(self, description) -> None: - """Set the description of the functionality being tested. """ + """Set the description of the functionality being tested.""" self.description = description def set_diff_function(self, diff=_Null, stdout=_Null, stderr=_Null) -> None: @@ -1224,9 +1244,9 @@ def diff(self, a, b, name=None, diff_function=None, *args, **kw) -> None: print(self.banner(name)) if not is_List(a): - a=a.splitlines() + a = a.splitlines() if not is_List(b): - b=b.splitlines() + b = b.splitlines() args = (a, b) + args for line in diff_function(*args, **kw): @@ -1262,7 +1282,7 @@ def fail_test( function: Callable | None = None, skip: int = 0, message: str = "", - )-> None: + ) -> None: """Cause the test to fail.""" if not condition: return @@ -1272,7 +1292,7 @@ def fail_test( condition=condition, function=function, skip=skip, - message=message + message=message, ) def interpreter_set(self, interpreter) -> None: @@ -1282,7 +1302,7 @@ def interpreter_set(self, interpreter) -> None: self.interpreter = interpreter def set_match_function(self, match=_Null, stdout=_Null, stderr=_Null) -> None: - """Sets the specified match functions. """ + """Sets the specified match functions.""" if match is not _Null: self._match_function = match if stdout is not _Null: @@ -1331,17 +1351,14 @@ def match_stdout(self, lines, matches): match_re_dotall = staticmethod(match_re_dotall) - def no_result(self, condition: bool=True, function=None, skip: int=0) -> None: + def no_result(self, condition: bool = True, function=None, skip: int = 0) -> None: """Report that the test could not be run.""" if not condition: return self.condition = 'no_result' - no_result(self=self, - condition=condition, - function=function, - skip=skip) + no_result(self=self, condition=condition, function=function, skip=skip) - def pass_test(self, condition: bool=True, function=None) -> None: + def pass_test(self, condition: bool = True, function=None) -> None: """Cause the test to pass.""" if not condition: return @@ -1369,7 +1386,7 @@ def program_set(self, program) -> None: program = os.path.join(self._cwd, program) self.program = program - def read(self, file, mode: str='rb', newline=None): + def read(self, file, mode: str = 'rb', newline=None): """Reads and returns the contents of the specified file name. The file name may be a list, in which case the elements are @@ -1401,8 +1418,7 @@ def rmdir(self, dir) -> None: dir = self.canonicalize(dir) os.rmdir(dir) - - def parse_path(self, path, suppress_current: bool=False): + def parse_path(self, path, suppress_current: bool = False): """Return a list with the single path components of path.""" head, tail = os.path.split(path) result = [] @@ -1421,7 +1437,7 @@ def parse_path(self, path, suppress_current: bool=False): return result def dir_fixture(self, srcdir, dstdir=None) -> None: - """ Copies the contents of the fixture directory to the test directory. + """Copies the contents of the fixture directory to the test directory. If srcdir is an absolute path, it is tried directly, else the fixture_dirs are searched in order to find the named fixture @@ -1470,7 +1486,7 @@ def dir_fixture(self, srcdir, dstdir=None) -> None: shutil.copy(epath, dpath) def file_fixture(self, srcfile, dstfile=None) -> None: - """ Copies a fixture file to the test directory, optionally renaming. + """Copies a fixture file to the test directory, optionally renaming. If srcfile is an absolute path, it is tried directly, else the fixture_dirs are searched in order to find the named fixture @@ -1523,13 +1539,16 @@ def file_fixture(self, srcfile, dstfile=None) -> None: shutil.copy(spath, dpath) - def start(self, program=None, - interpreter=None, - arguments=None, - universal_newlines=None, - timeout=None, - **kw) -> Popen: - """ Starts a program or script for the test environment. + def start( + self, + program=None, + interpreter=None, + arguments=None, + universal_newlines=None, + timeout=None, + **kw, + ) -> Popen: + """Starts a program or script for the test environment. The specified program will have the original directory prepended unless it is enclosed in a [list]. @@ -1568,12 +1587,14 @@ def start(self, program=None, # It seems that all pythons up to py3.6 still set text mode if you set encoding. # TODO: File enhancement request on python to propagate universal_newlines even # if encoding is set.hg c - p = Popen(cmd, - stdin=stdin, - stdout=PIPE, - stderr=stderr_value, - env=os.environ, - universal_newlines=False) + p = Popen( + cmd, + stdin=stdin, + stdout=PIPE, + stderr=stderr_value, + env=os.environ, + universal_newlines=False, + ) self.process = p return p @@ -1601,7 +1622,7 @@ def fix_binary_stream(stream): return stream.replace('\r\n', '\n') def finish(self, popen=None, **kw) -> None: - """ Finishes and waits for the process. + """Finishes and waits for the process. Process being run under control of the specified popen argument is waited for, recording the exit status, output and error output. @@ -1639,13 +1660,16 @@ def finish(self, popen=None, **kw) -> None: self._stdout.append(stdout or '') self._stderr.append(stderr or '') - def run(self, program=None, - interpreter=None, - arguments=None, - chdir=None, - stdin=None, - universal_newlines=None, - timeout=None) -> None: + def run( + self, + program=None, + interpreter=None, + arguments=None, + chdir=None, + stdin=None, + universal_newlines=None, + timeout=None, + ) -> None: """Runs a test of the program or script for the test environment. Output and error output are saved for future retrieval via @@ -1675,12 +1699,14 @@ def run(self, program=None, os.chdir(chdir) if not timeout: timeout = self.timeout - p = self.start(program=program, - interpreter=interpreter, - arguments=arguments, - universal_newlines=universal_newlines, - timeout=timeout, - stdin=stdin) + p = self.start( + program=program, + interpreter=interpreter, + arguments=arguments, + universal_newlines=universal_newlines, + timeout=timeout, + stdin=stdin, + ) if is_List(stdin): stdin = ''.join(stdin) @@ -1813,7 +1839,6 @@ def subdir(self, *subdirs): return count - def symlink(self, target, link) -> None: """Creates a symlink to the specified target. @@ -1832,7 +1857,7 @@ def symlink(self, target, link) -> None: try: os.symlink(target, link) except AttributeError: - pass # Windows has no symlink + pass # Windows has no symlink def tempdir(self, path=None): """Creates a temporary directory. @@ -1957,7 +1982,7 @@ def workpath(self, *args): """ return os.path.join(self.workdir, *args) - def readable(self, top, read: bool=True) -> None: + def readable(self, top, read: bool = True) -> None: """Makes the specified directory tree readable or unreadable. Tree is made readable if `read` evaluates True (the default), @@ -1971,23 +1996,23 @@ def readable(self, top, read: bool=True) -> None: return if read: + def do_chmod(fname) -> None: try: st = os.stat(fname) except OSError: pass else: - os.chmod(fname, stat.S_IMODE( - st.st_mode | stat.S_IREAD)) + os.chmod(fname, stat.S_IMODE(st.st_mode | stat.S_IREAD)) else: + def do_chmod(fname) -> None: try: st = os.stat(fname) except OSError: pass else: - os.chmod(fname, stat.S_IMODE( - st.st_mode & ~stat.S_IREAD)) + os.chmod(fname, stat.S_IMODE(st.st_mode & ~stat.S_IREAD)) if os.path.isfile(top): # If it's a file, that's easy, just chmod it. @@ -2024,14 +2049,15 @@ def writable(self, top, write: bool = True) -> None: """ if sys.platform == 'win32': - if write: + def do_chmod(fname) -> None: try: os.chmod(fname, stat.S_IWRITE) except OSError: pass else: + def do_chmod(fname) -> None: try: os.chmod(fname, stat.S_IREAD) @@ -2039,8 +2065,8 @@ def do_chmod(fname) -> None: pass else: - if write: + def do_chmod(fname) -> None: try: st = os.stat(fname) @@ -2049,14 +2075,14 @@ def do_chmod(fname) -> None: else: os.chmod(fname, stat.S_IMODE(st.st_mode | stat.S_IWRITE)) else: + def do_chmod(fname) -> None: try: st = os.stat(fname) except OSError: pass else: - os.chmod(fname, stat.S_IMODE( - st.st_mode & ~stat.S_IWRITE)) + os.chmod(fname, stat.S_IMODE(st.st_mode & ~stat.S_IWRITE)) if os.path.isfile(top): do_chmod(top) @@ -2066,7 +2092,7 @@ def do_chmod(fname) -> None: for name in dirnames + filenames: do_chmod(os.path.join(dirpath, name)) - def executable(self, top, execute: bool=True) -> None: + def executable(self, top, execute: bool = True) -> None: """Make the specified directory tree executable or not executable. Tree is made executable if `execute` evaluates True (the default), @@ -2080,23 +2106,23 @@ def executable(self, top, execute: bool=True) -> None: return if execute: + def do_chmod(fname) -> None: try: st = os.stat(fname) except OSError: pass else: - os.chmod(fname, stat.S_IMODE( - st.st_mode | stat.S_IEXEC)) + os.chmod(fname, stat.S_IMODE(st.st_mode | stat.S_IEXEC)) else: + def do_chmod(fname) -> None: try: st = os.stat(fname) except OSError: pass else: - os.chmod(fname, stat.S_IMODE( - st.st_mode & ~stat.S_IEXEC)) + os.chmod(fname, stat.S_IMODE(st.st_mode & ~stat.S_IEXEC)) if os.path.isfile(top): # If it's a file, that's easy, just chmod it. @@ -2121,7 +2147,7 @@ def do_chmod(fname) -> None: do_chmod(os.path.join(dirpath, name)) do_chmod(top) - def write(self, file, content, mode: str='wb'): + def write(self, file, content, mode: str = 'wb'): """Writes data to file. The file is created under the temporary working directory. @@ -2146,6 +2172,7 @@ def write(self, file, content, mode: str='wb'): except TypeError as e: f.write(bytes(content, 'utf-8')) + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/testing/framework/TestCmdTests.py b/testing/framework/TestCmdTests.py index f7a437b106..8c286f55f5 100644 --- a/testing/framework/TestCmdTests.py +++ b/testing/framework/TestCmdTests.py @@ -45,18 +45,22 @@ import TestCmd from TestCmd import _python_ + def _is_readable(path): - # XXX this doesn't take into account UID, it assumes it's our file + # TODO this doesn't take into account UID, it assumes it's our file return os.stat(path).st_mode & stat.S_IREAD + def _is_writable(path): - # XXX this doesn't take into account UID, it assumes it's our file + # TODO this doesn't take into account UID, it assumes it's our file return os.stat(path).st_mode & stat.S_IWRITE + def _is_executable(path): - # XXX this doesn't take into account UID, it assumes it's our file + # TODO this doesn't take into account UID, it assumes it's our file return os.stat(path).st_mode & stat.S_IEXEC + def _clear_dict(dict, *keys) -> None: for key in keys: try: @@ -68,6 +72,7 @@ def _clear_dict(dict, *keys) -> None: class ExitError(Exception): pass + class TestCmdTestCase(unittest.TestCase): """Base class for TestCmd test cases, with fixture and utility methods.""" @@ -88,13 +93,19 @@ class T: t.script1 = 'script_1.txt' t.scriptout = 'scriptout' t.scripterr = 'scripterr' - fmt = "import os, sys; cwd = os.getcwd(); " + \ - "sys.stdout.write('%s: STDOUT: %%s: %%s\\n' %% (cwd, sys.argv[1:])); " + \ - "sys.stderr.write('%s: STDERR: %%s: %%s\\n' %% (cwd, sys.argv[1:]))" - fmtout = "import os, sys; cwd = os.getcwd(); " + \ - "sys.stdout.write('%s: STDOUT: %%s: %%s\\n' %% (cwd, sys.argv[1:]))" - fmterr = "import os, sys; cwd = os.getcwd(); " + \ - "sys.stderr.write('%s: STDERR: %%s: %%s\\n' %% (cwd, sys.argv[1:]))" + fmt = ( + "import os, sys; cwd = os.getcwd(); " + "sys.stdout.write('%s: STDOUT: %%s: %%s\\n' %% (cwd, sys.argv[1:])); " + "sys.stderr.write('%s: STDERR: %%s: %%s\\n' %% (cwd, sys.argv[1:]))" + ) + fmtout = ( + "import os, sys; cwd = os.getcwd(); " + "sys.stdout.write('%s: STDOUT: %%s: %%s\\n' %% (cwd, sys.argv[1:]))" + ) + fmterr = ( + "import os, sys; cwd = os.getcwd(); " + + "sys.stderr.write('%s: STDERR: %%s: %%s\\n' %% (cwd, sys.argv[1:]))" + ) text = fmt % (t.script, t.script) textx = fmt % (t.scriptx, t.scriptx) if sys.platform == 'win32': @@ -106,7 +117,7 @@ class T: textout = fmtout % t.scriptout texterr = fmterr % t.scripterr - run_env = TestCmd.TestCmd(workdir = '') + run_env = TestCmd.TestCmd(workdir='') run_env.subdir('sub dir') t.run_env = run_env @@ -148,7 +159,14 @@ def call_python(self, indata, python=None): stderr = self.translate_newlines(to_str(cp.stderr)) return stdout, stderr, cp.returncode - def popen_python(self, indata, status: int=0, stdout: str="", stderr: str="", python=None) -> None: + def popen_python( + self, + indata: str, + status: int = 0, + stdout: str = "", + stderr: str = "", + python: str = None, + ) -> None: if python is None: python = sys.executable _stdout, _stderr, _status = self.call_python(indata, python) @@ -166,6 +184,7 @@ def popen_python(self, indata, status: int=0, stdout: str="", stderr: str="", py f"Expected STDERR ==========\n{stderr}" f"Actual STDERR ============\n{_stderr}" ) + self.assertEqual(stderr, _stderr) def run_match(self, content, *args) -> None: expect = "%s: %s: %s: %s\n" % args @@ -176,17 +195,15 @@ def run_match(self, content, *args) -> None: ) - class __init__TestCase(TestCmdTestCase): def test_init(self) -> None: """Test init()""" test = TestCmd.TestCmd() - test = TestCmd.TestCmd(description = 'test') - test = TestCmd.TestCmd(description = 'test', program = 'foo') - test = TestCmd.TestCmd(description = 'test', - program = 'foo', - universal_newlines=None) - + test = TestCmd.TestCmd(description='test') + test = TestCmd.TestCmd(description='test', program='foo') + test = TestCmd.TestCmd( + description='test', program='foo', universal_newlines=None + ) class basename_TestCase(TestCmdTestCase): @@ -195,11 +212,10 @@ def test_basename(self) -> None: assert 1 == 1 - class cleanup_TestCase(TestCmdTestCase): def test_cleanup(self) -> None: """Test cleanup()""" - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') wdir = test.workdir test.write('file1', "Test file #1\n") test.cleanup() @@ -207,7 +223,7 @@ def test_cleanup(self) -> None: def test_writable(self) -> None: """Test cleanup() when the directory isn't writable""" - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') wdir = test.workdir test.write('file2', "Test file #2\n") os.chmod(test.workpath('file2'), 0o400) @@ -217,15 +233,18 @@ def test_writable(self) -> None: def test_shutil(self) -> None: """Test cleanup() when used with shutil""" - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') wdir = test.workdir os.chdir(wdir) import shutil + save_rmtree = shutil.rmtree - def my_rmtree(dir, ignore_errors: int=0, wdir=wdir, _rmtree=save_rmtree): + + def my_rmtree(dir, ignore_errors: bool = False, wdir=wdir, _rmtree=save_rmtree): assert os.getcwd() != wdir return _rmtree(dir, ignore_errors=ignore_errors) + try: shutil.rmtree = my_rmtree test.cleanup() @@ -234,7 +253,8 @@ def my_rmtree(dir, ignore_errors: int=0, wdir=wdir, _rmtree=save_rmtree): def test_atexit(self) -> None: """Test cleanup when atexit is used""" - self.popen_python(f"""\ + self.popen_python( + indata=f"""\ import atexit import sys import TestCmd @@ -247,13 +267,15 @@ def cleanup(): result = TestCmd.TestCmd(workdir='') sys.exit(0) -""", stdout='cleanup()\n') +""", + stdout='cleanup()\n', + ) class chmod_TestCase(TestCmdTestCase): def test_chmod(self) -> None: """Test chmod()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'sub') + test = TestCmd.TestCmd(workdir='', subdir='sub') wdir_file1 = os.path.join(test.workdir, 'file1') wdir_sub_file2 = os.path.join(test.workdir, 'sub', 'file2') @@ -264,7 +286,6 @@ def test_chmod(self) -> None: f.write("") if sys.platform == 'win32': - test.chmod(wdir_file1, stat.S_IREAD) test.chmod(['sub', 'file2'], stat.S_IWRITE) @@ -282,7 +303,6 @@ def test_chmod(self) -> None: assert file2_mode == 0o444, f'0{file2_mode:o}' else: - test.chmod(wdir_file1, 0o700) test.chmod(['sub', 'file2'], 0o760) @@ -300,35 +320,42 @@ def test_chmod(self) -> None: assert file2_mode == 0o567, f'0{file2_mode:o}' - class combine_TestCase(TestCmdTestCase): def test_combine(self): """Test combining stdout and stderr""" - run_env = TestCmd.TestCmd(workdir = '') - run_env.write('run1', """import sys + run_env = TestCmd.TestCmd(workdir='') + run_env.write( + 'run1', + """\ +import sys + sys.stdout.write("run1 STDOUT %s\\n" % sys.argv[1:]) sys.stdout.write("run1 STDOUT second line\\n") sys.stderr.write("run1 STDERR %s\\n" % sys.argv[1:]) sys.stderr.write("run1 STDERR second line\\n") sys.stdout.write("run1 STDOUT third line\\n") sys.stderr.write("run1 STDERR third line\\n") -""") - run_env.write('run2', """import sys +""", + ) + run_env.write( + 'run2', + """\ +import sys + sys.stdout.write("run2 STDOUT %s\\n" % sys.argv[1:]) sys.stdout.write("run2 STDOUT second line\\n") sys.stderr.write("run2 STDERR %s\\n" % sys.argv[1:]) sys.stderr.write("run2 STDERR second line\\n") sys.stdout.write("run2 STDOUT third line\\n") sys.stderr.write("run2 STDERR third line\\n") -""") +""", + ) cwd = os.getcwd() os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. try: - test = TestCmd.TestCmd(interpreter = 'python', - workdir = '', - combine = 1) + test = TestCmd.TestCmd(interpreter='python', workdir='', combine=1) output = test.stdout() if output is not None: raise IndexError(f"got unexpected output:\n\t`{output}'\n") @@ -337,7 +364,7 @@ def test_combine(self): # stdout and stderr in different orders, so we accomodate both. test.program_set('run1') - test.run(arguments = 'foo bar') + test.run(arguments='foo bar') stdout_lines = """\ run1 STDOUT ['foo', 'bar'] run1 STDOUT second line @@ -348,11 +375,10 @@ def test_combine(self): run1 STDERR second line run1 STDERR third line """ - foo_bar_expect = (stdout_lines + stderr_lines, - stderr_lines + stdout_lines) + foo_bar_expect = (stdout_lines + stderr_lines, stderr_lines + stdout_lines) test.program_set('run2') - test.run(arguments = 'snafu') + test.run(arguments='snafu') stdout_lines = """\ run2 STDOUT ['snafu'] run2 STDOUT second line @@ -363,8 +389,7 @@ def test_combine(self): run2 STDERR second line run2 STDERR third line """ - snafu_expect = (stdout_lines + stderr_lines, - stderr_lines + stdout_lines) + snafu_expect = (stdout_lines + stderr_lines, stderr_lines + stdout_lines) # XXX SHOULD TEST ABSOLUTE NUMBER AS WELL output = test.stdout() @@ -373,7 +398,7 @@ def test_combine(self): error = test.stderr() assert error == '', error - output = test.stdout(run = -1) + output = test.stdout(run=-1) output = self.translate_newlines(output) assert output in foo_bar_expect, output error = test.stderr(-1) @@ -382,19 +407,17 @@ def test_combine(self): os.chdir(cwd) - class description_TestCase(TestCmdTestCase): def test_description(self) -> None: """Test description()""" test = TestCmd.TestCmd() assert test.description is None, 'initialized description?' - test = TestCmd.TestCmd(description = 'test') + test = TestCmd.TestCmd(description='test') assert test.description == 'test', 'uninitialized description' test.description_set('foo') assert test.description == 'foo', 'did not set description' - class diff_TestCase(TestCmdTestCase): def test_diff_re(self) -> None: """Test diff_re()""" @@ -410,51 +433,57 @@ def test_diff_re(self) -> None: def test_diff_custom_function(self) -> None: """Test diff() using a custom function""" - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path + def my_diff(a, b): - return [ - '*****', - a, - '*****', - b, - '*****', - ] -test = TestCmd.TestCmd(diff = my_diff) + return '*****', a, '*****', b, '*****' + +test = TestCmd.TestCmd(diff=my_diff) test.diff("a\\nb1\\nc\\n", "a\\nb2\\nc\\n", "STDOUT") sys.exit(0) """, - stdout = """\ + stdout="""\ STDOUT========================================================================== ***** ['a', 'b1', 'c'] ***** ['a', 'b2', 'c'] ***** -""") +""", + ) def test_diff_string(self) -> None: - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(diff = 'diff_re') + +sys.path = [r'{self.orig_cwd}'] + sys.path +test = TestCmd.TestCmd(diff='diff_re') test.diff("a\\nb1\\nc\\n", "a\\nb2\\nc\\n", 'STDOUT') sys.exit(0) """, - stdout = """\ + stdout="""\ STDOUT========================================================================== 2c2 < 'b1' --- > 'b2' -""") +""", + ) def test_error(self) -> None: """Test handling a compilation error in TestCmd.diff_re()""" - script_input = f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + script_input = f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path assert TestCmd.diff_re([r"a.*(e"], ["abcde"]) sys.exit(0) """ @@ -462,29 +491,39 @@ def test_error(self) -> None: assert status == 1, status expect1 = "Regular expression error in '^a.*(e$': missing )" expect2 = "Regular expression error in '^a.*(e$': unbalanced parenthesis" - assert (stderr.find(expect1) != -1 or - stderr.find(expect2) != -1), repr(stderr) + assert stderr.find(expect1) != -1 or stderr.find(expect2) != -1, repr(stderr) def test_simple_diff_static_method(self) -> None: """Test calling the TestCmd.TestCmd.simple_diff() static method""" - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -result = TestCmd.TestCmd.simple_diff(['a', 'b', 'c', 'e', 'f1'], - ['a', 'c', 'd', 'e', 'f2']) + +sys.path = [r'{self.orig_cwd}'] + sys.path + +result = TestCmd.TestCmd.simple_diff( + ['a', 'b', 'c', 'e', 'f1'], ['a', 'c', 'd', 'e', 'f2'] +) result = list(result) expect = ['2d1', '< b', '3a3', '> d', '5c5', '< f1', '---', '> f2'] assert result == expect, result sys.exit(0) -""") +""", + ) def test_context_diff_static_method(self) -> None: """Test calling the TestCmd.TestCmd.context_diff() static method""" - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -result = TestCmd.TestCmd.context_diff(['a\\n', 'b\\n', 'c\\n', 'e\\n', 'f1\\n'], - ['a\\n', 'c\\n', 'd\\n', 'e\\n', 'f2\\n']) + +sys.path = [r'{self.orig_cwd}'] + sys.path +result = TestCmd.TestCmd.context_diff( + ['a\\n', 'b\\n', 'c\\n', 'e\\n', 'f1\\n'], + ['a\\n', 'c\\n', 'd\\n', 'e\\n', 'f2\\n' ], +) result = list(result) expect = [ '*** \\n', @@ -505,15 +544,21 @@ def test_context_diff_static_method(self) -> None: ] assert result == expect, result sys.exit(0) -""") +""", + ) def test_unified_diff_static_method(self) -> None: """Test calling the TestCmd.TestCmd.unified_diff() static method""" - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -result = TestCmd.TestCmd.unified_diff(['a\\n', 'b\\n', 'c\\n', 'e\\n', 'f1\\n'], - ['a\\n', 'c\\n', 'd\\n', 'e\\n', 'f2\\n']) + +sys.path = [r'{self.orig_cwd}'] + sys.path +result = TestCmd.TestCmd.unified_diff( + ['a\\n', 'b\\n', 'c\\n', 'e\\n', 'f1\\n'], + ['a\\n', 'c\\n', 'd\\n', 'e\\n', 'f2\\n'], +) result = list(result) expect = [ '--- \\n', @@ -525,19 +570,25 @@ def test_unified_diff_static_method(self) -> None: '+d\\n', ' e\\n', '-f1\\n', - '+f2\\n' + '+f2\\n', ] assert result == expect, result sys.exit(0) -""") +""", + ) def test_diff_re_static_method(self) -> None: """Test calling the TestCmd.TestCmd.diff_re() static method""" - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -result = TestCmd.TestCmd.diff_re(['a', 'b', 'c', '.', 'f1'], - ['a', 'c', 'd', 'e', 'f2']) + +sys.path = [r'{self.orig_cwd}'] + sys.path +result = TestCmd.TestCmd.diff_re( + ['a', 'b', 'c', '.', 'f1'], + ['a', 'c', 'd', 'e', 'f2'], +) result = list(result) expect = [ '2c2', @@ -551,255 +602,309 @@ def test_diff_re_static_method(self) -> None: '5c5', "< 'f1'", '---', - "> 'f2'" + "> 'f2'", ] assert result == expect, result sys.exit(0) -""") - +""", + ) class diff_stderr_TestCase(TestCmdTestCase): def test_diff_stderr_default(self) -> None: """Test diff_stderr() default behavior""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path + test = TestCmd.TestCmd() -test.diff_stderr('a\nb1\nc\n', 'a\nb2\nc\n') +test.diff_stderr('a\\nb1\\nc\\n', 'a\\nb2\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ 2c2 < b1 --- > b2 -""") +""", + ) def test_diff_stderr_not_affecting_diff_stdout(self) -> None: """Test diff_stderr() not affecting diff_stdout() behavior""" - self.popen_python(fr""" + self.popen_python( + indata=f"""\ import sys -sys.path = [r'{self.orig_cwd}'] + sys.path import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd(diff_stderr='diff_re') print("diff_stderr:") -test.diff_stderr('a\nb.\nc\n', 'a\nbb\nc\n') +test.diff_stderr('a\\nb.\\nc\\n', 'a\\nbb\\nc\\n') print("diff_stdout:") -test.diff_stdout('a\nb.\nc\n', 'a\nbb\nc\n') +test.diff_stdout('a\\nb.\\nc\\n', 'a\\nbb\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ diff_stderr: diff_stdout: 2c2 < b. --- > bb -""") +""", + ) def test_diff_stderr_custom_function(self) -> None: """Test diff_stderr() using a custom function""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path + def my_diff(a, b): return ["a:"] + a + ["b:"] + b + test = TestCmd.TestCmd(diff_stderr=my_diff) test.diff_stderr('abc', 'def') sys.exit(0) """, - stdout="""\ + stdout="""\ a: abc b: def -""") +""", + ) def test_diff_stderr_TestCmd_function(self) -> None: """Test diff_stderr() using a TestCmd function""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(diff_stderr = TestCmd.diff_re) -test.diff_stderr('a\n.\n', 'b\nc\n') + +sys.path = [r'{self.orig_cwd}'] + sys.path +test = TestCmd.TestCmd(diff_stderr=TestCmd.diff_re) +test.diff_stderr('a\\n.\\n', 'b\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ 1c1 < 'a' --- > 'b' -""") +""", + ) def test_diff_stderr_static_method(self) -> None: """Test diff_stderr() using a static method""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd(diff_stderr=TestCmd.TestCmd.diff_re) -test.diff_stderr('a\n.\n', 'b\nc\n') +test.diff_stderr('a\\n.\\n', 'b\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ 1c1 < 'a' --- > 'b' -""") +""", + ) def test_diff_stderr_string(self) -> None: """Test diff_stderr() using a string to fetch the diff method""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd(diff_stderr='diff_re') -test.diff_stderr('a\n.\n', 'b\nc\n') +test.diff_stderr('a\\n.\\n', 'b\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ 1c1 < 'a' --- > 'b' -""") - +""", + ) class diff_stdout_TestCase(TestCmdTestCase): def test_diff_stdout_default(self) -> None: """Test diff_stdout() default behavior""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd() -test.diff_stdout('a\nb1\nc\n', 'a\nb2\nc\n') +test.diff_stdout('a\\nb1\\nc\\n', 'a\\nb2\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ 2c2 < b1 --- > b2 -""") +""", + ) def test_diff_stdout_not_affecting_diff_stderr(self) -> None: """Test diff_stdout() not affecting diff_stderr() behavior""" - self.popen_python(fr""" + self.popen_python( + indata=f"""\ import sys -sys.path = [r'{self.orig_cwd}'] + sys.path import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd(diff_stdout='diff_re') print("diff_stdout:") -test.diff_stdout('a\nb.\nc\n', 'a\nbb\nc\n') +test.diff_stdout('a\\nb.\\nc\\n', 'a\\nbb\\nc\\n') print("diff_stderr:") -test.diff_stderr('a\nb.\nc\n', 'a\nbb\nc\n') +test.diff_stderr('a\\nb.\\nc\\n', 'a\\nbb\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ diff_stdout: diff_stderr: 2c2 < b. --- > bb -""") +""", + ) def test_diff_stdout_custom_function(self) -> None: """Test diff_stdout() using a custom function""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path + def my_diff(a, b): return ["a:"] + a + ["b:"] + b + test = TestCmd.TestCmd(diff_stdout=my_diff) test.diff_stdout('abc', 'def') sys.exit(0) """, - stdout="""\ + stdout="""\ a: abc b: def -""") +""", + ) def test_diff_stdout_TestCmd_function(self) -> None: """Test diff_stdout() using a TestCmd function""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(diff_stdout = TestCmd.diff_re) -test.diff_stdout('a\n.\n', 'b\nc\n') + +sys.path = [r'{self.orig_cwd}'] + sys.path +test = TestCmd.TestCmd(diff_stdout=TestCmd.diff_re) +test.diff_stdout('a\\n.\\n', 'b\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ 1c1 < 'a' --- > 'b' -""") +""", + ) def test_diff_stdout_static_method(self) -> None: """Test diff_stdout() using a static method""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd(diff_stdout=TestCmd.TestCmd.diff_re) -test.diff_stdout('a\n.\n', 'b\nc\n') +test.diff_stdout('a\\n.\\n', 'b\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ 1c1 < 'a' --- > 'b' -""") +""", + ) def test_diff_stdout_string(self) -> None: """Test diff_stdout() using a string to fetch the diff method""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd(diff_stdout='diff_re') -test.diff_stdout('a\n.\n', 'b\nc\n') +test.diff_stdout('a\\n.\\n', 'b\\nc\\n') sys.exit(0) """, - stdout="""\ + stdout="""\ 1c1 < 'a' --- > 'b' -""") - +""", + ) class exit_TestCase(TestCmdTestCase): def test_exit(self) -> None: """Test exit()""" + def _test_it(cwd, tempdir, condition, preserved): close_true = {'pass_test': 1, 'fail_test': 0, 'no_result': 0} exit_status = {'pass_test': 0, 'fail_test': 1, 'no_result': 2} - result_string = {'pass_test': "PASSED\n", - 'fail_test': "FAILED test at line 5 of \n", - 'no_result': "NO RESULT for test at line 5 of \n"} + result_string = { + 'pass_test': "PASSED\n", + 'fail_test': "FAILED test at line 6 of \n", + 'no_result': "NO RESULT for test at line 6 of \n", + } global ExitError - input = f"""import sys -sys.path = [r'{cwd}'] + sys.path + input = f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(workdir = '{tempdir}') + +sys.path = [r'{cwd}'] + sys.path +test = TestCmd.TestCmd(workdir='{tempdir}') test.{condition}() """ stdout, stderr, status = self.call_python(input, python="python") if close_true[condition]: - unexpected = (status != 0) + unexpected = status != 0 else: - unexpected = (status == 0) + unexpected = status == 0 if unexpected: msg = "Unexpected exit status from python: %s\n" raise ExitError(msg % status + stdout + stderr) if status != exit_status[condition]: - msg = "Expected exit status %d, got %d\n" - raise ExitError(msg % (exit_status[condition], status)) + msg = "Expected exit status %d, got %d\n" + raise ExitError(msg % (exit_status[condition], status)) if stderr != result_string[condition]: msg = "Expected error output:\n%s\nGot error output:\n%s" raise ExitError(msg % (result_string[condition], stderr)) @@ -812,13 +917,19 @@ def _test_it(cwd, tempdir, condition, preserved): msg = "Working directory %s was mistakenly preserved\n" raise ExitError(msg % tempdir + stdout) - run_env = TestCmd.TestCmd(workdir = '') + run_env = TestCmd.TestCmd(workdir='') os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. try: cwd = self.orig_cwd - _clear_dict(os.environ, 'PRESERVE', 'PRESERVE_PASS', 'PRESERVE_FAIL', 'PRESERVE_NO_RESULT') + _clear_dict( + os.environ, + 'PRESERVE', + 'PRESERVE_PASS', + 'PRESERVE_FAIL', + 'PRESERVE_NO_RESULT', + ) _test_it(cwd, 'dir01', 'pass_test', 0) _test_it(cwd, 'dir02', 'fail_test', 0) _test_it(cwd, 'dir03', 'no_result', 0) @@ -843,89 +954,168 @@ def _test_it(cwd, tempdir, condition, preserved): _test_it(cwd, 'dir15', 'no_result', 1) del os.environ['PRESERVE_NO_RESULT'] finally: - _clear_dict(os.environ, 'PRESERVE', 'PRESERVE_PASS', 'PRESERVE_FAIL', 'PRESERVE_NO_RESULT') - + _clear_dict( + os.environ, + 'PRESERVE', + 'PRESERVE_PASS', + 'PRESERVE_FAIL', + 'PRESERVE_NO_RESULT', + ) class fail_test_TestCase(TestCmdTestCase): def test_fail_test(self) -> None: """Test fail_test()""" - run_env = TestCmd.TestCmd(workdir = '') - run_env.write('run', """import sys + run_env = TestCmd.TestCmd(workdir='') + run_env.write( + 'run', + """\ +import sys + sys.stdout.write("run: STDOUT\\n") sys.stderr.write("run: STDERR\\n") -""") +""", + ) os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -TestCmd.fail_test(condition = 1) -""", status = 1, stderr = "FAILED test at line 4 of \n") - self.popen_python(f"""import sys sys.path = [r'{self.orig_cwd}'] + sys.path +TestCmd.fail_test(condition=1) +""", + status=1, + stderr="FAILED test at line 5 of \n", + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '') -test.run() -test.fail_test(condition = (test.status == 0)) -""", status = 1, stderr = f"FAILED test of {run_env.workpath('run')}\n\tat line 6 of \n") - self.popen_python(f"""import sys sys.path = [r'{self.orig_cwd}'] + sys.path -import TestCmd -test = TestCmd.TestCmd(program = 'run', interpreter = 'python', description = 'xyzzy', workdir = '') +test = TestCmd.TestCmd(program='run', interpreter='python', workdir='') test.run() -test.fail_test(condition = (test.status == 0)) -""", status = 1, stderr = f"FAILED test of {run_env.workpath('run')} [xyzzy]\n\tat line 6 of \n") +test.fail_test(condition=(test.status == 0)) +""", + status=1, + stderr=( + f"FAILED test of {run_env.workpath('run')}\n" + "\tat line 7 of \n" + ), + ) + + self.popen_python( + indata=f"""\ +import sys +import TestCmd - self.popen_python(f"""import sys sys.path = [r'{self.orig_cwd}'] + sys.path +test = TestCmd.TestCmd( + program='run', interpreter='python', description='xyzzy', workdir='' +) +test.run() +test.fail_test(condition=(test.status == 0)) +""", + status=1, + stderr=( + f"FAILED test of {run_env.workpath('run')} [xyzzy]\n" + "\tat line 9 of \n" + ), + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '') + +sys.path = [r'{self.orig_cwd}'] + sys.path +test = TestCmd.TestCmd(program='run', interpreter='python', workdir='') test.run() + def xxx(): sys.stderr.write("printed on failure\\n") -test.fail_test(condition = (test.status == 0), function = xxx) -""", status = 1, stderr = f"printed on failure\nFAILED test of {run_env.workpath('run')}\n\tat line 8 of \n") - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path +test.fail_test(condition=(test.status == 0), function=xxx) +""", + status=1, + stderr=( + "printed on failure\n" + f"FAILED test of {run_env.workpath('run')}\n" + "\tat line 11 of \n" + ), + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path + def test1(self): self.run() - self.fail_test(condition = (self.status == 0)) + self.fail_test(condition=(self.status == 0)) + def test2(self): test1(self) -test2(TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')) -""", status = 1, stderr = f"FAILED test of {run_env.workpath('run')}\n\tat line 6 of (test1)\n\tfrom line 8 of (test2)\n\tfrom line 9 of \n") - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path +test2(TestCmd.TestCmd(program='run', interpreter='python', workdir='')) +""", + status=1, + stderr=( + f"FAILED test of {run_env.workpath('run')}\n" + "\tat line 8 of (test1)\n" + "\tfrom line 11 of (test2)\n" + "\tfrom line 13 of \n" + ), + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path + def test1(self): self.run() - self.fail_test(condition = (self.status == 0), skip = 1) + self.fail_test(condition=(self.status == 0), skip=1) + def test2(self): test1(self) -test2(TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')) -""", status = 1, stderr = f"FAILED test of {run_env.workpath('run')}\n\tat line 8 of (test2)\n\tfrom line 9 of \n") +test2(TestCmd.TestCmd(program='run', interpreter='python', workdir='')) +""", + status=1, + stderr=( + f"FAILED test of {run_env.workpath('run')}\n" + "\tat line 11 of (test2)\n" + "\tfrom line 13 of \n" + ), + ) class interpreter_TestCase(TestCmdTestCase): def test_interpreter(self) -> None: """Test interpreter()""" - run_env = TestCmd.TestCmd(workdir = '') - run_env.write('run', """import sys + run_env = TestCmd.TestCmd(workdir='') + run_env.write( + 'run', + """\ +import sys + sys.stdout.write("run: STDOUT\\n") sys.stderr.write("run: STDERR\\n") -""") +""", + ) os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. - test = TestCmd.TestCmd(program = 'run', workdir = '') + test = TestCmd.TestCmd(program='run', workdir='') test.interpreter_set('foo') assert test.interpreter == 'foo', 'did not set interpreter' test.interpreter_set('python') @@ -933,7 +1123,6 @@ def test_interpreter(self) -> None: test.run() - class match_TestCase(TestCmdTestCase): def test_match_default(self) -> None: """Test match() default behavior""" @@ -946,8 +1135,10 @@ def test_match_default(self) -> None: def test_match_custom_function(self) -> None: """Test match() using a custom function""" + def match_length(lines, matches): return len(lines) == len(matches) + test = TestCmd.TestCmd(match=match_length) assert not test.match("123\n", "1\n") assert test.match("123\n", "111\n") @@ -955,11 +1146,11 @@ def match_length(lines, matches): assert test.match("123\n123\n", "111\n111\n") lines = ["123\n", "123\n"] regexes = ["1\n", "1\n"] - assert test.match(lines, regexes) # due to equal numbers of lines + assert test.match(lines, regexes) # due to equal numbers of lines def test_match_TestCmd_function(self) -> None: """Test match() using a TestCmd function""" - test = TestCmd.TestCmd(match = TestCmd.match_exact) + test = TestCmd.TestCmd(match=TestCmd.match_exact) assert not test.match("abcde\n", "a.*e\n") assert test.match("abcde\n", "abcde\n") assert not test.match("12345\nabcde\n", "1\\d+5\na.*e\n") @@ -994,7 +1185,6 @@ def test_match_string(self) -> None: assert test.match(lines, lines) - class match_exact_TestCase(TestCmdTestCase): def test_match_exact_function(self) -> None: """Test calling the TestCmd.match_exact() function""" @@ -1019,14 +1209,18 @@ def test_evaluation(self) -> None: assert test.match_exact("abcde\n", "abcde\n") assert not test.match_exact(["12345\n", "abcde\n"], ["1[0-9]*5\n", "a.*e\n"]) assert test.match_exact(["12345\n", "abcde\n"], ["12345\n", "abcde\n"]) - assert not test.match_exact(UserList(["12345\n", "abcde\n"]), - ["1[0-9]*5\n", "a.*e\n"]) - assert test.match_exact(UserList(["12345\n", "abcde\n"]), - ["12345\n", "abcde\n"]) - assert not test.match_exact(["12345\n", "abcde\n"], - UserList(["1[0-9]*5\n", "a.*e\n"])) - assert test.match_exact(["12345\n", "abcde\n"], - UserList(["12345\n", "abcde\n"])) + assert not test.match_exact( + UserList(["12345\n", "abcde\n"]), ["1[0-9]*5\n", "a.*e\n"] + ) + assert test.match_exact( + UserList(["12345\n", "abcde\n"]), ["12345\n", "abcde\n"] + ) + assert not test.match_exact( + ["12345\n", "abcde\n"], UserList(["1[0-9]*5\n", "a.*e\n"]) + ) + assert test.match_exact( + ["12345\n", "abcde\n"], UserList(["12345\n", "abcde\n"]) + ) assert not test.match_exact("12345\nabcde\n", "1[0-9]*5\na.*e\n") assert test.match_exact("12345\nabcde\n", "12345\nabcde\n") lines = ["vwxyz\n", "67890\n"] @@ -1035,7 +1229,6 @@ def test_evaluation(self) -> None: assert test.match_exact(lines, lines) - class match_re_dotall_TestCase(TestCmdTestCase): def test_match_re_dotall_function(self) -> None: """Test calling the TestCmd.match_re_dotall() function""" @@ -1052,7 +1245,7 @@ def test_match_re_dotall_static_method(self) -> None: def test_error(self) -> None: """Test handling a compilation error in TestCmd.match_re_dotall()""" - run_env = TestCmd.TestCmd(workdir = '') + run_env = TestCmd.TestCmd(workdir='') cwd = os.getcwd() os.chdir(run_env.workdir) # Everything before this prepared our "source directory." @@ -1068,8 +1261,9 @@ def test_error(self) -> None: assert status == 1, status expect1 = "Regular expression error in '^a.*(e$': missing )" expect2 = "Regular expression error in '^a.*(e$': unbalanced parenthesis" - assert (stderr.find(expect1) != -1 or - stderr.find(expect2) != -1), repr(stderr) + assert stderr.find(expect1) != -1 or stderr.find(expect2) != -1, repr( + stderr + ) finally: os.chdir(cwd) @@ -1079,36 +1273,44 @@ def test_evaluation(self) -> None: assert test.match_re_dotall("abcde\nfghij\n", r"a.*e\nf.*j\n") assert test.match_re_dotall("abcde\nfghij\n", r"a[^j]*j\n") assert test.match_re_dotall("abcde\nfghij\n", r"abcde\nfghij\n") - assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - [r"1[0-9]*5\n", r"a.*e\n", r"f.*j\n"]) - assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - [r"1.*j\n"]) - assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - [r"12345\n", r"abcde\n", r"fghij\n"]) - assert test.match_re_dotall(UserList(["12345\n", "abcde\n", "fghij\n"]), - [r"1[0-9]*5\n", r"a.*e\n", r"f.*j\n"]) - assert test.match_re_dotall(UserList(["12345\n", "abcde\n", "fghij\n"]), - [r"1.*j\n"]) - assert test.match_re_dotall(UserList(["12345\n", "abcde\n", "fghij\n"]), - [r"12345\n", r"abcde\n", r"fghij\n"]) - assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - UserList([r"1[0-9]*5\n", r"a.*e\n", r"f.*j\n"])) - assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - UserList([r"1.*j\n"])) - assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - UserList([r"12345\n", r"abcde\n", r"fghij\n"])) - assert test.match_re_dotall("12345\nabcde\nfghij\n", - r"1[0-9]*5\na.*e\nf.*j\n") + assert test.match_re_dotall( + ["12345\n", "abcde\n", "fghij\n"], [r"1[0-9]*5\n", r"a.*e\n", r"f.*j\n"] + ) + assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], [r"1.*j\n"]) + assert test.match_re_dotall( + ["12345\n", "abcde\n", "fghij\n"], [r"12345\n", r"abcde\n", r"fghij\n"] + ) + assert test.match_re_dotall( + UserList(["12345\n", "abcde\n", "fghij\n"]), + [r"1[0-9]*5\n", r"a.*e\n", r"f.*j\n"], + ) + assert test.match_re_dotall( + UserList(["12345\n", "abcde\n", "fghij\n"]), [r"1.*j\n"] + ) + assert test.match_re_dotall( + UserList(["12345\n", "abcde\n", "fghij\n"]), + [r"12345\n", r"abcde\n", r"fghij\n"], + ) + assert test.match_re_dotall( + ["12345\n", "abcde\n", "fghij\n"], + UserList([r"1[0-9]*5\n", r"a.*e\n", r"f.*j\n"]), + ) + assert test.match_re_dotall( + ["12345\n", "abcde\n", "fghij\n"], UserList([r"1.*j\n"]) + ) + assert test.match_re_dotall( + ["12345\n", "abcde\n", "fghij\n"], + UserList([r"12345\n", r"abcde\n", r"fghij\n"]), + ) + assert test.match_re_dotall("12345\nabcde\nfghij\n", r"1[0-9]*5\na.*e\nf.*j\n") assert test.match_re_dotall("12345\nabcde\nfghij\n", r"1.*j\n") - assert test.match_re_dotall("12345\nabcde\nfghij\n", - r"12345\nabcde\nfghij\n") + assert test.match_re_dotall("12345\nabcde\nfghij\n", r"12345\nabcde\nfghij\n") lines = ["vwxyz\n", "67890\n"] regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"] assert test.match_re_dotall(lines, regexes) assert test.match_re_dotall(lines, lines) - class match_re_TestCase(TestCmdTestCase): def test_match_re_function(self) -> None: """Test calling the TestCmd.match_re() function""" @@ -1125,7 +1327,7 @@ def test_match_re_static_method(self) -> None: def test_error(self) -> None: """Test handling a compilation error in TestCmd.match_re()""" - run_env = TestCmd.TestCmd(workdir = '') + run_env = TestCmd.TestCmd(workdir='') cwd = os.getcwd() os.chdir(run_env.workdir) # Everything before this prepared our "source directory." @@ -1143,8 +1345,9 @@ def test_error(self) -> None: assert status == 1, status expect1 = "Regular expression error in '^a.*(e$': missing )" expect2 = "Regular expression error in '^a.*(e$': unbalanced parenthesis" - assert (stderr.find(expect1) != -1 or - stderr.find(expect2) != -1), repr(stderr) + assert stderr.find(expect1) != -1 or stderr.find(expect2) != -1, repr( + stderr + ) finally: os.chdir(cwd) @@ -1155,14 +1358,10 @@ def test_evaluation(self) -> None: assert test.match_re("abcde\n", "abcde\n") assert test.match_re(["12345\n", "abcde\n"], ["1[0-9]*5\n", "a.*e\n"]) assert test.match_re(["12345\n", "abcde\n"], ["12345\n", "abcde\n"]) - assert test.match_re(UserList(["12345\n", "abcde\n"]), - ["1[0-9]*5\n", "a.*e\n"]) - assert test.match_re(UserList(["12345\n", "abcde\n"]), - ["12345\n", "abcde\n"]) - assert test.match_re(["12345\n", "abcde\n"], - UserList(["1[0-9]*5\n", "a.*e\n"])) - assert test.match_re(["12345\n", "abcde\n"], - UserList(["12345\n", "abcde\n"])) + assert test.match_re(UserList(["12345\n", "abcde\n"]), ["1[0-9]*5\n", "a.*e\n"]) + assert test.match_re(UserList(["12345\n", "abcde\n"]), ["12345\n", "abcde\n"]) + assert test.match_re(["12345\n", "abcde\n"], UserList(["1[0-9]*5\n", "a.*e\n"])) + assert test.match_re(["12345\n", "abcde\n"], UserList(["12345\n", "abcde\n"])) assert test.match_re("12345\nabcde\n", "1[0-9]*5\na.*e\n") assert test.match_re("12345\nabcde\n", "12345\nabcde\n") lines = ["vwxyz\n", "67890\n"] @@ -1171,7 +1370,6 @@ def test_evaluation(self) -> None: assert test.match_re(lines, lines) - class match_stderr_TestCase(TestCmdTestCase): def test_match_stderr_default(self) -> None: """Test match_stderr() default behavior""" @@ -1203,8 +1401,10 @@ def test_match_stderr_not_affecting_match_stdout(self) -> None: def test_match_stderr_custom_function(self) -> None: """Test match_stderr() using a custom function""" + def match_length(lines, matches): return len(lines) == len(matches) + test = TestCmd.TestCmd(match_stderr=match_length) assert not test.match_stderr("123\n", "1\n") assert test.match_stderr("123\n", "111\n") @@ -1212,11 +1412,11 @@ def match_length(lines, matches): assert test.match_stderr("123\n123\n", "111\n111\n") lines = ["123\n", "123\n"] regexes = [r"1\n", r"1\n"] - assert test.match_stderr(lines, regexes) # equal numbers of lines + assert test.match_stderr(lines, regexes) # equal numbers of lines def test_match_stderr_TestCmd_function(self) -> None: """Test match_stderr() using a TestCmd function""" - test = TestCmd.TestCmd(match_stderr = TestCmd.match_exact) + test = TestCmd.TestCmd(match_stderr=TestCmd.match_exact) assert not test.match_stderr("abcde\n", "a.*e\n") assert test.match_stderr("abcde\n", "abcde\n") assert not test.match_stderr("12345\nabcde\n", "1\\d+5\na.*e\n") @@ -1251,7 +1451,6 @@ def test_match_stderr_string(self) -> None: assert test.match_stderr(lines, lines) - class match_stdout_TestCase(TestCmdTestCase): def test_match_stdout_default(self) -> None: """Test match_stdout() default behavior""" @@ -1283,8 +1482,10 @@ def test_match_stdout_not_affecting_match_stderr(self) -> None: def test_match_stdout_custom_function(self) -> None: """Test match_stdout() using a custom function""" + def match_length(lines, matches): return len(lines) == len(matches) + test = TestCmd.TestCmd(match_stdout=match_length) assert not test.match_stdout("123\n", "1\n") assert test.match_stdout("123\n", "111\n") @@ -1292,11 +1493,11 @@ def match_length(lines, matches): assert test.match_stdout("123\n123\n", "111\n111\n") lines = ["123\n", "123\n"] regexes = [r"1\n", r"1\n"] - assert test.match_stdout(lines, regexes) # equal numbers of lines + assert test.match_stdout(lines, regexes) # equal numbers of lines def test_match_stdout_TestCmd_function(self) -> None: """Test match_stdout() using a TestCmd function""" - test = TestCmd.TestCmd(match_stdout = TestCmd.match_exact) + test = TestCmd.TestCmd(match_stdout=TestCmd.match_exact) assert not test.match_stdout("abcde\n", "a.*e\n") assert test.match_stdout("abcde\n", "abcde\n") assert not test.match_stdout("12345\nabcde\n", "1\\d+5\na.*e\n") @@ -1331,117 +1532,207 @@ def test_match_stdout_string(self) -> None: assert test.match_stdout(lines, lines) - class no_result_TestCase(TestCmdTestCase): def test_no_result(self) -> None: """Test no_result()""" - run_env = TestCmd.TestCmd(workdir = '') - run_env.write('run', """import sys + run_env = TestCmd.TestCmd(workdir='') + run_env.write( + 'run', + """\ +import sys + sys.stdout.write("run: STDOUT\\n") sys.stderr.write("run: STDERR\\n") -""") +""", + ) os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -TestCmd.no_result(condition = 1) -""", status = 2, stderr = "NO RESULT for test at line 4 of \n") - self.popen_python(f"""import sys sys.path = [r'{self.orig_cwd}'] + sys.path +TestCmd.no_result(condition=1) +""", + status=2, + stderr="NO RESULT for test at line 5 of \n", + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '') -test.run() -test.no_result(condition = (test.status == 0)) -""", status = 2, stderr = f"NO RESULT for test of {run_env.workpath('run')}\n\tat line 6 of \n") - self.popen_python(f"""import sys sys.path = [r'{self.orig_cwd}'] + sys.path -import TestCmd -test = TestCmd.TestCmd(program = 'run', interpreter = 'python', description = 'xyzzy', workdir = '') +test = TestCmd.TestCmd(program='run', interpreter='python', workdir='') test.run() -test.no_result(condition = (test.status == 0)) -""", status = 2, stderr = f"NO RESULT for test of {run_env.workpath('run')} [xyzzy]\n\tat line 6 of \n") +test.no_result(condition=(test.status == 0)) +""", + status=2, + stderr=( + f"NO RESULT for test of {run_env.workpath('run')}\n" + "\tat line 7 of \n" + ), + ) + + self.popen_python( + indata=f"""\ +import sys +import TestCmd - self.popen_python(f"""import sys sys.path = [r'{self.orig_cwd}'] + sys.path +test = TestCmd.TestCmd( + program='run', interpreter='python', description='xyzzy', workdir='' +) +test.run() +test.no_result(condition=(test.status == 0)) +""", + status=2, + stderr=( + f"NO RESULT for test of {run_env.workpath('run')} [xyzzy]\n" + "\tat line 9 of \n" + ), + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '') + +sys.path = [r'{self.orig_cwd}'] + sys.path +test = TestCmd.TestCmd(program='run', interpreter='python', workdir='') test.run() + def xxx(): sys.stderr.write("printed on no result\\n") -test.no_result(condition = (test.status == 0), function = xxx) -""", status = 2, stderr = f"printed on no result\nNO RESULT for test of {run_env.workpath('run')}\n\tat line 8 of \n") - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path +test.no_result(condition=(test.status == 0), function=xxx) +""", + status=2, + stderr=( + "printed on no result\n" + f"NO RESULT for test of {run_env.workpath('run')}\n" + "\tat line 11 of \n" + ), + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path + def test1(self): self.run() - self.no_result(condition = (self.status == 0)) + self.no_result(condition=(self.status == 0)) + def test2(self): test1(self) -test2(TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')) -""", status = 2, stderr = f"NO RESULT for test of {run_env.workpath('run')}\n\tat line 6 of (test1)\n\tfrom line 8 of (test2)\n\tfrom line 9 of \n") - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path +test2(TestCmd.TestCmd(program='run', interpreter='python', workdir='')) +""", + status=2, + stderr=( + f"NO RESULT for test of {run_env.workpath('run')}\n" + "\tat line 8 of (test1)\n" + "\tfrom line 11 of (test2)\n" + "\tfrom line 13 of \n" + ), + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path + def test1(self): self.run() - self.no_result(condition = (self.status == 0), skip = 1) + self.no_result(condition=(self.status == 0), skip=1) + def test2(self): test1(self) -test2(TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')) -""", status = 2, stderr = f"NO RESULT for test of {run_env.workpath('run')}\n\tat line 8 of (test2)\n\tfrom line 9 of \n") +test2(TestCmd.TestCmd(program='run', interpreter='python', workdir='')) +""", + status=2, + stderr=( + f"NO RESULT for test of {run_env.workpath('run')}\n" + "\tat line 11 of (test2)\n" + "\tfrom line 13 of \n" + ), + ) class pass_test_TestCase(TestCmdTestCase): def test_pass_test(self) -> None: """Test pass_test()""" - run_env = TestCmd.TestCmd(workdir = '') - run_env.write('run', """import sys + run_env = TestCmd.TestCmd(workdir='') + run_env.write( + 'run', + """\ +import sys + sys.stdout.write("run: STDOUT\\n") sys.stderr.write("run: STDERR\\n") -""") +""", + ) os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd -TestCmd.pass_test(condition = 1) -""", stderr = "PASSED\n") - self.popen_python(f"""import sys sys.path = [r'{self.orig_cwd}'] + sys.path +TestCmd.pass_test(condition=1) +""", + stderr="PASSED\n", + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '') -test.run() -test.pass_test(condition = (test.status == 0)) -""", stderr = "PASSED\n") - self.popen_python(f"""import sys sys.path = [r'{self.orig_cwd}'] + sys.path +test = TestCmd.TestCmd(program='run', interpreter='python', workdir='') +test.run() +test.pass_test(condition=(test.status == 0)) +""", + stderr="PASSED\n", + ) + + self.popen_python( + indata=f"""\ +import sys import TestCmd -test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '') + +sys.path = [r'{self.orig_cwd}'] + sys.path +test = TestCmd.TestCmd(program='run', interpreter='python', workdir='') test.run() + def brag(): sys.stderr.write("printed on success\\n") -test.pass_test(condition = (test.status == 0), function = brag) -""", stderr = "printed on success\nPASSED\n") - # TODO(sgk): SHOULD ALSO TEST FAILURE CONDITIONS +test.pass_test(condition=(test.status == 0), function=brag) +""", + stderr="printed on success\nPASSED\n", + ) + # TODO(sgk): SHOULD ALSO TEST FAILURE CONDITIONS class preserve_TestCase(TestCmdTestCase): def test_preserve(self) -> None: """Test preserve()""" - def cleanup_test(test, cond=None, stdout: str="") -> None: + + def cleanup_test(test, cond=None, stdout: str = "") -> None: save = sys.stdout with closing(StringIO()) as io: sys.stdout = io @@ -1459,12 +1750,14 @@ def cleanup_test(test, cond=None, stdout: str="") -> None: wdir = test.workdir try: test.write('file1', "Test file #1\n") - #test.cleanup() - cleanup_test(test, ) + # test.cleanup() + cleanup_test( + test, + ) assert not os.path.exists(wdir) finally: if os.path.exists(wdir): - shutil.rmtree(wdir, ignore_errors=1) + shutil.rmtree(wdir, ignore_errors=True) test._dirlist.remove(wdir) test = TestCmd.TestCmd(workdir='') @@ -1478,10 +1771,10 @@ def cleanup_test(test, cond=None, stdout: str="") -> None: assert not os.path.exists(wdir) finally: if os.path.exists(wdir): - shutil.rmtree(wdir, ignore_errors = 1) + shutil.rmtree(wdir, ignore_errors=True) test._dirlist.remove(wdir) - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') wdir = test.workdir try: test.write('file3', "Test file #3\n") @@ -1492,10 +1785,10 @@ def cleanup_test(test, cond=None, stdout: str="") -> None: assert not os.path.exists(wdir) finally: if os.path.exists(wdir): - shutil.rmtree(wdir, ignore_errors = 1) + shutil.rmtree(wdir, ignore_errors=True) test._dirlist.remove(wdir) - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') wdir = test.workdir try: test.write('file4', "Test file #4\n") @@ -1508,10 +1801,10 @@ def cleanup_test(test, cond=None, stdout: str="") -> None: assert not os.path.exists(wdir) finally: if os.path.exists(wdir): - shutil.rmtree(wdir, ignore_errors = 1) + shutil.rmtree(wdir, ignore_errors=True) test._dirlist.remove(wdir) - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') wdir = test.workdir try: test.preserve() @@ -1523,27 +1816,27 @@ def cleanup_test(test, cond=None, stdout: str="") -> None: assert os.path.isdir(wdir) finally: if os.path.exists(wdir): - shutil.rmtree(wdir, ignore_errors = 1) + shutil.rmtree(wdir, ignore_errors=True) test._dirlist.remove(wdir) - class program_TestCase(TestCmdTestCase): def test_program(self) -> None: """Test program()""" test = TestCmd.TestCmd() assert test.program is None, 'initialized program?' - test = TestCmd.TestCmd(program = 'test') - assert test.program == os.path.join(os.getcwd(), 'test'), 'uninitialized program' + test = TestCmd.TestCmd(program='test') + assert test.program == os.path.join( + os.getcwd(), 'test' + ), 'uninitialized program' test.program_set('foo') assert test.program == os.path.join(os.getcwd(), 'foo'), 'did not set program' - class read_TestCase(TestCmdTestCase): def test_read(self): """Test read()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'foo') + test = TestCmd.TestCmd(workdir='', subdir='foo') wdir_file1 = os.path.join(test.workdir, 'file1') wdir_file2 = os.path.join(test.workdir, 'file2') wdir_foo_file3 = os.path.join(test.workdir, 'foo', 'file3') @@ -1569,7 +1862,7 @@ def test_read(self): raise try: - test.read(test.workpath('file_x'), mode = 'w') + test.read(test.workpath('file_x'), mode='w') except ValueError: # expect "mode must begin with 'r' pass except: @@ -1577,30 +1870,33 @@ def test_read(self): def _file_matches(file, contents, expected) -> None: contents = to_str(contents) - assert contents == expected, \ - "Expected contents of " + str(file) + "==========\n" + \ - expected + \ - "Actual contents of " + str(file) + "============\n" + \ - contents + assert contents == expected, ( + "Expected contents of " + + str(file) + + "==========\n" + + expected + + "Actual contents of " + + str(file) + + "============\n" + + contents + ) _file_matches(wdir_file1, test.read('file1'), "") _file_matches(wdir_file2, test.read('file2'), "Test\nfile\n#2.\n") - _file_matches(wdir_foo_file3, test.read(['foo', 'file3']), - "Test\nfile\n#3.\n") - _file_matches(wdir_foo_file3, - test.read(UserList(['foo', 'file3'])), - "Test\nfile\n#3.\n") - _file_matches(wdir_file4, test.read('file4', mode = 'r'), - "Test\nfile\n#4.\n") - _file_matches(wdir_file5, test.read('file5', mode = 'rb'), - "Test\r\nfile\r\n#5.\r\n") - + _file_matches(wdir_foo_file3, test.read(['foo', 'file3']), "Test\nfile\n#3.\n") + _file_matches( + wdir_foo_file3, test.read(UserList(['foo', 'file3'])), "Test\nfile\n#3.\n" + ) + _file_matches(wdir_file4, test.read('file4', mode='r'), "Test\nfile\n#4.\n") + _file_matches( + wdir_file5, test.read('file5', mode='rb'), "Test\r\nfile\r\n#5.\r\n" + ) class rmdir_TestCase(TestCmdTestCase): def test_rmdir(self): """Test rmdir()""" - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') try: test.rmdir(['no', 'such', 'dir']) @@ -1609,9 +1905,7 @@ def test_rmdir(self): else: raise Exception("did not catch expected FileNotFoundError") - test.subdir(['sub'], - ['sub', 'dir'], - ['sub', 'dir', 'one']) + test.subdir(['sub'], ['sub', 'dir'], ['sub', 'dir', 'one']) s = test.workpath('sub') s_d = test.workpath('sub', 'dir') @@ -1659,58 +1953,64 @@ def test_run(self) -> None: # Everything before this prepared our "source directory." # Now do the real test. try: - test = TestCmd.TestCmd(program = t.script, - interpreter = 'python', - workdir = '', - subdir = 'script_subdir') + test = TestCmd.TestCmd( + program=t.script, + interpreter='python', + workdir='', + subdir='script_subdir', + ) test.run() - self.run_match(test.stdout(), t.script, "STDOUT", t.workdir, - repr([])) - self.run_match(test.stderr(), t.script, "STDERR", t.workdir, - repr([])) - - test.run(arguments = 'arg1 arg2 arg3') - self.run_match(test.stdout(), t.script, "STDOUT", t.workdir, - repr(['arg1', 'arg2', 'arg3'])) - self.run_match(test.stderr(), t.script, "STDERR", t.workdir, - repr(['arg1', 'arg2', 'arg3'])) - - test.run(program = t.scriptx, arguments = 'foo') - self.run_match(test.stdout(), t.scriptx, "STDOUT", t.workdir, - repr(['foo'])) - self.run_match(test.stderr(), t.scriptx, "STDERR", t.workdir, - repr(['foo'])) - - test.run(chdir = os.curdir, arguments = 'x y z') - self.run_match(test.stdout(), t.script, "STDOUT", test.workdir, - repr(['x', 'y', 'z'])) - self.run_match(test.stderr(), t.script, "STDERR", test.workdir, - repr(['x', 'y', 'z'])) - - test.run(chdir = 'script_subdir') + self.run_match(test.stdout(), t.script, "STDOUT", t.workdir, repr([])) + self.run_match(test.stderr(), t.script, "STDERR", t.workdir, repr([])) + + test.run(arguments='arg1 arg2 arg3') + self.run_match( + test.stdout(), + t.script, + "STDOUT", + t.workdir, + repr(['arg1', 'arg2', 'arg3']), + ) + self.run_match( + test.stderr(), + t.script, + "STDERR", + t.workdir, + repr(['arg1', 'arg2', 'arg3']), + ) + + test.run(program=t.scriptx, arguments='foo') + self.run_match(test.stdout(), t.scriptx, "STDOUT", t.workdir, repr(['foo'])) + self.run_match(test.stderr(), t.scriptx, "STDERR", t.workdir, repr(['foo'])) + + test.run(chdir=os.curdir, arguments='x y z') + self.run_match( + test.stdout(), t.script, "STDOUT", test.workdir, repr(['x', 'y', 'z']) + ) + self.run_match( + test.stderr(), t.script, "STDERR", test.workdir, repr(['x', 'y', 'z']) + ) + + test.run(chdir='script_subdir') script_subdir = test.workpath('script_subdir') - self.run_match(test.stdout(), t.script, "STDOUT", script_subdir, - repr([])) - self.run_match(test.stderr(), t.script, "STDERR", script_subdir, - repr([])) + self.run_match(test.stdout(), t.script, "STDOUT", script_subdir, repr([])) + self.run_match(test.stderr(), t.script, "STDERR", script_subdir, repr([])) - test.run(program = t.script1, interpreter = ['python', '-x']) - self.run_match(test.stdout(), t.script1, "STDOUT", t.workdir, - repr([])) - self.run_match(test.stderr(), t.script1, "STDERR", t.workdir, - repr([])) + test.run(program=t.script1, interpreter=['python', '-x']) + self.run_match(test.stdout(), t.script1, "STDOUT", t.workdir, repr([])) + self.run_match(test.stderr(), t.script1, "STDERR", t.workdir, repr([])) try: - test.run(chdir = 'no_subdir') + test.run(chdir='no_subdir') except OSError: pass - test.run(program = 'no_script', interpreter = 'python') + test.run(program='no_script', interpreter='python') assert test.status is not None, test.status try: - test.run(program = 'no_script', interpreter = 'no_interpreter') + test.run(program='no_script', interpreter='no_interpreter') except OSError: # Python versions that use subprocess throw an OSError # exception when they try to execute something that @@ -1722,61 +2022,59 @@ def test_run(self) -> None: # a non-zero exit status. assert test.status is not None, test.status - testx = TestCmd.TestCmd(program = t.scriptx, - workdir = '', - subdir = 't.scriptx_subdir') + testx = TestCmd.TestCmd( + program=t.scriptx, workdir='', subdir='t.scriptx_subdir' + ) testx.run() - self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.workdir, - repr([])) - self.run_match(testx.stderr(), t.scriptx, "STDERR", t.workdir, - repr([])) - - testx.run(arguments = 'foo bar') - self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.workdir, - repr(['foo', 'bar'])) - self.run_match(testx.stderr(), t.scriptx, "STDERR", t.workdir, - repr(['foo', 'bar'])) - - testx.run(program = t.script, interpreter = 'python', arguments = 'bar') - self.run_match(testx.stdout(), t.script, "STDOUT", t.workdir, - repr(['bar'])) - self.run_match(testx.stderr(), t.script, "STDERR", t.workdir, - repr(['bar'])) - - testx.run(chdir = os.curdir, arguments = 'baz') - self.run_match(testx.stdout(), t.scriptx, "STDOUT", testx.workdir, - repr(['baz'])) - self.run_match(testx.stderr(), t.scriptx, "STDERR", testx.workdir, - repr(['baz'])) - - testx.run(chdir = 't.scriptx_subdir') + self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.workdir, repr([])) + self.run_match(testx.stderr(), t.scriptx, "STDERR", t.workdir, repr([])) + + testx.run(arguments='foo bar') + self.run_match( + testx.stdout(), t.scriptx, "STDOUT", t.workdir, repr(['foo', 'bar']) + ) + self.run_match( + testx.stderr(), t.scriptx, "STDERR", t.workdir, repr(['foo', 'bar']) + ) + + testx.run(program=t.script, interpreter='python', arguments='bar') + self.run_match(testx.stdout(), t.script, "STDOUT", t.workdir, repr(['bar'])) + self.run_match(testx.stderr(), t.script, "STDERR", t.workdir, repr(['bar'])) + + testx.run(chdir=os.curdir, arguments='baz') + self.run_match( + testx.stdout(), t.scriptx, "STDOUT", testx.workdir, repr(['baz']) + ) + self.run_match( + testx.stderr(), t.scriptx, "STDERR", testx.workdir, repr(['baz']) + ) + + testx.run(chdir='t.scriptx_subdir') t.scriptx_subdir = testx.workpath('t.scriptx_subdir') - self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.scriptx_subdir, - repr([])) - self.run_match(testx.stderr(), t.scriptx, "STDERR", t.scriptx_subdir, - repr([])) + self.run_match( + testx.stdout(), t.scriptx, "STDOUT", t.scriptx_subdir, repr([]) + ) + self.run_match( + testx.stderr(), t.scriptx, "STDERR", t.scriptx_subdir, repr([]) + ) - testx.run(program = t.script1, interpreter = ('python', '-x')) - self.run_match(testx.stdout(), t.script1, "STDOUT", t.workdir, - repr([])) - self.run_match(testx.stderr(), t.script1, "STDERR", t.workdir, - repr([])) + testx.run(program=t.script1, interpreter=('python', '-x')) + self.run_match(testx.stdout(), t.script1, "STDOUT", t.workdir, repr([])) + self.run_match(testx.stderr(), t.script1, "STDERR", t.workdir, repr([])) s = os.path.join('.', t.scriptx) - testx.run(program = [s]) - self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.workdir, - repr([])) - self.run_match(testx.stderr(), t.scriptx, "STDERR", t.workdir, - repr([])) + testx.run(program=[s]) + self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.workdir, repr([])) + self.run_match(testx.stderr(), t.scriptx, "STDERR", t.workdir, repr([])) try: - testx.run(chdir = 'no_subdir') + testx.run(chdir='no_subdir') except OSError: pass try: - testx.run(program = 'no_program') + testx.run(program='no_program') except OSError: # Python versions that use subprocess throw an OSError # exception when they try to execute something that @@ -1788,15 +2086,13 @@ def test_run(self) -> None: # a non-zero exit status. assert test.status is not None - test1 = TestCmd.TestCmd(program = t.script1, - interpreter = ['python', '-x'], - workdir = '') + test1 = TestCmd.TestCmd( + program=t.script1, interpreter=['python', '-x'], workdir='' + ) test1.run() - self.run_match(test1.stdout(), t.script1, "STDOUT", t.workdir, - repr([])) - self.run_match(test1.stderr(), t.script1, "STDERR", t.workdir, - repr([])) + self.run_match(test1.stdout(), t.script1, "STDOUT", t.workdir, repr([])) + self.run_match(test1.stderr(), t.script1, "STDERR", t.workdir, repr([])) finally: os.chdir(t.orig_cwd) @@ -1814,16 +2110,16 @@ def start(self, additional_argument=None, **kw): return TestCmd.TestCmd.start(self, **kw) try: - test = MyTestCmdSubclass(program = t.script, - interpreter = 'python', - workdir = '', - subdir = 'script_subdir') + test = MyTestCmdSubclass( + program=t.script, + interpreter='python', + workdir='', + subdir='script_subdir', + ) test.run() - self.run_match(test.stdout(), t.script, "STDOUT", t.workdir, - repr([])) - self.run_match(test.stderr(), t.script, "STDERR", t.workdir, - repr([])) + self.run_match(test.stdout(), t.script, "STDOUT", t.workdir, repr([])) + self.run_match(test.stderr(), t.script, "STDERR", t.workdir, repr([])) finally: os.chdir(t.orig_cwd) @@ -1841,26 +2137,23 @@ def test_run_verbose(self) -> None: try: # Test calling TestCmd() with an explicit verbose = 1. - test = TestCmd.TestCmd(program = t.script, - interpreter = 'python', - workdir = '', - verbose = 1) + test = TestCmd.TestCmd( + program=t.script, interpreter='python', workdir='', verbose=1 + ) with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - test.run(arguments = ['arg1 arg2']) + test.run(arguments=['arg1 arg2']) o = sys.stdout.getvalue() assert o == '', o e = sys.stderr.getvalue() - expect = f'python "{t.script_path}" "arg1 arg2\"\n' - assert expect == e, (expect, e) + expect = f'python "{t.script_path}" "arg1 arg2"\n' + self.assertEqual(expect, e) - testx = TestCmd.TestCmd(program = t.scriptx, - workdir = '', - verbose = 1) + testx = TestCmd.TestCmd(program=t.scriptx, workdir='', verbose=1) with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - testx.run(arguments = ['arg1 arg2']) - expect = f'"{t.scriptx_path}" "arg1 arg2\"\n' + testx.run(arguments=['arg1 arg2']) + expect = f'"{t.scriptx_path}" "arg1 arg2"\n' o = sys.stdout.getvalue() assert o == '', o e = sys.stderr.getvalue() @@ -1888,54 +2181,58 @@ def test_run_verbose(self) -> None: %s============ END STDERR """ - test = TestCmd.TestCmd(program = t.script, - interpreter = 'python', - workdir = '', - verbose = 2) + test = TestCmd.TestCmd( + program=t.script, interpreter='python', workdir='', verbose=2 + ) with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - test.run(arguments = ['arg1 arg2']) + test.run(arguments=['arg1 arg2']) line_fmt = "script: %s: %s: ['arg1 arg2']\n" stdout_line = line_fmt % ('STDOUT', t.sub_dir) stderr_line = line_fmt % ('STDERR', t.sub_dir) - expect = outerr_fmt % (len(stdout_line), stdout_line, - len(stderr_line), stderr_line) + expect = outerr_fmt % ( + len(stdout_line), + stdout_line, + len(stderr_line), + stderr_line, + ) o = sys.stdout.getvalue() assert expect == o, (expect, o) - expect = f'python "{t.script_path}" "arg1 arg2\"\n' + expect = f'python "{t.script_path}" "arg1 arg2"\n' e = sys.stderr.getvalue() assert e == expect, (e, expect) - testx = TestCmd.TestCmd(program = t.scriptx, - workdir = '', - verbose = 2) + testx = TestCmd.TestCmd(program=t.scriptx, workdir='', verbose=2) with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - testx.run(arguments = ['arg1 arg2']) + testx.run(arguments=['arg1 arg2']) line_fmt = "scriptx.bat: %s: %s: ['arg1 arg2']\n" stdout_line = line_fmt % ('STDOUT', t.sub_dir) stderr_line = line_fmt % ('STDERR', t.sub_dir) - expect = outerr_fmt % (len(stdout_line), stdout_line, - len(stderr_line), stderr_line) + expect = outerr_fmt % ( + len(stdout_line), + stdout_line, + len(stderr_line), + stderr_line, + ) o = sys.stdout.getvalue() assert expect == o, (expect, o) - expect = f'"{t.scriptx_path}" "arg1 arg2\"\n' + expect = f'"{t.scriptx_path}" "arg1 arg2"\n' e = sys.stderr.getvalue() assert e == expect, (e, expect) # Test calling TestCmd() with an explicit verbose = 3. - test = TestCmd.TestCmd(program = t.scriptout, - interpreter = 'python', - workdir = '', - verbose = 2) + test = TestCmd.TestCmd( + program=t.scriptout, interpreter='python', workdir='', verbose=2 + ) with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - test.run(arguments = ['arg1 arg2']) + test.run(arguments=['arg1 arg2']) line_fmt = "scriptout: %s: %s: ['arg1 arg2']\n" stdout_line = line_fmt % ('STDOUT', t.sub_dir) @@ -1944,66 +2241,69 @@ def test_run_verbose(self) -> None: assert expect == o, (expect, o) e = sys.stderr.getvalue() - expect = f'python "{t.scriptout_path}" "arg1 arg2\"\n' + expect = f'python "{t.scriptout_path}" "arg1 arg2"\n' assert e == expect, (e, expect) - test = TestCmd.TestCmd(program = t.scriptout, - interpreter = 'python', - workdir = '', - verbose = 3) + test = TestCmd.TestCmd( + program=t.scriptout, interpreter='python', workdir='', verbose=3 + ) with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - test.run(arguments = ['arg1 arg2']) + test.run(arguments=['arg1 arg2']) line_fmt = "scriptout: %s: %s: ['arg1 arg2']\n" stdout_line = line_fmt % ('STDOUT', t.sub_dir) - expect = outerr_fmt % (len(stdout_line), stdout_line, - '0', '') + expect = outerr_fmt % (len(stdout_line), stdout_line, '0', '') o = sys.stdout.getvalue() assert expect == o, (expect, o) e = sys.stderr.getvalue() - expect = f'python "{t.scriptout_path}" "arg1 arg2\"\n' + expect = f'python "{t.scriptout_path}" "arg1 arg2"\n' assert e == expect, (e, expect) # Test letting TestCmd() pick up verbose = 2 from the environment. os.environ['TESTCMD_VERBOSE'] = '2' - test = TestCmd.TestCmd(program = t.script, - interpreter = 'python', - workdir = '') + test = TestCmd.TestCmd(program=t.script, interpreter='python', workdir='') with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - test.run(arguments = ['arg1 arg2']) + test.run(arguments=['arg1 arg2']) line_fmt = "script: %s: %s: ['arg1 arg2']\n" stdout_line = line_fmt % ('STDOUT', t.sub_dir) stderr_line = line_fmt % ('STDERR', t.sub_dir) - expect = outerr_fmt % (len(stdout_line), stdout_line, - len(stderr_line), stderr_line) + expect = outerr_fmt % ( + len(stdout_line), + stdout_line, + len(stderr_line), + stderr_line, + ) o = sys.stdout.getvalue() assert expect == o, (expect, o) - expect = f'python "{t.script_path}" "arg1 arg2\"\n' + expect = f'python "{t.script_path}" "arg1 arg2"\n' e = sys.stderr.getvalue() assert e == expect, (e, expect) - testx = TestCmd.TestCmd(program = t.scriptx, - workdir = '') + testx = TestCmd.TestCmd(program=t.scriptx, workdir='') with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - testx.run(arguments = ['arg1 arg2']) + testx.run(arguments=['arg1 arg2']) line_fmt = "scriptx.bat: %s: %s: ['arg1 arg2']\n" stdout_line = line_fmt % ('STDOUT', t.sub_dir) stderr_line = line_fmt % ('STDERR', t.sub_dir) - expect = outerr_fmt % (len(stdout_line), stdout_line, - len(stderr_line), stderr_line) + expect = outerr_fmt % ( + len(stdout_line), + stdout_line, + len(stderr_line), + stderr_line, + ) o = sys.stdout.getvalue() assert expect == o, (expect, o) - expect = f'"{t.scriptx_path}" "arg1 arg2\"\n' + expect = f'"{t.scriptx_path}" "arg1 arg2"\n' e = sys.stderr.getvalue() assert e == expect, (e, expect) @@ -2011,30 +2311,27 @@ def test_run_verbose(self) -> None: os.environ['TESTCMD_VERBOSE'] = '1' - test = TestCmd.TestCmd(program = t.script, - interpreter = 'python', - workdir = '', - verbose = 1) + test = TestCmd.TestCmd( + program=t.script, interpreter='python', workdir='', verbose=1 + ) with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - test.run(arguments = ['arg1 arg2']) + test.run(arguments=['arg1 arg2']) o = sys.stdout.getvalue() assert o == '', o e = sys.stderr.getvalue() - expect = f'python "{t.script_path}" "arg1 arg2\"\n' + expect = f'python "{t.script_path}" "arg1 arg2"\n' assert expect == e, (expect, e) - testx = TestCmd.TestCmd(program = t.scriptx, - workdir = '', - verbose = 1) + testx = TestCmd.TestCmd(program=t.scriptx, workdir='', verbose=1) with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr: - testx.run(arguments = ['arg1 arg2']) - expect = f'"{t.scriptx_path}" "arg1 arg2\"\n' + testx.run(arguments=['arg1 arg2']) o = sys.stdout.getvalue() assert o == '', o e = sys.stderr.getvalue() - assert expect == e, (expect, e) + expect = f'"{t.scriptx_path}" "arg1 arg2"\n' + self.assertEqual(expect, e) finally: sys.stdout = save_stdout @@ -2043,25 +2340,31 @@ def test_run_verbose(self) -> None: os.environ['TESTCMD_VERBOSE'] = '' - class set_diff_function_TestCase(TestCmdTestCase): def test_set_diff_function(self) -> None: """Test set_diff_function()""" - self.popen_python(fr"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd() -test.diff("a\n", "a\n") +test.diff("a\\n", "a\\n") test.set_diff_function('diff_re') -test.diff(".\n", "a\n") +test.diff(".\\n", "a\\n") sys.exit(0) -""") +""", + ) def test_set_diff_function_stdout(self) -> None: """Test set_diff_function(): stdout""" - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + self.popen_python( + indata=f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd() print("diff:") test.diff("a\\n", "a\\n") @@ -2074,7 +2377,7 @@ def test_set_diff_function_stdout(self) -> None: test.diff_stdout(".\\n", "a\\n") sys.exit(0) """, - stdout="""\ + stdout="""\ diff: diff_stdout: diff: @@ -2083,13 +2386,17 @@ def test_set_diff_function_stdout(self) -> None: --- > a diff_stdout: -""") +""", + ) def test_set_diff_function_stderr(self) -> None: - """Test set_diff_function(): stderr """ - self.popen_python(f"""import sys -sys.path = [r'{self.orig_cwd}'] + sys.path + """Test set_diff_function(): stderr""" + self.popen_python( + f"""\ +import sys import TestCmd + +sys.path = [r'{self.orig_cwd}'] + sys.path test = TestCmd.TestCmd() print("diff:") test.diff("a\\n", "a\\n") @@ -2102,7 +2409,7 @@ def test_set_diff_function_stderr(self) -> None: test.diff_stderr(".\\n", "a\\n") sys.exit(0) """, - stdout="""\ + stdout="""\ diff: diff_stderr: diff: @@ -2111,8 +2418,8 @@ def test_set_diff_function_stderr(self) -> None: --- > a diff_stderr: -""") - +""", + ) class set_match_function_TestCase(TestCmdTestCase): @@ -2128,7 +2435,7 @@ def test_set_match_function(self) -> None: assert test.match("abcde\n", "abcde\n") def test_set_match_function_stdout(self) -> None: - """Test set_match_function(): stdout """ + """Test set_match_function(): stdout""" test = TestCmd.TestCmd() assert test.match("abcde\n", "a.*e\n") assert test.match("abcde\n", "abcde\n") @@ -2143,7 +2450,7 @@ def test_set_match_function_stdout(self) -> None: assert test.match_stdout("abcde\n", "abcde\n") def test_set_match_function_stderr(self) -> None: - """Test set_match_function(): stderr """ + """Test set_match_function(): stderr""" test = TestCmd.TestCmd() assert test.match("abcde\n", "a.*e\n") assert test.match("abcde\n", "abcde\n") @@ -2158,7 +2465,6 @@ def test_set_match_function_stderr(self) -> None: assert test.match_stderr("abcde\n", "abcde\n") - class sleep_TestCase(TestCmdTestCase): def test_sleep(self) -> None: """Test sleep()""" @@ -2168,36 +2474,49 @@ def test_sleep(self) -> None: test.sleep() end = time.perf_counter() diff = end - start - assert diff > 0.9, f"only slept {diff:f} seconds (start {start:f}, end {end:f}), not default" + assert ( + diff > 0.9 + ), f"only slept {diff:f} seconds (start {start:f}, end {end:f}), not default" start = time.perf_counter() test.sleep(3) end = time.perf_counter() diff = end - start - assert diff > 2.9, f"only slept {diff:f} seconds (start {start:f}, end {end:f}), not 3" - + assert ( + diff > 2.9 + ), f"only slept {diff:f} seconds (start {start:f}, end {end:f}), not 3" class stderr_TestCase(TestCmdTestCase): def test_stderr(self): """Test stderr()""" - run_env = TestCmd.TestCmd(workdir = '') - run_env.write('run1', """import sys + run_env = TestCmd.TestCmd(workdir='') + run_env.write( + 'run1', + """\ +import sys + sys.stdout.write("run1 STDOUT %s\\n" % sys.argv[1:]) sys.stdout.write("run1 STDOUT second line\\n") sys.stderr.write("run1 STDERR %s\\n" % sys.argv[1:]) sys.stderr.write("run1 STDERR second line\\n") -""") - run_env.write('run2', """import sys +""", + ) + run_env.write( + 'run2', + """\ +import sys + sys.stdout.write("run2 STDOUT %s\\n" % sys.argv[1:]) sys.stdout.write("run2 STDOUT second line\\n") sys.stderr.write("run2 STDERR %s\\n" % sys.argv[1:]) sys.stderr.write("run2 STDERR second line\\n") -""") +""", + ) os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. - test = TestCmd.TestCmd(interpreter = 'python', workdir = '') + test = TestCmd.TestCmd(interpreter='python', workdir='') try: output = test.stderr() except IndexError: @@ -2206,25 +2525,24 @@ def test_stderr(self): if output is not None: raise IndexError(f"got unexpected output:\n{output}") test.program_set('run1') - test.run(arguments = 'foo bar') + test.run(arguments='foo bar') test.program_set('run2') - test.run(arguments = 'snafu') + test.run(arguments='snafu') # XXX SHOULD TEST ABSOLUTE NUMBER AS WELL output = test.stderr() assert output == "run2 STDERR ['snafu']\nrun2 STDERR second line\n", output - output = test.stderr(run = -1) + output = test.stderr(run=-1) assert output == "run1 STDERR ['foo', 'bar']\nrun1 STDERR second line\n", output - class command_args_TestCase(TestCmdTestCase): def test_command_args(self) -> None: """Test command_args()""" - run_env = TestCmd.TestCmd(workdir = '') + run_env = TestCmd.TestCmd(workdir='') os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') r = test.command_args('prog') expect = [run_env.workpath('prog')] @@ -2268,7 +2586,7 @@ def test_command_args(self) -> None: self.assertEqual(expect, r) # Test arguments = dict - r = test.command_args(interpreter='PYTHON', arguments={'VAR1':'1'}) + r = test.command_args(interpreter='PYTHON', arguments={'VAR1': '1'}) expect = ['PYTHON', default_prog, 'VAR1=1'] self.assertEqual(expect, r) @@ -2297,21 +2615,23 @@ def setup_run_scripts(self): t.recv_script = 'script_recv' t.recv_script_path = t.run_env.workpath(t.sub_dir, t.recv_script) t.recv_out_path = t.run_env.workpath('script_recv.out') - text = f"""import os + text = f"""\ +import os import sys class Unbuffered: def __init__(self, file): self.file = file + def write(self, arg): self.file.write(arg) self.file.flush() + def __getattr__(self, attr): return getattr(self.file, attr) sys.stdout = Unbuffered(sys.stdout) sys.stderr = Unbuffered(sys.stderr) - sys.stdout.write('script_recv: STDOUT\\n') sys.stderr.write('script_recv: STDERR\\n') with open(r'{t.recv_out_path}', 'w') as logfp: @@ -2342,40 +2662,50 @@ def test_start(self) -> None: # Everything before this prepared our "source directory." # Now do the real test. try: - test = TestCmd.TestCmd(program = t.script, - interpreter = 'python', - workdir = '', - subdir = 'script_subdir') + test = TestCmd.TestCmd( + program=t.script, + interpreter='python', + workdir='', + subdir='script_subdir', + ) p = test.start() - self.run_match(p.stdout.read(), t.script, "STDOUT", t.workdir, - repr([])) - self.run_match(p.stderr.read(), t.script, "STDERR", t.workdir, - repr([])) + self.run_match(p.stdout.read(), t.script, "STDOUT", t.workdir, repr([])) + self.run_match(p.stderr.read(), t.script, "STDERR", t.workdir, repr([])) p.wait() self._cleanup(p) p = test.start(arguments='arg1 arg2 arg3') - self.run_match(p.stdout.read(), t.script, "STDOUT", t.workdir, - repr(['arg1', 'arg2', 'arg3'])) - self.run_match(p.stderr.read(), t.script, "STDERR", t.workdir, - repr(['arg1', 'arg2', 'arg3'])) + self.run_match( + p.stdout.read(), + t.script, + "STDOUT", + t.workdir, + repr(['arg1', 'arg2', 'arg3']), + ) + self.run_match( + p.stderr.read(), + t.script, + "STDERR", + t.workdir, + repr(['arg1', 'arg2', 'arg3']), + ) p.wait() self._cleanup(p) p = test.start(program=t.scriptx, arguments='foo') - self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir, - repr(['foo'])) - self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir, - repr(['foo'])) + self.run_match( + p.stdout.read(), t.scriptx, "STDOUT", t.workdir, repr(['foo']) + ) + self.run_match( + p.stderr.read(), t.scriptx, "STDERR", t.workdir, repr(['foo']) + ) p.wait() self._cleanup(p) p = test.start(program=t.script1, interpreter=['python', '-x']) - self.run_match(p.stdout.read(), t.script1, "STDOUT", t.workdir, - repr([])) - self.run_match(p.stderr.read(), t.script1, "STDERR", t.workdir, - repr([])) + self.run_match(p.stdout.read(), t.script1, "STDOUT", t.workdir, repr([])) + self.run_match(p.stderr.read(), t.script1, "STDERR", t.workdir, repr([])) p.wait() self._cleanup(p) @@ -2399,48 +2729,46 @@ def test_start(self) -> None: # a non-zero exit status. assert status is not None, status - testx = TestCmd.TestCmd(program = t.scriptx, - workdir = '', - subdir = 't.scriptx_subdir') + testx = TestCmd.TestCmd( + program=t.scriptx, workdir='', subdir='t.scriptx_subdir' + ) p = testx.start() - self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir, - repr([])) - self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir, - repr([])) + self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir, repr([])) + self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir, repr([])) p.wait() self._cleanup(p) p = testx.start(arguments='foo bar') - self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir, - repr(['foo', 'bar'])) - self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir, - repr(['foo', 'bar'])) + self.run_match( + p.stdout.read(), t.scriptx, "STDOUT", t.workdir, repr(['foo', 'bar']) + ) + self.run_match( + p.stderr.read(), t.scriptx, "STDERR", t.workdir, repr(['foo', 'bar']) + ) p.wait() self._cleanup(p) p = testx.start(program=t.script, interpreter='python', arguments='bar') - self.run_match(p.stdout.read(), t.script, "STDOUT", t.workdir, - repr(['bar'])) - self.run_match(p.stderr.read(), t.script, "STDERR", t.workdir, - repr(['bar'])) + self.run_match( + p.stdout.read(), t.script, "STDOUT", t.workdir, repr(['bar']) + ) + self.run_match( + p.stderr.read(), t.script, "STDERR", t.workdir, repr(['bar']) + ) p.wait() self._cleanup(p) p = testx.start(program=t.script1, interpreter=('python', '-x')) - self.run_match(p.stdout.read(), t.script1, "STDOUT", t.workdir, - repr([])) - self.run_match(p.stderr.read(), t.script1, "STDERR", t.workdir, - repr([])) + self.run_match(p.stdout.read(), t.script1, "STDOUT", t.workdir, repr([])) + self.run_match(p.stderr.read(), t.script1, "STDERR", t.workdir, repr([])) p.wait() self._cleanup(p) s = os.path.join('.', t.scriptx) p = testx.start(program=[s]) - self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir, - repr([])) - self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir, - repr([])) + self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir, repr([])) + self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir, repr([])) p.wait() self._cleanup(p) @@ -2462,15 +2790,13 @@ def test_start(self) -> None: except OSError: pass - test1 = TestCmd.TestCmd(program = t.script1, - interpreter = ['python', '-x'], - workdir = '') + test1 = TestCmd.TestCmd( + program=t.script1, interpreter=['python', '-x'], workdir='' + ) p = test1.start() - self.run_match(p.stdout.read(), t.script1, "STDOUT", t.workdir, - repr([])) - self.run_match(p.stderr.read(), t.script1, "STDERR", t.workdir, - repr([])) + self.run_match(p.stdout.read(), t.script1, "STDOUT", t.workdir, repr([])) + self.run_match(p.stderr.read(), t.script1, "STDERR", t.workdir, repr([])) p.wait() self._cleanup(p) @@ -2485,11 +2811,12 @@ def test_finish(self) -> None: # Everything before this prepared our "source directory." # Now do the real test. try: - - test = TestCmd.TestCmd(program = t.recv_script, - interpreter = 'python', - workdir = '', - subdir = 'script_subdir') + test = TestCmd.TestCmd( + program=t.recv_script, + interpreter='python', + workdir='', + subdir='script_subdir', + ) test.start(stdin=1) test.finish() @@ -2546,19 +2873,21 @@ def test_recv(self) -> None: # Everything before this prepared our "source directory." # Now do the real test. try: - test = TestCmd.TestCmd(program = t.script, - interpreter = 'python', - workdir = '', - subdir = 'script_subdir') + test = TestCmd.TestCmd( + program=t.script, + interpreter='python', + workdir='', + subdir='script_subdir', + ) p = test.start() stdout = p.recv() while stdout == '': import time + time.sleep(1) stdout = p.recv() - self.run_match(stdout, t.script, "STDOUT", t.workdir, - repr([])) + self.run_match(stdout, t.script, "STDOUT", t.workdir, repr([])) p.wait() finally: @@ -2572,23 +2901,23 @@ def test_recv_err(self) -> None: # Everything before this prepared our "source directory." # Now do the real test. try: - - test = TestCmd.TestCmd(program = t.script, - interpreter = 'python', - workdir = '', - subdir = 'script_subdir') + test = TestCmd.TestCmd( + program=t.script, + interpreter='python', + workdir='', + subdir='script_subdir', + ) p = test.start() stderr = p.recv_err() while stderr == '': import time + time.sleep(1) stderr = p.recv_err() - self.run_match(stderr, t.script, "STDERR", t.workdir, - repr([])) + self.run_match(stderr, t.script, "STDERR", t.workdir, repr([])) p.wait() - finally: os.chdir(t.orig_cwd) @@ -2600,11 +2929,12 @@ def test_send(self) -> None: # Everything before this prepared our "source directory." # Now do the real test. try: - - test = TestCmd.TestCmd(program = t.recv_script, - interpreter = 'python', - workdir = '', - subdir = 'script_subdir') + test = TestCmd.TestCmd( + program=t.recv_script, + interpreter='python', + workdir='', + subdir='script_subdir', + ) p = test.start(stdin=1) input = 'stdin.write() input to the receive script\n' @@ -2614,7 +2944,9 @@ def test_send(self) -> None: with open(t.recv_out_path, 'r') as f: result = to_str(f.read()) expect = f"script_recv: {input}" - assert result == expect, f"Result:[{result}] should match\nExpected:[{expect}]" + assert ( + result == expect + ), f"Result:[{result}] should match\nExpected:[{expect}]" # TODO: Python 3.6+ ResourceWarning: unclosed file <_io.BufferedReader name=9> p = test.start(stdin=1) @@ -2639,11 +2971,12 @@ def __FLAKY__test_send_recv(self) -> None: # Everything before this prepared our "source directory." # Now do the real test. try: - - test = TestCmd.TestCmd(program = t.recv_script, - interpreter = 'python', - workdir = '', - subdir = 'script_subdir') + test = TestCmd.TestCmd( + program=t.recv_script, + interpreter='python', + workdir='', + subdir='script_subdir', + ) def do_send_recv(p, input): send, stdout, stderr = p.send_recv(input) @@ -2691,67 +3024,78 @@ def do_send_recv(p, input): os.chdir(t.orig_cwd) - class stdin_TestCase(TestCmdTestCase): def test_stdin(self) -> None: """Test stdin()""" - run_env = TestCmd.TestCmd(workdir = '') - run_env.write('run', """\ + run_env = TestCmd.TestCmd(workdir='') + run_env.write( + 'run', + """\ import fileinput + for line in fileinput.input(): print('Y'.join(line[:-1].split('X'))) -""") +""", + ) run_env.write('input', "X on X this X line X\n") os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. - test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '') - test.run(arguments = 'input') + test = TestCmd.TestCmd(program='run', interpreter='python', workdir='') + test.run(arguments='input') assert test.stdout() == "Y on Y this Y line Y\n" - test.run(stdin = "X is X here X tooX\n") + test.run(stdin="X is X here X tooX\n") assert test.stdout() == "Y is Y here Y tooY\n" - test.run(stdin = """X here X + test.run( + stdin="""X here X X there X -""") +""" + ) assert test.stdout() == "Y here Y\nY there Y\n" - test.run(stdin = ["X line X\n", "X another X\n"]) + test.run(stdin=["X line X\n", "X another X\n"]) assert test.stdout() == "Y line Y\nY another Y\n" - class stdout_TestCase(TestCmdTestCase): def test_stdout(self): """Test stdout()""" - run_env = TestCmd.TestCmd(workdir = '') - run_env.write('run1', """\ + run_env = TestCmd.TestCmd(workdir='') + run_env.write( + 'run1', + """\ import sys + sys.stdout.write("run1 STDOUT %s\\n" % sys.argv[1:]) sys.stdout.write("run1 STDOUT second line\\n") sys.stderr.write("run1 STDERR %s\\n" % sys.argv[1:]) sys.stderr.write("run1 STDERR second line\\n") -""") - run_env.write('run2', """\ +""", + ) + run_env.write( + 'run2', + """\ import sys sys.stdout.write("run2 STDOUT %s\\n" % sys.argv[1:]) sys.stdout.write("run2 STDOUT second line\\n") sys.stderr.write("run2 STDERR %s\\n" % sys.argv[1:]) sys.stderr.write("run2 STDERR second line\\n") -""") +""", + ) os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. - test = TestCmd.TestCmd(interpreter = 'python', workdir = '') + test = TestCmd.TestCmd(interpreter='python', workdir='') output = test.stdout() if output is not None: raise IndexError(f"got unexpected output:\n\t`{output}'\n") test.program_set('run1') - test.run(arguments = 'foo bar') + test.run(arguments='foo bar') test.program_set('run2') - test.run(arguments = 'snafu') + test.run(arguments='snafu') # XXX SHOULD TEST ABSOLUTE NUMBER AS WELL output = test.stdout() assert output == "run2 STDOUT ['snafu']\nrun2 STDOUT second line\n", output - output = test.stdout(run = -1) + output = test.stdout(run=-1) assert output == "run1 STDOUT ['foo', 'bar']\nrun1 STDOUT second line\n", output @@ -2801,7 +3145,7 @@ class symlink_TestCase(TestCmdTestCase): @unittest.skipIf(sys.platform == 'win32', "Skip symlink test on win32") def test_symlink(self) -> None: """Test symlink()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'foo') + test = TestCmd.TestCmd(workdir='', subdir='foo') wdir_file1 = os.path.join(test.workdir, 'file1') wdir_target1 = os.path.join(test.workdir, 'target1') wdir_foo_file2 = os.path.join(test.workdir, 'foo', 'file2') @@ -2826,7 +3170,6 @@ def test_symlink(self) -> None: assert os.path.exists(wdir_foo_file2) - class tempdir_TestCase(TestCmdTestCase): def setUp(self) -> None: TestCmdTestCase.setUp(self) @@ -2860,6 +3203,7 @@ def test_tempdir(self) -> None: timeout_script = """\ import sys import time + seconds = int(sys.argv[1]) sys.stdout.write('sleeping %s\\n' % seconds) sys.stdout.flush() @@ -2869,6 +3213,7 @@ def test_tempdir(self) -> None: sys.exit(0) """ + class timeout_TestCase(TestCmdTestCase): def test_initialization(self) -> None: """Test initializating a TestCmd with a timeout""" @@ -2914,7 +3259,7 @@ def test_run(self) -> None: assert test.stdout() == 'sleeping 6\n', test.stdout() # This method has been removed - #def test_set_timeout(self): + # def test_set_timeout(self): # """Test set_timeout()""" # test = TestCmd.TestCmd(workdir='', timeout=2) # test.write('sleep.py', timeout_script) @@ -2940,11 +3285,10 @@ def test_run(self) -> None: # assert test.stdout() == 'sleeping 8\n', test.stdout() - class unlink_TestCase(TestCmdTestCase): def test_unlink(self): """Test unlink()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'foo') + test = TestCmd.TestCmd(workdir='', subdir='foo') wdir_file1 = os.path.join(test.workdir, 'file1') wdir_file2 = os.path.join(test.workdir, 'file2') wdir_foo_file3a = os.path.join(test.workdir, 'foo', 'file3a') @@ -2967,7 +3311,7 @@ def test_unlink(self): try: contents = test.unlink('no_file') - except OSError: # expect "No such file or directory" + except OSError: # expect "No such file or directory" pass except: raise @@ -2996,7 +3340,7 @@ def test_unlink(self): try: try: test.unlink('file5') - except OSError: # expect "Permission denied" + except OSError: # expect "Permission denied" pass except: raise @@ -3008,7 +3352,7 @@ def test_unlink(self): class unlink_files_TestCase(TestCmdTestCase): def test_unlink_files(self): """Test unlink_files()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'foo') + test = TestCmd.TestCmd(workdir='', subdir='foo') wdir_file1 = os.path.join(test.workdir, 'file1') wdir_file2 = os.path.join(test.workdir, 'file2') wdir_foo_file3a = os.path.join(test.workdir, 'foo', 'file3a') @@ -3044,43 +3388,24 @@ def test_unlink_files(self): with open(wdir_file5, 'w') as f: f.write("") - test.unlink_files('', [ - 'no_file_a', - 'no_file_b', - ]) - - test.unlink_files('', [ - 'file1', - 'file2', - ]) + test.unlink_files('', ['no_file_a', 'no_file_b']) + test.unlink_files('', ['file1', 'file2']) assert not os.path.exists(wdir_file1) assert not os.path.exists(wdir_file2) - test.unlink_files('foo', [ - 'file3a', - 'file3b', - ]) + test.unlink_files('foo', ['file3a', 'file3b']) assert not os.path.exists(wdir_foo_file3a) assert not os.path.exists(wdir_foo_file3b) - test.unlink_files(['foo'], [ - 'file3c', - 'file3d', - ]) + test.unlink_files(['foo'], ['file3c', 'file3d']) assert not os.path.exists(wdir_foo_file3c) assert not os.path.exists(wdir_foo_file3d) - test.unlink_files('', [ - ['foo', 'file4a'], - ['foo', 'file4b'], - ]) + test.unlink_files('', [['foo', 'file4a'], ['foo', 'file4b']]) assert not os.path.exists(wdir_foo_file4a) assert not os.path.exists(wdir_foo_file4b) - test.unlink_files([''], [ - ['foo', 'file4c'], - ['foo', 'file4d'], - ]) + test.unlink_files([''], [['foo', 'file4c'], ['foo', 'file4d']]) assert not os.path.exists(wdir_foo_file4c) assert not os.path.exists(wdir_foo_file4d) @@ -3093,7 +3418,7 @@ def test_unlink_files(self): try: try: test.unlink_files('', ['file5']) - except OSError: # expect "Permission denied" + except OSError: # expect "Permission denied" pass except: raise @@ -3105,7 +3430,7 @@ def test_unlink_files(self): class touch_TestCase(TestCmdTestCase): def test_touch(self) -> None: """Test touch()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'sub') + test = TestCmd.TestCmd(workdir='', subdir='sub') wdir_file1 = os.path.join(test.workdir, 'file1') wdir_sub_file2 = os.path.join(test.workdir, 'sub', 'file2') @@ -3138,49 +3463,47 @@ def test_touch(self) -> None: assert file2_new_time > file2_old_time - class verbose_TestCase(TestCmdTestCase): def test_verbose(self) -> None: """Test verbose()""" test = TestCmd.TestCmd() assert test.verbose == 0, 'verbose already initialized?' - test = TestCmd.TestCmd(verbose = 1) + test = TestCmd.TestCmd(verbose=1) assert test.verbose == 1, 'did not initialize verbose' test.verbose = 2 assert test.verbose == 2, 'did not set verbose' - class workdir_TestCase(TestCmdTestCase): def test_workdir(self): """Test workdir()""" - run_env = TestCmd.TestCmd(workdir = '') + run_env = TestCmd.TestCmd(workdir='') os.chdir(run_env.workdir) # Everything before this prepared our "source directory." # Now do the real test. test = TestCmd.TestCmd() assert test.workdir is None - test = TestCmd.TestCmd(workdir = None) + test = TestCmd.TestCmd(workdir=None) assert test.workdir is None - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') assert test.workdir is not None assert os.path.isdir(test.workdir) - test = TestCmd.TestCmd(workdir = 'dir') + test = TestCmd.TestCmd(workdir='dir') assert test.workdir is not None assert os.path.isdir(test.workdir) no_such_subdir = os.path.join('no', 'such', 'subdir') try: - test = TestCmd.TestCmd(workdir = no_such_subdir) + test = TestCmd.TestCmd(workdir=no_such_subdir) except OSError: # expect "No such file or directory" pass except: raise - test = TestCmd.TestCmd(workdir = 'foo') + test = TestCmd.TestCmd(workdir='foo') workdir_foo = test.workdir assert workdir_foo is not None @@ -3200,7 +3523,6 @@ def test_workdir(self): assert os.path.isdir(workdir_bar) - class workdirs_TestCase(TestCmdTestCase): def test_workdirs(self) -> None: """Test workdirs()""" @@ -3217,14 +3539,13 @@ def test_workdirs(self) -> None: assert not os.path.exists(wdir2) - class workpath_TestCase(TestCmdTestCase): def test_workpath(self) -> None: """Test workpath()""" test = TestCmd.TestCmd() assert test.workdir is None - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') wpath = test.workpath('foo', 'bar') assert wpath == os.path.join(test.workdir, 'foo', 'bar') @@ -3233,7 +3554,7 @@ class readable_TestCase(TestCmdTestCase): @unittest.skipIf(sys.platform == 'win32', "Skip permission fiddling on win32") def test_readable(self) -> None: """Test readable()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'foo') + test = TestCmd.TestCmd(workdir='', subdir='foo') test.write('file1', "Test file #1\n") test.write(['foo', 'file2'], "Test file #2\n") os.symlink('no_such_file', test.workpath('dangling_symlink')) @@ -3267,12 +3588,11 @@ def test_readable(self) -> None: test.readable(test.workdir, 1) - class writable_TestCase(TestCmdTestCase): @unittest.skipIf(sys.platform == 'win32', "Skip permission fiddling on win32") def test_writable(self) -> None: """Test writable()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'foo') + test = TestCmd.TestCmd(workdir='', subdir='foo') test.write('file1', "Test file #1\n") test.write(['foo', 'file2'], "Test file #2\n") os.symlink('no_such_file', test.workpath('dangling_symlink')) @@ -3308,18 +3628,18 @@ class executable_TestCase(TestCmdTestCase): @unittest.skipIf(sys.platform == 'win32', "Skip permission fiddling on win32") def test_executable(self) -> None: """Test executable()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'foo') + test = TestCmd.TestCmd(workdir='', subdir='foo') test.write('file1', "Test file #1\n") test.write(['foo', 'file2'], "Test file #2\n") os.symlink('no_such_file', test.workpath('dangling_symlink')) def make_executable(fname) -> None: st = os.stat(fname) - os.chmod(fname, stat.S_IMODE(st.st_mode|0o100)) + os.chmod(fname, stat.S_IMODE(st.st_mode | stat.S_IXUSR)) def make_non_executable(fname) -> None: st = os.stat(fname) - os.chmod(fname, stat.S_IMODE(st.st_mode&~0o100)) + os.chmod(fname, stat.S_IMODE(st.st_mode & ~stat.S_IXUSR)) test.executable(test.workdir, 0) # XXX skip these tests if euid == 0? @@ -3356,11 +3676,10 @@ def make_non_executable(fname) -> None: test.executable(test.workdir, 1) - class write_TestCase(TestCmdTestCase): def test_write(self): """Test write()""" - test = TestCmd.TestCmd(workdir = '', subdir = 'foo') + test = TestCmd.TestCmd(workdir='', subdir='foo') test.write('file1', "Test file #1\n") test.write(['foo', 'file2'], "Test file #2\n") try: @@ -3372,21 +3691,23 @@ def test_write(self): test.write(test.workpath('file4'), "Test file #4.\n") test.write(test.workpath('foo', 'file5'), "Test file #5.\n") try: - test.write(test.workpath('bar', 'file6'), "Test file #6 (should not get created)\n") + test.write( + test.workpath('bar', 'file6'), "Test file #6 (should not get created)\n" + ) except IOError: # expect "No such file or directory" pass except: raise try: - test.write('file7', "Test file #8.\n", mode = 'r') - except ValueError: # expect "mode must begin with 'w' + test.write('file7', "Test file #8.\n", mode='r') + except ValueError: # expect "mode must begin with 'w' pass except: raise - test.write('file8', "Test file #8.\n", mode = 'w') - test.write('file9', "Test file #9.\r\n", mode = 'wb') + test.write('file8', "Test file #8.\n", mode='w') + test.write('file9', "Test file #9.\r\n", mode='wb') if os.name != "nt": os.chmod(test.workdir, 0o500) @@ -3422,7 +3743,7 @@ def test_write(self): class variables_TestCase(TestCmdTestCase): def test_variables(self) -> None: """Test global variables""" - run_env = TestCmd.TestCmd(workdir = '') + run_env = TestCmd.TestCmd(workdir='') variables = [ 'fail_test', @@ -3436,14 +3757,16 @@ def test_variables(self) -> None: 'TestCmd', ] - script = "import TestCmd\n" + \ - '\n'.join([ "print(TestCmd.%s\n)" % v for v in variables ]) + script = "import TestCmd\n" + '\n'.join( + [f"print(TestCmd.{v}\n)" for v in variables] + ) run_env.run(program=sys.executable, stdin=script) stderr = run_env.stderr() assert stderr == "", stderr - script = "from TestCmd import *\n" + \ - '\n'.join([ "print(%s)" % v for v in variables ]) + script = "from TestCmd import *\n" + '\n'.join( + [f"print({v})" for v in variables] + ) run_env.run(program=sys.executable, stdin=script) stderr = run_env.stderr() assert stderr == "", stderr diff --git a/testing/framework/TestCommon.py b/testing/framework/TestCommon.py index 5038f1a665..2cd3c490af 100644 --- a/testing/framework/TestCommon.py +++ b/testing/framework/TestCommon.py @@ -150,74 +150,79 @@ else: obj_suffix = '.obj' shobj_suffix = '.obj' - exe_suffix = '.exe' + exe_suffix = '.exe' shobj_prefix = '' - lib_prefix = '' + lib_prefix = '' # TODO: for mingw, is this .lib or .a? - lib_suffix = '.lib' - dll_prefix = '' - dll_suffix = '.dll' + lib_suffix = '.lib' + dll_prefix = '' + dll_suffix = '.dll' elif sys.platform == 'cygwin': - exe_suffix = '.exe' - obj_suffix = '.o' + exe_suffix = '.exe' + obj_suffix = '.o' shobj_suffix = '.os' shobj_prefix = '' - lib_prefix = 'lib' - lib_suffix = '.a' - dll_prefix = 'cyg' - dll_suffix = '.dll' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'cyg' + dll_suffix = '.dll' elif sys.platform.find('irix') != -1: - exe_suffix = '' - obj_suffix = '.o' + exe_suffix = '' + obj_suffix = '.o' shobj_suffix = '.o' shobj_prefix = '' - lib_prefix = 'lib' - lib_suffix = '.a' - dll_prefix = 'lib' - dll_suffix = '.so' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.so' elif sys.platform.find('darwin') != -1: - exe_suffix = '' - obj_suffix = '.o' + exe_suffix = '' + obj_suffix = '.o' shobj_suffix = '.os' shobj_prefix = '' - lib_prefix = 'lib' - lib_suffix = '.a' - dll_prefix = 'lib' - dll_suffix = '.dylib' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.dylib' elif sys.platform.find('sunos') != -1: - exe_suffix = '' - obj_suffix = '.o' + exe_suffix = '' + obj_suffix = '.o' shobj_suffix = '.pic.o' shobj_prefix = '' - lib_prefix = 'lib' - lib_suffix = '.a' - dll_prefix = 'lib' - dll_suffix = '.so' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.so' else: - exe_suffix = '' - obj_suffix = '.o' + exe_suffix = '' + obj_suffix = '.o' shobj_suffix = '.os' shobj_prefix = '' - lib_prefix = 'lib' - lib_suffix = '.a' - dll_prefix = 'lib' - dll_suffix = '.so' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.so' + def is_List(e): return isinstance(e, (list, UserList)) + def is_Tuple(e): return isinstance(e, tuple) + def is_Sequence(e): - return (not hasattr(e, "strip") and - hasattr(e, "__getitem__") or - hasattr(e, "__iter__")) + return ( + not hasattr(e, "strip") and hasattr(e, "__getitem__") or hasattr(e, "__iter__") + ) + def is_writable(f): mode = os.stat(f).st_mode return mode & stat.S_IWUSR + def separate_files(flist): existing = [] missing = [] @@ -228,6 +233,7 @@ def separate_files(flist): missing.append(f) return existing, missing + def contains(seq, subseq, find: Callable | None = None) -> bool: if find is None: return subseq in seq @@ -235,6 +241,7 @@ def contains(seq, subseq, find: Callable | None = None) -> bool: f = find(seq, subseq) return f not in (None, -1) and f is not False + def find_index(seq, subseq, find: Callable | None = None) -> int | None: # Returns either an index of the subseq within the seq, or None. # Accepts a function find(seq, subseq), which returns an integer on success @@ -250,21 +257,24 @@ def find_index(seq, subseq, find: Callable | None = None) -> int | None: if os.name == 'posix': + def _failed(self, status: int = 0): if self.status is None or status is None: return None return _status(self) != status + def _status(self): return self.status elif os.name == 'nt': + def _failed(self, status: int = 0): - return not (self.status is None or status is None) and \ - self.status != status + return not (self.status is None or status is None) and self.status != status + def _status(self): return self.status -class TestCommon(TestCmd): +class TestCommon(TestCmd): # Additional methods from the Perl Test::Cmd::Common module # that we may wish to add in the future: # @@ -355,7 +365,9 @@ def must_contain( print(file_contents) self.fail_test() - def must_contain_all(self, output, input, title: str = "", find: Callable | None = None)-> None: + def must_contain_all( + self, output, input, title: str = "", find: Callable | None = None + ) -> None: """Ensures that the specified output string (first argument) contains all of the specified input as a block (second argument). @@ -378,7 +390,9 @@ def must_contain_all(self, output, input, title: str = "", find: Callable | None print(output) self.fail_test() - def must_contain_all_lines(self, output, lines, title: str = "", find: Callable | None = None) -> None: + def must_contain_all_lines( + self, output, lines, title: str = "", find: Callable | None = None + ) -> None: """Ensures that the specified output string (first argument) contains all of the specified lines (second argument). @@ -429,7 +443,9 @@ def must_contain_single_instance_of(self, output, lines, title: str = "") -> Non sys.stdout.write(output) self.fail_test() - def must_contain_any_line(self, output, lines, title: str = "", find: Callable | None = None) -> None: + def must_contain_any_line( + self, output, lines, title: str = "", find: Callable | None = None + ) -> None: """Ensures that the specified output string (first argument) contains at least one of the specified lines (second argument). @@ -453,7 +469,9 @@ def must_contain_any_line(self, output, lines, title: str = "", find: Callable | sys.stdout.write(output) self.fail_test() - def must_contain_exactly_lines(self, output, expect, title: str = "", find: Callable | None = None) -> None: + def must_contain_exactly_lines( + self, output, expect, title: str = "", find: Callable | None = None + ) -> None: """Ensures that the specified output string (first argument) contains all of the lines in the expected string (second argument) with none left over. @@ -468,7 +486,7 @@ def must_contain_exactly_lines(self, output, expect, title: str = "", find: Call """ out = output.splitlines() if is_List(expect): - exp = [ e.rstrip('\n') for e in expect ] + exp = [e.rstrip('\n') for e in expect] else: exp = expect.splitlines() if sorted(out) == sorted(exp): @@ -501,7 +519,9 @@ def must_contain_exactly_lines(self, output, expect, title: str = "", find: Call sys.stdout.flush() self.fail_test() - def must_contain_lines(self, lines, output, title: str = "", find: Callable | None = None) -> None: + def must_contain_lines( + self, lines, output, title: str = "", find: Callable | None = None + ) -> None: # Deprecated; retain for backwards compatibility. self.must_contain_all_lines(output, lines, title, find) @@ -594,13 +614,12 @@ def must_match_file( except KeyboardInterrupt: raise except: - print("Unexpected contents of `%s'" % file) + print(f"Unexpected contents of `{file}'") self.diff(golden_file_contents, file_contents, 'contents ') raise - def must_not_contain(self, file, banned, mode: str = 'rb', find = None) -> None: - """Ensures that the specified file doesn't contain the banned text. - """ + def must_not_contain(self, file, banned, mode: str = 'rb', find=None) -> None: + """Ensures that the specified file doesn't contain the banned text.""" file_contents = self.read(file, mode) if contains(file_contents, banned, find): @@ -611,7 +630,9 @@ def must_not_contain(self, file, banned, mode: str = 'rb', find = None) -> None: print(file_contents) self.fail_test() - def must_not_contain_any_line(self, output, lines, title: str = "", find: Callable | None = None) -> None: + def must_not_contain_any_line( + self, output, lines, title: str = "", find: Callable | None = None + ) -> None: """Ensures that the specified output string (first argument) does not contain any of the specified lines (second argument). @@ -637,7 +658,9 @@ def must_not_contain_any_line(self, output, lines, title: str = "", find: Callab sys.stdout.write(output) self.fail_test() - def must_not_contain_lines(self, lines, output, title: str = "", find: Callable | None = None) -> None: + def must_not_contain_lines( + self, lines, output, title: str = "", find: Callable | None = None + ) -> None: self.must_not_contain_any_line(output, lines, title, find) def must_not_exist(self, *files) -> None: @@ -705,8 +728,15 @@ def must_not_be_writable(self, *files) -> None: print("Writable files: `%s'" % "', `".join(writable)) self.fail_test(missing + writable) - def _complete(self, actual_stdout, expected_stdout, - actual_stderr, expected_stderr, status, match) -> None: + def _complete( + self, + actual_stdout, + expected_stdout, + actual_stderr, + expected_stderr, + status, + match, + ) -> None: """ Post-processes running a subcommand, checking for failure status and displaying output appropriately. @@ -721,34 +751,36 @@ def _complete(self, actual_stdout, expected_stdout, print(self.banner('STDERR ')) print(actual_stderr) self.fail_test() - if (expected_stdout is not None - and not match(actual_stdout, expected_stdout)): + if expected_stdout is not None and not match(actual_stdout, expected_stdout): self.diff(expected_stdout, actual_stdout, 'STDOUT ') if actual_stderr: print(self.banner('STDERR ')) print(actual_stderr) self.fail_test() - if (expected_stderr is not None - and not match(actual_stderr, expected_stderr)): + if expected_stderr is not None and not match(actual_stderr, expected_stderr): print(self.banner('STDOUT ')) print(actual_stdout) self.diff(expected_stderr, actual_stderr, 'STDERR ') self.fail_test() - def start(self, program = None, - interpreter = None, - options = None, - arguments = None, - universal_newlines = None, - **kw): + def start( + self, + program=None, + interpreter=None, + options=None, + arguments=None, + universal_newlines=None, + **kw, + ): """ Starts a program or script for the test environment, handling any exceptions. """ arguments = self.options_arguments(options, arguments) try: - return super().start(program, interpreter, arguments, - universal_newlines, **kw) + return super().start( + program, interpreter, arguments, universal_newlines, **kw + ) except KeyboardInterrupt: raise except Exception as e: @@ -766,7 +798,6 @@ def start(self, program = None, sys.stderr.write(f'Exception trying to execute: {cmd_args}\n') raise e - def finish( self, popen, @@ -797,7 +828,6 @@ def finish( match = kw.get('match', self.match) self._complete(self.stdout(), stdout, self.stderr(), stderr, status, match) - def run( self, options=None, @@ -834,10 +864,11 @@ def run( except KeyError: match = self.match super().run(**kw) - self._complete(self.stdout(), stdout, - self.stderr(), stderr, status, match) + self._complete(self.stdout(), stdout, self.stderr(), stderr, status, match) - def skip_test(self, message: str="Skipping test.\n", from_fw: bool=False) -> None: + def skip_test( + self, message: str = "Skipping test.\n", from_fw: bool = False + ) -> None: """Skips a test. Proper test-skipping behavior is dependent on the external @@ -886,9 +917,8 @@ def detailed_diff(value, expect) -> str: if len(v_split) != len(e_split): print(f"different number of lines:{len(v_split)} {len(e_split)}") - # breakpoint() for v, e in zip(v_split, e_split): - # print("%s:%s"%(v,e)) + # print(f"{v}:{e}") if v != e: print(f"\n[{v}]\n[{e}]") diff --git a/testing/framework/TestCommonTests.py b/testing/framework/TestCommonTests.py index 5ed2779c0a..3beca80102 100644 --- a/testing/framework/TestCommonTests.py +++ b/testing/framework/TestCommonTests.py @@ -36,10 +36,12 @@ import TestCmd import TestCommon + # this used to be a custom function, now use the stdlib equivalent def lstrip(s): return dedent(s) + expected_newline = '\\n' @@ -62,12 +64,13 @@ def assert_display(expect, result, error=None): class TestCommonTestCase(unittest.TestCase): """Base class for TestCommon test cases, fixture and utility methods.""" + create_run_env = True def setUp(self) -> None: self.orig_cwd = os.getcwd() if self.create_run_env: - self.run_env = TestCmd.TestCmd(workdir = '') + self.run_env = TestCmd.TestCmd(workdir='') def tearDown(self) -> None: os.chdir(self.orig_cwd) @@ -113,12 +116,15 @@ def set_up_execution_scripts(self) -> None: run_env.write(self.signal_script, wrapper % signal_body) - stdin_body = lstrip("""\ + stdin_body = lstrip( + """\ import sys input = sys.stdin.read()[:-1] sys.stdout.write(r'%s: STDOUT: ' + repr(input) + '\\n') sys.stderr.write(r'%s: STDERR: ' + repr(input) + '\\n') - """ % (self.stdin_script, self.stdin_script)) + """ + % (self.stdin_script, self.stdin_script) + ) run_env.write(self.stdin_script, wrapper % stdin_body) @@ -138,19 +144,15 @@ def run_execution_test(self, script, expect_stdout, expect_stderr) -> None: stderr = run_env.stderr() expect_stdout = expect_stdout % self.__dict__ - assert stdout == expect_stdout, assert_display(expect_stdout, - stdout, - stderr) + assert stdout == expect_stdout, assert_display(expect_stdout, stdout, stderr) try: match = expect_stderr.match except AttributeError: expect_stderr = expect_stderr % self.__dict__ - assert stderr == expect_stderr, assert_display(expect_stderr, - stderr) + assert stderr == expect_stderr, assert_display(expect_stderr, stderr) else: - assert expect_stderr.match(stderr), assert_display(expect_stderr, - stderr) + assert expect_stderr.match(stderr), assert_display(expect_stderr, stderr) class __init__TestCase(TestCommonTestCase): @@ -174,25 +176,30 @@ def test___init__(self) -> None: class banner_TestCase(TestCommonTestCase): create_run_env = False + def test_banner(self) -> None: """Test banner()""" tc = TestCommon.TestCommon(workdir='') - b = tc.banner('xyzzy ') - assert b == "xyzzy ==========================================================================", b + text = 'xyzzy ' + b = tc.banner(text) + expect = f"{text}{tc.banner_char * (tc.banner_width - len(text))}" + assert b == expect, b tc.banner_width = 10 + b = tc.banner(text) + expect = f"{text}{tc.banner_char * (tc.banner_width - len(text))}" + assert b == expect, b - b = tc.banner('xyzzy ') - assert b == "xyzzy ====", b - - b = tc.banner('xyzzy ', 20) - assert b == "xyzzy ==============", b + b = tc.banner(text, 20) + expect = f"{text}{tc.banner_char * (20 - len(text))}" + assert b == expect, b tc.banner_char = '-' + b = tc.banner(text) + expect = f"{text}{tc.banner_char * (tc.banner_width - len(text))}" + assert b == expect, b - b = tc.banner('xyzzy ') - assert b == "xyzzy ----", b class must_be_writable_TestCase(TestCommonTestCase): def test_file_does_not_exists(self) -> None: @@ -374,7 +381,6 @@ def test_mode(self) -> None: assert stderr == "PASSED\n", stderr - class must_contain_all_lines_TestCase(TestCommonTestCase): def test_success(self) -> None: """Test must_contain_all_lines(): success""" @@ -432,14 +438,17 @@ def test_failure(self) -> None: test.pass_test() """) - expect = lstrip("""\ + expect = lstrip( + """\ Missing expected lines from output: 'xxx%(expected_newline)s' 'yyy%(expected_newline)s' output ========================================================================= www zzz - """ % globals()) + """ + % globals() + ) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() @@ -505,14 +514,17 @@ def test_title(self) -> None: test.pass_test() """) - expect = lstrip("""\ + expect = lstrip( + """\ Missing expected lines from STDERR: 'xxx%(expected_newline)s' 'yyy%(expected_newline)s' STDERR ========================================================================= www zzz - """ % globals()) + """ + % globals() + ) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() @@ -521,7 +533,6 @@ def test_title(self) -> None: assert stderr.find("FAILED") != -1, stderr - class must_contain_any_line_TestCase(TestCommonTestCase): def test_success(self) -> None: """Test must_contain_any_line(): success""" @@ -579,14 +590,17 @@ def test_failure(self) -> None: test.pass_test() """) - expect = lstrip("""\ + expect = lstrip( + """\ Missing any expected line from output: 'xxx%(expected_newline)s' 'yyy%(expected_newline)s' output ========================================================================= www zzz - """ % globals()) + """ + % globals() + ) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() @@ -651,14 +665,17 @@ def test_title(self) -> None: test.pass_test() """) - expect = lstrip("""\ + expect = lstrip( + """\ Missing any expected line from STDOUT: 'xxx%(expected_newline)s' 'yyy%(expected_newline)s' STDOUT ========================================================================= www zzz - """ % globals()) + """ + % globals() + ) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() @@ -667,7 +684,6 @@ def test_title(self) -> None: assert stderr.find("FAILED") != -1, stderr - class must_contain_exactly_lines_TestCase(TestCommonTestCase): def test_success_list(self) -> None: """Test must_contain_exactly_lines(): success (input list)""" @@ -862,7 +878,6 @@ def test_title(self) -> None: assert stderr.find("FAILED") != -1, stderr - class must_contain_lines_TestCase(TestCommonTestCase): def test_success(self) -> None: """Test must_contain_lines(): success""" @@ -918,14 +933,17 @@ def test_failure(self) -> None: test.pass_test() """) - expect = lstrip("""\ + expect = lstrip( + """\ Missing expected lines from output: 'xxx%(expected_newline)s' 'yyy%(expected_newline)s' output ========================================================================= www zzz - """ % globals()) + """ + % globals() + ) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() @@ -934,7 +952,6 @@ def test_failure(self) -> None: assert stderr.find("FAILED") != -1, stderr - class must_exist_TestCase(TestCommonTestCase): def test_success(self) -> None: """Test must_exist(): success""" @@ -1004,7 +1021,7 @@ def test_file_specified_as_list(self) -> None: assert stderr == "PASSED\n", stderr @unittest.skipIf(sys.platform == 'win32', "Skip symlink test on win32") - def test_broken_link(self) -> None : + def test_broken_link(self) -> None: """Test must_exist(): exists but it is a broken link""" run_env = self.run_env @@ -1021,6 +1038,7 @@ def test_broken_link(self) -> None : stderr = run_env.stderr() assert stderr == "PASSED\n", stderr + class must_exist_one_of_TestCase(TestCommonTestCase): def test_success(self) -> None: """Test must_exist_one_of(): success""" @@ -1141,6 +1159,7 @@ def test_file_given_as_sequence(self) -> None: stderr = run_env.stderr() assert stderr == "PASSED\n", stderr + class must_match_TestCase(TestCommonTestCase): def test_success(self) -> None: """Test must_match(): success""" @@ -1224,7 +1243,6 @@ def test_mode(self) -> None: assert stderr == "PASSED\n", stderr - class must_not_be_writable_TestCase(TestCommonTestCase): def test_file_does_not_exists(self) -> None: """Test must_not_be_writable(): file does not exist""" @@ -1310,7 +1328,6 @@ def test_file_specified_as_list(self) -> None: assert stderr == "PASSED\n", stderr - class must_not_contain_TestCase(TestCommonTestCase): def test_success(self) -> None: """Test must_not_contain(): success""" @@ -1415,7 +1432,6 @@ def test_mode(self) -> None: assert stderr == "PASSED\n", stderr - class must_not_contain_any_line_TestCase(TestCommonTestCase): def test_failure(self) -> None: """Test must_not_contain_any_line(): failure""" @@ -1443,7 +1459,8 @@ def test_failure(self) -> None: test.pass_test() """) - expect = lstrip("""\ + expect = lstrip( + """\ Unexpected lines in output: 'xxx%(expected_newline)s' 'yyy%(expected_newline)s' @@ -1453,7 +1470,9 @@ def test_failure(self) -> None: xxx yyy zzz - """ % globals()) + """ + % globals() + ) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() @@ -1547,7 +1566,8 @@ def test_title(self) -> None: test.pass_test() """) - expect = lstrip("""\ + expect = lstrip( + """\ Unexpected lines in XYZZY: 'xxx%(expected_newline)s' 'yyy%(expected_newline)s' @@ -1556,7 +1576,9 @@ def test_title(self) -> None: xxx yyy zzz - """ % globals()) + """ + % globals() + ) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() @@ -1565,7 +1587,6 @@ def test_title(self) -> None: assert stderr.find("FAILED") != -1, stderr - class must_not_contain_lines_TestCase(TestCommonTestCase): def test_failure(self) -> None: """Test must_not_contain_lines(): failure""" @@ -1592,7 +1613,8 @@ def test_failure(self) -> None: test.pass_test() """) - expect = lstrip("""\ + expect = lstrip( + """\ Unexpected lines in output: 'xxx%(expected_newline)s' 'yyy%(expected_newline)s' @@ -1601,7 +1623,9 @@ def test_failure(self) -> None: xxx yyy zzz - """ % globals()) + """ + % globals() + ) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() @@ -1639,7 +1663,6 @@ def test_success(self) -> None: assert stderr == "PASSED\n", stderr - class must_not_exist_TestCase(TestCommonTestCase): def test_failure(self) -> None: """Test must_not_exist(): failure""" @@ -1709,6 +1732,7 @@ def test_existing_broken_link(self) -> None: stderr = run_env.stderr() assert stderr.find("FAILED") != -1, stderr + class must_not_exist_any_of_TestCase(TestCommonTestCase): def test_success(self) -> None: """Test must_not_exist_any_of(): success""" @@ -1814,6 +1838,7 @@ def test_file_given_as_sequence(self) -> None: stderr = run_env.stderr() assert stderr == "PASSED\n", stderr + class must_not_be_empty_TestCase(TestCommonTestCase): def test_failure(self) -> None: """Test must_not_be_empty(): failure""" @@ -1865,6 +1890,7 @@ def test_file_doesnt_exist(self) -> None: stderr = run_env.stderr() assert stderr.find("FAILED") != -1, stderr + class run_TestCase(TestCommonTestCase): def test_argument_handling(self) -> None: """Test run(): argument handling""" @@ -1975,43 +2001,47 @@ def raise_exception(*args, **kw): """) expect_stderr = lstrip( - fr"""Exception trying to execute: \[{re.escape(repr(sys.executable))}, '[^']*pass'\] + rf"""Exception trying to execute: \[{re.escape(repr(sys.executable))}, '[^']*pass'\] Traceback \(most recent call last\): File "", line \d+, in (\?|) File "[^"]+TestCommon\.py", line \d+, in run super\(\)\.run\(\*\*kw\) File "[^"]+TestCmd\.py", line \d+, in run - p = self\.start\(program=program, + p = self\.start\( (?:\s*\^*\s)? File \"[^\"]+TestCommon\.py\", line \d+, in start raise e File "[^"]+TestCommon\.py", line \d+, in start - return super\(\)\.start\(program, interpreter, arguments, + return super\(\)\.start\( (?:\s*\^*\s)? File \"\", line \d+, in raise_exception TypeError: forced TypeError -""") +""" + ) # Python 3.13+ expanded error msgs again, not in a way we can easily # accomodate with the other regex. + # TODO: broken again after reformat work expect_enhanced_stderr = lstrip( - fr"""Exception trying to execute: \[{re.escape(repr(sys.executable))}, '[^']*pass'\] + rf"""Exception trying to execute: \[{re.escape(repr(sys.executable))}, '[^']*pass'\] Traceback \(most recent call last\): File "", line \d+, in (\?|) File "[^"]+TestCommon\.py", line \d+, in run super\(\)\.run\(\*\*kw\) (?:\s*[~\^]*\s*)?File "[^"]+TestCmd\.py", line \d+, in run - p = self\.start\(program=program, - interpreter=interpreter, - \.\.\.<2 lines>\.\.\. - timeout=timeout, - stdin=stdin\) + p = self\.start\( + program=program, + \.\.\.<4 lines>\.\.\. + stdin=stdin, + \) (?:\s*[~\^]*\s*)?File \"[^\"]+TestCommon\.py\", line \d+, in start raise e File "[^"]+TestCommon\.py", line \d+, in start - return super\(\)\.start\(program, interpreter, arguments, -(?:\s*[~\^]*\s*)?universal_newlines, \*\*kw\) + return super\(\)\.start\( +(?:\s*[~\^]*\s*)?program, interpreter, arguments, universal_newlines, \*\*kw +(?:\s*[~\^]*\s*)?\) (?:\s*[~\^]*\s*)?File \"\", line \d+, in raise_exception TypeError: forced TypeError -""") +""" + ) if sys.version_info[:2] > (3, 12): expect_stderr = re.compile(expect_enhanced_stderr, re.M) else: @@ -2331,7 +2361,6 @@ def test_stdin(self) -> None: self.run_execution_test(script, "", "") - class start_TestCase(TestCommonTestCase): def test_option_handling(self) -> None: """Test start(): option handling""" @@ -2367,7 +2396,6 @@ def test_options_plus_arguments(self) -> None: self.run_execution_test(script, "", "") - class skip_test_TestCase(TestCommonTestCase): def test_skip_test(self) -> None: """Test skip_test()""" @@ -2404,6 +2432,7 @@ def test_skip_test(self) -> None: assert stderr in expect, repr(stderr) import os + os.environ['TESTCOMMON_PASS_SKIPS'] = '1' try: @@ -2422,7 +2451,6 @@ def test_skip_test(self) -> None: del os.environ['TESTCOMMON_PASS_SKIPS'] - class variables_TestCase(TestCommonTestCase): def test_variables(self) -> None: """Test global variables""" @@ -2438,7 +2466,6 @@ def test_variables(self) -> None: 'python', '_python_', 'TestCmd', - 'TestCommon', 'exe_suffix', 'obj_suffix', @@ -2450,20 +2477,21 @@ def test_variables(self) -> None: 'dll_suffix', ] - script = "import TestCommon\n" + \ - '\n'.join([f"print(TestCommon.{v})\n" for v in variables]) + script = "import TestCommon\n" + '\n'.join( + [f"print(TestCommon.{v})\n" for v in variables] + ) run_env.run(program=sys.executable, stdin=script) stderr = run_env.stderr() assert stderr == "", stderr - script = "from TestCommon import *\n" + \ - '\n'.join([f"print({v})" for v in variables]) + script = "from TestCommon import *\n" + '\n'.join( + [f"print({v})" for v in variables] + ) run_env.run(program=sys.executable, stdin=script) stderr = run_env.stderr() assert stderr == "", stderr - if __name__ == "__main__": unittest.main() diff --git a/testing/framework/TestRuntest.py b/testing/framework/TestRuntest.py index 5277690867..d277cc16e0 100644 --- a/testing/framework/TestRuntest.py +++ b/testing/framework/TestRuntest.py @@ -43,13 +43,7 @@ from TestCommon import * from TestCommon import __all__ -__all__.extend( - [ - 'TestRuntest', - 'pythonstring', - 'pythonflags', - ] -) +__all__.extend(['TestRuntest', 'pythonstring', 'pythonflags']) pythonstring = python pythonflags = '' @@ -91,6 +85,7 @@ __developer__ = 'John Doe' """ + class TestRuntest(TestCommon): """Class for testing the runtest.py script. @@ -122,7 +117,9 @@ def __init__(self, **kw) -> None: if 'program' not in kw: kw['program'] = 'runtest.py' if 'interpreter' not in kw: - kw['interpreter'] = [python,] + kw['interpreter'] = [ + python, + ] if 'match' not in kw: kw['match'] = match_exact if 'workdir' not in kw: @@ -176,6 +173,7 @@ def write_no_result_test(self, name) -> None: def write_passing_test(self, name) -> None: self.write(name, passing_test_template) + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index 5c95c24236..fda32b8130 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -39,8 +39,8 @@ import os import re import shutil -import sys import subprocess as sp +import sys import time import zipfile from collections import namedtuple @@ -63,20 +63,22 @@ SConsVersion = default_version -__all__.extend([ - 'TestSCons', - 'machine', - 'python', - '_exe', - '_obj', - '_shobj', - 'shobj_', - 'lib_', - '_lib', - 'dll_', - '_dll', - 'NINJA_BINARY' -]) +__all__.extend( + [ + 'TestSCons', + 'machine', + 'python', + '_exe', + '_obj', + '_shobj', + 'shobj_', + 'lib_', + '_lib', + 'dll_', + '_dll', + 'NINJA_BINARY', + ] +) machine_map = { 'i686': 'i386', @@ -106,6 +108,7 @@ try: import ninja + NINJA_BINARY = os.path.abspath(os.path.join(ninja.BIN_DIR, 'ninja' + _exe)) except ImportError: NINJA_BINARY = None @@ -116,8 +119,10 @@ def case_sensitive_suffixes(s1, s2) -> int: return 0 else: + def case_sensitive_suffixes(s1, s2): - return (os.path.normcase(s1) != os.path.normcase(s2)) + return os.path.normcase(s1) != os.path.normcase(s2) + file_expr = r"""File "[^"]*", line \d+, in [^\n]+ """ @@ -135,8 +140,8 @@ def re_escape(str): # when searching for special strings in stdout/stderr. # def search_re(out, l): - """ Search the regular expression 'l' in the output 'out' - and return the start index when successful. + """Search the regular expression 'l' in the output 'out' + and return the start index when successful. """ m = re.search(l, out) if m: @@ -146,9 +151,9 @@ def search_re(out, l): def search_re_in_list(out, l): - """ Search the regular expression 'l' in each line of - the given string list 'out' and return the line's index - when successful. + """Search the regular expression 'l' in each line of + the given string list 'out' and return the line's index + when successful. """ for idx, o in enumerate(out): m = re.search(l, o) @@ -210,8 +215,7 @@ def initialize_sconsflags(ignore_python_version): # (The intended use case is to set it to null when running # timing tests of earlier versions of SCons which don't # support the --warn=no-visual-c-missing warning.) - visual_c = os.environ.get('TESTSCONS_SCONSFLAGS', - '--warn=no-visual-c-missing') + visual_c = os.environ.get('TESTSCONS_SCONSFLAGS', '--warn=no-visual-c-missing') if visual_c and visual_c not in sconsflags: sconsflags.append(visual_c) os.environ['SCONSFLAGS'] = ' '.join(sconsflags) @@ -226,14 +230,15 @@ def restore_sconsflags(sconsflags) -> None: # Helpers for Configure()'s config.log processing -ConfigCheckInfo = namedtuple('ConfigCheckInfo', - ['check_string', 'result', 'cached', 'temp_filename']) - - -# check_string: the string output to for this checker -# results : The expected results for each check -# cached : If the corresponding check is expected to be cached -# temp_filename : The name of the generated tempfile for this check +ConfigCheckInfo = namedtuple( + 'ConfigCheckInfo', + [ + 'check_string', # string output to for this checker + 'result', # expected results for each check + 'cached', # If the corresponding check is expected to be cached + 'temp_filename', # name of the generated tempfile for this check + ], +) class NoMatch(Exception): @@ -309,7 +314,7 @@ def __init__(self, **kw) -> None: elif not self.external and not os.path.isabs(kw['program']): kw['program'] = os.path.join(self.orig_cwd, kw['program']) if 'interpreter' not in kw and not os.environ.get('SCONS_EXEC'): - kw['interpreter'] = [python, ] + kw['interpreter'] = [python] if 'match' not in kw: kw['match'] = match_exact if 'workdir' not in kw: @@ -328,6 +333,7 @@ def __init__(self, **kw) -> None: if not self.external: import SCons.Node.FS + if SCons.Node.FS.default_fs is None: SCons.Node.FS.default_fs = SCons.Node.FS.FS() @@ -344,6 +350,7 @@ def Environment(self, ENV=None, *args, **kw): if not self.external: import SCons.Environment import SCons.Errors + if ENV is not None: kw['ENV'] = ENV try: @@ -420,13 +427,15 @@ def where_is(self, prog, path=None, pathext=None): return os.path.normpath(result) else: import SCons.Environment + env = SCons.Environment.Environment() return env.WhereIs(prog, path, pathext) return None - def wrap_stdout(self, build_str: str = "", read_str: str = "", error: int = 0, - cleaning: int = 0) -> str: + def wrap_stdout( + self, build_str: str = "", read_str: str = "", error: int = 0, cleaning: int = 0 + ) -> str: """Wraps "expect" strings in SCons boilerplate. Given strings of expected output specific to a test, @@ -444,19 +453,20 @@ def wrap_stdout(self, build_str: str = "", read_str: str = "", error: int = 0, cleaning: index into type messages, if 0 selects build messages, if 1 selects clean messages. """ - cap, lc = [('Build', 'build'), - ('Clean', 'clean')][cleaning] + cap, lc = [('Build', 'build'), ('Clean', 'clean')][cleaning] if error: term = f"scons: {lc}ing terminated because of errors.\n" else: term = f"scons: done {lc}ing targets.\n" - return "scons: Reading SConscript files ...\n" + \ - read_str + \ - "scons: done reading SConscript files.\n" + \ - f"scons: {cap}ing targets ...\n" + \ - build_str + \ - term + return ( + "scons: Reading SConscript files ...\n" + + read_str + + "scons: done reading SConscript files.\n" + + f"scons: {cap}ing targets ...\n" + + build_str + + term + ) def run(self, *args, **kw) -> None: """ @@ -519,7 +529,8 @@ def not_up_to_date(self, arguments: str = '.', read_str: str = "", **kw) -> None s = f"({s}[^\n]*\n)*" kw['arguments'] = arguments stdout = re.escape( - self.wrap_stdout(read_str=read_str, build_str='ARGUMENTSGOHERE')) + self.wrap_stdout(read_str=read_str, build_str='ARGUMENTSGOHERE') + ) kw['stdout'] = stdout.replace('ARGUMENTSGOHERE', s) kw['match'] = self.match_re_dotall self.run(**kw) @@ -560,11 +571,16 @@ def deprecated_fatal(self, warn, msg): TODO: Actually detect that it's now an error. We don't have any cases yet, so there's no way to test it. """ - self.write('SConstruct', """if True: - WARN = ARGUMENTS.get('WARN') - if WARN: SetOption('warn', WARN) - SConscript('SConscript') - """) + self.write( + 'SConstruct', + """\ +if True: + WARN = ARGUMENTS.get('WARN') + if WARN: + SetOption('warn', WARN) + SConscript('SConscript') +""", + ) def err_out(): # TODO calculate stderr for fatal error @@ -607,14 +623,18 @@ def deprecated_warning(self, warn, msg): def RunPair(option, expected) -> None: # run the same test with the option on the command line and # then with the option passed via SetOption(). - self.run(options=f"--warn={option}", - arguments='.', - stderr=expected, - match=match_re_dotall) - self.run(options=f"WARN={option}", - arguments='.', - stderr=expected, - match=match_re_dotall) + self.run( + options=f"--warn={option}", + arguments='.', + stderr=expected, + match=match_re_dotall, + ) + self.run( + options=f"WARN={option}", + arguments='.', + stderr=expected, + match=match_re_dotall, + ) # all warnings off, should get no output RunPair('no-deprecated', '') @@ -623,7 +643,9 @@ def RunPair(option, expected) -> None: RunPair(warn, warning) # warning disabled, should get either nothing or mandatory message - expect = f"""()|(Can not disable mandataory warning: 'no-{warn}'\n\n{warning})""" + expect = ( + f"""()|(Can not disable mandataory warning: 'no-{warn}'\n\n{warning})""" + ) RunPair(f"no-{warn}", expect) return warning @@ -632,12 +654,12 @@ def diff_substr(self, expect, actual, prelen: int = 20, postlen: int = 40) -> st i = 0 for x, y in zip(expect, actual): if x != y: - return "Actual did not match expect at char %d:\n" \ - " Expect: %s\n" \ - " Actual: %s\n" \ - % (i, repr(expect[i - prelen:i + postlen]), - repr(actual[i - prelen:i + postlen])) - i = i + 1 + return ( + f"Actual did not match expect at char {i}:\n" + f" Expect: {expect[i - prelen : i + postlen]!r}\n" + f" Actual: {actual[i - prelen : i + postlen]!r}\n" + ) + i += 1 return "Actual matched the expected output???" def python_file_line(self, file, line): @@ -668,14 +690,12 @@ def python_file_line(self, file, line): return x def normalize_ps(self, s): - s = re.sub(r'(Creation|Mod)Date: .*', - r'\1Date XXXX', s) - s = re.sub(r'%DVIPSSource:\s+TeX output\s.*', - r'%DVIPSSource: TeX output XXXX', s) - s = re.sub(r'/(BaseFont|FontName) /[A-Z0-9]{6}', - r'/\1 /XXXXXX', s) - s = re.sub(r'BeginFont: [A-Z0-9]{6}', - r'BeginFont: XXXXXX', s) + s = re.sub(r'(Creation|Mod)Date: .*', r'\1Date XXXX', s) + s = re.sub( + r'%DVIPSSource:\s+TeX output\s.*', r'%DVIPSSource: TeX output XXXX', s + ) + s = re.sub(r'/(BaseFont|FontName) /[A-Z0-9]{6}', r'/\1 /XXXXXX', s) + s = re.sub(r'BeginFont: [A-Z0-9]{6}', r'BeginFont: XXXXXX', s) return s @@ -690,14 +710,18 @@ def to_bytes_re_sub(pattern, repl, string, count: int = 0, flags: int = 0): return re.sub(pattern, repl, string, count=count, flags=flags) def normalize_pdf(self, s): - s = self.to_bytes_re_sub(r'/(Creation|Mod)Date \(D:[^)]*\)', - r'/\1Date (D:XXXX)', s) - s = self.to_bytes_re_sub(r'/ID \[<[0-9a-fA-F]*> <[0-9a-fA-F]*>\]', - r'/ID [ ]', s) - s = self.to_bytes_re_sub(r'/(BaseFont|FontName) /[A-Z]{6}', - r'/\1 /XXXXXX', s) - s = self.to_bytes_re_sub(r'/Length \d+ *\n/Filter /FlateDecode\n', - r'/Length XXXX\n/Filter /FlateDecode\n', s) + s = self.to_bytes_re_sub( + r'/(Creation|Mod)Date \(D:[^)]*\)', r'/\1Date (D:XXXX)', s + ) + s = self.to_bytes_re_sub( + r'/ID \[<[0-9a-fA-F]*> <[0-9a-fA-F]*>\]', r'/ID [ ]', s + ) + s = self.to_bytes_re_sub(r'/(BaseFont|FontName) /[A-Z]{6}', r'/\1 /XXXXXX', s) + s = self.to_bytes_re_sub( + r'/Length \d+ *\n/Filter /FlateDecode\n', + r'/Length XXXX\n/Filter /FlateDecode\n', + s, + ) try: import zlib @@ -720,13 +744,19 @@ def normalize_pdf(self, s): for b, e in encoded: r.append(s[x:b]) d = zlib.decompress(s[b:e]) - d = self.to_bytes_re_sub(r'%%CreationDate: [^\n]*\n', - r'%%CreationDate: 1970 Jan 01 00:00:00\n', d) + d = self.to_bytes_re_sub( + r'%%CreationDate: [^\n]*\n', + r'%%CreationDate: 1970 Jan 01 00:00:00\n', + d, + ) d = self.to_bytes_re_sub( r'%DVIPSSource: TeX output \d\d\d\d\.\d\d\.\d\d:\d\d\d\d', - r'%DVIPSSource: TeX output 1970.01.01:0000', d) - d = self.to_bytes_re_sub(r'/(BaseFont|FontName) /[A-Z]{6}', - r'/\1 /XXXXXX', d) + r'%DVIPSSource: TeX output 1970.01.01:0000', + d, + ) + d = self.to_bytes_re_sub( + r'/(BaseFont|FontName) /[A-Z]{6}', r'/\1 /XXXXXX', d + ) r.append(d) x = e r.append(s[x:]) @@ -736,6 +766,7 @@ def normalize_pdf(self, s): def paths(self, patterns): import glob + result = [] for p in patterns: result.extend(sorted(glob.glob(p))) @@ -781,8 +812,8 @@ def unlink_sconsignfile(self, name: str = '.sconsign.dblite') -> None: """ return self.unlink(name) - def java_ENV(self, version=None): - """ Initialize JAVA SDK environment. + def java_ENV(self, version: str | None = None): + """Initialize JAVA SDK environment. Initialize with a default external environment that uses a local Java SDK in preference to whatever's found in the default PATH. @@ -802,6 +833,7 @@ def java_ENV(self, version=None): pass import SCons.Environment + env = SCons.Environment.Environment() self._java_env[version] = env @@ -835,8 +867,8 @@ def java_ENV(self, version=None): return None - def java_where_includes(self, version=None): - """ Find include path needed for compiling java jni code. + def java_where_includes(self, version: str | None = None) -> list[str] | None: + """Find include path needed for compiling java jni code. Args: version: if set, match only that version @@ -855,15 +887,22 @@ def java_where_includes(self, version=None): if not version: version = '' - jni_dirs = ['/System/Library/Frameworks/JavaVM.framework/Headers/jni.h', - '/usr/lib/jvm/default-java/include/jni.h', - '/usr/lib/jvm/java-*-oracle/include/jni.h'] + jni_dirs = [ + '/System/Library/Frameworks/JavaVM.framework/Headers/jni.h', + '/usr/lib/jvm/default-java/include/jni.h', + '/usr/lib/jvm/java-*-oracle/include/jni.h', + ] else: jni_dirs = [ - f'/System/Library/Frameworks/JavaVM.framework/Versions/{version}*/Headers/jni.h'] - jni_dirs.extend([f'/usr/lib/jvm/java-*-sun-{version}*/include/jni.h', - f'/usr/lib/jvm/java-{version}*-openjdk*/include/jni.h', - f'/usr/java/jdk{version}*/include/jni.h']) + f'/System/Library/Frameworks/JavaVM.framework/Versions/{version}*/Headers/jni.h' + ] + jni_dirs.extend( + [ + f'/usr/lib/jvm/java-*-sun-{version}*/include/jni.h', + f'/usr/lib/jvm/java-{version}*-openjdk*/include/jni.h', + f'/usr/java/jdk{version}*/include/jni.h', + ] + ) dirs = self.paths(jni_dirs) if not dirs: return None @@ -876,8 +915,8 @@ def java_where_includes(self, version=None): result.append(os.path.join(d, 'linux')) return result - def java_where_java_home(self, version=None) -> str | None: - """ Find path to what would be JAVA_HOME. + def java_where_java_home(self, version: str | None = None) -> str | None: + """Find path to what would be JAVA_HOME. SCons does not read JAVA_HOME from the environment, so deduce it. @@ -903,7 +942,7 @@ def java_where_java_home(self, version=None) -> str | None: for home in [ '/System/Library/Frameworks/JavaVM.framework/Home', # osx 10.10 - '/System/Library/Frameworks/JavaVM.framework/Versions/Current/Home' + '/System/Library/Frameworks/JavaVM.framework/Versions/Current/Home', ]: if os.path.exists(home): return home @@ -913,7 +952,7 @@ def java_where_java_home(self, version=None) -> str | None: for home in [ f'/System/Library/Frameworks/JavaVM.framework/Versions/{version}/Home', # osx 10.10 - '/System/Library/Frameworks/JavaVM.framework/Versions/Current/' + '/System/Library/Frameworks/JavaVM.framework/Versions/Current/', ]: if os.path.exists(home): return home @@ -951,8 +990,8 @@ def java_mac_check(self, where_java_bin, java_bin_name) -> None: from_fw=True, ) - def java_where_jar(self, version=None) -> str: - """ Find java archiver jar. + def java_where_jar(self, version: str | None = None) -> str: + """Find java archiver jar. Args: version: if set, match only that version @@ -972,8 +1011,8 @@ def java_where_jar(self, version=None) -> str: return where_jar - def java_where_java(self, version=None) -> str: - """ Find java executable. + def java_where_java(self, version: str | None = None) -> str: + """Find java executable. Args: version: if set, match only that version @@ -985,15 +1024,16 @@ def java_where_java(self, version=None) -> str: where_java = self.where_is('java', ENV['PATH']) if not where_java: - self.skip_test("Could not find Java java, skipping test(s).\n", - from_fw=True) + self.skip_test( + "Could not find Java java, skipping test(s).\n", from_fw=True + ) elif sys.platform == "darwin": self.java_mac_check(where_java, 'java') return where_java - def java_where_javac(self, version=None) -> tuple[str, str]: - """ Find java compiler. + def java_where_javac(self, version: str | None = None) -> tuple[str, str]: + """Find java compiler. Args: version: if set, match only that version @@ -1007,15 +1047,13 @@ def java_where_javac(self, version=None) -> tuple[str, str]: else: where_javac = self.where_is('javac', ENV['PATH']) if not where_javac: - self.skip_test("Could not find Java javac, skipping test(s).\n", - from_fw=True) + self.skip_test( + "Could not find Java javac, skipping test(s).\n", from_fw=True + ) elif sys.platform == "darwin": self.java_mac_check(where_javac, 'javac') - self.run(program=where_javac, - arguments='-version', - stderr=None, - status=None) + self.run(program=where_javac, arguments='-version', stderr=None, status=None) # Note recent versions output version info to stdout instead of stderr stdout = self.stdout() or "" stderr = self.stderr() or "" @@ -1043,8 +1081,8 @@ def java_where_javac(self, version=None) -> tuple[str, str]: self.javac_is_gcj = False return where_javac, version - def java_where_javah(self, version=None) -> str: - """ Find java header generation tool. + def java_where_javah(self, version: str | None = None) -> str: + """Find java header generation tool. TODO issue #3347 since JDK10, there is no separate javah command, 'javac -h' is used. We should not return a javah from a different @@ -1062,12 +1100,13 @@ def java_where_javah(self, version=None) -> str: else: where_javah = self.where_is('javah', ENV['PATH']) if not where_javah: - self.skip_test("Could not find Java javah, skipping test(s).\n", - from_fw=True) + self.skip_test( + "Could not find Java javah, skipping test(s).\n", from_fw=True + ) return where_javah - def java_where_rmic(self, version=None) -> str: - """ Find java rmic tool. + def java_where_rmic(self, version: str | None = None) -> str: + """Find java rmic tool. Args: version: if set, match only that version @@ -1083,7 +1122,8 @@ def java_where_rmic(self, version=None) -> str: if not where_rmic: self.skip_test( "Could not find Java rmic, skipping non-simulated test(s).\n", - from_fw=True) + from_fw=True, + ) return where_rmic def java_get_class_files(self, dir): @@ -1099,18 +1139,24 @@ def Qt_dummy_installation(self, dir: str = 'qt') -> None: self.subdir(dir, [dir, 'bin'], [dir, 'include'], [dir, 'lib']) - self.write([dir, 'bin', 'mymoc.py'], """\ + self.write( + [dir, 'bin', 'mymoc.py'], + """\ import getopt import sys import re + # -w and -z are fake options used in test/QT/QTFLAGS.py cmd_opts, args = getopt.getopt(sys.argv[1:], 'io:wz', []) impl = 0 opt_string = '' for opt, arg in cmd_opts: - if opt == '-o': outfile = arg - elif opt == '-i': impl = 1 - else: opt_string = opt_string + ' ' + opt + if opt == '-o': + outfile = arg + elif opt == '-i': + impl = 1 + else: + opt_string = opt_string + ' ' + opt with open(outfile, 'w') as ofp: ofp.write("/* mymoc.py%s */\\n" % opt_string) @@ -1123,12 +1169,16 @@ def Qt_dummy_installation(self, dir: str = 'qt') -> None: contents = re.sub(r'#include.*', '', contents) ofp.write(contents.replace('Q_OBJECT', subst)) sys.exit(0) -""") +""", + ) - self.write([dir, 'bin', 'myuic.py'], """\ + self.write( + [dir, 'bin', 'myuic.py'], + """\ import os.path import re import sys + output_arg = 0 impl_arg = 0 impl = None @@ -1164,22 +1214,31 @@ def Qt_dummy_installation(self, dir: str = 'qt') -> None: else: ofp.write('#include "my_qobject.h"\\n' + ifp.read() + " Q_OBJECT \\n") sys.exit(0) -""") +""", + ) - self.write([dir, 'include', 'my_qobject.h'], r""" + self.write( + [dir, 'include', 'my_qobject.h'], + """\ #define Q_OBJECT ; void my_qt_symbol(const char *arg); -""") +""", + ) - self.write([dir, 'lib', 'my_qobject.cpp'], r""" + self.write( + [dir, 'lib', 'my_qobject.cpp'], + """\ #include "../include/my_qobject.h" #include void my_qt_symbol(const char *arg) { fputs(arg, stdout); } -""") +""", + ) - self.write([dir, 'lib', 'SConstruct'], r""" + self.write( + [dir, 'lib', 'SConstruct'], + r""" import sys DefaultEnvironment(tools=[]) # test speedup env = Environment() @@ -1187,12 +1246,15 @@ def Qt_dummy_installation(self, dir: str = 'qt') -> None: env.StaticLibrary('myqt', 'my_qobject.cpp') else: env.SharedLibrary('myqt', 'my_qobject.cpp') -""") +""", + ) - self.run(chdir=self.workpath(dir, 'lib'), - arguments='.', - stderr=noisy_ar, - match=self.match_re_dotall) + self.run( + chdir=self.workpath(dir, 'lib'), + arguments='.', + stderr=noisy_ar, + match=self.match_re_dotall, + ) self.QT = self.workpath(dir) self.QT_LIB = 'myqt' @@ -1205,15 +1267,20 @@ def Qt_create_SConstruct(self, place, qt_tool: str = 'qt3') -> None: place = self.workpath(*place) var_prefix = qt_tool.upper() - self.write(place, f"""\ + self.write( + place, + f"""\ if ARGUMENTS.get('noqtdir', 0): {var_prefix}DIR = None else: {var_prefix}DIR = r'{self.QT}' DefaultEnvironment(tools=[]) # test speedup env = Environment( - {var_prefix}DIR={var_prefix}DIR, {var_prefix}_LIB=r'{self.QT_LIB}', {var_prefix}_MOC=r'{self.QT_MOC}', - {var_prefix}_UIC=r'{self.QT_UIC}', tools=['default', '{qt_tool}'] + {var_prefix}DIR={var_prefix}DIR, + {var_prefix}_LIB=r'{self.QT_LIB}', + {var_prefix}_MOC=r'{self.QT_MOC}', + {var_prefix}_UIC=r'{self.QT_UIC}', + tools=['default', '{qt_tool}'], ) dup = 1 if ARGUMENTS.get('variant_dir', 0): @@ -1234,7 +1301,8 @@ def Qt_create_SConstruct(self, place, qt_tool: str = 'qt3') -> None: sconscript = File('SConscript') Export("env dup") SConscript(sconscript) -""") +""", + ) NCR = 0 # non-cached rebuild CR = 1 # cached rebuild (up to date) @@ -1250,12 +1318,11 @@ def Qt_create_SConstruct(self, place, qt_tool: str = 'qt3') -> None: # Configure_lib = 'm' def coverage_run(self) -> bool: - """ Check if the the tests are being run under coverage. - """ + """Check if the the tests are being run under coverage.""" return 'COVERAGE_PROCESS_START' in os.environ or 'COVERAGE_FILE' in os.environ def skip_if_not_msvc(self, check_platform: bool = True) -> None: - """ Skip test if MSVC is not available. + """Skip test if MSVC is not available. Check whether we are on a Windows platform and skip the test if not. This check can be omitted by setting check_platform to False. @@ -1272,18 +1339,23 @@ def skip_if_not_msvc(self, check_platform: bool = True) -> None: try: import SCons.Tool.MSCommon as msc + if not msc.msvc_exists(): msg = "No MSVC toolchain found...skipping test\n" self.skip_test(msg, from_fw=True) except Exception: pass - def checkConfigureLogAndStdout(self, checks, - logfile: str = 'config.log', - sconf_dir: str = '.sconf_temp', - sconstruct: str = "SConstruct", - doCheckLog: bool = True, doCheckStdout: bool = True): - """ Verify expected output from Configure. + def checkConfigureLogAndStdout( + self, + checks, + logfile: str = 'config.log', + sconf_dir: str = '.sconf_temp', + sconstruct: str = "SConstruct", + doCheckLog: bool = True, + doCheckStdout: bool = True, + ): + """Verify expected output from Configure. Used to verify the expected output from using Configure() via the contents of one or both of stdout or config.log file. @@ -1312,9 +1384,13 @@ def checkConfigureLogAndStdout(self, checks, # Some debug code to keep around.. # sys.stderr.write("LOGFILE[%s]:%s"%(type(logfile),logfile)) - if (doCheckLog and - logfile.find( - "scons: warning: The stored build information has an unexpected class.") >= 0): + if ( + doCheckLog + and logfile.find( + "scons: warning: The stored build information has an unexpected class." + ) + >= 0 + ): self.fail_test() log = r'file \S*%s\,line \d+:' % re.escape(sconstruct) + ls @@ -1351,13 +1427,21 @@ def checkConfigureLogAndStdout(self, checks, if flag == self.CR: # CR = cached rebuild (up to date)s # up to date - log = log + \ - re.escape("scons: Configure: \"") + \ - conf_filename + \ - re.escape("\" is up to date.") + ls - log = log + re.escape( - "scons: Configure: The original builder " - "output was:") + ls + log = ( + log + + re.escape("scons: Configure: \"") + + conf_filename + + re.escape("\" is up to date.") + + ls + ) + log = ( + log + + re.escape( + "scons: Configure: The original builder " + "output was:" + ) + + ls + ) log = f"{log}( \\|.*{ls})+" if flag == self.NCF: # non-cached rebuild failure @@ -1365,13 +1449,22 @@ def checkConfigureLogAndStdout(self, checks, result_cached = 0 if flag == self.CF: # cached rebuild failure - log = log + \ - re.escape("scons: Configure: Building \"") + \ - conf_filename + \ - re.escape( - "\" failed in a previous run and all its sources are up to date.") + ls - log = log + re.escape( - "scons: Configure: The original builder output was:") + ls + log = ( + log + + re.escape("scons: Configure: Building \"") + + conf_filename + + re.escape( + "\" failed in a previous run and all its sources are up to date." + ) + + ls + ) + log = ( + log + + re.escape( + "scons: Configure: The original builder output was:" + ) + + ls + ) log = f"{log}( \\|.*{ls})+" if result_cached: result = f"(cached) {check_info.result}" @@ -1395,7 +1488,7 @@ def checkConfigureLogAndStdout(self, checks, print("Cannot match log file against log regexp.") print("log file: ") print("------------------------------------------------------") - print(logfile[m.pos:]) + print(logfile[m.pos :]) print("------------------------------------------------------") print("log regexp: ") print("------------------------------------------------------") @@ -1415,10 +1508,18 @@ def checkConfigureLogAndStdout(self, checks, print("-----------------------------------------------------") self.fail_test() - def checkLogAndStdout(self, checks, results, cached, - logfile, sconf_dir, sconstruct, - doCheckLog: bool = True, doCheckStdout: bool = True): - """ Verify expected output from Configure. + def checkLogAndStdout( + self, + checks, + results, + cached, + logfile, + sconf_dir, + sconstruct, + doCheckLog: bool = True, + doCheckStdout: bool = True, + ): + """Verify expected output from Configure. Used to verify the expected output from using Configure() via the contents of one or both of stdout or config.log file. @@ -1439,7 +1540,6 @@ def checkLogAndStdout(self, checks, results, cached, doCheckStdout: Check stdout, defaults to true """ try: - ls = '\n' nols = '([^\n])' lastEnd = 0 @@ -1450,9 +1550,13 @@ def checkLogAndStdout(self, checks, results, cached, # Some debug code to keep around.. # sys.stderr.write("LOGFILE[%s]:%s"%(type(logfile),logfile)) - if (doCheckLog and - logfile.find( - "scons: warning: The stored build information has an unexpected class.") >= 0): + if ( + doCheckLog + and logfile.find( + "scons: warning: The stored build information has an unexpected class." + ) + >= 0 + ): self.fail_test() sconf_dir = sconf_dir @@ -1481,26 +1585,30 @@ def checkLogAndStdout(self, checks, results, cached, for ext, flag in bld_desc: # each file in TryBuild if ext in ['.c', '.cpp']: conf_filename = re.escape( - os.path.join(sconf_dir, "conftest")) + \ - r'_[a-z0-9]{32,64}_\d+%s' % re.escape(ext) + os.path.join(sconf_dir, "conftest") + ) + r'_[a-z0-9]{32,64}_\d+%s' % re.escape(ext) elif ext == '': - conf_filename = re.escape( - os.path.join(sconf_dir, "conftest")) + \ - r'_[a-z0-9]{32,64}(_\d+_[a-z0-9]{32,64})?' + conf_filename = ( + re.escape(os.path.join(sconf_dir, "conftest")) + + r'_[a-z0-9]{32,64}(_\d+_[a-z0-9]{32,64})?' + ) else: - # We allow the second hash group to be optional because - # TryLink() will create a c file, then compile to obj, then link that - # The intermediate object file will not get the action hash - # But TryCompile()'s where the product is the .o will get the - # action hash. Rather than add a ton of complications to this logic - # this shortcut should be sufficient. - # TODO: perhaps revisit and/or fix file naming for intermediate files in - # Configure context logic - conf_filename = re.escape( - os.path.join(sconf_dir, "conftest")) + \ - r'_[a-z0-9]{32,64}_\d+(_[a-z0-9]{32,64})?%s' % re.escape( - ext) + # We allow the second hash group to be optional + # because TryLink() will create a c file, then + # compile to obj, then link that The intermediate + # object file will not get the action hash But + # TryCompile()'s where the product is the .o will + # get the action hash. Rather than add a ton of + # complications to this logic this shortcut should + # be sufficient. TODO: perhaps revisit and/or fix + # file naming for intermediate files in Configure + # context logic + conf_filename = ( + re.escape(os.path.join(sconf_dir, "conftest")) + + r'_[a-z0-9]{32,64}_\d+(_[a-z0-9]{32,64})?%s' + % re.escape(ext) + ) if flag == self.NCR: # NCR = Non Cached Rebuild @@ -1514,13 +1622,21 @@ def checkLogAndStdout(self, checks, results, cached, if flag == self.CR: # CR = cached rebuild (up to date)s # up to date - log = log + \ - re.escape("scons: Configure: \"") + \ - conf_filename + \ - re.escape("\" is up to date.") + ls - log = log + re.escape( - "scons: Configure: The original builder " - "output was:") + ls + log = ( + log + + re.escape("scons: Configure: \"") + + conf_filename + + re.escape("\" is up to date.") + + ls + ) + log = ( + log + + re.escape( + "scons: Configure: The original builder " + "output was:" + ) + + ls + ) log = f"{log}( \\|.*{ls})+" if flag == self.NCF: # non-cached rebuild failure @@ -1528,13 +1644,22 @@ def checkLogAndStdout(self, checks, results, cached, result_cached = 0 if flag == self.CF: # cached rebuild failure - log = log + \ - re.escape("scons: Configure: Building \"") + \ - conf_filename + \ - re.escape( - "\" failed in a previous run and all its sources are up to date.") + ls - log = log + re.escape( - "scons: Configure: The original builder output was:") + ls + log = ( + log + + re.escape("scons: Configure: Building \"") + + conf_filename + + re.escape( + "\" failed in a previous run and all its sources are up to date." + ) + + ls + ) + log = ( + log + + re.escape( + "scons: Configure: The original builder output was:" + ) + + ls + ) log = f"{log}( \\|.*{ls})+" # cnt = cnt + 1 if result_cached: @@ -1558,7 +1683,7 @@ def checkLogAndStdout(self, checks, results, cached, print("Cannot match log file against log regexp.") print("log file: ") print("------------------------------------------------------") - print(logfile[m.pos:]) + print(logfile[m.pos :]) print("------------------------------------------------------") print("log regexp: ") print("------------------------------------------------------") @@ -1579,7 +1704,7 @@ def checkLogAndStdout(self, checks, results, cached, self.fail_test() def get_python_version(self) -> str: - """ Returns the Python version. + """Returns the Python version. Convenience function so everyone doesn't have to hand-code slicing the right number of characters @@ -1602,14 +1727,17 @@ def get_platform_python_info(self, python_h_required: bool = False): """ python = os.environ.get('python_executable', self.where_is('python')) if not python: - self.skip_test('Can not find installed "python", skipping test.\n', - from_fw=True) + self.skip_test( + 'Can not find installed "python", skipping test.\n', from_fw=True + ) # construct a program to run in the intended environment # in order to fetch the characteristics of that Python. # Windows Python doesn't store all the info in config vars. if sys.platform == 'win32': - self.run(program=python, stdin="""\ + self.run( + program=python, + stdin="""\ import sysconfig, sys, os.path py_ver = 'python%d%d' % sys.version_info[:2] try: @@ -1641,9 +1769,12 @@ def venv_path(): print(Python_h) else: print("False") -""") +""", + ) else: - self.run(program=python, stdin="""\ + self.run( + program=python, + stdin="""\ import sys, sysconfig, os.path include = sysconfig.get_config_var("INCLUDEPY") print(include) @@ -1657,12 +1788,14 @@ def venv_path(): print(Python_h) else: print("False") -""") +""", + ) stdout = self.stdout() or "" incpath, libpath, libname, python_h = stdout.strip().split('\n') if python_h == "False" and python_h_required: - self.skip_test('Can not find required "Python.h", skipping test.\n', - from_fw=True) + self.skip_test( + 'Can not find required "Python.h", skipping test.\n', from_fw=True + ) return (python, incpath, libpath, libname + _lib) @@ -1755,24 +1888,34 @@ def __init__(self, name, units, expression, convert=None) -> None: StatList = [ - Stat('memory-initial', 'kbytes', - r'Memory before reading SConscript files:\s+(\d+)', - convert=lambda s: int(s) // 1024), - Stat('memory-prebuild', 'kbytes', - r'Memory before building targets:\s+(\d+)', - convert=lambda s: int(s) // 1024), - Stat('memory-final', 'kbytes', - r'Memory after building targets:\s+(\d+)', - convert=lambda s: int(s) // 1024), - - Stat('time-sconscript', 'seconds', - r'Total SConscript file execution time:\s+([\d.]+) seconds'), - Stat('time-scons', 'seconds', - r'Total SCons execution time:\s+([\d.]+) seconds'), - Stat('time-commands', 'seconds', - r'Total command execution time:\s+([\d.]+) seconds'), - Stat('time-total', 'seconds', - r'Total build time:\s+([\d.]+) seconds'), + Stat( + 'memory-initial', + 'kbytes', + r'Memory before reading SConscript files:\s+(\d+)', + convert=lambda s: int(s) // 1024, + ), + Stat( + 'memory-prebuild', + 'kbytes', + r'Memory before building targets:\s+(\d+)', + convert=lambda s: int(s) // 1024, + ), + Stat( + 'memory-final', + 'kbytes', + r'Memory after building targets:\s+(\d+)', + convert=lambda s: int(s) // 1024, + ), + Stat( + 'time-sconscript', + 'seconds', + r'Total SConscript file execution time:\s+([\d.]+) seconds', + ), + Stat('time-scons', 'seconds', r'Total SCons execution time:\s+([\d.]+) seconds'), + Stat( + 'time-commands', 'seconds', r'Total command execution time:\s+([\d.]+) seconds' + ), + Stat('time-total', 'seconds', r'Total build time:\s+([\d.]+) seconds'), ] @@ -1867,11 +2010,7 @@ def trace(self, graph, name, value, units, sort=None) -> None: sys.stdout.flush() def report_traces(self, trace, stats) -> None: - self.trace('TimeSCons-elapsed', - trace, - self.elapsed_time(), - "seconds", - sort=0) + self.trace('TimeSCons-elapsed', trace, self.elapsed_time(), "seconds", sort=0) for name, args in stats.items(): self.trace(name, trace, **args) diff --git a/testing/framework/TestSConsMSVS.py b/testing/framework/TestSConsMSVS.py index 0951b4626a..88026e141b 100644 --- a/testing/framework/TestSConsMSVS.py +++ b/testing/framework/TestSConsMSVS.py @@ -40,6 +40,7 @@ import platform import traceback from xml.etree import ElementTree + try: import winreg except ImportError: @@ -50,7 +51,7 @@ from TestSCons import __all__ -PROJECT_GUID = "{00000000-0000-0000-0000-000000000000}" +PROJECT_GUID = "{00000000-0000-0000-0000-000000000000}" PROJECT_GUID_1 = "{11111111-1111-1111-1111-111111111111}" PROJECT_GUID_2 = "{22222222-2222-2222-2222-222222222222}" @@ -217,7 +218,6 @@ """ - expected_slnfile_7_0 = """\ Microsoft Visual Studio Solution File, Format Version 7.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "" @@ -341,7 +341,6 @@ """ - expected_slnfile_7_1 = """\ Microsoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "" @@ -825,6 +824,7 @@ ) """ + def get_tested_proj_file_vc_versions(): """ Returns all MSVC versions that we want to test project file creation for. @@ -837,7 +837,6 @@ class TestSConsMSVS(TestSCons): def msvs_versions(self): if not hasattr(self, '_msvs_versions'): - # Determine the SCons version and the versions of the MSVS # environments installed on the test machine. # @@ -846,21 +845,23 @@ def msvs_versions(self): # we can just exec(). We construct the SCons.__"version"__ # string in the input here so that the SCons build itself # doesn't fill it in when packaging SCons. - input = """\ + input = ( + """\ import SCons import SCons.Tool.MSCommon print("self.scons_version =%%s"%%repr(SCons.__%s__)) print("self._msvs_versions =%%s"%%str(SCons.Tool.MSCommon.query_versions(env=None))) -""" % 'version' +""" + % 'version' + ) - self.run(arguments = '-n -q -Q -f -', stdin = input) + self.run(arguments='-n -q -Q -f -', stdin=input) exec(self.stdout()) return self._msvs_versions def vcproj_sys_path(self, fname) -> None: - """ - """ + """ """ orig = 'sys.path = [ join(sys' enginepath = repr(os.path.join(self._cwd, '..', 'engine')) @@ -870,11 +871,17 @@ def vcproj_sys_path(self, fname) -> None: contents = contents.replace(orig, replace) self.write(fname, contents) - def msvs_substitute(self, input, msvs_ver, - subdir=None, sconscript=None, - python=None, - project_guid=None, - vcproj_sccinfo: str='', sln_sccinfo: str=''): + def msvs_substitute( + self, + input, + msvs_ver, + subdir=None, + sconscript=None, + python=None, + project_guid=None, + vcproj_sccinfo: str = '', + sln_sccinfo: str = '', + ): if not hasattr(self, '_msvs_versions'): self.msvs_versions() @@ -937,23 +944,23 @@ def run(self, *args, **kw): return result def get_vs_host_arch(self): - """ Returns an MSVS, SDK, and/or MSVS acceptable platform arch. """ + """Returns an MSVS, SDK, and/or MSVS acceptable platform arch.""" # Dict to 'canonicalize' the arch (synchronize with MSCommon\vc.py) _ARCH_TO_CANONICAL = { - "amd64" : "amd64", - "emt64" : "amd64", - "i386" : "x86", - "i486" : "x86", - "i586" : "x86", - "i686" : "x86", - "ia64" : "ia64", # deprecated - "itanium" : "ia64", # deprecated - "x86" : "x86", - "x86_64" : "amd64", - "arm" : "arm", - "arm64" : "arm64", - "aarch64" : "arm64", + "amd64": "amd64", + "emt64": "amd64", + "i386": "x86", + "i486": "x86", + "i586": "x86", + "i686": "x86", + "ia64": "ia64", # deprecated + "itanium": "ia64", # deprecated + "x86": "x86", + "x86_64": "amd64", + "arm": "arm", + "arm64": "arm64", + "aarch64": "arm64", } host_platform = None @@ -962,7 +969,7 @@ def get_vs_host_arch(self): try: winkey = winreg.OpenKeyEx( winreg.HKEY_LOCAL_MACHINE, - r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment' + r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', ) host_platform, _ = winreg.QueryValueEx(winkey, 'PROCESSOR_ARCHITECTURE') except OSError: @@ -979,7 +986,7 @@ def get_vs_host_arch(self): return host - def validate_msvs_file(self, file) -> None: + def validate_msvs_file(self, file) -> None: try: x = ElementTree.parse(file) except: @@ -1125,7 +1132,9 @@ def get_expected_sconscript_file_contents(self, vc_version, project_file): } def msvs_substitute_projects( - self, input, *, + self, + input, + *, subdir=None, sconscript=None, python=None, @@ -1133,8 +1142,8 @@ def msvs_substitute_projects( project_guid_2=None, solution_guid_1=None, solution_guid_2=None, - vcproj_sccinfo: str='', - sln_sccinfo: str='' + vcproj_sccinfo: str = '', + sln_sccinfo: str = '', ): if not hasattr(self, '_msvs_versions'): self.msvs_versions() @@ -1181,7 +1190,9 @@ def msvs_substitute_projects( result = result.replace('\n', sln_sccinfo) return result - def get_expected_projects_proj_file_contents(self, vc_version, dirs, project_file, project_guid): + def get_expected_projects_proj_file_contents( + self, vc_version, dirs, project_file, project_guid + ): """Returns the expected .vcxproj file contents""" if project_file.endswith('.vcxproj'): fmt = expected_vcxprojfile_fmt @@ -1198,8 +1209,10 @@ def get_expected_projects_proj_file_contents(self, vc_version, dirs, project_fil } def get_expected_projects_sln_file_contents( - self, vc_version, - project_file_1, project_file_2, + self, + vc_version, + project_file_1, + project_file_2, have_solution_project_nodes=False, autofilter_solution_project_nodes=None, ): @@ -1226,13 +1239,15 @@ def get_expected_projects_sln_file_contents( return rval def get_expected_projects_sconscript_file_contents( - self, vc_version, - project_file_1, project_file_2, solution_file, + self, + vc_version, + project_file_1, + project_file_2, + solution_file, autobuild_solution=0, autofilter_projects=None, default_guids=False, ): - values = { 'HOST_ARCH': self.get_vs_host_arch(), 'MSVS_VERSION': vc_version, @@ -1248,12 +1263,15 @@ def get_expected_projects_sconscript_file_contents( else: format = SConscript_projects_contents_fmt - values.update({ - 'PROJECT_GUID_1': PROJECT_GUID_1, - 'PROJECT_GUID_2': PROJECT_GUID_2, - }) + values.update( + { + 'PROJECT_GUID_1': PROJECT_GUID_1, + 'PROJECT_GUID_2': PROJECT_GUID_2, + } + ) return format % values + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/testing/framework/TestSCons_time.py b/testing/framework/TestSCons_time.py index 6ee4b10e27..7748c7c7ce 100644 --- a/testing/framework/TestSCons_time.py +++ b/testing/framework/TestSCons_time.py @@ -41,10 +41,11 @@ from TestCommon import * from TestCommon import __all__ from TestCmd import IS_WINDOWS + # some of the scons_time tests may need regex-based matching: from TestSCons import search_re, search_re_in_list -__all__.extend(['TestSCons_time',]) +__all__.extend(['TestSCons_time']) SConstruct = """\ import os @@ -190,7 +191,9 @@ def __init__(self, **kw) -> None: kw['program'] = p if 'interpreter' not in kw: - kw['interpreter'] = [python,] + kw['interpreter'] = [ + python, + ] if 'match' not in kw: kw['match'] = match_exact @@ -206,20 +209,20 @@ def archive_split(self, path): else: return os.path.splitext(path) - def fake_logfile(self, logfile_name, index: int=0) -> None: + def fake_logfile(self, logfile_name, index: int = 0) -> None: self.write(self.workpath(logfile_name), logfile_contents % locals()) def profile_data(self, profile_name, python_name, call, body) -> None: profile_name = self.workpath(profile_name) python_name = self.workpath(python_name) d = { - 'profile_name' : profile_name, - 'python_name' : python_name, - 'call' : call, - 'body' : body, + 'profile_name': profile_name, + 'python_name': python_name, + 'call': call, + 'body': body, } self.write(python_name, profile_py % d) - self.run(program = python_name, interpreter = sys.executable) + self.run(program=python_name, interpreter=sys.executable) def tempdir_re(self, *args): """ @@ -243,7 +246,10 @@ def tempdir_re(self, *args): if not IS_WINDOWS: tempdir = realpath(tempdir) - args = (tempdir, 'scons-time-',) + args + args = ( + tempdir, + 'scons-time-', + ) + args x = os.path.join(*args) x = re.escape(x) x = x.replace('time\\-', f'time\\-[^{sep}]*') @@ -279,19 +285,20 @@ def write_sample_directory(self, archive, dir, files): def write_sample_tarfile(self, archive, dir, files): import shutil import tarfile + base, suffix = self.archive_split(archive) mode = { - '.tar' : 'w', - '.tar.gz' : 'w:gz', - '.tgz' : 'w:gz', + '.tar': 'w', + '.tar.gz': 'w:gz', + '.tgz': 'w:gz', } with tarfile.open(archive, mode[suffix]) as tar: for name, content in files: path = os.path.join(dir, name) with open(path, 'wb') as f: - f.write(bytearray(content,'utf-8')) + f.write(bytearray(content, 'utf-8')) tarinfo = tar.gettarinfo(path, path) tarinfo.uid = 111 tarinfo.gid = 111 @@ -305,6 +312,7 @@ def write_sample_tarfile(self, archive, dir, files): def write_sample_zipfile(self, archive, dir, files): import shutil import zipfile + with zipfile.ZipFile(archive, 'w') as zip: for name, content in files: path = os.path.join(dir, name) @@ -315,17 +323,17 @@ def write_sample_zipfile(self, archive, dir, files): return self.workpath(archive) sample_project_files = [ - ('SConstruct', SConstruct), + ('SConstruct', SConstruct), ] def write_sample_project(self, archive, dir=None): base, suffix = self.archive_split(archive) write_sample = { - '.tar' : self.write_sample_tarfile, - '.tar.gz' : self.write_sample_tarfile, - '.tgz' : self.write_sample_tarfile, - '.zip' : self.write_sample_zipfile, + '.tar': self.write_sample_tarfile, + '.tar.gz': self.write_sample_tarfile, + '.tgz': self.write_sample_tarfile, + '.zip': self.write_sample_zipfile, }.get(suffix, self.write_sample_directory) if not dir: @@ -336,6 +344,7 @@ def write_sample_project(self, archive, dir=None): return path + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/testing/framework/TestSConsign.py b/testing/framework/TestSConsign.py index 9f02b4937a..18dd333dbd 100644 --- a/testing/framework/TestSConsign.py +++ b/testing/framework/TestSConsign.py @@ -41,7 +41,8 @@ from TestSCons import * from TestSCons import __all__ -__all__.extend([ 'TestSConsign', ]) +__all__.extend(['TestSConsign']) + class TestSConsign(TestSCons): """Class for testing the sconsign.py script. @@ -55,6 +56,7 @@ class TestSConsign(TestSCons): "scons" itself, since we need to run scons to generate the .sconsign files that we want the sconsign script to read. """ + def __init__(self, *args, **kw) -> None: try: script_dir = os.environ['SCONS_SCRIPT_DIR'] @@ -67,7 +69,7 @@ def __init__(self, *args, **kw) -> None: super().__init__(*args, **kw) self.my_kw = { - 'interpreter' : python, # imported from TestSCons + 'interpreter': python, # imported from TestSCons } if 'program' not in kw: @@ -99,6 +101,7 @@ def run_sconsign(self, *args, **kw): kw.update(self.my_kw) return self.run(*args, **kw) + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/testing/framework/TestUnit/cli.py b/testing/framework/TestUnit/cli.py index defe5a1eff..b46951fcec 100644 --- a/testing/framework/TestUnit/cli.py +++ b/testing/framework/TestUnit/cli.py @@ -10,8 +10,11 @@ def get_runner(): parser = optparse.OptionParser() - parser.add_option('--runner', default='unittest.TextTestRunner', - help='name of test runner class to use') + parser.add_option( + '--runner', + default='unittest.TextTestRunner', + help='name of test runner class to use', + ) opts, args = parser.parse_args() fromsplit = opts.runner.rsplit('.', 1) diff --git a/testing/framework/TestUnit/taprunner.py b/testing/framework/TestUnit/taprunner.py index b52c762a82..c4e6f41775 100644 --- a/testing/framework/TestUnit/taprunner.py +++ b/testing/framework/TestUnit/taprunner.py @@ -15,6 +15,7 @@ from unittest import TextTestRunner + try: from unittest import TextTestResult except ImportError: @@ -23,19 +24,18 @@ class TAPTestResult(TextTestResult): - - def _process(self, test, msg, failtype = None, directive = None) -> None: - """ increase the counter, format and output TAP info """ + def _process(self, test, msg, failtype=None, directive=None) -> None: + """increase the counter, format and output TAP info""" # counterhack: increase test counter test.suite.tap_counter += 1 msg = "%s %d" % (msg, test.suite.tap_counter) if "not" not in msg: msg += " " # justify - self.stream.write("%s - " % msg) + self.stream.write(f"{msg} - ") if failtype: - self.stream.write("%s - " % failtype) - self.stream.write("%s" % test.__class__.__name__) - self.stream.write(".%s" % test._testMethodName) + self.stream.write(f"{failtype} - ") + self.stream.write(f"{test.__class__.__name__}") + self.stream.write(f".{test._testMethodName}") if directive: self.stream.write(directive) self.stream.write("\n") @@ -58,7 +58,7 @@ def addError(self, test, err) -> None: def addSkip(self, test, reason) -> None: super().addSkip(test, reason) - self._process(test, "ok", directive=(" # SKIP %s" % reason)) + self._process(test, "ok", directive=f" # SKIP {reason}") def addExpectedFailure(self, test, err) -> None: super().addExpectedFailure(test, err) @@ -82,7 +82,7 @@ def run(self, test): # [ ] add commented block with test suite __doc__ # [ ] check call with a single test # if isinstance(test, suite.TestSuite): - self.stream.write("1..%s\n" % len(list(test))) + self.stream.write(f"1..{len(list(test))}\n") # counterhack: inject test counter into test suite test.tap_counter = 0 @@ -98,33 +98,40 @@ def run(self, test): import unittest class Test(unittest.TestCase): - def test_ok(self) -> None: - pass - def test_fail(self) -> None: - self.assertTrue(False) - def test_error(self) -> None: - bad_symbol - @unittest.skip("skipin'") - def test_skip(self) -> None: - pass - @unittest.expectedFailure - def test_not_ready(self) -> None: - self.fail() - @unittest.expectedFailure - def test_invalid_fail_mark(self) -> None: - pass - def test_another_ok(self) -> None: - pass - - - suite = unittest.TestSuite([ - Test('test_ok'), - Test('test_fail'), - Test('test_error'), - Test('test_skip'), - Test('test_not_ready'), - Test('test_invalid_fail_mark'), - Test('test_another_ok') - ]) + def test_ok(self) -> None: + pass + + def test_fail(self) -> None: + self.assertTrue(False) + + def test_error(self) -> None: + bad_symbol + + @unittest.skip("skipin'") + def test_skip(self) -> None: + pass + + @unittest.expectedFailure + def test_not_ready(self) -> None: + self.fail() + + @unittest.expectedFailure + def test_invalid_fail_mark(self) -> None: + pass + + def test_another_ok(self) -> None: + pass + + suite = unittest.TestSuite( + [ + Test('test_ok'), + Test('test_fail'), + Test('test_error'), + Test('test_skip'), + Test('test_not_ready'), + Test('test_invalid_fail_mark'), + Test('test_another_ok'), + ] + ) if not TAPTestRunner().run(suite).wasSuccessful(): - sys.exit(1) + sys.exit(1)