diff options
| author | Charles Cabergs <me@cacharle.xyz> | 2021-02-27 12:24:37 +0100 |
|---|---|---|
| committer | Charles Cabergs <me@cacharle.xyz> | 2021-02-27 12:24:37 +0100 |
| commit | 7081b93b8ed4f98c628400e05d22d0523f41a842 (patch) | |
| tree | 4b945840ade4d1869ceedf94e9bca4581f096d0f | |
| parent | ad7233a4a5f45be6f991ed38a7351a6ef826356b (diff) | |
| download | minishell_test-7081b93b8ed4f98c628400e05d22d0523f41a842.tar.gz minishell_test-7081b93b8ed4f98c628400e05d22d0523f41a842.tar.bz2 minishell_test-7081b93b8ed4f98c628400e05d22d0523f41a842.zip | |
Fixing #16 - Adding support for custom config file in user directory
| -rwxr-xr-x | minishell_test/__main__.py | 71 | ||||
| -rw-r--r-- | minishell_test/args.py | 57 | ||||
| -rw-r--r-- | minishell_test/config.py | 192 | ||||
| -rw-r--r-- | minishell_test/data/__init__.py | 0 | ||||
| -rw-r--r-- | minishell_test/data/default.cfg | 27 | ||||
| -rw-r--r-- | minishell_test/data/lorem | 13 | ||||
| -rw-r--r-- | minishell_test/hooks.py | 25 | ||||
| -rw-r--r-- | minishell_test/minishell_test.cfg | 2 | ||||
| -rw-r--r-- | minishell_test/result_config.cfg | 23 | ||||
| -rw-r--r-- | minishell_test/sandbox.py | 14 | ||||
| -rw-r--r-- | minishell_test/suite/suite.py | 35 | ||||
| -rw-r--r-- | minishell_test/suites/builtin.py | 6 | ||||
| -rw-r--r-- | minishell_test/suites/cmd.py | 6 | ||||
| -rw-r--r-- | minishell_test/suites/flow.py | 4 | ||||
| -rw-r--r-- | minishell_test/suites/preprocess.py | 6 | ||||
| -rw-r--r-- | minishell_test/test/captured.py | 20 | ||||
| -rw-r--r-- | minishell_test/test/result.py | 34 | ||||
| -rw-r--r-- | minishell_test/test/test.py | 30 | ||||
| -rw-r--r-- | setup.cfg | 3 |
19 files changed, 289 insertions, 279 deletions
diff --git a/minishell_test/__main__.py b/minishell_test/__main__.py index 3ae1648..7da33cd 100755 --- a/minishell_test/__main__.py +++ b/minishell_test/__main__.py @@ -18,8 +18,8 @@ import shutil import distutils.spawn import subprocess -import minishell_test.config as config -import minishell_test.sandbox as sandbox +from minishell_test import config +from minishell_test import sandbox from minishell_test.args import parse_args from minishell_test.suite.suite import Suite, SuiteException from minishell_test.suites import * # noqa: F403,F401 @@ -28,67 +28,49 @@ from minishell_test.test import Test def main(argv=None): args = parse_args() + if args.list: Suite.list() sys.exit(0) - config.MINISHELL_DIR = args.path - config.MINISHELL_PATH = os.path.abspath( - os.path.join(config.MINISHELL_DIR, config.MINISHELL_EXEC) - ) - config.VALGRIND_CMD[-1] = config.MINISHELL_PATH - - if config.MINISHELL_MAKE or args.make: + # running ``make`` in minishell directory + if config.MAKE or args.make: + print("{:=^{width}}".format("MAKE", width=config.TERM_COLS)) try: - print("{:=^{width}}".format("MAKE", width=config.TERM_COLS)) - subprocess.run(["make", "--no-print-directory", "-C", config.MINISHELL_DIR], - check=True, - env={"MINISHELL_TEST_FLAGS": "-DMINISHELL_TEST", **os.environ}) - print("=" * config.TERM_COLS) + subprocess.run( + ["make", "--no-print-directory", "-C", config.MINISHELL_DIR], + check=True, + env={"MINISHELL_TEST_FLAGS": "-DMINISHELL_TEST", **os.environ} + ) except subprocess.CalledProcessError: sys.exit(1) + print("=" * config.TERM_COLS) if args.make: sys.exit(0) - if not os.path.exists(config.EXECUTABLES_PATH): - os.mkdir(config.EXECUTABLES_PATH) - for cmd in config.AVAILABLE_COMMANDS: - cmd_path = distutils.spawn.find_executable(cmd) - if cmd_path is None: - raise RuntimeError - shutil.copy(cmd_path, - os.path.join(config.EXECUTABLES_PATH, cmd)) + # setup available commands + if not config.SHELL_AVAILABLE_COMMANDS_DIR.exists(): + config.SHELL_AVAILABLE_COMMANDS_DIR.mkdir(parents=True, exist_ok=True) + for cmd in config.SHELL_AVAILABLE_COMMANDS: + copied_path = config.SHELL_AVAILABLE_COMMANDS_DIR / cmd + if copied_path.exists(): + continue + cmd_path = distutils.spawn.find_executable(cmd) + if cmd_path is None: + raise RuntimeError(f"Command not found {cmd}") + shutil.copy(cmd_path, copied_path) if args.try_cmd is not None: print("Output") print(Test.try_run(args.try_cmd)) sys.exit(0) - reference_args = os.environ.get("MINISHELL_TEST_ARGS") - if reference_args is not None: - config.REFERENCE_ARGS.extend(reference_args.split(',')) - - pager = os.environ.get("MINISHELL_TEST_PAGER") - if pager is not None: - config.PAGER = pager - - config.VERBOSE_LEVEL = args.verbose - if args.bonus or os.environ.get("MINISHELL_TEST_BONUS") == "yes": - config.BONUS = True - if args.no_bonus: - config.BONUS = False - config.EXIT_FIRST = args.exit_first - config.CHECK_LEAKS = args.check_leaks - config.RANGE = args.range - config.SHOW_RANGE = args.show_range - if config.RANGE is not None or config.CHECK_LEAKS: - config.SHOW_RANGE = True - try: Suite.setup(args.suites) except SuiteException as e: print(e) sys.exit(1) + try: Suite.run_all() except KeyboardInterrupt: @@ -103,8 +85,9 @@ def main(argv=None): print("HELP: Valgrind is really slow the -x and --range options could be useful" " ({} -h for more details)".format(sys.argv[0])) - if args.pager: - subprocess.run([config.PAGER, config.LOG_PATH]) + if config.PAGER: + # TODO {} replaced by filename in pager config var + subprocess.run([config.PAGER_PROG, config.LOG_PATH]) if __name__ == "__main__": diff --git a/minishell_test/args.py b/minishell_test/args.py index ef47081..3f56b8c 100644 --- a/minishell_test/args.py +++ b/minishell_test/args.py @@ -6,16 +6,16 @@ # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/07/15 18:24:32 by charles #+# #+# # -# Updated: 2021/02/24 08:48:15 by cacharle ### ########.fr # +# Updated: 2021/02/27 12:08:55 by cacharle ### ########.fr # # # # ############################################################################ # import argparse import textwrap - -import minishell_test.config as config +import functools +@functools.lru_cache(maxsize=1) def parse_args(): """Parse command line arguments""" @@ -25,65 +25,64 @@ def parse_args(): epilog="Made by cacharle - https://cacharle.xyz" ) parser.add_argument( - "-p", "--path", default=config.MINISHELL_DIR, + "-p", "--path", + default=".", help="Path to minishell directory" ) parser.add_argument( - "-l", "--list", action="store_true", + "-l", "--list", + action="store_true", help="Print available test suites" ) parser.add_argument( - "-t", "--try-cmd", metavar="COMMAND", + "-t", "--try", + metavar="COMMAND", + dest='try_cmd', help=textwrap.dedent("""\ Run a custom command like this test would (the only environment variable passed to your executable are TERM and PATH) """) ) parser.add_argument( - "-k", "--check-leaks", action="store_true", + "-k", "--check-leaks", + action="store_true", help="Run valgrind on tests (disable usual comparison with bash)" ) parser.add_argument( - "-r", "--range", nargs=2, type=int, metavar=("BEGIN", "END"), + "-r", "--range", + nargs=2, + type=int, + metavar=("BEGIN", "END"), help="Range of test index to run (imply --show-index)" ) parser.add_argument( - "--show-range", action="store_true", + "--show-range", + action="store_true", help="Show test index (useful with --range)" ) parser.add_argument( - "-x", "--exit-first", action="store_true", + "-x", "--exit-first", + action="store_true", help="Exit on first fail" ) parser.add_argument( - "-v", "--verbose", action="count", - help="Increase verbosity level (e.g -vv == 2)" - ) - parser.add_argument( - "-b", "--bonus", action="store_true", - help="Enable bonus tests" - ) - parser.add_argument( - "-n", "--no-bonus", action="store_true", - help="Disable bonus tests" - ) - parser.add_argument( - "-m", "--make", action="store_true", + "-m", "--make", + action="store_true", help="Make minishell and exit" ) parser.add_argument( - "-g", "--pager", action="store_true", + "-g", "--pager", + action="store_true", help="After running the test, display the result in a pager of your choice" ) parser.add_argument( - "suites", nargs='*', metavar="suite", + "suites", + nargs='*', + metavar="SUITE", help=textwrap.dedent("""\ Test suites/group to run. It tries to be smart and autocomplete the suite name (e.g ./run int -> ./run preprocess/interpolation) """) ) - tmp = parser.parse_args() - if tmp.verbose is None: - tmp.verbose = 1 - return tmp + return parser.parse_args() diff --git a/minishell_test/config.py b/minishell_test/config.py index ac5b3ca..8f2f712 100644 --- a/minishell_test/config.py +++ b/minishell_test/config.py @@ -3,118 +3,104 @@ # ::: :::::::: # # config.py :+: :+: :+: # # +:+ +:+ +:+ # -# By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # +# By: cacharle <me@cacharle.xyz> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # -# Created: 2020/07/15 18:24:19 by charles #+# #+# # -# Updated: 2021/02/24 07:50:26 by cacharle ### ########.fr # +# Created: 2021/02/26 09:40:36 by cacharle #+# #+# # +# Updated: 2021/02/27 12:18:55 by cacharle ### ########.fr # # # # ############################################################################ # -################################################################################ -# Minishell configuration file # -################################################################################ - import os +import sys +import configparser +import inspect import shutil -import distutils.spawn -from typing import List - -# run the bonus tests -# can be changed with `export MINISHELL_TEST_BONUS=yes` in your shell rc file. -BONUS = False - -# minishell dir path -MINISHELL_DIR = "." - -# minishell executable -MINISHELL_EXEC = "minishell" - -# make minishell before executing the test if set to True -MINISHELL_MAKE = True - -# path to reference shell (shell which will be compared minishell) -# has to support the -c option (sh, bash and zsh support it) -REFERENCE_PATH = "/bin/bash" -# can be changed with `export MINISHELL_TEST_ARGS=--poxix,--otherarg` -REFERENCE_ARGS: List[str] = [] # ["--posix"] - -# pager to use with --pager option -# can be changed with `export MINISHELL_TEST_PAGER=yourpager` -PAGER = "less" - -# log file path -LOG_PATH = "minishell_test_result.log" - -# path to the sandbox directory -# WARNING: will be rm -rf so be careful -SANDBOX_PATH = "sandbox" - -# where the availables commands are stored -EXECUTABLES_PATH = "/tmp/minishell_test_bin" - -# commands available in test" -AVAILABLE_COMMANDS = ["rmdir", "env", "cat", "touch", "ls", "grep", "sh", "head"] - -# $PATH environment variable passed to the shell -PATH_VARIABLE = os.path.abspath(EXECUTABLES_PATH) - -# test timeout -TIMEOUT = 0.5 - -# check leaks test timeout -CHECK_LEAKS_TIMEOUT = 10 - -LOREM = """ -Mollitia asperiores assumenda excepturi et ipsa. Nihil corporis facere aut a rem consequatur. -Quas molestiae corporis et quibusdam maiores. Molestiae sed unde aut at sed. -Deserunt quidem quidem aspernatur pariatur vel illum voluptatum. Culpa unde dolor aspernatur sit. -Mollitia tenetur sed eaque autem placeat a aut in. Ipsam ea consequuntur omnis. -Non et qui vel corrupti similique eum aut voluptatibus. Iste consequatur voluptatum et omnis debitis. -Sit quia neque nihil consequatur sint. Velit libero ut aut et et rerum. -Placeat cumque incidunt non repellat sunt perspiciatis ullam. -Repellendus repudiandae nostrum quia quis corrupti. -Rerum veniam earum cumque pariatur accusantium voluptatum omnis. -Alias ut et et adipisci. Tempore omnis numquam ullam et animi et eveniet. -Dolor itaque distinctio in. Magnam rerum quia est laboriosam repellat perspiciatis eos. -Consequuntur quae corrupti atque. Numquam enim ut ut. -Perspiciatis ut maxime et libero quo voluptas consequatur illum. Pariatur porro dolor cumque molestiae harum. -""" -LOREM = ' '.join(LOREM.split('\n')) - -############################################################################### -# You probably shouldn't edit after # -############################################################################### - -MINISHELL_PATH = os.path.abspath( - os.path.join(MINISHELL_DIR, MINISHELL_EXEC) -) - -VALGRIND_CMD: List[str] = [ - distutils.spawn.find_executable("valgrind") or "couldn't find valgrind", - # "valgrind", - "--trace-children=no", - "--leak-check=yes", - "--child-silent-after-fork=yes", - "--show-leak-kinds=definite", - MINISHELL_PATH, -] - -# 0, 1, 2 -VERBOSE_LEVEL = 1 - -MINISHELL_ERROR_BEGIN = os.path.basename(MINISHELL_PATH) + ": " -REFERENCE_ERROR_BEGIN = REFERENCE_PATH + ": line 0: " +import distutils +from pathlib import Path -TERM_COLS = shutil.get_terminal_size().columns -if TERM_COLS < 40: - raise RuntimeError("You're terminal isn't wide enough") +import minishell_test.data +from minishell_test.args import parse_args + + +DATA_DIR = Path(inspect.getfile(minishell_test.data)).parent +CONFIG_FILENAME = Path('minishell_test.cfg') + +config = configparser.ConfigParser() +config.read(DATA_DIR / 'default.cfg') + +# TODO check user_config for unkown stuff +user_config = configparser.ConfigParser() +user_config.read(Path(".") / CONFIG_FILENAME) +config.read_dict({**config, **user_config}) + +args = parse_args() + +BONUS = config.getboolean('minishell_test', 'bonus') +EXEC_NAME = Path(config.get('minishell_test', 'exec_name')) +MAKE = config.getboolean('minishell_test', 'make') +PAGER = config.getboolean('minishell_test', 'pager') +PAGER_PROG = config.get('minishell_test', 'pager_prog') +LOG_PATH = Path(config.get('minishell_test', 'log_path')) + +SHELL_AVAILABLE_COMMANDS = config.get('shell', 'available_commands').strip().split('\n') +SHELL_PATH_VARIABLE = config.get('shell', 'path_variable') + +SHELL_REFERENCE_PATH = Path(config.get('shell:reference', 'path')) -PLATFORM = os.uname().sysname +reference_args = config.get('shell:reference', 'args') +SHELL_REFERENCE_ARGS = reference_args.strip().split(' ') if len(reference_args) != 0 else [] -EXIT_FIRST = False +TIMEOUT_TEST = config.getfloat('timeout', 'test') +TIMEOUT_LEAKS = config.getfloat('timeout', 'leaks') -CHECK_LEAKS = False -SHOW_RANGE = False +xdg_cache_home = os.environ.get('XDG_CACHE_HOME') +home = os.environ.get('HOME') +if xdg_cache_home is not None: + CACHE_DIR = Path(xdg_cache_home) / 'minishell_test' +elif home is not None: + CACHE_DIR = Path(home) / '.cache' / 'minishell_test' +else: + CACHE_DIR = Path('.cache', 'minishell_test') + +SANDBOX_DIR = CACHE_DIR / 'sandbox' +SHELL_AVAILABLE_COMMANDS_DIR = CACHE_DIR / 'bin' + +SHELL_PATH_VARIABLE = SHELL_PATH_VARIABLE.format(shell_available_commands_dir=SHELL_AVAILABLE_COMMANDS_DIR) + +with open(DATA_DIR / 'lorem') as f: + LOREM = ' '.join(f.read().split('\n')) + +MINISHELL_DIR = Path(args.path) +MINISHELL_EXEC_PATH = MINISHELL_DIR / EXEC_NAME + +EXIT_FIRST = args.exit_first +RANGE = args.range +CHECK_LEAKS = args.check_leaks + +if RANGE is not None or CHECK_LEAKS: + SHOW_RANGE = True +else: + SHOW_RANGE = args.show_range + +if CHECK_LEAKS: + valgrind_path = distutils.spawn.find_executable("valgrind") + if valgrind_path is None: + raise RuntimeError("Could not find valgrind command on your system") + VALGRIND_CMD = [ + str(valgrind_path), + "--trace-children=no", + "--leak-check=yes", + "--child-silent-after-fork=yes", + "--show-leak-kinds=definite", + str(MINISHELL_EXEC_PATH), + ] + +TERM_COLS = shutil.get_terminal_size().columns +if TERM_COLS < 40: + raise RuntimeError("You're terminal isn't wide enough 40 cols minimum required") -RANGE = None +PLATFORM = sys.platform +supported = ['linux', 'darwin'] +if PLATFORM not in supported: + raise RuntimeError("Your platform ({PLATFORM}) is not supported, supported platforms are: {', '.join(supported)}") diff --git a/minishell_test/data/__init__.py b/minishell_test/data/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/minishell_test/data/__init__.py diff --git a/minishell_test/data/default.cfg b/minishell_test/data/default.cfg new file mode 100644 index 0000000..62edbfd --- /dev/null +++ b/minishell_test/data/default.cfg @@ -0,0 +1,27 @@ +[minishell_test] +bonus = false +exec_name = minishell +make = true +pager = false +pager_prog = less +log_path = minishell_test.log + +[shell] +available_commands = + rmdir + env + cat + touch + ls + grep + sh + head +path_variable = {shell_available_commands_dir} + +[shell:reference] +path = /bin/bash +args = + +[timeout] +test = 0.5 +leaks = 10 diff --git a/minishell_test/data/lorem b/minishell_test/data/lorem new file mode 100644 index 0000000..388f482 --- /dev/null +++ b/minishell_test/data/lorem @@ -0,0 +1,13 @@ +Mollitia asperiores assumenda excepturi et ipsa. Nihil corporis facere aut a rem consequatur. +Quas molestiae corporis et quibusdam maiores. Molestiae sed unde aut at sed. +Deserunt quidem quidem aspernatur pariatur vel illum voluptatum. Culpa unde dolor aspernatur sit. +Mollitia tenetur sed eaque autem placeat a aut in. Ipsam ea consequuntur omnis. +Non et qui vel corrupti similique eum aut voluptatibus. Iste consequatur voluptatum et omnis debitis. +Sit quia neque nihil consequatur sint. Velit libero ut aut et et rerum. +Placeat cumque incidunt non repellat sunt perspiciatis ullam. +Repellendus repudiandae nostrum quia quis corrupti. +Rerum veniam earum cumque pariatur accusantium voluptatum omnis. +Alias ut et et adipisci. Tempore omnis numquam ullam et animi et eveniet. +Dolor itaque distinctio in. Magnam rerum quia est laboriosam repellat perspiciatis eos. +Consequuntur quae corrupti atque. Numquam enim ut ut. +Perspiciatis ut maxime et libero quo voluptas consequatur illum. Pariatur porro dolor cumque molestiae harum. diff --git a/minishell_test/hooks.py b/minishell_test/hooks.py index 9881354..dbbd975 100644 --- a/minishell_test/hooks.py +++ b/minishell_test/hooks.py @@ -6,15 +6,14 @@ # By: charles <me@cacharle.xyz> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/09/11 16:10:20 by charles #+# #+# # -# Updated: 2021/02/05 15:13:30 by charles ### ########.fr # +# Updated: 2021/02/27 12:09:25 by cacharle ### ########.fr # # # # ############################################################################ # import re -import sys import os -import minishell_test.config as config +from minishell_test import config def sort_lines(output): @@ -31,7 +30,7 @@ def error_line0(output): lines = output.split('\n') if len(lines) != 3: return output - prefix = "{}: -c: line 0: ".format(config.REFERENCE_PATH) + prefix = "{}: -c: line 0: ".format(config.SHELL_REFERENCE_PATH) if lines[0].find(prefix) != 0: return output return lines[0].replace(prefix, "minishell: ") + "\n" @@ -44,7 +43,7 @@ def discard(output): def export_singleton(output): """Remove variable that are not set to anything in a call to export without arguments""" - prefix = "export " if ("--posix" in config.REFERENCE_ARGS) else "declare -x " + prefix = "export " if ("--posix" in config.SHELL_REFERENCE_ARGS) else "declare -x " return sort_lines( '\n'.join([line for line in output.split('\n') if re.match("^{}[a-zA-Z]+$".format(prefix), line) is None]) @@ -63,20 +62,16 @@ def replace_double_semi_colon(output): def platform_status(darwin_status, linux_status, windows_status=None): def hook(status): - if config.PLATFORM == "Darwin": + if config.PLATFORM == "darwin": return status - elif config.PLATFORM == "Linux": + elif config.PLATFORM == "linux": return (darwin_status if status == linux_status else status) - else: - raise RuntimeError("This platform exit codes are not supported yet," - "feel free to contact me to add it.") - sys.exit(2) return status return hook def is_directory(output): - if config.PLATFORM == "Linux": + if config.PLATFORM == "linux": return output.replace("Is a directory", "is a directory") else: return output @@ -88,14 +83,14 @@ def is_directory(output): def shlvl_0_to_1(output): - if config.PLATFORM == "Linux": + if config.PLATFORM == "linux": return output.replace("SHLVL=0", "SHLVL=1") else: return output def delete_escape(output): - if config.PLATFORM == "Linux": + if config.PLATFORM == "linux": return output.replace("\\", "") else: return output @@ -109,7 +104,7 @@ def error_eof_to_expected_token(output): def linux_discard(output): - if config.PLATFORM == "Linux": + if config.PLATFORM == "linux": return "DISCARDED BY MINISHELL TEST" else: return output diff --git a/minishell_test/minishell_test.cfg b/minishell_test/minishell_test.cfg new file mode 100644 index 0000000..e800bf4 --- /dev/null +++ b/minishell_test/minishell_test.cfg @@ -0,0 +1,2 @@ +[minishell_test] +bonus = true diff --git a/minishell_test/result_config.cfg b/minishell_test/result_config.cfg new file mode 100644 index 0000000..aac2388 --- /dev/null +++ b/minishell_test/result_config.cfg @@ -0,0 +1,23 @@ +[minishell_test] +bonus = true + +[shell] +available_commands = + rmdir + env + cat + touch + ls + grep + sh + head +path_variable = /home/cacharles/.cache/minishell_test/bin + +[reference] +path = /bin/bash +args = [] + +[timeout] +test = 0.5 +leaks = 10 + diff --git a/minishell_test/sandbox.py b/minishell_test/sandbox.py index f10eacf..e5a1850 100644 --- a/minishell_test/sandbox.py +++ b/minishell_test/sandbox.py @@ -6,23 +6,21 @@ # By: charles <me@cacharle.xyz> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/09/11 13:48:07 by charles #+# #+# # -# Updated: 2021/02/05 14:54:37 by charles ### ########.fr # +# Updated: 2021/02/27 12:05:35 by cacharle ### ########.fr # # # # ############################################################################ # -import os -import glob import shutil import subprocess from contextlib import contextmanager -import minishell_test.config as config +from minishell_test import config def create(): """Create a new sandbox directory""" try: - os.mkdir(config.SANDBOX_PATH) + config.SANDBOX_DIR.mkdir(parents=True, exist_ok=True) except OSError: pass @@ -32,10 +30,10 @@ def remove(): Brute force rm -rf if clean removal doesn't work due to permissions. """ try: - shutil.rmtree(config.SANDBOX_PATH) + shutil.rmtree(config.SANDBOX_DIR) except PermissionError: - subprocess.run(["chmod", "777", *glob.glob(config.SANDBOX_PATH + "/*")], check=True) - subprocess.run(["rm", "-rf", config.SANDBOX_PATH], check=True) + subprocess.run(["chmod", "777", *config.SANDBOX_DIR.glob("*")], check=True) + shutil.rmtree(config.SANDBOX_DIR) except FileNotFoundError: pass diff --git a/minishell_test/suite/suite.py b/minishell_test/suite/suite.py index 8c57633..5d36600 100644 --- a/minishell_test/suite/suite.py +++ b/minishell_test/suite/suite.py @@ -6,13 +6,13 @@ # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/07/15 18:24:29 by charles #+# #+# # -# Updated: 2021/02/05 18:15:26 by charles ### ########.fr # +# Updated: 2021/02/27 12:07:59 by cacharle ### ########.fr # # # # ############################################################################ # from typing import List, Tuple, Optional, Callable -import minishell_test.config as config +from minishell_test import config from minishell_test.test import Test @@ -139,24 +139,19 @@ class Suite: def run(self) -> bool: """Run all test in the suite""" - if config.VERBOSE_LEVEL == 0: - print(self.name + ": ", end="") - else: - print("{}{:#^{width}}{}".format( - self.BLUE_CHARS, - " " + self.name + " ", - self.CLOSE_CHARS, - width=config.TERM_COLS - )) - for i, t in enumerate(self.tests): - if config.RANGE is not None: - if not (config.RANGE[0] <= i <= config.RANGE[1]): - continue - t.run(i) - if config.EXIT_FIRST and t.result is not None and t.result.failed: - return False - if config.VERBOSE_LEVEL == 0: - print() + print("{}{:#^{width}}{}".format( + self.BLUE_CHARS, + " " + self.name + " ", + self.CLOSE_CHARS, + width=config.TERM_COLS + )) + for i, t in enumerate(self.tests): + if config.RANGE is not None: + if not (config.RANGE[0] <= i <= config.RANGE[1]): + continue + t.run(i) + if config.EXIT_FIRST and t.result is not None and t.result.failed: + return False return True def total(self) -> Tuple[int, int]: diff --git a/minishell_test/suites/builtin.py b/minishell_test/suites/builtin.py index 768850a..c373ce6 100644 --- a/minishell_test/suites/builtin.py +++ b/minishell_test/suites/builtin.py @@ -6,15 +6,15 @@ # By: juligonz <juligonz@student.42.fr> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/07/15 18:24:43 by charles #+# #+# # -# Updated: 2021/02/05 14:48:47 by charles ### ########.fr # +# Updated: 2021/02/27 12:07:46 by cacharle ### ########.fr # # Updated: 2020/09/11 18:01:27 by juligonz ### ########.fr # # # # **************************************************************************** # import os -import minishell_test.config as config -import minishell_test.hooks as hooks +from minishell_test import config +from minishell_test import hooks from minishell_test.suite.decorator import suite from minishell_test.hooks import linux_discard diff --git a/minishell_test/suites/cmd.py b/minishell_test/suites/cmd.py index da3b14a..8d2bc09 100644 --- a/minishell_test/suites/cmd.py +++ b/minishell_test/suites/cmd.py @@ -6,14 +6,14 @@ # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/07/15 15:11:46 by charles #+# #+# # -# Updated: 2021/02/05 16:15:42 by charles ### ########.fr # +# Updated: 2021/02/27 12:07:29 by cacharle ### ########.fr # # # # ############################################################################ # import distutils -import minishell_test.hooks as hooks -import minishell_test.config as config +from minishell_test import hooks +from minishell_test import config from minishell_test.suite.decorator import suite diff --git a/minishell_test/suites/flow.py b/minishell_test/suites/flow.py index ed5fd03..2adbb4b 100644 --- a/minishell_test/suites/flow.py +++ b/minishell_test/suites/flow.py @@ -6,11 +6,11 @@ # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/07/15 18:24:52 by charles #+# #+# # -# Updated: 2021/02/05 17:40:00 by charles ### ########.fr # +# Updated: 2021/02/27 12:06:58 by cacharle ### ########.fr # # # # ############################################################################ # -import minishell_test.config as config +from minishell_test import config from minishell_test.suite.decorator import suite from minishell_test.hooks import ( error_line0, diff --git a/minishell_test/suites/preprocess.py b/minishell_test/suites/preprocess.py index d7d6bbc..c296dcb 100644 --- a/minishell_test/suites/preprocess.py +++ b/minishell_test/suites/preprocess.py @@ -6,12 +6,12 @@ # By: juligonz <juligonz@student.42.fr> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/07/15 18:25:00 by charles #+# #+# # -# Updated: 2021/02/05 14:43:27 by charles ### ########.fr # +# Updated: 2021/02/27 12:07:11 by cacharle ### ########.fr # # # # **************************************************************************** # -import minishell_test.config as config -import minishell_test.hooks as hooks +from minishell_test import config +from minishell_test import hooks from minishell_test.suite.decorator import suite diff --git a/minishell_test/test/captured.py b/minishell_test/test/captured.py index 7db9739..a6141e8 100644 --- a/minishell_test/test/captured.py +++ b/minishell_test/test/captured.py @@ -6,13 +6,13 @@ # By: charles <me@cacharle.xyz> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/09/11 12:16:25 by charles #+# #+# # -# Updated: 2021/02/05 17:47:10 by charles ### ########.fr # +# Updated: 2021/02/27 12:20:00 by cacharle ### ########.fr # # # # ############################################################################ # from typing import List, Optional -import minishell_test.config as config +# from minishell_test import config class Captured: @@ -29,13 +29,15 @@ class Captured: files_content: content of the files altered by the command is_timeout: the command has timed out """ - lines = output.split('\n') - for i, l in enumerate(lines): - if l.find(config.REFERENCE_ERROR_BEGIN) == 0: - lines[i] = l.replace(config.REFERENCE_ERROR_BEGIN, config.MINISHELL_ERROR_BEGIN, 1) - elif l.find(config.REFERENCE_PATH + ": ") == 0: - lines[i] = l.replace(config.REFERENCE_PATH + ": ", config.MINISHELL_ERROR_BEGIN, 1) - self.output = '\n'.join(lines) + + # lines = output.split('\n') + # for i, l in enumerate(lines): + # if l.find(config.REFERENCE_ERROR_BEGIN) == 0: + # lines[i] = l.replace(config.REFERENCE_ERROR_BEGIN, config.MINISHELL_ERROR_BEGIN, 1) + # elif l.find(config.REFERENCE_PATH + ": ") == 0: + # lines[i] = l.replace(config.REFERENCE_PATH + ": ", config.MINISHELL_ERROR_BEGIN, 1) + + self.output = output # '\n'.join(lines) self.status = status self.files_content = files_content diff --git a/minishell_test/test/result.py b/minishell_test/test/result.py index fe465e5..b25face 100644 --- a/minishell_test/test/result.py +++ b/minishell_test/test/result.py @@ -6,15 +6,14 @@ # By: charles <me@cacharle.xyz> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/09/11 12:17:34 by charles #+# #+# # -# Updated: 2021/02/24 08:56:03 by cacharle ### ########.fr # +# Updated: 2021/02/27 12:10:13 by cacharle ### ########.fr # # # # ############################################################################ # -import sys import re from typing import Match, List, Optional -import minishell_test.config as config +from minishell_test import config from minishell_test.test.captured import Captured @@ -42,31 +41,18 @@ class BaseResult: def __repr__(self): """Returns a representation of the result based on the verbosity""" - if config.VERBOSE_LEVEL == 0: - return self.green('.') if self.passed else self.red('!') - if config.VERBOSE_LEVEL == 1: - printed = self._escaped_cmd[:] - if config.SHOW_RANGE: - printed = "{:2}: ".format(self.index) + printed - if len(printed) > config.TERM_COLS - 7: - printed = printed[:config.TERM_COLS - 10] + "..." - fmt = self.green("{:{width}} [PASS]") if self.passed else self.red("{:{width}} [FAIL]") - return fmt.format(printed, width=config.TERM_COLS - 7) - elif config.VERBOSE_LEVEL == 2: - return self.full_diff() - else: - raise RuntimeError("Invalid verbose level") + printed = self._escaped_cmd[:] + if config.SHOW_RANGE: + printed = "{:2}: ".format(self.index) + printed + if len(printed) > config.TERM_COLS - 7: + printed = printed[:config.TERM_COLS - 10] + "..." + fmt = self.green("{:{width}} [PASS]") if self.passed else self.red("{:{width}} [FAIL]") + return fmt.format(printed, width=config.TERM_COLS - 7) def put(self, index: int) -> None: """Print a summary of the result""" - if config.VERBOSE_LEVEL == 2 and self.passed: - return self.index = index - print(self, end="") - if config.VERBOSE_LEVEL == 0: - sys.stdout.flush() - else: - print() + print(self) def indicator(self, title: str, prefix: str) -> str: return self.bold(self.blue(prefix + " " + title)) diff --git a/minishell_test/test/test.py b/minishell_test/test/test.py index ff60522..c0e402f 100644 --- a/minishell_test/test/test.py +++ b/minishell_test/test/test.py @@ -6,19 +6,20 @@ # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/06/16 21:48:50 by charles #+# #+# # -# Updated: 2021/02/24 09:09:39 by cacharle ### ########.fr # +# Updated: 2021/02/27 12:19:15 by cacharle ### ########.fr # # # # ############################################################################ # import os import sys import subprocess +from pathlib import Path from typing import Optional, List, Dict, Union, Callable -import minishell_test.config as config +from minishell_test import config from minishell_test.test.captured import Captured from minishell_test.test.result import Result, LeakResult -import minishell_test.sandbox as sandbox +from minishell_test import sandbox HookType = Union[Callable[[str], str], List[Callable[[str], str]]] HookStatusType = Union[Callable[[int], int], List[Callable[[int], int]]] @@ -31,7 +32,7 @@ class Test: setup: str = "", files: List[str] = [], exports: Dict[str, str] = {}, - timeout: float = config.TIMEOUT, + timeout: float = config.TIMEOUT_TEST, hook: HookType = [], hook_status: HookStatusType = [], ): @@ -64,18 +65,16 @@ class Test: self.hook = [] self.hook_status = [] captured = self._run_sandboxed([*config.VALGRIND_CMD, "-c"]) - if config.VERBOSE_LEVEL == 2: - print(captured.output) self.result = LeakResult(self.full_cmd, captured) self.result.put(index) return - expected = self._run_sandboxed([config.REFERENCE_PATH, *config.REFERENCE_ARGS, "-c"]) - actual = self._run_sandboxed([config.MINISHELL_PATH, "-c"]) + expected = self._run_sandboxed([config.SHELL_REFERENCE_PATH, *config.SHELL_REFERENCE_ARGS, "-c"]) + actual = self._run_sandboxed([config.MINISHELL_EXEC_PATH, "-c"]) self.result = Result(self.full_cmd, self.files, expected, actual) self.result.put(index) - def _run_sandboxed(self, shell_cmd: List[str]) -> Captured: + def _run_sandboxed(self, shell_cmd: List[Union[str, Path]]) -> Captured: """ Run the command in a sandbox environment """ with sandbox.context(): if self.setup != "": @@ -83,7 +82,7 @@ class Test: subprocess.run( self.setup, shell=True, - cwd=config.SANDBOX_PATH, + cwd=config.SANDBOX_DIR, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, check=True @@ -97,7 +96,7 @@ class Test: sys.exit(1) return self._run_capture(shell_cmd) - def _run_capture(self, shell_cmd: List[str]) -> Captured: + def _run_capture(self, shell_cmd: List[Union[str, Path]]) -> Captured: """ Capture the output (stdout and stderr) Capture the content of the watched files after the command is run """ @@ -106,9 +105,9 @@ class Test: [*shell_cmd, self.cmd], stderr=subprocess.STDOUT, stdout=subprocess.PIPE, - cwd=config.SANDBOX_PATH, + cwd=config.SANDBOX_DIR, env={ - 'PATH': config.PATH_VARIABLE, + 'PATH': config.SHELL_PATH_VARIABLE, 'TERM': 'xterm-256color', **self.exports, }, @@ -117,7 +116,7 @@ class Test: # https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate try: stdout, _ = process.communicate( - timeout=(self.timeout if not config.CHECK_LEAKS else config.CHECK_LEAKS_TIMEOUT)) + timeout=(self.timeout if not config.CHECK_LEAKS else config.TIMEOUT_LEAKS)) except subprocess.TimeoutExpired: process.kill() # _, _ = process.communicate(timeout=2) @@ -131,7 +130,7 @@ class Test: files_content: List[Optional[str]] = [] for file_name in self.files: try: - with open(os.path.join(config.SANDBOX_PATH, file_name), "rb") as f: + with open(os.path.join(config.SANDBOX_DIR, file_name), "rb") as f: files_content.append(f.read().decode()) except FileNotFoundError: files_content.append(None) @@ -156,7 +155,6 @@ class Test: @classmethod def try_run(cls, cmd: str) -> str: - config.VERBOSE_LEVEL = 2 test = Test(cmd) test.run(0) if isinstance(test.result, LeakResult): @@ -28,6 +28,9 @@ classifiers = packages = find: python_requires = >=3.6 +[options.package_data] +c_formatter_42/data = * + [options.entry_points] console_scripts = minishell_test = minishell_test.__main__:main |
