feat(diff): auto detect testcases (#13)
All checks were successful
build / build (push) Successful in 2m1s

- added support for subfolders
- complete the duplication for `*.toml` file, now ta only need to specify the param for the specific one. default values are hardcoded
- all testcases should be named as `casei.in/out`, with no interactions in their name in each of the subfolders, (for hidden cases and non-hidden cases, just change position and run again)

Co-authored-by: Boming Zhang <bomingzh@sjtu.edu.cn>
Reviewed-on: #13
Reviewed-by: 张泊明518370910136 <bomingzh@sjtu.edu.cn>
Co-authored-by: jon-lee <jon-lee@sjtu.edu.cn>
Co-committed-by: jon-lee <jon-lee@sjtu.edu.cn>
This commit is contained in:
李衍志523370910113 2025-05-15 17:47:08 +08:00 committed by 张泊明518370910136
parent 305663538d
commit 8a6c34f3e9
22 changed files with 232 additions and 8 deletions

View File

@ -5,6 +5,7 @@ from joj3_config_generator.models.common import Memory, Time
DEFAULT_CPU_LIMIT = Time("1s") DEFAULT_CPU_LIMIT = Time("1s")
DEFAULT_MEMORY_LIMIT = Memory("256m") DEFAULT_MEMORY_LIMIT = Memory("256m")
DEFAULT_FILE_LIMIT = Memory("32m") DEFAULT_FILE_LIMIT = Memory("32m")
DEFAULT_CASE_SCORE = 5
JOJ3_CONFIG_ROOT = Path("/home/tt/.config/joj") JOJ3_CONFIG_ROOT = Path("/home/tt/.config/joj")
TEAPOT_CONFIG_ROOT = Path("/home/tt/.config/teapot") TEAPOT_CONFIG_ROOT = Path("/home/tt/.config/teapot")

View File

@ -2,9 +2,9 @@ import re
import shlex import shlex
from functools import partial from functools import partial
from pathlib import Path from pathlib import Path
from typing import Any, Callable, Dict, List, Tuple from typing import Any, Callable, Dict, List, Set, Tuple
from joj3_config_generator.models import result, task from joj3_config_generator.models import const, result, task
from joj3_config_generator.models.common import Memory, Time from joj3_config_generator.models.common import Memory, Time
from joj3_config_generator.models.const import JOJ3_CONFIG_ROOT from joj3_config_generator.models.const import JOJ3_CONFIG_ROOT
from joj3_config_generator.models.task import Parser as ParserEnum from joj3_config_generator.models.task import Parser as ParserEnum
@ -32,7 +32,8 @@ def get_conf_stage(
parser_handler_map = get_parser_handler_map( parser_handler_map = get_parser_handler_map(
task_stage, task_stage,
conf_stage.executor, conf_stage.executor,
JOJ3_CONFIG_ROOT / task_conf.path.parent, task_conf.root,
task_conf.path,
) )
for idx, parser in enumerate(task_stage.parsers): for idx, parser in enumerate(task_stage.parsers):
if parser not in parser_handler_map: if parser not in parser_handler_map:
@ -45,7 +46,8 @@ def get_conf_stage(
def get_parser_handler_map( def get_parser_handler_map(
task_stage: task.Stage, task_stage: task.Stage,
executor: result.Executor, executor: result.Executor,
base_dir: Path, task_root: Path,
task_path: Path,
) -> Dict[ParserEnum, Tuple[Callable[[Any, result.Parser], None], Any]]: ) -> Dict[ParserEnum, Tuple[Callable[[Any, result.Parser], None], Any]]:
return { return {
ParserEnum.CLANG_TIDY: (fix_keyword, task_stage.clangtidy), ParserEnum.CLANG_TIDY: (fix_keyword, task_stage.clangtidy),
@ -61,7 +63,8 @@ def get_parser_handler_map(
fix_diff, fix_diff,
task_stage=task_stage, task_stage=task_stage,
executor=executor, executor=executor,
base_dir=base_dir, task_root=task_root,
task_path=task_path,
), ),
task_stage.diff, task_stage.diff,
), ),
@ -159,12 +162,22 @@ def fix_diff(
diff_parser: result.Parser, diff_parser: result.Parser,
task_stage: task.Stage, task_stage: task.Stage,
executor: result.Executor, executor: result.Executor,
base_dir: Path, task_root: Path,
task_path: Path,
) -> None: ) -> None:
base_dir = JOJ3_CONFIG_ROOT / task_path.parent
valid_cases = ( valid_cases = (
(case, task_stage.cases[case]) (case, task_stage.cases[case])
for case in task_stage.cases for case in task_stage.cases
if case not in task_stage.skip and case in task_stage.cases if case not in task_stage.skip
)
testcases = get_testcases(task_root, task_path)
default_cases = sorted(
[
case
for case in testcases
if any(case.endswith(other) for other in task_stage.cases)
]
) )
stage_cases = [] stage_cases = []
parser_cases = [] parser_cases = []
@ -203,5 +216,33 @@ def fix_diff(
] ]
) )
parser_cases.append(parser_case) parser_cases.append(parser_case)
for case in default_cases:
cmd = result.OptionalCmd(
stdin=result.LocalFile(src=str(base_dir / f"{case}.in"))
)
stage_cases.append(cmd)
parser_case = result.DiffCasesConfig(
outputs=[
result.DiffOutputConfig(
score=const.DEFAULT_CASE_SCORE,
file_name="stdout",
answer_path=str(base_dir / f"{case}.out"),
)
]
)
parser_cases.append(parser_case)
executor.with_.cases = stage_cases executor.with_.cases = stage_cases
diff_parser.with_ = result.DiffConfig(name="diff", cases=parser_cases) diff_parser.with_ = result.DiffConfig(name="diff", cases=parser_cases)
def get_testcases(
task_root: Path, task_path: Path
) -> Set[str]: # basedir here should be task_conf.root / task_conf.path
testcases = set()
for testcases_path in (task_root / task_path).parent.glob("**/*.in"):
testcases.add(
str(
testcases_path.relative_to((task_root / task_path).parent)
).removesuffix(".in")
)
return testcases

