import difflib import os import shutil, logging from typing import Tuple, Dict from mjtest.environment import Environment, TestMode, TEST_MODES from mjtest.test.syntax_tests import BasicSyntaxTest from mjtest.test.tests import TestCase, BasicDiffTestResult, BasicTestResult from os import path from mjtest.util.utils import decode _LOG = logging.getLogger("tests") class ASTPrettyPrintTest(BasicSyntaxTest): FILE_ENDINGS = [".mj", ".valid.mj"] INVALID_FILE_ENDINGS = [".invalid.mj"] def __init__(self, env: Environment, type: str, file: str, preprocessed_file: str, log_file_mode: str): super().__init__(env, type, file, preprocessed_file, log_file_mode) if type != TestMode.ast and TEST_MODES.index(TestMode.ast) < TEST_MODES.index(type): self._should_succeed = True def run(self) -> BasicTestResult: tmp_file = self.env.create_tmpfile() rtcode, out, err = self._pretty_print(self.preprocessed_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_file) 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 #out_lex = self._line_count(out_lex.decode()) #out_lex2 = self._line_count(out_lex2.decode()) #comp = self._comp_dicts(out_lex, out_lex2) incorrect_msg, rtcode = "", 0 if out2 != out: incorrect_msg, rtcode = "Not idempotent", 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)) os.remove(tmp_file) os.remove(tmp_file2) return btr def _diff(self, first: str, second: str) -> str: return "".join(difflib.Differ().compare(first.splitlines(True), second.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, "wb", errors="backslashreplace") as f: f.write(out) f.flush() return rtcode, decode(out), decode(err) TestCase.TEST_CASE_CLASSES["ast"].append(ASTPrettyPrintTest)