From 01ab72e746c731c3d56282e9d19891d782442afc Mon Sep 17 00:00:00 2001 From: mzuenni Date: Mon, 27 Jan 2025 20:19:36 +0100 Subject: [PATCH] more limits --- bin/generate.py | 9 +++++++++ bin/problem.py | 2 +- bin/run.py | 6 ++++-- bin/testcase.py | 4 +++- bin/validate.py | 9 ++++++++- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/bin/generate.py b/bin/generate.py index 1915a60f..a18bcd16 100644 --- a/bin/generate.py +++ b/bin/generate.py @@ -710,6 +710,15 @@ def validate_ans(t, problem, testcase, meta_yaml, bar): multipass = 'multipass ' if problem.multipass else '' bar.warn(f'.ans file for {interactive}{multipass}problem is expected to be empty.') else: + size = ansfile.stat().st_size + if ( + size <= problem.limits.output * 1024 * 1024 + and problem.limits.output * 1024 * 1024 < 2 * size + ): # we already warn if the limit is exceeded + bar.warn( + f'.ans file is close to output limit (set limits->output to at least {(2*size + 1024 * 1024 - 1) // 1024 // 1024}MiB in problem.yaml)' + ) + answer_validator_hashes = { **testcase.validator_hashes(validate.AnswerValidator, bar), **testcase.validator_hashes(validate.OutputValidator, bar), diff --git a/bin/problem.py b/bin/problem.py index 36321965..9797aea7 100644 --- a/bin/problem.py +++ b/bin/problem.py @@ -132,7 +132,7 @@ def _read_settings(self): 'time_safety_margin': 1.5, 'time_resolution': 1.0, 'memory': 2048, # in MiB - # 'output': 8, # in MiB + 'output': 8, # in MiB 'code': 128, # in KiB # 'compilation_time': 60, # in seconds # 'compilation_memory': 2048, # in MiB diff --git a/bin/run.py b/bin/run.py index 9148973b..e8af49ab 100644 --- a/bin/run.py +++ b/bin/run.py @@ -116,7 +116,7 @@ def run(self, bar, *, interaction=None, submission_args=None): ) elif result.status: result.verdict = Verdict.ACCEPTED - validate.sanity_check(self.out_path, bar, strict_whitespace=False) + validate.sanity_check(self.problem, self.out_path, bar, strict_whitespace=False) elif result.status == ExecStatus.REJECTED: result.verdict = Verdict.WRONG_ANSWER if nextpass and nextpass.is_file(): @@ -250,7 +250,9 @@ def build(self, bar: ProgressBar): if ok: size = sum(f.stat().st_size for f in self.source_files) if size > self.problem.limits.code * 1024: - bar.warn(f'Code limit exceeded ({size // 1024}KiB)') + bar.warn( + f'Code limit exceeded (set limits->code to at least {(size + 1023) // 1024}KiB in problem.yaml)' + ) return ok def _get_expected_verdicts(self) -> list[Verdict]: diff --git a/bin/testcase.py b/bin/testcase.py index 543fae85..43674d7f 100644 --- a/bin/testcase.py +++ b/bin/testcase.py @@ -368,7 +368,9 @@ def _run_validators( success = all(results) if success: validate.sanity_check( - self.in_path if mode == validate.Mode.INPUT else self.ans_path, bar + self.problem, + self.in_path if mode == validate.Mode.INPUT else self.ans_path, + bar, ) return success diff --git a/bin/validate.py b/bin/validate.py index b4916cc3..0e324abc 100644 --- a/bin/validate.py +++ b/bin/validate.py @@ -390,7 +390,7 @@ def _has_consecutive_whitespaces(bytes): return False -def sanity_check(path, bar, strict_whitespace=True): +def sanity_check(problem, path, bar, strict_whitespace=True): """ Does some generic checks on input, answer, or output files of a testcase, including @@ -427,6 +427,13 @@ def sanity_check(path, bar, strict_whitespace=True): bar.warn(f'{name} is empty but was accepted!') elif len(file_bytes) > 20_000_000: bar.warn(f'{name} is larger than 20MB!') + elif ( + path.suffix in ['.ans', '.out'] + and len(file_bytes) > problem.limits.output * 1024 * 1024 + ): + bar.warn( + f'{name} exceeds output limit (set limits->output to at least {(len(file_bytes) + 1024 * 1024 - 1) // 1024 // 1024}MiB in problem.yaml)' + ) elif strict_whitespace: if file_bytes[0] in [ord(' '), ord('\n')]: bar.warn(f'{name} starts with whitespace but was accepted!')