aboutsummaryrefslogtreecommitdiff
path: root/src/test.py
diff options
context:
space:
mode:
authorCharles Cabergs <me@cacharle.xyz>2020-10-01 11:49:53 +0200
committerCharles Cabergs <me@cacharle.xyz>2020-10-01 11:49:53 +0200
commit1f18e740539aed751865ecff9d0f3cba44230e54 (patch)
treee23254751cc5a3be551233efb979a00571f40dc6 /src/test.py
parent763f02a8b1e69c0e26a088824981d23ba1e5386d (diff)
downloadphilosophers_test-1f18e740539aed751865ecff9d0f3cba44230e54.tar.gz
philosophers_test-1f18e740539aed751865ecff9d0f3cba44230e54.tar.bz2
philosophers_test-1f18e740539aed751865ecff9d0f3cba44230e54.zip
Refactoring file structure, Added summary
Diffstat (limited to 'src/test.py')
-rw-r--r--src/test.py145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/test.py b/src/test.py
new file mode 100644
index 0000000..49059f6
--- /dev/null
+++ b/src/test.py
@@ -0,0 +1,145 @@
+# ############################################################################ #
+# #
+# ::: :::::::: #
+# test.py :+: :+: :+: #
+# +:+ +:+ +:+ #
+# By: charles <me@cacharle.xyz> +#+ +:+ +#+ #
+# +#+#+#+#+#+ +#+ #
+# Created: 2020/09/27 11:36:32 by charles #+# #+# #
+# Updated: 2020/10/01 11:41:21 by cacharle ### ########.fr #
+# #
+# ############################################################################ #
+
+import os
+import time
+import subprocess
+
+import config
+import philo
+from helper import current_ms, red, green
+
+
+class Test:
+ _tests = []
+ _exec_path = None
+ _fail_summaries = []
+
+ @classmethod
+ def run_all(cls, exec_path: str):
+ cls._exec_path = exec_path
+ for t in cls._tests:
+ t.run()
+
+ @staticmethod
+ def new_error(error_cmd: [str]):
+ Test(error_cmd=error_cmd)
+
+ def __init__(
+ self,
+ philo_num: int = None,
+ timeout_die: int = None,
+ timeout_eat: int = None,
+ timeout_sleep: int = None,
+ meal_num: int = None,
+ error_cmd: [str] = None,
+ ):
+ self._philo_num = philo_num
+ self._timeout_die = timeout_die
+ self._timeout_eat = timeout_eat
+ self._timeout_sleep = timeout_sleep
+ self._meal_num = meal_num
+ self._error_cmd = error_cmd
+ Test._tests.append(self)
+
+ def run(self):
+ try:
+ self._run_tested()
+ except philo.error.Philo as e:
+ self._print_fail(e.summary)
+ Test._fail_summaries.append(self._argv_str + '\n' + e.full_summary)
+ else:
+ self._print_pass()
+
+ @classmethod
+ def write_failed(cls):
+ with open(config.RESULT_FILE, "w") as f:
+ f.write('\n\n'.join(cls._fail_summaries))
+
+ @classmethod
+ def print_summary(cls):
+ fail_total = len(cls._fail_summaries)
+ pass_total = len(cls._tests) - fail_total
+ print("Summary: Total {} {} {}".format(
+ len(cls._tests),
+ green("[PASS] {:3}".format(pass_total)),
+ red("[FAIL] {:3}".format(fail_total))
+ ))
+
+ def _run_tested(self):
+ start_time = current_ms()
+ process = subprocess.Popen(
+ self._argv(),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT
+ )
+ if self._error_cmd is not None:
+ self._check_error(process)
+ return
+
+ out = ""
+ try:
+ out, _ = process.communicate(timeout=1)
+ except subprocess.TimeoutExpired as e:
+ out = e.stdout
+ end_time = current_ms()
+ try:
+ out = out.decode()
+ except UnicodeDecodeError:
+ pass # TODO
+
+ table = philo.Table(
+ self._philo_num,
+ self._timeout_die,
+ self._timeout_eat,
+ self._timeout_sleep,
+ 1 if self._meal_num is None else self._meal_num
+ )
+ for line in out.split('\n')[:-1]:
+ table.add_log(philo.Log(line, self._philo_num, start_time, end_time))
+ table.check()
+
+ def _check_error(self, process):
+ try:
+ out, _ = process.communicate(timeout=config.TIMEOUT_ERROR)
+ except subprocess.TimeoutExpired:
+ raise error.ShouldFail("no error message")
+ if process.returncode == 0:
+ raise error.ShouldFail("non zero status code: {}".format(process.returncode))
+ if out.decode().count('\n') != 1:
+ raise error.ShouldFail("no error message")
+
+ def _argv(self, basename=False):
+ exec_path = os.path.basename(Test._exec_path) if basename else Test._exec_path
+ if self._error_cmd is not None:
+ return [exec_path, *self._error_cmd]
+ else:
+ argv = [
+ exec_path,
+ str(self._philo_num),
+ str(self._timeout_die),
+ str(self._timeout_eat),
+ str(self._timeout_sleep)
+ ]
+ if self._meal_num is not None:
+ argv.append(str(self._meal_num))
+ return argv
+
+ @property
+ def _argv_str(self):
+ return ' '.join(self._argv(basename=True))
+
+ def _print_fail(self, msg):
+ print(red("[FAIL] {}: {}".format(self._argv_str, msg)))
+
+ def _print_pass(self):
+ print(green("[PASS] {}".format(self._argv_str)))