Skip to content

Commit d5b35c4

Browse files
committed
Do not allow an unnumbered test case to be named 'test_group'
This is also mentioned in https://icpc.io/problem-package-format/spec/2023-07-draft.html#test-data
1 parent a1f5264 commit d5b35c4

File tree

3 files changed

+28
-6
lines changed

3 files changed

+28
-6
lines changed

bin/generate.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -457,12 +457,17 @@ def __init__(
457457
# root in /data
458458
self.root = self.path.parts[0]
459459

460-
if not config.COMPILED_FILE_NAME_REGEX.fullmatch(name + ".in"):
461-
raise ParseException("Testcase does not have a valid name.")
462-
463460
# files to consider for hashing
464461
hashes = {}
465462
try:
463+
if not config.COMPILED_FILE_NAME_REGEX.fullmatch(name + ".in"):
464+
raise ParseException("Test case does not have a valid name.")
465+
466+
if not parent.numbered and key == "test_group":
467+
raise ParseException(
468+
"Test case must not be named 'test_group', this clashes with the group-level 'test_group.yaml'."
469+
)
470+
466471
if yaml is None:
467472
raise ParseException(
468473
"Empty yaml entry (Testcases must be generated not only mentioned)."
@@ -1678,7 +1683,7 @@ def parse(key: str, name_gen: Callable[[], str], yaml: dict, parent: AnyDirector
16781683

16791684
if is_testcase(yaml):
16801685
if isinstance(parent, RootDirectory):
1681-
raise ParseException("Testcase must be inside Directory", name)
1686+
raise ParseException("Test case must be inside a Directory.", name)
16821687

16831688
count = parse_count(yaml, parent.path / name)
16841689

bin/problem.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,15 @@ def get_test_case_yaml(
612612

613613
return []
614614

615+
# Because Problem.testcases() may be called multiple times (e.g. validating multiple modes, or with `bt all`),
616+
# this cache makes sure that some warnings (like malformed test case names) only appear once.
617+
_warned_for_test_case = set[str]()
618+
619+
def _warn_once(p, test_name, msg):
620+
if test_name not in p._warned_for_test_case:
621+
p._warned_for_test_case.add(test_name)
622+
warn(msg)
623+
615624
def testcases(
616625
p,
617626
*,
@@ -660,6 +669,15 @@ def testcases(
660669
testcases = []
661670
for f in in_paths:
662671
t = testcase.Testcase(p, f)
672+
if not config.COMPILED_FILE_NAME_REGEX.fullmatch(f.name):
673+
p._warn_once(t.name, f"Test case name {t.name} is not valid. Skipping.")
674+
continue
675+
if f.name.startswith("test_group"):
676+
p._warn_once(
677+
t.name,
678+
"Test case must not be named 'test_group', this clashes with the group-level 'test_group.yaml'. Skipping.",
679+
)
680+
continue
663681
if (
664682
(p.interactive or p.multi_pass)
665683
and mode in [validate.Mode.INVALID, validate.Mode.VALID_OUTPUT]
@@ -671,7 +689,7 @@ def testcases(
671689
continue
672690
if needans and not t.ans_path.is_file():
673691
if t.root != "invalid_input":
674-
warn(f"Found input file {f} without a .ans file. Skipping.")
692+
p._warn_once(t.name, f"Found input file {f} without a .ans file. Skipping.")
675693
continue
676694
if mode == validate.Mode.VALID_OUTPUT:
677695
if t.out_path is None:

bin/testcase.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ def __init__(
8787

8888
self.problem = base_problem
8989

90-
# TODO add self.out_path
9190
if short_path is None:
9291
try:
9392
self.short_path: Path = path.relative_to(self.problem.path / "data")

0 commit comments

Comments
 (0)