diff --git a/mjtest/environment.py b/mjtest/environment.py index 921bd3b906203cb328d798009564f6c3673cd83a..51a3dabe1ae431c59579e4d5907babc653bd1627 100644 --- a/mjtest/environment.py +++ b/mjtest/environment.py @@ -131,7 +131,7 @@ class Environment: if not self.own_tmp_dir: shutil.rmtree(self.tmp_dir) - def run_mj_command(self, mode: str, *args: Tuple[str]) -> Tuple[bytes, bytes, int]: + def run_mj_command(self, mode: str, *args: Tuple[str], timeout: float = None) -> Tuple[bytes, bytes, int]: """ Execute the MiniJava `run` script with the given arguments. @@ -146,15 +146,15 @@ class Environment: TestMode.compile_firm: "--compile-firm" }[mode] cmd = [self.mj_run_cmd, mode_flag] + list(args) - return execute(cmd, timeout=self.timeout) + return execute(cmd, timeout=timeout or self.timeout) - def run_command(self, cmd: str, *args: Tuple[str]) -> Tuple[bytes, bytes, int]: + def run_command(self, cmd: str, *args: Tuple[str], timeout: float = None) -> Tuple[bytes, bytes, int]: """ Execute the passend command with its arguments :return: (out, err, return code) """ - return execute([cmd] + list(args), timeout=self.timeout) + return execute([cmd] + list(args), timeout=timeout or self.timeout) def has_to_preprocess(self, file: str) -> bool: return os.path.relpath(file, self.test_dir).startswith("exec") diff --git a/mjtest/test/exec_tests.py b/mjtest/test/exec_tests.py index 23fb5ee7778a085f623bcc0432cacdb8dd26c955..1dfc800acbd17cc24425bab4ec7356138eb1ecc0 100644 --- a/mjtest/test/exec_tests.py +++ b/mjtest/test/exec_tests.py @@ -2,6 +2,7 @@ import hashlib import logging import os import shutil +import signal from os import path from mjtest.environment import TestMode, Environment from mjtest.test.syntax_tests import BasicSyntaxTest @@ -17,6 +18,7 @@ class JavaExecTest(BasicSyntaxTest): """ FILE_ENDINGS = [".java"] + INVALID_FILE_ENDINGS = [".inf.java"] OUTPUT_FILE_ENDING = ".out" MODE = TestMode.compile_firm @@ -89,4 +91,38 @@ class JavaExecTest(BasicSyntaxTest): with open(file, "r") as f: return hashlib.sha256(f.read().encode()).hexdigest() -TestCase.TEST_CASE_CLASSES[TestMode.compile_firm].append(JavaExecTest) \ No newline at end of file +TestCase.TEST_CASE_CLASSES[TestMode.compile_firm].append(JavaExecTest) + + +class JavaInfiniteLoopTest(BasicSyntaxTest): + + FILE_ENDINGS = [".inf.java"] + MODE = TestMode.compile_firm + + def __init__(self, env: Environment, type: str, file: str, preprocessed_file: str): + super().__init__(env, type, file, preprocessed_file) + + def run(self) -> BasicTestResult: + base_filename = path.basename(self.file).split(".")[0] + tmp_dir = self.env.create_pid_local_tmpdir() + shutil.copy(self.preprocessed_file, path.join(tmp_dir, base_filename + ".java")) + cwd = os.getcwd() + os.chdir(tmp_dir) + timeout = 1 + try: + _, err, rtcode = self.env.run_mj_command(self.MODE, base_filename + ".java") + out, _, _ = self.env.run_command("./" + base_filename, timeout=timeout) + except SigKill as kill: + os.chdir(cwd) + if kill.retcode == signal.SIGXCPU: + return BasicTestResult(self, err.decode(), 0, out.decode()) + else: + return BasicTestResult(self, kill.retcode, "", "", "No timeout, got " + kill.name) + except: + os.chdir(cwd) + raise + os.chdir(cwd) + return BasicTestResult(self, 1, "", "", "No timeout") + + +TestCase.TEST_CASE_CLASSES[TestMode.compile_firm].append(JavaInfiniteLoopTest) \ No newline at end of file