aboutsummaryrefslogtreecommitdiff
path: root/minishell_test
diff options
context:
space:
mode:
authorCharles Cabergs <me@cacharle.xyz>2021-02-27 12:24:37 +0100
committerCharles Cabergs <me@cacharle.xyz>2021-02-27 12:24:37 +0100
commit7081b93b8ed4f98c628400e05d22d0523f41a842 (patch)
tree4b945840ade4d1869ceedf94e9bca4581f096d0f /minishell_test
parentad7233a4a5f45be6f991ed38a7351a6ef826356b (diff)
downloadminishell_test-7081b93b8ed4f98c628400e05d22d0523f41a842.tar.gz
minishell_test-7081b93b8ed4f98c628400e05d22d0523f41a842.tar.bz2
minishell_test-7081b93b8ed4f98c628400e05d22d0523f41a842.zip
Fixing #16 - Adding support for custom config file in user directory
Diffstat (limited to 'minishell_test')
-rwxr-xr-xminishell_test/__main__.py71
-rw-r--r--minishell_test/args.py57
-rw-r--r--minishell_test/config.py192
-rw-r--r--minishell_test/data/__init__.py0
-rw-r--r--minishell_test/data/default.cfg27
-rw-r--r--minishell_test/data/lorem13
-rw-r--r--minishell_test/hooks.py25
-rw-r--r--minishell_test/minishell_test.cfg2
-rw-r--r--minishell_test/result_config.cfg23
-rw-r--r--minishell_test/sandbox.py14
-rw-r--r--minishell_test/suite/suite.py35
-rw-r--r--minishell_test/suites/builtin.py6
-rw-r--r--minishell_test/suites/cmd.py6
-rw-r--r--minishell_test/suites/flow.py4
-rw-r--r--minishell_test/suites/preprocess.py6
-rw-r--r--minishell_test/test/captured.py20
-rw-r--r--minishell_test/test/result.py34
-rw-r--r--minishell_test/test/test.py30
18 files changed, 286 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):