import logging import os import shutil import tempfile from datetime import datetime, time from mjtest.util.shell import execute from mjtest.util.utils import get_mjtest_basedir from typing import Tuple, List class TestMode: syntax = "syntax" semantic = "semantic" exec = "exec" """ All 'success' tests of the n.th mode can used as 'success' tests for the n-1.th mode""" TEST_MODES = [TestMode.syntax, TestMode.semantic, TestMode.exec] class Environment: LOG_LEVELS = { "info": logging.INFO, "error": logging.ERROR, "warn": logging.WARN, "debug": logging.DEBUG } def __init__(self, mode, mj_run: str, tmp_dir: str = "", test_dir: str = "", only_incorrect_tests: bool = False, parallel: bool = False, timeout: int = 30, report_dir: str = "", log_level: str = "warn", produce_no_reports: bool = True, output_incorrect_reports: bool = True): self.mode = mode self.mj_run_cmd = os.path.realpath(mj_run) if tmp_dir: self.own_tmp_dir = True self.tmp_dir = os.path.abspath(os.path.expandvars(tmp_dir)) if not os.path.exists(tmp_dir): os.mkdir(self.tmp_dir) else: self.own_tmp_dir = False self.tmp_dir = tempfile.mkdtemp("mjtest") if test_dir: self.test_dir = os.path.abspath(os.path.realpath(test_dir)) else: self.test_dir = os.path.join(get_mjtest_basedir(), "tests") if not os.path.exists(self.test_dir): os.mkdir(self.test_dir) for d in [TestMode.syntax, TestMode.semantic, TestMode.exec]: os.mkdir(os.path.join(self.test_dir, d)) self.only_incorrect_tests = only_incorrect_tests self.parallel = parallel self.timeout = timeout if not produce_no_reports: if report_dir: self.report_dir = os.path.abspath(os.path.expandvars(report_dir)) if not os.path.exists(report_dir): os.mkdir(self.report_dir) else: self.report_dir = os.path.join(get_mjtest_basedir(), "reports") if not os.path.exists(self.report_dir): os.mkdir(self.report_dir) self.report_dir = os.path.join(self.report_dir, datetime.now().strftime("%d-%m-%y_%H-%M-%S")) os.mkdir(self.report_dir) else: self.report_dir = None logging.basicConfig(level=self.LOG_LEVELS[log_level]) self.produce_reports = not produce_no_reports # type: bool self.output_incorrect_reports = True def create_tmpfile(self) -> str: return os.path.join(self.tmp_dir, str(os.times())) def create_tmpdir(self) -> str: dir = self.create_tmpfile() os.mkdir(dir) return dir def clean_up(self): 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]: """ Execute the MiniJava `run` script with the given arguments. :param args: arguments for the MiniJava `run` script :return: (out, err, return code) """ mode_flag = { TestMode.syntax: "--parsetest" }[mode] cmd = [self.mj_run_cmd, mode_flag] + list(args) return execute(cmd, timeout=self.timeout) def run_command(self, cmd: str, *args: Tuple[str]) -> Tuple[bytes, bytes, int]: """ Execute the passend command with its arguments :return: (out, err, return code) """ return execute([cmd] + list(args), timeout=self.timeout)