diff options
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | preview.gif (renamed from recording.gif) | bin | 6275302 -> 6275302 bytes | |||
| -rw-r--r-- | src/config.py | 4 | ||||
| -rw-r--r-- | src/sandbox.py | 11 | ||||
| -rw-r--r-- | src/suite/suite.py | 8 | ||||
| -rw-r--r-- | src/suites/flow.py (renamed from src/suites/operation.py) | 50 | ||||
| -rw-r--r-- | src/suites/parenthesis.py | 54 | ||||
| -rw-r--r-- | src/test/test.py | 72 |
8 files changed, 102 insertions, 99 deletions
@@ -2,7 +2,7 @@ Test for the minishell project of school 42. - + ## Usage diff --git a/recording.gif b/preview.gif Binary files differindex 618bd36..618bd36 100644 --- a/recording.gif +++ b/preview.gif diff --git a/src/config.py b/src/config.py index a9a3b78..7092fea 100644 --- a/src/config.py +++ b/src/config.py @@ -6,7 +6,7 @@ # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/07/15 18:24:19 by charles #+# #+# # -# Updated: 2020/09/12 01:33:18 by charles ### ########.fr # +# Updated: 2020/09/12 16:56:23 by charles ### ########.fr # # # # ############################################################################ # @@ -50,7 +50,7 @@ AVAILABLE_COMMANDS = ["rmdir", "env", "cat", "touch", "ls", "grep", "sh"] PATH_VARIABLE = os.path.abspath(EXECUTABLES_PATH) # default test timeout -TIMEOUT = 1 +TIMEOUT = 0.5 LOREM = """ Mollitia asperiores assumenda excepturi et ipsa. Nihil corporis facere aut a rem consequatur. diff --git a/src/sandbox.py b/src/sandbox.py index efad60c..8194556 100644 --- a/src/sandbox.py +++ b/src/sandbox.py @@ -6,7 +6,7 @@ # By: charles <me@cacharle.xyz> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/09/11 13:48:07 by charles #+# #+# # -# Updated: 2020/09/11 20:25:38 by charles ### ########.fr # +# Updated: 2020/09/12 17:06:28 by charles ### ########.fr # # # # ############################################################################ # @@ -14,6 +14,7 @@ import os import glob import shutil import subprocess +from contextlib import contextmanager import config @@ -35,3 +36,11 @@ def remove(): except PermissionError: subprocess.run(["chmod", "777", *glob.glob(config.SANDBOX_PATH + "/*")], check=True) subprocess.run(["rm", "-rf", config.SANDBOX_PATH], check=True) + + +@contextmanager +def context(): + """Sandbox context manager""" + create() + yield + remove() diff --git a/src/suite/suite.py b/src/suite/suite.py index ee13268..63421f6 100644 --- a/src/suite/suite.py +++ b/src/suite/suite.py @@ -6,7 +6,7 @@ # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/07/15 18:24:29 by charles #+# #+# # -# Updated: 2020/09/12 10:53:42 by charles ### ########.fr # +# Updated: 2020/09/12 17:07:00 by charles ### ########.fr # # # # ############################################################################ # @@ -40,8 +40,8 @@ class Suite: continue matches = [n for n in suite_names if n.find("/") != -1 - and n[n.find("/") + 1:].startswith(name) - or n.startswith(name)] + and n[n.find("/") + 1:].startswith(name) + or n.startswith(name)] if len(matches) == 1: names.append(matches[0]) elif len(matches) != 0 and all([n.startswith(name) for n in matches]): @@ -61,10 +61,10 @@ class Suite: [s for s in cls.available if s.name in names] + [s for s in cls.available if any([g for g in s.groups if g in names])] )) + cls.available.sort(key=lambda s: s.name) for s in cls.available: s.generator_func() - @classmethod def available_names(cls) -> [str]: """List of available suites names""" diff --git a/src/suites/operation.py b/src/suites/flow.py index 18ebd72..cf8ca61 100644 --- a/src/suites/operation.py +++ b/src/suites/flow.py @@ -1,12 +1,12 @@ # ############################################################################ # # # # ::: :::::::: # -# operation.py :+: :+: :+: # +# flow.py :+: :+: :+: # # +:+ +:+ +:+ # # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/07/15 18:24:52 by charles #+# #+# # -# Updated: 2020/09/11 20:12:54 by charles ### ########.fr # +# Updated: 2020/09/12 15:30:37 by charles ### ########.fr # # # # ############################################################################ # @@ -39,8 +39,13 @@ def suite_end(test): @suite() def suite_pipe(test): + test("cat /etc/shells | head -c 10") + test("cat -e /etc/shells | head -c 10") + test("cat -e /etc/shells | cat -e | head -c 10") + test("cat -e /etc/shells | cat -e | cat -e | head -c 10") test("echo bonjour | cat") test("echo bonjour | cat -e") + test("echo bonjour | cat -e | cat -e | cat -e | cat -e | cat -e | cat -e | cat -e") test("ls | cat -e", setup="touch a b c d; mkdir m1 m2 m3") test("ls -l | cat -e", setup="touch a b c d; mkdir m1 m2 m3") test("ls -l | cat -e | cat | cat | cat", setup="touch a b c d; mkdir m1 m2 m3") @@ -102,3 +107,44 @@ def suite_or(test): test("ls doesnotexists || echo bonjour") test("ls doesnotexists|| echo bonjour") test("echo bonjour|| ls doesnotexists") + + +@suite(bonus=True) +def suite_parenthesis(test): + test("(echo bonjour)") + test("(echo bonjour )") + test("( echo bonjour )") + test("(echo a && echo b) && echo c") + test("(echo a || echo b) || echo c") + test("(ls doesnotexist || echo b) || echo c") + test("(echo a || ls doesnotexist) || echo c") + test("echo aa && (echo b && echo c)") + test("ls doesnotexist || (echo b && echo c)") + test("(echo bonjour > f1)", files=["f1"]) + test("(echo bonjour > f1 > f2 > f3)", files=["f1", "f2", "f3"]) + test("(echo bonjour > f1 > f2 > f3 > f4 > f5 > f6 > f7 > f8 > f9)", + files=["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9"]) + test("(echo bonjour) > f1", files=["f1"]) + test("(echo bonjour) > f1 > f2 > f3", files=["f1", "f2", "f3"]) + test("(echo bonjour) > f1 > f2 > f3 > f4 > f5 > f6 > f7 > f8 > f9", + files=["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9"]) + test("(cat -e < f1)", setup="echo bonjour > f1") + test("(cat -e < f1 < f2 < f3)", setup="touch f1 f2 f3 f4; echo bonjour > f3") + test("(cat -e < f1 < f2 < f3 < f4 < f5 < f6 < f7 < f8 < f9)", + setup="touch f1 f2 f3 f4 f5 f6 f7 f8 f9; echo bonjour > f9") + test("(cat -e) < f1", setup="echo bonjour > f1") + test("(cat -e) < f1 < f2 < f3", setup="touch f1 f2 f3 f4; echo bonjour > f3") + test("(cat -e) < f1 < f2 < f3 < f4 < f5 < f6 < f7 < f8 < f9", + setup="touch f1 f2 f3 f4 f5 f6 f7 f8 f9; echo bonjour > f9") + test("(echo bonjour > f1 > f2 > f3 > f4) > f5 > f6 > f7 > f8 > f9", + files=["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9"]) + test("(cat -e < f1 < f2 < f3 < f4) < f5 < f6 < f7 < f8 < f9", + setup="touch f1 f2 f3 f4 f5 f6 f7 f8 f9; echo bonjour > f4") + test("(echo bonjour > f1) > f2", files=["f1", "f2"]) + test("(cat -e > f1) < f2", setup="ls -l / > f2", files=["f1"]) + test("(exit); echo bonjour") + test("(echo bonjour; exit; echo aurevoir)") + test("(ls && ls)") + test("(ls doesntexist || ls)") + test("(ls doesntexist && ls)") + test("(ls && ls) && echo $?") diff --git a/src/suites/parenthesis.py b/src/suites/parenthesis.py deleted file mode 100644 index 6a1e7f1..0000000 --- a/src/suites/parenthesis.py +++ /dev/null @@ -1,54 +0,0 @@ -# ############################################################################ # -# # -# ::: :::::::: # -# parenthesis.py :+: :+: :+: # -# +:+ +:+ +:+ # -# By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # -# +#+#+#+#+#+ +#+ # -# Created: 2020/07/15 18:24:57 by charles #+# #+# # -# Updated: 2020/09/11 20:12:27 by charles ### ########.fr # -# # -# ############################################################################ # - -from suite import suite - - -@suite(bonus=True) -def suite_parenthesis(test): - test("(echo bonjour)") - test("(echo bonjour )") - test("( echo bonjour )") - test("(echo a && echo b) && echo c") - test("(echo a || echo b) || echo c") - test("(ls doesnotexist || echo b) || echo c") - test("(echo a || ls doesnotexist) || echo c") - test("echo aa && (echo b && echo c)") - test("ls doesnotexist || (echo b && echo c)") - test("(echo bonjour > f1)", files=["f1"]) - test("(echo bonjour > f1 > f2 > f3)", files=["f1", "f2", "f3"]) - test("(echo bonjour > f1 > f2 > f3 > f4 > f5 > f6 > f7 > f8 > f9)", - files=["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9"]) - test("(echo bonjour) > f1", files=["f1"]) - test("(echo bonjour) > f1 > f2 > f3", files=["f1", "f2", "f3"]) - test("(echo bonjour) > f1 > f2 > f3 > f4 > f5 > f6 > f7 > f8 > f9", - files=["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9"]) - test("(cat -e < f1)", setup="echo bonjour > f1") - test("(cat -e < f1 < f2 < f3)", setup="touch f1 f2 f3 f4; echo bonjour > f3") - test("(cat -e < f1 < f2 < f3 < f4 < f5 < f6 < f7 < f8 < f9)", - setup="touch f1 f2 f3 f4 f5 f6 f7 f8 f9; echo bonjour > f9") - test("(cat -e) < f1", setup="echo bonjour > f1") - test("(cat -e) < f1 < f2 < f3", setup="touch f1 f2 f3 f4; echo bonjour > f3") - test("(cat -e) < f1 < f2 < f3 < f4 < f5 < f6 < f7 < f8 < f9", - setup="touch f1 f2 f3 f4 f5 f6 f7 f8 f9; echo bonjour > f9") - test("(echo bonjour > f1 > f2 > f3 > f4) > f5 > f6 > f7 > f8 > f9", - files=["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9"]) - test("(cat -e < f1 < f2 < f3 < f4) < f5 < f6 < f7 < f8 < f9", - setup="touch f1 f2 f3 f4 f5 f6 f7 f8 f9; echo bonjour > f4") - test("(echo bonjour > f1) > f2", files=["f1", "f2"]) - test("(cat -e > f1) < f2", setup="ls -l / > f2", files=["f1"]) - test("(exit); echo bonjour") - test("(echo bonjour; exit; echo aurevoir)") - test("(ls && ls)") - test("(ls doesntexist || ls)") - test("(ls doesntexist && ls)") - test("(ls && ls) && echo $?") diff --git a/src/test/test.py b/src/test/test.py index b5abd85..00e5516 100644 --- a/src/test/test.py +++ b/src/test/test.py @@ -6,14 +6,14 @@ # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/06/16 21:48:50 by charles #+# #+# # -# Updated: 2020/09/12 01:35:46 by charles ### ########.fr # +# Updated: 2020/09/12 17:07:22 by charles ### ########.fr # # # # ############################################################################ # import os import sys import subprocess -import time +# import time import config from test.captured import Captured @@ -62,30 +62,31 @@ class Test: self.result.put() def _run_sandboxed(self, shell_path: str, shell_options: str) -> Captured: - """ Run the command in a sandbox environment - Capture the output (stdout and stderr) + """ Run the command in a sandbox environment """ + with sandbox.context(): + if self.setup != "": + try: + subprocess.run( + self.setup, + shell=True, + cwd=config.SANDBOX_PATH, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + check=True + ) + except subprocess.CalledProcessError as e: + print("Error: `{}` setup command failed for `{}`\n\twith '{}'" + .format(self.setup, + self.cmd, + "no stderr" if e.stdout is None + else e.stdout.decode().strip())) + sys.exit(1) + return self._run_capture(shell_path, shell_options) + + def _run_capture(self, shell_path: str, shell_options: str) -> Captured: + """ Capture the output (stdout and stderr) Capture the content of the watched files after the command is run """ - - # create and setup sandbox - sandbox.create() - if self.setup != "": - try: - subprocess.run( - self.setup, - shell=True, - cwd=config.SANDBOX_PATH, - stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, - check=True - ) - except subprocess.CalledProcessError as e: - print("Error: `{}` setup command failed for `{}`\n\twith '{}'" - .format(self.setup, - self.cmd, - "no stderr" if e.stdout is None else e.stdout.decode().strip())) - sys.exit(1) - # run the command in the sandbox process = subprocess.Popen( [shell_path, *shell_options, self.cmd], @@ -98,18 +99,19 @@ class Test: **self.exports, }, ) - if self.signal is not None: - time.sleep(0.2) - process.send_signal(self.signal) - else: - try: - process.wait(timeout=self.timeout) - except subprocess.TimeoutExpired: - return Captured.timeout() + # if self.signal is not None: + # time.sleep(0.2) + # process.send_signal(self.signal) + # else: - # get command output + # https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate + try: + stdout, _ = process.communicate(timeout=self.timeout) + except subprocess.TimeoutExpired: + process.kill() + # _, _ = process.communicate(timeout=2) + return Captured.timeout() try: - stdout, _ = process.communicate() output = stdout.decode() except UnicodeDecodeError: output = "UNICODE ERROR: {}".format(process.stdout) @@ -123,7 +125,7 @@ class Test: except FileNotFoundError: files_content.append(None) - sandbox.remove() + # sandbox.remove() if self.hook is not None: output = self.hook(output) return Captured(output, process.returncode, files_content) |
