OJ 评测系统 / 第 19 课
测试数据怎样变成判题结果
追踪固定版本中的用例文件读取、stdin/stdout 执行、输出比较和终态映射,不把未实现的能力当成事实。
队列 Worker 已经把任务交给 InternalJudgeService;这节继续追踪它传给 JudgeEngine 的输入。题目记录提供 prefix、logicId、用例数量和资源限制。problemCases 根据配置的测试数据根目录定位 <prefix>/<logicId>/,依次读取 1.in、1.out,再读取下一编号,直到 problem.cases。输入与期望输出组成一个 JudgeCase,并以异步迭代器逐个交给引擎,因此代码不必一次把所有测试文件装进内存。
题目目录 /prefix/logicId/
1.in + 1.out → case 1 → 程序 stdin → stdout 与期望比较
2.in + 2.out → case 2 → ...
首个非 AC verdict → 保留为整次提交状态
读取不是“找不到文件就当空字符串”。目录需位于测试数据根目录内;文件解析真实路径后须仍在题目目录、是普通文件且不超过 1 MiB。读取使用 O_NOFOLLOW,UTF-8 解码采用 fatal 模式。缺文件、路径越界、类型或大小不合规、无效 UTF-8 都会报告测试数据不可用;没有有效用例也会失败。这些限制是读可信题目数据的边界,不是用户程序的判题输出。题目若配置 3 个 case,引擎会按编号依次读取 1、2、3,而不是通过目录扫描决定测试顺序;缺少 2.out 时不会跳过它继续假装判完。测试迭代器在引擎运行中抛出的错误会被包装成 SE 结果,再交给内部服务结算,不会误报成 WA;这条路径不保证额外产生 Worker 错误日志,应同时查看结果中的 error 字段。
沙箱与逐用例判定
引擎先准备用户程序;准备阶段出现沙箱 CE 会成为提交 CE 并记录编译错误。随后可选地准备题目配置的 checker。每个 case 都把 .in 内容作为程序输入,在题目和语言额度限制下运行;这里是逐个调用 program.run(test.input, limits),不是把整批测试拼成一个输入。运行结果 OK / RE / TLE / MLE / OLE / SE 映射为相应状态;代码也将取消映射为 SE 的内部映射值,但取消由专门分支抛出,不当普通 verdict 继续判。
没有 checker 时,只有沙箱 OK 才继续比较输出。比较规则是:按换行拆分、每行去掉末尾空白、删除末尾空行,之后逐行精确相等;行首空格仍然有意义。所以它不是忽略所有空白的比较。比如期望 "a \n" 与实际 "a\n\n" 在此规则下相等,但 " a\n" 与 "a\n" 不等。这是教学示例,说明规范化边界,并非执行用户代码。
若题目有 checkerCode,引擎将 input.txt、expected.txt、actual.txt 作为 checker 文件,并传入这些文件名参数。checker 退出码 0 判 AC,1 判 WA,2 判 PE;其余情况转 SE。源码确有可选 checker 路径,但不能据此推断所有 checker 类型或特殊判题协议。每个 case 记录 verdict、测得时间/内存、输出预览和信息;只在当前总状态仍为 AC 时,首个非 AC verdict 覆盖它,之后正常完成的用例不会把 WA 改成 AC。不过后续发生测试数据读取等基础设施异常时,引擎会返回 SE;“首个非 AC”规则适用于用例处理正常完成的情况。没有用例也会返回系统级错误路径。
要避免把状态名按常识扩写:本引擎明确支持 CE、WA、RE、TLE、MLE、OLE、AC、PE、SE 的路径。状态枚举还包含 CRLE 和 SC,但这里未由引擎的沙箱映射产生;不能声称此链路会判出它们。时间记录取观测到的运行 wall time,内存仅在沙箱报告时记录,不能误说一定有 CPU 时间或内存数据。
小练习
期望行是 " 42 "、实际行是 " 42",此引擎会判 WA 吗?若期望末尾多一个空行呢?
**答案:**不会因末尾空格判 WA,因为会去掉每行末尾空白;末尾空行也会被移除。若差异是行首空格,则仍会判不相等。以上按普通比较路径描述;若题目提供 checker,则由 checker 退出码决定结果。
去真实仓库看看
以下均固定到公开提交 de34b268e75f293e904d7734c194a4ff2467b7a8:
互动练习:按普通比较器的规则看输出
题目没有配置 checker。期望输出是数字 7 加换行;程序输出在 7 后多了一个空格再换行。按本课公开实现,这两份输出如何比较?
内部判题按题目 cases 顺序读取编号 .in/.out 文件,把输入交给沙箱并比较输出;用例处理正常完成时,首个非 AC verdict 决定总结果。