本月测试基础设施更新:2025 年 3 月刊
这是对 2025-03-11 至 2025-04-13 期间 rust-lang/rust 仓库1 测试基础设施变化的快速总结。
在此期间,compiletest 和 bootstrap 有一些重要变化,贡献者应予以了解。
和往常一样,如果您在使用我们的测试基础设施时遇到 bug 或用户体验问题,请提交 issue。如果我们不知道 bug 和小问题,就无法修复它们!
感谢所有为我们的测试基础设施做出贡献的人!
要点
compiletest
现在支持匹配下方行的诊断信息
以前,UI 错误注解可以匹配针对上方行 (//~^
) 或同一行 (//~
) 发出的诊断信息,但无法表达匹配针对下方行发出的诊断信息。根据 #139100,测试编写者现在可以使用 //~v
来匹配针对下方行发出的诊断信息。这对于例如解析器测试特别有用,在这些测试中,测试文件可能会触发词法分析器/解析器诊断信息,并且测试文件本身在语法上是无效的(因此不能在之后使用注释来匹配之前的行)。
示例
// tests/ui/parser/issues/issue-103451.rs
//~vv ERROR this file contains an unclosed delimiter
compiletest
现在支持对与主测试文件无关行信息的诊断信息进行精确和穷尽匹配
以前,测试编写者必须借助于 //@ error-pattern
来匹配与主测试文件没有关联行信息的诊断信息。现在,测试编写者可以使用 //~? DIAGNOSTIC_KIND diagnostic_message
来匹配诊断类别为 DIAGNOSTIC_KIND
(例如 ERROR
或 HELP
)且消息为 diagnostic_message
的诊断信息。参见 compiletest: Support matching on diagnostics without a span #138865。//~?
可以出现在测试文件的任意行,但通常习惯性地放在末尾。
示例
// tests/ui/invalid-module-declaration/invalid-module-declaration.rs
//~? ERROR file not found for module `baz`
与 //@ error-pattern
相比,//~?
错误注解是精确的和穷尽的。
- 精确的:
//~?
注解不会匹配那些带有行信息的诊断信息。 - 穷尽的:如果主测试文件中存在多个缺乏行信息的诊断信息,那么所有这些诊断信息都需要使用
//~?
进行注解。
总的来说,//~?
有助于防止意外地忽略主测试文件中没有关联行信息的诊断信息。
//@ error-pattern
对于例如没有特定 span 的运行时错误消息,或由于多行平台特定诊断信息而需要不精确匹配的编译时消息仍然有用。在合适的地方,应优先使用 //~?
。
值得关注的变化
本节旨在作为“兼容性说明”,但面向人工测试编写者。
compiletest
使用 stage 0 的 libtest
为准备 stage 0 std 重大调整,现在可以为 根据 stage 0 std 重大调整,构建库树将需要 stage 1 编译器。compiletest
有些奇怪,因为它目前依赖于树内的 libtest——这意味着随着 stage 0 std 的重大调整,对编译器树的更改将需要重建 compiletest
,从而给编译器开发周期带来更多麻烦。为了缓解这个问题,bootstrap 现在支持一个新的配置选项,可以将 compiletest
切换为依赖 stage 0 libtest 而不是树内的 libtest,这样对 compiler/
树的更改就不会导致 compiletest
重建。
[]
= true
请注意,作为权衡,我们在 PR CI 中会检查这个 force-stage0-libtest 配置。这意味着在升级 stage 0 编译器之前,libtest 可能存在修改的时间窗口,这可能需要修改 libtest 的 PR 作者根据情况在依赖 libtest 编程 API 的 compiletest 部分添加 cfg(bootstrap)
/cfg(not(bootstrap))
。这是基于 libtest 编程 API 更改相对不频繁的假设进行的。如果事实证明这是一个重大负担,bootstrap 团队愿意重新考虑此方案。
请注意,从长远来看,我们希望摆脱对树内 libtest 的依赖(既是为了使这种变通方法不再必要,也是为了更好地控制测试执行)。
config.toml
已重命名为 bootstrap.toml
bootstrap 的 以前,bootstrap 在 checkout 根目录下使用 config.toml
作为配置文件。这可能令人困惑,因为 Cargo 也使用 config.toml
作为其配置文件名。现在,bootstrap 改为使用 bootstrap.toml
作为配置文件名。示例配置文件 config.example.toml
也已重命名为 bootstrap.example.toml
。
config.toml
作为备用配置文件被临时接受,以缓解不同 checkout 之间的迁移麻烦,但将来会被淘汰。
compiletest
现在强制对诊断类别进行更严格的解析
以前,compiletest
对诊断类别(即错误注解中的 ERROR
/HELP
部分)的大小写要求非常宽松。这意味着诸如以下形式的注解也曾被接受:
//~ Error xxx
//~ Error: xxx
它们也被接受了,与更常见的 //~ ERROR
或 //~ error
形式相比。
与更常见的 //~ ERROR
或 //~ error
形式相比,以前也接受了。最终,我们希望将错误注解规范化为一种形式。为了使这一转变不那么突然,作为中间步骤,compiletest 现在将
- 强制要求错误注解诊断类别必须全大写(例如
ERROR
)或全小写(例如error
)。像//~ Error
这样的混合大小写现在将被拒绝。 - 空诊断(例如空的
//~ NOTE
)将不再被静默忽略。这些表示 rustc 发出了应该修复的愚蠢的空诊断说明。
compiletest
现在强制要求即使使用了 //@ error-pattern
指令,也必须提供错误注解
与之前 //~?
的改进相关,compiletest 现在也会在使用 //@ error-pattern
的测试中检查是否存在错误注解(//~
),以最大限度地降低意外忽略诊断信息的风险,包括那些与主测试文件没有关联行信息的诊断信息。。
在特殊情况下,测试编写者可以通过 //@ compile-flags: --error-format=human
选择不进行错误注解检查。
compiletest
现在允许通过新的指令 //@ dont-require-annotations: DIAGNOSTIC_KIND
选择性地允许对特定诊断类别进行非穷尽匹配
compiletest
现在有一个新指令 //@ dont-require-annotations: DIAGNOSTIC_KIND
(其中 DIAGNOSTIC_KIND
例如可以是 ERROR
/HELP
/SUGGESTION
),允许选择性地对指定的 DIAGNOSTIC_KIND
进行非穷尽匹配。这包括 ERROR
诊断类别,以前无法选择退出穷尽匹配。
应谨慎并少量使用此指令。
compiletest
不再接受 {true, false}
作为修订名称
在支持修订的测试套件中,以前接受 //@ revisions: true
和 //@ revisions: false
作为修订名称。然而,这令人困惑,因为它们会自动注册为 --cfg={true,false}
传递给 rustc
,但测试编写者必须在测试中使用 cfg(r#true)
和 cfg(r#false)
。因此,compiletest 不再允许使用 {true,false}
作为修订名称。
compiletest
现在支持 //@ needs-crate-type
指令
测试编写者现在可以使用 //@ needs-crate-type
指令,根据目标平台是否支持所有必需的 crate 类型来限制测试执行。
该指令接受一个逗号分隔的有效 crate 类型列表,这些类型是 rustc --crate-type
标志接受的。例如://@ needs-crate-type: dylib, proc-macro
。
示例
// This test would be ignored on targets e.g. `wasm32-unknown-unknown` that
// do not (currently) support `dylib` crate type.
//@ needs-crate-type: dylib
//@ compile-flags: --crate-type=dylib
compiletest
现在会修剪传递给 //@ {unset,}-{exec,rustc}-env
指令的环境变量名中的空白字符
compiletest
有一个由来已久的怪癖,即
//@ rustc-env: RUSTC_BOOTSTRAP=1
与以下形式不同
//@ rustc-env:RUSTC_BOOTSTRAP=1
其中前者被视为 ⌴RUSTC_BOOTSTRAP
。//@ exec-env
和 //@ unset-{exec,rustc}-env
指令也存在同样的问题。
现在这个问题已经修复了。compiletest
现在会修剪环境变量名中的空白字符,因此前面提到的形式现在是等效的
//@ rustc-env: RUSTC_BOOTSTRAP=1
//@ rustc-env:RUSTC_BOOTSTRAP=1
都对应于环境变量名 RUSTC_BOOTSTRAP
。
compiletest
现在强制要求必须使用 //@ edition
指令而不是 //@ compile-flags: --edition=xxx
compiletest
有一个 --edition
标志,允许更改运行测试时使用的默认版次 (edition)。然而,目前没有测试套件在使用非 2015 版次时能够通过,但将来我们希望能够跨所有版次运行测试套件,以确保对所有版次都有良好的测试覆盖(受进一步设计考虑的影响)。
为了使这成为可能,我们首先需要确保 compiletest
的 --edition
覆盖标志能够正常工作。这意味着现在,compiletest
将拒绝通过 //@ compile-flags
传递的 rustc --edition
标志,转而支持 //@ edition
指令,以确保 compiletest
可以覆盖测试的版次。
如果测试作者需要测试 rustc --edition
标志本身的行为,应使用 run-make
测试。
即将到来的变化
以下更改尚未合并,但将在不久的将来合并,或者我们正在积极推进这些工作。
compiletest
即将也将把 SUGGESTION
错误注解视为病毒式传播(viral)
以前,如果测试编写者指定 //~ HELP
或 //~ NOTE
,那么 compiletest
会将它们视为病毒式传播(viral)——如果指定了其中一个,则所有同类别的 HELP
/NOTE
诊断信息都必须穷尽式地指定。为了保持一致性并更严格地检查编译器发出的诊断信息,我们计划也将 //~ SUGGESTION
注解视为病毒式传播(viral)。
这种病毒式穷尽匹配行为可以通过新引入的 //@ dont-require-annotations: SUGGESTION
选择退出(有关此新指令的说明,请参阅值得关注的变化部分)。
run-make
测试(以及 run-make-support
库)很快将默认进行交叉编译以针对目标平台
我们正在努力修复 run-make
测试套件和 run-make-support
库,使其默认能正确测试交叉编译目标平台。如果测试只能在主机上运行,测试作者仍然可以使用 //@ ignore-cross-compile
。
参见 https://github.com/rust-lang/rust/pull/138066 以及相关的进行中的工作。
PR 列表
改进
- bootstrap: 将
config.toml
更改为bootstrap.toml
- bootstrap: 使
compiletest
可以使用 stage0 libtest - citool: 将 bootstrap 步骤差异添加到 CI 作业分析中
- citool: 在合并后报告中添加作业摘要链接
- citool: 改进合并后工作流程
- compiletest: 指出哪个测试未能通过
COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS
断言 - compiletest: 支持匹配没有 span 的诊断信息
- compiletest: 如果被强制,报告 compiletest 通过模式
- compiletest: 支持匹配下方行的诊断信息
- compiletest: 即使指定了
error-pattern
,也要求//~
注解 - compiletest: 引入
compiletest
指令//@ needs-crate-type
- compiletest: 对诊断类别进行更严格的解析
- compiletest: 添加指令
//@ dont-require-annotations
修复
- bootstrap: 仅为
{incremental,ui}
测试套件构建rust_test_helpers
- compiletest: 更新
compiletest
的has_asm_support
以匹配rustc
- compiletest: 更新错误消息
- compiletest: 拒绝
{true,false}
作为修订名称 - compiletest: 修剪环境变量名中的空白字符
- compiletest: 修复使用
--test-args=--edition=2015
运行compiletest
时的中断问题 - run-make: 在
run-make
测试中重新引入远程测试支持 - run-make-support: 计算目标平台而不是主机平台的 artifact 名称
清理
- compiletest: 封装所有涉及 libtest 的代码
- compiletest: 排序依赖并移除对
anyhow
的依赖 - compiletest: 移除
--logfile
标志 - compiletest: 将 compiletest 更新到 Edition 2024
- compiletest: 不对
compose_and_run
使用字符串路径
文档更新
请注意,由于 rustc-dev-guide 成为了 rust-lang/rust 中的一个 josh 子树,一些文档更新是伴随 rust-lang/rust PR 本身进行的(此处不再重复列出)。
- rustc-dev-guide: 测试指令可以出现在文件中的任何位置
- rustc-dev-guide: 添加一些关于
rustdoc-gui
测试套件的链接 - rustc-dev-guide: 稍微重新组织生态系统测试,创建 codegen 后端测试页面的占位符
- rustc-dev-guide: 添加关于
rustdoc
测试套件的新章节 - rustc-dev-guide: 添加 Fuchsia ping group 页面并在集成测试页面中提及 Fuchsia 和 RfL ping group
- rustc-dev-guide: 提及
//@ known-bug
测试指令接受参数 - rustc-dev-guide: 清理“运行测试”章节
- rustc-dev-guide: 移除关于
no-system-llvm
的文档 - rustc-dev-guide: 修复
ui.md
中指向rustc_*
测试属性的链接