exec_tests.py 3.72 KB
Newer Older
1 2 3 4 5 6 7
import logging
import os
import shutil
from os import path
from mjtest.environment import TestMode, Environment
from mjtest.test.syntax_tests import BasicSyntaxTest
from mjtest.test.tests import TestCase, BasicDiffTestResult, BasicTestResult
8
from mjtest.util.shell import SigKill
9 10 11 12 13 14 15 16 17 18

_LOG = logging.getLogger("exec_tests")

class JavaExecTest(BasicSyntaxTest):
    """
    The MiniJava compiler should behave the same as javac
    """

    FILE_ENDINGS = [".java"]
    OUTPUT_FILE_ENDING = ".out"
19
    MODE = TestMode.compile_firm
20 21 22 23

    def __init__(self, env: Environment, type: str, file: str, preprocessed_file: str):
        super().__init__(env, type, file, preprocessed_file)
        self._expected_output_file = file + self.OUTPUT_FILE_ENDING
24 25 26 27
        prev_out_dir = path.join(path.dirname(file), ".java_output")
        if not path.exists(prev_out_dir):
            os.mkdir(prev_out_dir)
        self._prev_out_file = path.join(prev_out_dir, path.basename(self._expected_output_file))
28
        self._has_expected_output_file = path.exists(self._expected_output_file)
29 30 31 32 33
        if not self._has_expected_output_file:
            if path.exists(self._prev_out_file) and self.compare_files_by_age(file, self._prev_out_file) == -1:
                self._has_expected_output_file = True
                self._expected_output_file = self._prev_out_file
                _LOG.info("Reuse old java output file \"{}\"".format(path.relpath(self._prev_out_file)))
34 35 36 37
        self._should_succeed = True

    def run(self) -> BasicDiffTestResult:
        base_filename = path.basename(self.file).split(".")[0]
38
        tmp_dir = self.env.create_pid_local_tmpdir()
39 40 41 42 43 44 45 46 47
        shutil.copy(self.preprocessed_file, path.join(tmp_dir, base_filename + ".java"))
        cwd = os.getcwd()
        os.chdir(tmp_dir)
        exp_out = None
        if not self._has_expected_output_file:
            _, _, javac_rtcode = \
                self.env.run_command("javac", base_filename + ".java")
            if javac_rtcode != 0:
                _LOG.error("File \"{}\" isn't valid Java".format(self.preprocessed_file))
48
                os.chdir(cwd)
49 50 51
                raise InterruptedError()
            exp_out, _, _ = \
                self.env.run_command("java", base_filename)
52
            exp_out = exp_out.decode().strip()
53 54 55
            with open(self._prev_out_file, "w") as f:
                f.write(exp_out)
                f.flush()
56 57 58
        if self._has_expected_output_file and self.type == self.MODE and self.env.mode == self.MODE:
            with open(self._expected_output_file, "r") as f:
                exp_out = f.read()
59 60 61 62 63 64 65
        try:
            _, err, rtcode = self.env.run_mj_command(self.MODE, base_filename + ".java")
            out, _, _ = self.env.run_command("./" + base_filename)
            out = out.decode().strip()
            os.chdir(cwd)
            if self.type == self.MODE and self.env.mode == self.MODE:
                return BasicDiffTestResult(self, rtcode, out, err.decode(), exp_out)
Johannes Bechberger's avatar
Johannes Bechberger committed
66
            return BasicTestResult(self, rtcode, out, err.decode())
67 68 69
        except SigKill as sig:
            os.chdir(cwd)
            return BasicTestResult(self, sig.retcode, "", exp_out, sig.name)
70 71 72
        except:
            os.chdir(cwd)
            raise
73

74 75 76 77 78 79 80 81 82 83 84 85 86 87
    def get_file_time(self, file: str) -> float:
        return max(os.path.getmtime(file), os.path.getatime(file))

    def compare_files_by_age(self, file: str, other_file: str) -> int:
        """
        :return: -1 == file is older, 0 == almost equal ages, 1 == other file is older
        """
        diff = self.get_file_time(file) - self.get_file_time(other_file)
        if diff < 60:
            return -1
        if diff > -60:
            return 1
        return 0

88
TestCase.TEST_CASE_CLASSES[TestMode.compile_firm].append(JavaExecTest)