diff options
| author | Charles Cabergs <me@cacharle.xyz> | 2021-01-31 04:13:22 +0100 |
|---|---|---|
| committer | Charles Cabergs <me@cacharle.xyz> | 2021-01-31 04:13:22 +0100 |
| commit | 361e1fe39e88788ef4173083482d520753225a3e (patch) | |
| tree | 9df150f1bbdc8848d44effb6fe4da5643c013d05 | |
| parent | aa962c545496fc645d3f78370d7190ae1f3db11e (diff) | |
| download | minishell_test-361e1fe39e88788ef4173083482d520753225a3e.tar.gz minishell_test-361e1fe39e88788ef4173083482d520753225a3e.tar.bz2 minishell_test-361e1fe39e88788ef4173083482d520753225a3e.zip | |
Refactoring Result into BaseResult, Result and LeakResult
| -rw-r--r-- | src/sandbox.py | 4 | ||||
| -rw-r--r-- | src/test/result.py | 228 | ||||
| -rw-r--r-- | src/test/test.py | 6 |
3 files changed, 128 insertions, 110 deletions
diff --git a/src/sandbox.py b/src/sandbox.py index 8194556..bd49d1e 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/12 17:06:28 by charles ### ########.fr # +# Updated: 2021/01/31 03:59:30 by charles ### ########.fr # # # # ############################################################################ # @@ -36,6 +36,8 @@ def remove(): except PermissionError: subprocess.run(["chmod", "777", *glob.glob(config.SANDBOX_PATH + "/*")], check=True) subprocess.run(["rm", "-rf", config.SANDBOX_PATH], check=True) + except FileNotFoundError: + pass @contextmanager diff --git a/src/test/result.py b/src/test/result.py index 4d060fa..e4512ac 100644 --- a/src/test/result.py +++ b/src/test/result.py @@ -6,7 +6,7 @@ # By: charles <me@cacharle.xyz> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/09/11 12:17:34 by charles #+# #+# # -# Updated: 2021/01/31 03:35:53 by charles ### ########.fr # +# Updated: 2021/01/31 04:10:31 by charles ### ########.fr # # # # ############################################################################ # @@ -18,73 +18,21 @@ import config from test.captured import Captured -# TODO split into BaseResult, Result and LeakResult -class Result: +class BaseResult: 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: List[str], - expected: Captured, - actual: Captured, - leak_output: str = None - ): - """Result class - cmd: runned command - file_names: names of watched files - expected: expected capture - actual: actual capture - leak_output: output of valgrind in check leak mode - """ - self.cmd = cmd - self.file_names = file_names - self.expected = expected - self.actual = actual + def __init__(self): self.colored = True - self.leak_output = leak_output self.set_colors() - @staticmethod - def leak(cmd: str, captured: Captured): - return Result(cmd, [], None, captured, captured.output) - - def _search_leak_kind(self, kind: str) -> Match: - match = re.search( - r"==\d+==\s+" + kind + r" lost: (?P<bytes>[0-9,]+) bytes in [0-9,]+ blocks", - self.leak_output - ) - if match is None: - raise RuntimeError( - "valgrind output parsing failed for `{}`:\n{}" - .format(self.cmd, self.leak_output) - ) - return match - - @property - def lost_bytes(self): - if self.leak_output.find("All heap blocks were freed -- no leaks are possible") != -1: - definite_bytes = 0 - indirect_bytes = 0 - else: - definite_match = self._search_leak_kind("definitely") - indirect_match = self._search_leak_kind("indirectly") - definite_bytes = int(definite_match.group("bytes").replace(",", "")) - indirect_bytes = int(indirect_match.group("bytes").replace(",", "")) - return definite_bytes + indirect_bytes - @property def passed(self): """Check if the result passed""" - if self.leak_output is not None: - if self.actual.is_timeout: - return False - return self.lost_bytes == 0 - return self.actual == self.expected + raise NotImplementedError @property def failed(self): @@ -96,7 +44,7 @@ class Result: if config.VERBOSE_LEVEL == 0: return self.green('.') if self.passed else self.red('!') elif config.VERBOSE_LEVEL == 1: - printed = self.escaped_cmd[:] + printed = self._escaped_cmd[:] if config.SHOW_RANGE: printed = "{:2}: ".format(self.index) + printed if len(printed) > config.TERM_COLS - 7: @@ -119,8 +67,79 @@ class Result: else: print() + def indicator(self, title: str, prefix: str) -> str: + return self.bold(self.blue(prefix + " " + title)) + + def full_diff(self) -> str: + raise NotImplementedError + + @property + def _escaped_cmd(self): + """Escape common control characters""" + return (self.cmd + .replace("\t", "\\t") + .replace("\n", "\\n") + .replace("\v", "\\v") + .replace("\r", "\\r") + .replace("\f", "\\f")) + + @property + def _header_with(self): + return self.indicator("WITH {}".format(self._escaped_cmd), "|>") + '\n' + + def set_colors(self): + """Set colors strings on or off based on self.colored""" + 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 + + +class Result(BaseResult): + def __init__( + self, + cmd: str, + file_names: List[str], + expected: Captured, + actual: Captured, + ): + """Result class + cmd: runned command + file_names: names of watched files + expected: expected capture + actual: actual capture + """ + self.cmd = cmd + self.file_names = file_names + self.expected = expected + self.actual = actual + super().__init__() + + @property + def passed(self): + return self.actual == self.expected + def header(self, title: str) -> str: - """Create a one line header with a title""" return self.bold("|---------------------------------------{:-<40}".format(title)) @property @@ -131,8 +150,14 @@ class Result: 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 cat_e(self, s: str) -> str: + """Pass a string through a cat -e like output""" + s = s.replace("\n", "$\n") + if len(s) < 2: + return s + if s[-1] != '\n': + s += '\n' + return s def file_diff(self, file_name: str, expected: str, actual: str) -> str: """Difference between 2 files""" @@ -173,55 +198,46 @@ class Result: def full_diff(self) -> str: """Concat all difference reports""" - rest = "" - if self.leak_output is not None: - rest = self.leak_output - else: - rest = (self.output_diff() + self.files_diff() + "=" * 80 + '\n') - return (self.indicator("WITH {}".format(self.escaped_cmd), "|>") + '\n' + rest) - - def cat_e(self, s: str) -> str: - """Pass a string through a cat -e like output""" - s = s.replace("\n", "$\n") - if len(s) < 2: - return s - if s[-1] != '\n': - s += '\n' - return s + return self._header_with + self.output_diff() + self.files_diff() + "=" * 80 + '\n' - @property - def escaped_cmd(self): - """Escape common control characters""" - return (self.cmd - .replace("\t", "\\t") - .replace("\n", "\\n") - .replace("\v", "\\v") - .replace("\r", "\\r") - .replace("\f", "\\f")) - def set_colors(self): - """Set colors strings on or off based on self.colored""" - 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 = "" +class LeakResult(BaseResult): + def __init__(self, cmd: str, captured: Captured): + self.cmd = cmd + self.captured = captured + super().__init__() - def green(self, s): - return self.color_green + s + self.color_close + def _search_leak_kind(self, kind: str) -> Match: + match = re.search( + r"==\d+==\s+" + kind + r" lost: (?P<bytes>[0-9,]+) bytes in [0-9,]+ blocks", + self.captured.output + ) + if match is None: + raise RuntimeError( + "valgrind output parsing failed for `{}`:\n{}" + .format(self.cmd, self.captured.output) + ) + return match - def red(self, s): - return self.color_red + s + self.color_close + @property + def _lost_bytes(self): + if self.captured.output.find("All heap blocks were freed -- no leaks are possible") != -1: + definite_bytes = 0 + indirect_bytes = 0 + else: + definite_match = self._search_leak_kind("definitely") + indirect_match = self._search_leak_kind("indirectly") + definite_bytes = int(definite_match.group("bytes").replace(",", "")) + indirect_bytes = int(indirect_match.group("bytes").replace(",", "")) + return definite_bytes + indirect_bytes - def blue(self, s): - return self.color_blue + s + self.color_close + @property + def passed(self): + """Check if the result passed""" + if self.captured.is_timeout: + return False + return self._lost_bytes == 0 - def bold(self, s): - return self.color_bold + s + self.color_close + def full_diff(self) -> str: + """Concat all difference reports""" + return self._header_with + self.captured.output diff --git a/src/test/test.py b/src/test/test.py index 517e610..6f3aad5 100644 --- a/src/test/test.py +++ b/src/test/test.py @@ -6,7 +6,7 @@ # By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/06/16 21:48:50 by charles #+# #+# # -# Updated: 2021/01/31 03:30:15 by charles ### ########.fr # +# Updated: 2021/01/31 03:55:43 by charles ### ########.fr # # # # ############################################################################ # @@ -17,7 +17,7 @@ from typing import Optional, List, Dict import config from test.captured import Captured -from test.result import Result +from test.result import Result, LeakResult import sandbox @@ -64,7 +64,7 @@ class Test: captured = self._run_sandboxed([*config.VALGRIND_CMD, "-c"]) if config.VERBOSE_LEVEL == 2: print(captured.output) - self.result = Result.leak(self.full_cmd, captured) + self.result = LeakResult(self.full_cmd, captured) self.result.put(index) return |