View File

View File

View File

View File

View File

View File

View File

@ -75,6 +75,60 @@
"cpuLimit": 2000000000, "cpuLimit": 2000000000,
"clockLimit": 4000000000, "clockLimit": 4000000000,
"memoryLimit": 4194304 "memoryLimit": 4194304
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/case9.in"
},
"memoryLimit": 268435456
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/case11.in"
},
"memoryLimit": 268435456
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/case10.in"
},
"memoryLimit": 268435456
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/case5.in"
},
"memoryLimit": 268435456
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/case0.in"
}
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/case1.in"
}
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/case9.in"
}
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/task1/case5.in"
}
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/task1/subtask1/case10.in"
}
},
{
"stdin": {
"src": "/home/tt/.config/joj/diff/task1/subtask1/case11.in"
}
} }
] ]
} }
@ -85,6 +139,78 @@
"with": { "with": {
"name": "diff", "name": "diff",
"cases": [ "cases": [
{
"outputs": [
{
"score": 5,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/case0.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
},
{
"outputs": [
{
"score": 123214122421,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/case1.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
},
{
"outputs": [
{
"score": 1232131,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/case9.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
},
{
"outputs": [
{
"score": 92321,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/case11.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
},
{
"outputs": [
{
"score": 823131,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/case10.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
},
{
"outputs": [
{
"score": 2590,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/case5.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
},
{ {
"outputs": [ "outputs": [
{ {
@ -108,6 +234,54 @@
"compareSpace": false "compareSpace": false
} }
] ]
},
{
"outputs": [
{
"score": 5,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/case9.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
},
{
"outputs": [
{
"score": 5,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/task1/case5.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
},
{
"outputs": [
{
"score": 5,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/task1/subtask1/case10.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
},
{
"outputs": [
{
"score": 5,
"fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/task1/subtask1/case11.out",
"forceQuitOnDiff": false,
"alwaysHide": false,
"compareSpace": false
}
]
} }
] ]
} }

View File

@ -23,10 +23,18 @@ case0.diff.output.ignore_spaces = true
#case0.command = "./h7/build/ex2" #case0.command = "./h7/build/ex2"
case0.in = "case0.in" case0.in = "case0.in"
case1.diff.output.score = 5 case1.diff.output.score = 123214122421
case1.limit.cpu = "2s" case1.limit.cpu = "2s"
case1.limit.mem = "4m" case1.limit.mem = "4m"
case1.diff.output.ignore_spaces = true case1.diff.output.ignore_spaces = true
#case1.limit.stdout = 8 #case1.limit.stdout = 8
#case1.command = "./h7/build/ex2" #case1.command = "./h7/build/ex2"
case1.in = "case1.in" case1.in = "case1.in"
case9.diff.output.score = 1232131
case11.diff.output.score = 92321
case10.diff.output.score = 823131
case5.diff.output.score = 2590

View File

View File

View File

View File

View File

View File

View File

View File