environment.py 3.93 KB
Newer Older
Johannes Bechberger's avatar
Johannes Bechberger committed
1 2 3 4 5 6 7 8 9 10 11
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:
12 13 14

    lexer = "lexer"

Johannes Bechberger's avatar
Johannes Bechberger committed
15 16
    syntax = "syntax"

Johannes Bechberger's avatar
Johannes Bechberger committed
17 18
    ast = "ast"

Johannes Bechberger's avatar
Johannes Bechberger committed
19 20 21 22
    semantic = "semantic"

    exec = "exec"

Johannes Bechberger's avatar
Johannes Bechberger committed
23 24 25 26
    USE_TESTS_OF_OTHER = {
        ast: [syntax]
    }

Johannes Bechberger's avatar
Johannes Bechberger committed
27
""" All 'success' tests of the n.th mode can used as 'success' tests for the n-1.th mode"""
28
TEST_MODES = [TestMode.lexer, TestMode.syntax, TestMode.ast, TestMode.semantic, TestMode.exec]
Johannes Bechberger's avatar
Johannes Bechberger committed
29 30 31 32 33 34 35 36 37 38

class Environment:

    LOG_LEVELS = {
        "info": logging.INFO,
        "error": logging.ERROR,
        "warn": logging.WARN,
        "debug": logging.DEBUG
    }

39
    def __init__(self, mode, mj_run: str, tmp_dir: str = "", test_dir: str = "",
Johannes Bechberger's avatar
Johannes Bechberger committed
40
                 only_incorrect_tests: bool = False, parallel: bool = False,
41
                 timeout: int = 30, report_dir: str = "", log_level: str = "warn",
42
                 produce_no_reports: bool = True, output_no_incorrect_reports: bool = False,
43 44
                 produce_all_reports: bool = False, report_subdir: str = None,
                 ci_testing: bool = False):
Johannes Bechberger's avatar
Johannes Bechberger committed
45
        self.mode = mode
46
        self.mj_run_cmd = os.path.realpath(mj_run)
Johannes Bechberger's avatar
Johannes Bechberger committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

        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)
Johannes Bechberger's avatar
Johannes Bechberger committed
63
            for d in TEST_MODES:
Johannes Bechberger's avatar
Johannes Bechberger committed
64 65 66 67 68
                os.mkdir(os.path.join(self.test_dir, d))

        self.only_incorrect_tests = only_incorrect_tests
        self.parallel = parallel
        self.timeout = timeout
69 70 71 72 73
        if not produce_no_reports:
            if report_dir:
                self.report_dir = os.path.abspath(os.path.expandvars(report_dir))
            else:
                self.report_dir = os.path.join(get_mjtest_basedir(), "reports")
74 75 76 77
            try:
                os.mkdir(self.report_dir)
            except IOError:
                pass
78
            self.report_dir = os.path.join(self.report_dir, report_subdir or datetime.now().strftime("%d-%m-%y_%H-%M-%S"))
Johannes Bechberger's avatar
Johannes Bechberger committed
79
        else:
80
            self.report_dir = None
Johannes Bechberger's avatar
Johannes Bechberger committed
81
        logging.basicConfig(level=self.LOG_LEVELS[log_level])
82
        self.produce_reports = not produce_no_reports # type: bool
83 84
        self.output_incorrect_reports = not output_no_incorrect_reports
        self.produce_all_reports = produce_all_reports
85
        self.ci_testing = ci_testing
Johannes Bechberger's avatar
Johannes Bechberger committed
86 87

    def create_tmpfile(self) -> str:
88 89 90 91 92 93
        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
94 95 96 97 98

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

Johannes Bechberger's avatar
Johannes Bechberger committed
99
    def run_mj_command(self, mode: str, *args: Tuple[str]) -> Tuple[bytes, bytes, int]:
Johannes Bechberger's avatar
Johannes Bechberger committed
100 101 102 103 104 105
        """
        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
106
        mode_flag = {
107
            TestMode.lexer: "--lextest",
Johannes Bechberger's avatar
Johannes Bechberger committed
108
            TestMode.syntax: "--parsetest",
Johannes Bechberger's avatar
Johannes Bechberger committed
109
            TestMode.ast: "--pretty-print"
Johannes Bechberger's avatar
Johannes Bechberger committed
110 111
        }[mode]
        cmd = [self.mj_run_cmd, mode_flag] + list(args)
112 113 114 115 116 117 118 119 120
        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)