environment.py 3.32 KB
Newer Older
Johannes Bechberger's avatar
Johannes Bechberger committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
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
    }

30
    def __init__(self, mode, mj_run: str, tmp_dir: str = "", test_dir: str = "",
Johannes Bechberger's avatar
Johannes Bechberger committed
31 32 33
                 only_incorrect_tests: bool = False, parallel: bool = False,
                 timeout: int = 30, report_dir: str = "", log_level: str = "warn"):
        self.mode = mode
34
        self.mj_run_cmd = os.path.realpath(mj_run)
Johannes Bechberger's avatar
Johannes Bechberger committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

        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

58
        if report_dir:
Johannes Bechberger's avatar
Johannes Bechberger committed
59 60 61 62 63 64 65
            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)
66
        self.report_dir = os.path.join(self.report_dir, datetime.now().strftime("%d-%m-%y_%H-%M-%S"))
Johannes Bechberger's avatar
Johannes Bechberger committed
67 68 69 70
        os.mkdir(self.report_dir)
        logging.basicConfig(level=self.LOG_LEVELS[log_level])

    def create_tmpfile(self) -> str:
71 72 73 74 75 76
        return os.path.join(self.tmp_dir, str(os.times()))

    def create_tmpdir(self) -> str:
        dir = self.create_tmpfile()
        os.mkdir(dir)
        return dir
Johannes Bechberger's avatar
Johannes Bechberger committed
77 78 79 80 81

    def clean_up(self):
        if not self.own_tmp_dir:
            shutil.rmtree(self.tmp_dir)

Johannes Bechberger's avatar
Johannes Bechberger committed
82
    def run_mj_command(self, mode: str, *args: Tuple[str]) -> Tuple[bytes, bytes, int]:
Johannes Bechberger's avatar
Johannes Bechberger committed
83 84 85 86 87 88
        """
        Execute the MiniJava `run` script with the given arguments.

        :param args: arguments for the MiniJava `run` script
        :return: (out, err, return code)
        """
Johannes Bechberger's avatar
Johannes Bechberger committed
89 90 91 92
        mode_flag = {
            TestMode.syntax: "--parsetest"
        }[mode]
        cmd = [self.mj_run_cmd, mode_flag] + list(args)
93 94 95 96 97 98 99 100 101
        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)