aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/captured.py2
-rw-r--r--src/test/result.py101
-rw-r--r--src/test/test.py32
3 files changed, 87 insertions, 48 deletions
diff --git a/src/test/captured.py b/src/test/captured.py
index f855212..4a9966d 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: 2020/09/11 20:42:05 by charles ### ########.fr #
+# Updated: 2020/10/07 18:25:05 by cacharle ### ########.fr #
# #
# ############################################################################ #
diff --git a/src/test/result.py b/src/test/result.py
index 5e7c2e9..30ce31e 100644
--- a/src/test/result.py
+++ b/src/test/result.py
@@ -6,11 +6,12 @@
# By: charles <me@cacharle.xyz> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2020/09/11 12:17:34 by charles #+# #+# #
-# Updated: 2020/10/06 16:56:30 by cacharle ### ########.fr #
+# Updated: 2020/10/07 18:53:27 by cacharle ### ########.fr #
# #
# ############################################################################ #
import sys
+import re
import config
from test.captured import Captured
@@ -23,50 +24,51 @@ class Result:
BOLD_CHARS = "\033[1m"
CLOSE_CHARS = "\033[0m"
- def __init__(self, cmd: str, file_names: [str], expected: Captured, actual: Captured):
+ def __init__(
+ self,
+ cmd: str,
+ file_names: [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
+ 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
self.colored = True
+ self.leak_output = leak_output
self.set_colors()
- 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 = ""
+ @staticmethod
+ def leak(cmd: str, leak_output: str = None):
+ return Result(cmd, None, None, None, leak_output)
- 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 lost_bytes(self):
+ m = re.search(
+ r"definitely lost: (?P<bytes>[0-9,]+) bytes in [0-9,]+ blocks",
+ self.leak_output
+ )
+ if m is None:
+ raise RuntimeError(
+ "valgrind output parsing failed for `{}`:\n{}"
+ .format(self.cmd, self.leak_output)
+ )
+ return int(m.group("bytes"))
@property
def passed(self):
"""Check if the result passed"""
+ if self.leak_output is not None:
+ return self.lost_bytes == 0
return self.actual == self.expected
@property
@@ -153,10 +155,12 @@ class Result:
def full_diff(self) -> str:
"""Concat all difference reports"""
- return (self.indicator("WITH {}".format(self.escaped_cmd), "|>") + '\n'
- + self.output_diff()
- + self.files_diff()
- + "=" * 80 + '\n')
+ 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"""
@@ -176,3 +180,30 @@ class Result:
.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 = ""
+
+ 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
diff --git a/src/test/test.py b/src/test/test.py
index c4e183c..52b6db3 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/10/07 08:12:00 by charles ### ########.fr #
+# Updated: 2020/10/07 18:54:13 by cacharle ### ########.fr #
# #
# ############################################################################ #
import os
import sys
import subprocess
-# import time
+#import time
import config
from test.captured import Captured
@@ -57,8 +57,17 @@ class Test:
def run(self):
""" Run the test for minishell and the reference shell and print the result out """
- expected = self._run_sandboxed(config.REFERENCE_PATH, config.REFERENCE_ARGS + ["-c"])
- actual = self._run_sandboxed(config.MINISHELL_PATH, ["-c"])
+
+ if config.CHECK_LEAKS:
+ self.hook = []
+ self.hook_status = []
+ captured = self._run_sandboxed([*config.VALGRIND_CMD, "-c"])
+ self.result = Result.leak(self.cmd, captured.output)
+ self.result.put()
+ return
+
+ expected = self._run_sandboxed([config.REFERENCE_PATH, *config.REFERENCE_ARGS, "-c"])
+ actual = self._run_sandboxed([config.MINISHELL_PATH, "-c"])
s = self.cmd
if self.setup != "":
s = "[SETUP {}] {}".format(self.setup, s)
@@ -68,7 +77,7 @@ class Test:
self.result = Result(s, self.files, expected, actual)
self.result.put()
- def _run_sandboxed(self, shell_path: str, shell_options: str) -> Captured:
+ def _run_sandboxed(self, shell_cmd: [str]) -> Captured:
""" Run the command in a sandbox environment """
with sandbox.context():
if self.setup != "":
@@ -88,15 +97,15 @@ class Test:
"no stderr" if e.stdout is None
else e.stdout.decode().strip()))
sys.exit(1)
- return self._run_capture(shell_path, shell_options)
+ return self._run_capture(shell_cmd)
- def _run_capture(self, shell_path: str, shell_options: str) -> Captured:
+ def _run_capture(self, shell_cmd: [str]) -> Captured:
""" Capture the output (stdout and stderr)
Capture the content of the watched files after the command is run
"""
# run the command in the sandbox
process = subprocess.Popen(
- [shell_path, *shell_options, self.cmd],
+ [*shell_cmd, self.cmd],
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
cwd=config.SANDBOX_PATH,
@@ -107,13 +116,12 @@ class Test:
},
)
# if self.signal is not None:
- # time.sleep(0.2)
+ # time.sleep(0.1)
# process.send_signal(self.signal)
- # else:
# https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
try:
- stdout, _ = process.communicate(timeout=self.timeout)
+ stdout, _ = process.communicate(timeout=(self.timeout if not config.CHECK_LEAKS else 10))
except subprocess.TimeoutExpired:
process.kill()
# _, _ = process.communicate(timeout=2)
@@ -132,7 +140,7 @@ class Test:
except FileNotFoundError:
files_content.append(None)
- # sandbox.remove()
+ # apply output/status hooks
for h in self.hook:
output = h(output)
for h in self.hook_status: