From 58d5a537479c5dd2779a1878713abaa4460752c1 Mon Sep 17 00:00:00 2001 From: Tagl Date: Mon, 19 Aug 2024 22:49:03 +0000 Subject: [PATCH] Allow symlinks to test cases with other output validator flags and warn if output validators fails to compile. --- problemtools/verifyproblem.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index a45cbf9..3cd7ab8 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -183,8 +183,8 @@ def __init__(self, problem: Problem, base: str, testcasegroup: TestCaseGroup) -> self._problem = problem self.testcasegroup = testcasegroup self.reuse_result_from: TestCase|None = None - self.counter = len(problem.testcase_by_infile) - problem.testcase_by_infile[self.infile] = self + self.counter = len(problem.testcase_by_input) + problem.testcase_by_input[(self.infile, self.testcasegroup.config['output_validator_flags'])] = self def check_newlines(self, filename: str) -> None: with open(filename, 'rb') as f: @@ -248,9 +248,9 @@ def matches_filter(self, filter_re: Pattern[str]) -> bool: def set_symlinks(self) -> None: if not os.path.islink(self.infile): return - target = os.path.realpath(self.infile) - if target in self._problem.testcase_by_infile: - self.reuse_result_from = self._problem.testcase_by_infile[target] + target = os.path.realpath(self.infile), self.testcasegroup.config['output_validator_flags'] + if target in self._problem.testcase_by_input: + self.reuse_result_from = self._problem.testcase_by_input[target] def _check_symlinks(self) -> bool: if not os.path.islink(self.infile): @@ -264,12 +264,9 @@ def _check_symlinks(self) -> bool: if ans_target != f'{in_target[:-3]}.ans': self.error(f"Symbolic link '{nicepath}' must have a corresponding link for answer file") return False - if self.reuse_result_from is None: + if not nicepath.startswith('data'): self.error(f"Symbolic link points outside data/ directory for file '{nicepath}'") return False - if self.testcasegroup.config['output_validator_flags'] != self.reuse_result_from.testcasegroup.config['output_validator_flags']: - self.error(f"Symbolic link '{nicepath}' points to testcase with different output validator flags") - return False return True def run_submission(self, sub, runner: Runner, context: Context) -> Result: @@ -1661,7 +1658,8 @@ def validate(self, testcase: TestCase, submission_output: str) -> SubmissionResu val_memlim = self._problem.config.get('limits')['validation_memory'] flags = self._problem.config.get('validator_flags').split() + testcase.testcasegroup.config['output_validator_flags'].split() for val in self._actual_validators(): - if val.compile()[0]: + compile_res = val.compile() + if compile_res[0]: feedbackdir = tempfile.mkdtemp(prefix='feedback', dir=self._problem.tmpdir) validator_output = tempfile.mkdtemp(prefix='checker_out', dir=self._problem.tmpdir) outfile = validator_output + "/out.txt" @@ -1670,6 +1668,7 @@ def validate(self, testcase: TestCase, submission_output: str) -> SubmissionResu args=[testcase.infile, testcase.ansfile, feedbackdir] + flags, timelim=val_timelim, memlim=val_memlim, outfile=outfile, errfile=errfile) + if self.log.isEnabledFor(logging.DEBUG): try: with open(outfile, mode="rt") as f: @@ -1687,6 +1686,8 @@ def validate(self, testcase: TestCase, submission_output: str) -> SubmissionResu shutil.rmtree(validator_output) if res.verdict != 'AC': return res + else: + self.warning(f"Compilation failed for {val.name}: {compile_res[1]}") # TODO: check that all output validators give same result return res @@ -1982,7 +1983,7 @@ def __enter__(self) -> Problem: self.input_validators = InputValidators(self) self.output_validators = OutputValidators(self) self.graders = Graders(self) - self.testcase_by_infile: dict[str, TestCase] = {} + self.testcase_by_input: dict[tuple[str, str], TestCase] = {} self.testdata = TestCaseGroup(self, os.path.join(self.probdir, 'data')) self.submissions = Submissions(self) self.generators = Generators(self)