aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/captured.py4
-rw-r--r--src/test/result.py55
-rw-r--r--src/test/test.py53
3 files changed, 57 insertions, 55 deletions
diff --git a/src/test/captured.py b/src/test/captured.py
index 4cf9184..f7dae3e 100644
--- a/src/test/captured.py
+++ b/src/test/captured.py
@@ -6,7 +6,7 @@
# By: charles <me@cacharle.xyz> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2020/09/11 12:16:25 by charles #+# #+# #
-# Updated: 2021/01/31 04:23:03 by charles ### ########.fr #
+# Updated: 2021/02/04 15:52:19 by charles ### ########.fr #
# #
# ############################################################################ #
@@ -48,7 +48,7 @@ class Captured:
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)]))
+ and all(x == y for x, y in zip(self.files_content, other.files_content)))
@staticmethod
def timeout():
diff --git a/src/test/result.py b/src/test/result.py
index e4512ac..eff7b8b 100644
--- a/src/test/result.py
+++ b/src/test/result.py
@@ -6,13 +6,13 @@
# By: charles <me@cacharle.xyz> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2020/09/11 12:17:34 by charles #+# #+# #
-# Updated: 2021/01/31 04:10:31 by charles ### ########.fr #
+# Updated: 2021/02/05 01:36:44 by charles ### ########.fr #
# #
# ############################################################################ #
import sys
import re
-from typing import Match, List
+from typing import Match, List, Optional
import config
from test.captured import Captured
@@ -25,7 +25,8 @@ class BaseResult:
BOLD_CHARS = "\033[1m"
CLOSE_CHARS = "\033[0m"
- def __init__(self):
+ def __init__(self, cmd: str):
+ self.cmd = cmd
self.colored = True
self.set_colors()
@@ -43,7 +44,7 @@ class BaseResult:
"""Returns a representation of the result based on the verbosity"""
if config.VERBOSE_LEVEL == 0:
return self.green('.') if self.passed else self.red('!')
- elif config.VERBOSE_LEVEL == 1:
+ if config.VERBOSE_LEVEL == 1:
printed = self._escaped_cmd[:]
if config.SHOW_RANGE:
printed = "{:2}: ".format(self.index) + printed
@@ -56,7 +57,7 @@ class BaseResult:
else:
raise RuntimeError("Invalid verbose level")
- def put(self, index: int):
+ def put(self, index: int) -> None:
"""Print a summary of the result"""
if config.VERBOSE_LEVEL == 2 and self.passed:
return
@@ -76,12 +77,13 @@ class BaseResult:
@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"))
+ c = self.cmd
+ c = c.replace("\t", "\\t")
+ c = c.replace("\n", "\\n")
+ c = c.replace("\v", "\\v")
+ c = c.replace("\r", "\\r")
+ c = c.replace("\f", "\\f")
+ return c
@property
def _header_with(self):
@@ -129,11 +131,10 @@ class Result(BaseResult):
expected: expected capture
actual: actual capture
"""
- self.cmd = cmd
self.file_names = file_names
self.expected = expected
self.actual = actual
- super().__init__()
+ super().__init__(cmd)
@property
def passed(self):
@@ -144,14 +145,16 @@ class Result(BaseResult):
@property
def expected_header(self) -> str:
- return self.green(self.header("EXPECTED"))
+ return self.green(self.header("EXPECTED")) + '\n'
@property
def actual_header(self) -> str:
- return self.red(self.header("ACTUAL"))
+ return self.red(self.header("ACTUAL")) + '\n'
- def cat_e(self, s: str) -> str:
+ def cat_e(self, s: Optional[str]) -> str:
"""Pass a string through a cat -e like output"""
+ if s is None:
+ return "FROM TEST: File not created\n"
s = s.replace("\n", "$\n")
if len(s) < 2:
return s
@@ -159,16 +162,17 @@ class Result(BaseResult):
s += '\n'
return s
- def file_diff(self, file_name: str, expected: str, actual: str) -> str:
+ def file_diff(self, file_name: str, expected: Optional[str], actual: Optional[str]) -> str:
"""Difference between 2 files"""
if expected == actual:
return ""
+ file_header = self.indicator("FILE {}".format(file_name), "|#") + '\n'
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))
+ file_header
+ + self.expected_header
+ + self.cat_e(expected)
+ + self.actual_header
+ + self.cat_e(actual)
)
def files_diff(self):
@@ -190,9 +194,9 @@ class Result(BaseResult):
.format(self.expected.status, self.actual.status), "| "
) + '\n'
if self.expected.output != self.actual.output:
- out += (self.expected_header + '\n'
+ out += (self.expected_header
+ self.cat_e(self.expected.output)
- + self.actual_header + '\n'
+ + self.actual_header
+ self.cat_e(self.actual.output))
return out
@@ -203,9 +207,8 @@ class Result(BaseResult):
class LeakResult(BaseResult):
def __init__(self, cmd: str, captured: Captured):
- self.cmd = cmd
self.captured = captured
- super().__init__()
+ super().__init__(cmd)
def _search_leak_kind(self, kind: str) -> Match:
match = re.search(
diff --git a/src/test/test.py b/src/test/test.py
index 1f8fa82..ab68d1e 100644
--- a/src/test/test.py
+++ b/src/test/test.py
@@ -6,38 +6,41 @@
# By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2020/06/16 21:48:50 by charles #+# #+# #
-# Updated: 2021/01/31 04:41:43 by charles ### ########.fr #
+# Updated: 2021/02/05 01:37:44 by charles ### ########.fr #
# #
# ############################################################################ #
import os
import sys
import subprocess
-from typing import Optional, List, Dict, Union
+from typing import Optional, List, Dict, Union, Callable
import config
from test.captured import Captured
from test.result import Result, LeakResult
import sandbox
+HookType = Union[Callable[[str], str], List[Callable[[str], str]]]
+HookStatusType = Union[Callable[[int], int], List[Callable[[int], int]]]
+
class Test:
- def __init__(self,
- cmd: str,
- setup: str = "",
- files: List[str] = [],
- exports: Dict[str, str] = {},
- timeout: float = config.TIMEOUT,
- signal=None,
- hook=[],
- hook_status=[]):
+ def __init__(
+ self,
+ cmd: str,
+ setup: str = "",
+ files: List[str] = [],
+ exports: Dict[str, str] = {},
+ timeout: float = config.TIMEOUT,
+ hook: HookType = [],
+ hook_status: HookStatusType = [],
+ ):
""" Test class
cmd: command to execute
setup: command to execute before tested command
files: files to watch (check content after test)
exports: exported variables
timeout: maximum amount of time taken by the test
- signal: signal to send to the test
hook: function to execute on the output of the test
hook_status: function to execute on status code
"""
@@ -47,15 +50,14 @@ class Test:
self.exports = exports
self.result: Optional[Union[Result, LeakResult]] = None
self.timeout = timeout
- self.signal = signal
- self.hook = hook
- self.hook_status = hook_status
- if type(self.hook) is not list:
- self.hook = [self.hook]
- if type(self.hook_status) is not list:
- self.hook_status = [self.hook_status]
+ if type(hook) is not list:
+ hook = [hook] # type: ignore
+ if type(hook_status) is not list:
+ hook_status = [hook_status] # type: ignore
+ self.hook: List[Callable[[str], str]] = hook # type: ignore
+ self.hook_status: List[Callable[[int], int]] = hook_status # type: ignore
- def run(self, index: int):
+ def run(self, index: int) -> None:
""" Run the test for minishell and the reference shell and print the result out """
if config.CHECK_LEAKS:
@@ -111,9 +113,6 @@ class Test:
**self.exports,
},
)
- # if self.signal is not None:
- # time.sleep(0.1)
- # process.send_signal(self.signal)
# https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
try:
@@ -138,10 +137,10 @@ class Test:
files_content.append(None)
# apply output/status hooks
- for h in self.hook:
- output = h(output)
- for h in self.hook_status:
- process.returncode = h(process.returncode)
+ for hook in self.hook:
+ output = hook(output)
+ for hook_status in self.hook_status:
+ process.returncode = hook_status(process.returncode)
return Captured(output, process.returncode, files_content)
@property