ast_tests.py 3.03 KB
Newer Older
Johannes Bechberger's avatar
Johannes Bechberger committed
1 2
import difflib
import os
Johannes Bechberger's avatar
Johannes Bechberger committed
3
import shutil, logging
Johannes Bechberger's avatar
Johannes Bechberger committed
4
from typing import Tuple
Johannes Bechberger's avatar
Johannes Bechberger committed
5
from mjtest.environment import Environment, TestMode
Johannes Bechberger's avatar
Johannes Bechberger committed
6
from mjtest.test.syntax_tests import BasicSyntaxTest
7
from mjtest.test.tests import TestCase, BasicDiffTestResult, BasicTestResult
Johannes Bechberger's avatar
Johannes Bechberger committed
8 9 10 11 12
from os import path

_LOG = logging.getLogger("tests")


Johannes Bechberger's avatar
Johannes Bechberger committed
13
class ASTPrettyPrintTest(BasicSyntaxTest):
Johannes Bechberger's avatar
Johannes Bechberger committed
14

Johannes Bechberger's avatar
Johannes Bechberger committed
15 16
    FILE_ENDINGS = [".mj", ".valid.mj"]
    INVALID_FILE_ENDINGS = [".invalid.mj"]
Johannes Bechberger's avatar
Johannes Bechberger committed
17 18 19

    def __init__(self, env: Environment, type: str, file: str):
        super().__init__(env, type, file)
Johannes Bechberger's avatar
Johannes Bechberger committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

    def run(self) -> BasicTestResult:
        tmp_file = self.env.create_tmpfile()
        rtcode, out, err = self._pretty_print(self.file, tmp_file)
        if rtcode > 0:
            os.remove(tmp_file)
            return BasicTestResult(self, rtcode, out, err)
        _file = self.file
        tmp_file2 = self.env.create_tmpfile()
        rtcode, out2, err2 = self._pretty_print(tmp_file, tmp_file2)
        if rtcode > 0:
            os.remove(tmp_file2)
            btr = BasicTestResult(self, rtcode, out2, err2)
            btr.add_additional_text("Prior out", out)
            btr.add_additional_text("Prior err", err)
            return btr
        rtcode_lex, out_lex, err_lex = self.env.run_mj_command(TestMode.lexer, self.file)
        rtcode_lex2, out_lex2, err_lex2 = self.env.run_mj_command(TestMode.lexer, tmp_file2)
        os.remove(tmp_file2)
        out_lex = self._sort_lexed(out_lex.decode())
        out_lex2 = self._sort_lexed(out_lex2.decode())
        incorrect_msg, rtcode = "", 0
        if rtcode_lex + rtcode_lex2:
            incorrect_msg, rtcode = "Lexing failed", 1
        elif out != out2:
            incorrect_msg, rtcode = "Not idempotent", 1
        elif out_lex != out_lex2:
            incorrect_msg, rtcode = "Sorted and lexed second pretty print differs from original", 1
        btr = BasicTestResult(self, rtcode, incorrect_msg=incorrect_msg)
        btr.add_additional_text("First round output", out)
        btr.add_additional_text("Second round output", out2)
        btr.add_additional_text("Diff", self._diff(out, out2))
        btr.add_additional_text("Original file, sorted and lexed", out_lex)
        btr.add_additional_text("Second round output, sorted and lexed", out_lex2)
        btr.add_additional_text("Diff", self._diff(out_lex, out_lex2))
        return btr

    def _diff(self, first: str, second: str) -> str:
        return "".join(difflib.Differ().compare(first.splitlines(True), second.splitlines(True)))

    def _sort_lexed(self, lexed: str) -> str:
                #return "".join(difflib.Differ().compare(self.expected_output.splitlines(True), self.output.splitlines(True)))
        return "".join(sorted(lexed.splitlines(True)))



    def _pretty_print(self, input_file: str, output_file: str) -> Tuple[int, str, str]:
        out, err, rtcode = self.env.run_mj_command(TestMode.ast, input_file)
        with open(output_file, "w") as f:
            print(out, file=f)
        return rtcode, out.decode(), err.decode()

TestCase.TEST_CASE_CLASSES["ast"].append(ASTPrettyPrintTest)