aboutsummaryrefslogtreecommitdiff
path: root/test.py
diff options
context:
space:
mode:
authorCharles Cabergs <me@cacharle.xyz>2020-09-11 12:33:34 +0200
committerCharles Cabergs <me@cacharle.xyz>2020-09-11 12:33:34 +0200
commit46ba2708f83bf46186c33bf84975d39e87f467c1 (patch)
tree8275c80bba98d63e81e3af9a1df8be62e0419003 /test.py
parentc0b1a90cf9c52a0c9b1623ac695516031d5ccdba (diff)
downloadminishell_test-46ba2708f83bf46186c33bf84975d39e87f467c1.tar.gz
minishell_test-46ba2708f83bf46186c33bf84975d39e87f467c1.tar.bz2
minishell_test-46ba2708f83bf46186c33bf84975d39e87f467c1.zip
Refactoring files, splited test.py and suite.py in packages
Diffstat (limited to 'test.py')
-rw-r--r--test.py282
1 files changed, 0 insertions, 282 deletions
diff --git a/test.py b/test.py
deleted file mode 100644
index 05bd2df..0000000
--- a/test.py
+++ /dev/null
@@ -1,282 +0,0 @@
-# ############################################################################ #
-# #
-# ::: :::::::: #
-# test.py :+: :+: :+: #
-# +:+ +:+ +:+ #
-# By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ #
-# +#+#+#+#+#+ +#+ #
-# Created: 2020/06/16 21:48:50 by charles #+# #+# #
-# Updated: 2020/09/10 09:38:26 by charles ### ########.fr #
-# #
-# ############################################################################ #
-
-import os
-import sys
-import subprocess
-import shutil
-import glob
-
-import config
-
-class Captured:
- def __init__(self, output: str, status: int, files_content: [str], is_timeout: bool = False):
- 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)
-
- self.status = status
- self.files_content = files_content
- self.is_timeout = is_timeout
-
- def __eq__(self, other: 'Result') -> bool:
- if self.is_timeout:
- return self.is_timeout == other.is_timeout
- return (self.output == other.output and
- self.status == other.status and
- all([x == y for x, y in zip(self.files_content, other.files_content)]))
-
- @staticmethod
- def timeout():
- return Captured("", 0, [], is_timeout = True)
-
-
-class Result:
- RED_CHARS = "\033[31m"
- GREEN_CHARS = "\033[32m"
- BLUE_CHARS = "\033[34m"
- BOLD_CHARS = "\033[1m"
- CLOSE_CHARS = "\033[0m"
-
- def __init__(self, cmd: str, file_names: [str], expected: Captured, actual: Captured):
- self.cmd = cmd
- self.file_names = file_names
- self.expected = expected
- self.actual = actual
- self.colored = True
- self.set_colors()
-
- def toggle_colors(self):
- self.colored = not self.colored
-
- def set_colors(self):
- if self.colored:
- self.color_red = self.RED_CHARS
- self.color_green = self.GREEN_CHARS
- self.color_blue = self.BLUE_CHARS
- self.color_bold = self.BOLD_CHARS
- self.color_close = self.CLOSE_CHARS
- else:
- self.color_red = ""
- self.color_green = ""
- self.color_blue = ""
- self.color_bold = ""
- self.color_close = ""
-
- def green(self, s):
- return self.color_green + s + self.color_close
-
- def red(self, s):
- return self.color_red + s + self.color_close
-
- def blue(self, s):
- return self.color_blue + s + self.color_close
-
- def bold(self, s):
- return self.color_bold + s + self.color_close
-
- @property
- def passed(self):
- return self.actual == self.expected
-
- @property
- def failed(self):
- return not self.passed
-
- def __repr__(self):
- if config.VERBOSE_LEVEL == 0:
- return self.green('.') if self.passed else self.red('!')
- elif config.VERBOSE_LEVEL == 1:
- printed = self.escaped_cmd[:]
- if len(printed) > 70:
- printed = printed[:67] + "..."
- fmt = self.green("{:74} [PASS]") if self.passed else self.red("{:74} [FAIL]")
- return fmt.format(printed)
- elif config.VERBOSE_LEVEL == 2:
- return self.full_diff()
- else:
- raise RuntimeError
-
- def put(self):
- if config.VERBOSE_LEVEL == 2 and self.passed:
- return
- print(self, end="")
- if config.VERBOSE_LEVEL == 0:
- sys.stdout.flush()
- else:
- print()
-
- def header(self, title: str) -> str:
- return self.bold("|---------------------------------------{:-<40}".format(title))
-
- @property
- def expected_header(self) -> str:
- return self.green(self.header("EXPECTED"))
-
- @property
- def actual_header(self) -> str:
- return self.red(self.header("ACTUAL"))
-
- def indicator(self, title: str, prefix: str) -> str:
- return self.bold(self.blue(prefix + " " + title))
-
- def file_diff(self, file_name: str, expected: str, actual: str) -> str:
- if expected == actual:
- return ""
- return (
- self.indicator("FILE {}".format(file_name), "|#") + '\n'
- + self.expected_header + '\n'
- + ("FROM TEST: File not created\n" if expected is None else self.cat_e(expected))
- + self.actual_header + '\n'
- + ("FROM TEST: File not created\n" if actual is None else self.cat_e(actual))
- )
-
- def files_diff(self):
- return '\n'.join([self.file_diff(n, e, a) for n, e, a in
- zip(self.file_names,
- self.expected.files_content,
- self.actual.files_content)
- if e != a])
-
- def output_diff(self) -> str:
- out = ""
- if self.actual.is_timeout:
- return "TIMEOUT\n"
- if self.expected.status != self.actual.status:
- out += self.indicator("STATUS: expected {} actual {}"
- .format(self.expected.status, self.actual.status), "| ") + '\n'
- if self.expected.output != self.actual.output:
- out += (self.expected_header + '\n'
- + self.cat_e(self.expected.output)
- + self.actual_header + '\n'
- + self.cat_e(self.actual.output))
- return out
-
- def full_diff(self) -> str:
- return (self.indicator("WITH {}".format(self.escaped_cmd), "|>") + '\n'
- + self.output_diff()
- + self.files_diff()
- + "=" * 80 + '\n')
-
- def cat_e(self, s: str) -> str:
- s = s.replace("\n", "$\n")
- if len(s) < 2:
- return s
- if s[-1] != '\n':
- s += '\n'
- return s
-
- @property
- def escaped_cmd(self):
- return (self.cmd
- .replace("\t", "\\t")
- .replace("\n", "\\n")
- .replace("\v", "\\v")
- .replace("\r", "\\r")
- .replace("\f", "\\f")
- )
-
-
-class Test:
- def __init__(self,
- cmd: str,
- setup: str = "",
- files: [str] = [],
- exports: {str: str} = {},
- timeout: float = config.TIMEOUT):
- self.cmd = cmd
- self.setup = setup
- self.files = files
- self.exports = exports
- self.result = None
- self.timeout = timeout
-
- def run(self):
- expected = self._run_sandboxed(config.REFERENCE_PATH, "-c")
- actual = self._run_sandboxed(config.MINISHELL_PATH, "-c")
- s = self.cmd
- if self.setup != "":
- s = "[SETUP {}] {}".format(self.setup, s)
- if len(self.exports) != 0:
- s = "[EXPORTS {}] {}".format(
- ' '.join(["{}='{:.20}'".format(k, v) for k, v in self.exports.items()]), s)
- self.result = Result(s, self.files, expected, actual)
- self.result.put()
-
- def _run_sandboxed(self, shell_path: str, shell_option: str) -> Captured:
- """ run the command in a sandbox environment
-
- capture the output (stdout and stderr)
- capture the content of the watched files after the command is run
- """
-
- try:
- os.mkdir(config.SANDBOX_PATH)
- except OSError:
- pass
- if self.setup != "":
- try:
- setup_status = 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)
-
- try:
- process_status = subprocess.run(
- [shell_path, shell_option, self.cmd],
- stderr=subprocess.STDOUT,
- stdout=subprocess.PIPE,
- cwd=config.SANDBOX_PATH,
- env={
- 'PATH': config.PATH_VARIABLE,
- 'TERM': 'xterm-256color',
- **self.exports
- },
- timeout=self.timeout
- )
- except subprocess.TimeoutExpired:
- return Captured.timeout()
-
- try:
- output = process_status.stdout.decode()
- except UnicodeDecodeError:
- output = "UNICODE ERROR: {}".format(process_status.stdout)
-
- # capture watched files content
- files_content = []
- for file_name in self.files:
- try:
- with open(os.path.join(config.SANDBOX_PATH, file_name), "rb") as f:
- files_content.append(f.read().decode())
- except FileNotFoundError as e:
- files_content.append(None)
- try:
- shutil.rmtree(config.SANDBOX_PATH)
- except:
- subprocess.check_output(["chmod", "777", *glob.glob(config.SANDBOX_PATH + "/*")])
- subprocess.check_output(["rm", "-rf", config.SANDBOX_PATH])
- return Captured(output, process_status.returncode, files_content)