测试运行完全指南:从 `./x test` 全量套件到远程设备、模拟器与 WebAssembly 测试)
Rust 编译器rustc测试运行完全指南从./x test全量套件到远程设备、模拟器与 WebAssembly 测试【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust本指南基于 rustc 官方开发指南rustc-dev-guide中“Running tests”章节系统讲解在 rust-lang/rust 源码仓库中运行测试的全部方式包括全量测试、按测试套件/子目录/单文件筛选、--bless更新参考输出、--pass与 compare-mode 高级模式以及在远程机器、QEMU 模拟器、iOS 模拟器和 wasm32-wasip1WASI上执行测试的完整配置流程。读完本文你将掌握 rustc 本地开发中最常用的测试命令组合并理解其背后的 compiletest 测试框架实现原理。一、全量测试./x test与其代价在仓库根目录包含x.py的位置运行以下命令即可执行整个测试集合./x test但请注意本地开发中几乎不应该运行全量测试因为它耗时极长。./x test会先构建 stage 1 编译器然后运行整个测试套件——它不仅包含tests/目录下的 compiletest 测试还包含library/、compiler/、src/tools/中的包级测试#[test]单元测试等更多内容。经验法则通常你只想运行预期能覆盖你改动的那些测试子集甚至比子集更小的一组测试。PR CI 只跑部分测试集合而 merge queue CIbors才会跑全部测试集合。测试结果缓存与强制重跑测试结果会被缓存此前已通过的测试在后续运行中会被ignored跳过。每个测试的 stdout/stderr 内容以及时间戳文件位于build/target-tuple/test/目录下target-tuple为目标三元组如x86_64-unknown-linux-gnu。如果测试运行器未能察觉源文件的改动可以用--force-rerun强制重跑./x test tests/ui --force-rerun该选项也可以作为--test-args的子参数传递见下文“单个测试”章节。在 bootstrap 层面x test直接接受--force-rerun等公共参数。外部依赖注意事项部分测试套件依赖外部程序尤其是debuginfo 测试某些 debuginfo 测试需要支持 Python 的 gdb。你可以在 gdb 内执行python命令验证输入python回车后键入print(hi)再按CTRLD执行。如果是从源码构建 gdb需要以--with-pythonpath-to-python-binary配置。从源码层面看compiletest 是 rustc 测试套件的主测试框架harness它负责组织成千上万的测试并支持并行执行。所有测试套件的模式如Ui、DebugInfo、Incremental、RunMake等都定义在 src/tools/compiletest/src/common.rs 的TestMode枚举中——Ui ui、DebugInfo debuginfo等字符串与命令行中传入的路径一一对应这正是./x test tests/ui、./x test tests/debuginfo能被识别的底层机制。二、运行测试子集本地开发核心操作2.1 UI 冒烟测试修改 rustc 后最常用的“冒烟测试”是运行ui测试套件对应 tests/ui 目录./x test tests/ui2.2 按任务选择测试套件测试套件的选择是灵活的应以你的任务为准。例如./x test tests/debuginfo2.3 按子目录过滤任何测试套件下都可以把子目录作为过滤器传给./x test./x test tests/ui/const-genericsMSYS2 用户注意在 MSYS2 环境下路径处理比较特殊./x test既无法识别tests/ui/const-generics也无法识别tests\ui\const-generics。解决办法是用--test-args传参./x test ui --test-argstests/ui/const-generics2.4 运行单个测试文件直接传入文件路径即可./x test tests/ui/const-generics/const-test.rs注意x目前还不支持通过传入文件路径来运行单个工具tool测试此时必须使用--test-args见下文例如./x test src/tools/miri --test-args tests/fail/uninit/padding-enum.rs三、tidy 与标准库测试的组合运行3.1 只运行 tidy 脚本./x test tidytidy 负责检查代码风格、目录文件数量限制、revsion 名称一致性等仓库级约束相关实现见 src/tools/tidy。3.2 在标准库上运行测试stage 0./x test --stage 0 library/std注意这只测试std。如果要测试core或其他 crate必须显式指定例如./x test --stage 0 library/core。3.3 同时运行 tidy 与标准库测试./x test --stage 0 tidy library/std3.4 用 stage 1 编译器测试标准库./x test --stage 1 library/std通过显式列出要运行的测试套件可以避免为没有改动的组件白白跑测试。但要注意bors 只运行完整的 stage 2 构建下的测试因此 stage 1 下测试通常可行但存在一些限制。3.5 用 stage 2 编译器运行全部测试./x test --stage 2你几乎不需要在本地这样做——CI 会替你运行这些测试。四、编译器/标准库的单元测试你可能想对某个具体文件运行单元测试例如./x test compiler/rustc_data_structures/src/thin_vec/tests.rs但很遗憾这样是行不通的。正确做法是传入包目录再用--test-args过滤测试名./x test compiler/rustc_data_structures/ --test-args thin_vec--test-args的过滤语义来自标准 Rust 测试运行器即#[test]使用的同一个运行器它会筛选出名称中包含指定字符串的测试。五、运行单个测试individual test开发中最常见的需求是运行你要修复的那一个测试。除了前文提到的传入完整文件路径外也可以结合--test-args./x test tests/ui --test-args issue-1234在底层测试运行器调用的是标准 Rust 测试运行器因此上述命令等价于筛选名称中包含issue-1234的所有测试。这也意味着--test-args非常适合运行一组相关联的测试例如同一 issue 派生出的多个测试。compiletest 本身也接受通过--test-args或--后置方式传递参数例如./x test --test-args --force-rerun ./x test -- --force-rerunbootstrap 还会直接透传一些常用参数x test --no-capture --force-rerun --run --pass。compiletest 会尽量避免在相关产物主要是编译器本身未变化时重复运行测试--force-rerun正是用来打破这种缓存的。六、给测试中的 rustc 传递额外参数有时需要在开发不稳定特性时例如使用-Z标志给测试中的编译器传参而又不想动用RUSTFLAGS。此时使用--compiletest-rustc-args./x test tests/ui --compiletest-rustc-args-Zsome-unstable-flag该选项会把附加参数在构建测试时传给编译器。七、--bless更新参考文件如果你有意改变了编译器的输出或正在编写新测试可以给测试子命令传入--bless./x test tests/ui --bless它会自动调整tests/ui下所有测试的.stderr、.stdout或.fixed文件。同样可以结合--test-args your_test_name只针对特定测试执行与不带--bless时筛选方式一致./x test tests/ui --test-args issue-1234 --bless注意--bless只应在确认新输出正确后使用——它会把当前输出直接写成“预期输出”。对 UI 测试而言参考文件snapshot的命名规则为*test-name*.*revision*.*compare_mode*.*extension*详见 UI 测试文档 中的“Output comparison”一节。八、配置测试运行行为8.1rust.verbose-testsbootstrap.example.toml 提供了rust.verbose-tests选项示例配置位于该文件约 790 行rust.verbose-tests false # 默认每个测试打印一个点若为false默认值每个测试只打印一个点.若为true打印每个测试的名称它等价于 Rust 测试框架中的--quiet选项。8.2RUST_TEST_THREADS环境变量RUST_TEST_THREADS控制测试使用的并发线程数RUST_TEST_THREADS8 ./x test tests/ui九、--pass $mode强制通过模式通过型 UI 测试现在有三种模式check-pass、build-pass和run-pass。传入--pass $mode时这些测试会被强制以给定$mode运行——除非测试文件中存在// no-pass-override指令。例如把tests/ui中所有测试以check-pass方式运行./x test tests/ui --pass check通过--pass $mode可以显著缩短测试时间例如check-pass跳过 codegen 阶段。--pass只影响 UI 测试。各模式的语义check-pass 跳过 codegen、build-pass 编译链接但不运行、run-pass 运行且需退出码为 0详见 UI 测试文档中的 “Controlling pass/fail expectations” 一节。十、Compare modes在不同编译模式下对比输出UI 测试可能因编译器所处的“模式”不同而输出不同。例如使用 Polonius 模式时测试foo.rs会优先查找foo.polonius.stderr作为预期输出找不到时回退到常规的foo.stderr。运行方式./x test tests/ui --compare-modepolonius目前可用的 compare modes 包括定义于 compiletest 的CompareMode枚举见 src/tools/compiletest/src/common.rspolonius— 以-Zpoloniusnext运行next-solver— 以-Znext-solver使用下一代 trait solver 运行next-solver-coherence— 以-Znext-solvercoherence运行 coherence 检查split-dwarf/split-dwarf-single— 分别以-Csplit-debuginfounpacked/-Csplit-debuginfopacked运行。compare modes 与 revisions 是两回事运行./x test tests/ui会测试所有 revision而 compare modes 必须通过--compare-mode手动逐个运行。CI 中目前只有一个 Linux builder 使用 compare modetests/debuginfo套件使用split-dwarf模式。更多细节见 compiletest 文档中的 Compare modes 一节。十一、手动运行测试跳过框架有时手工运行更快大部分测试就是.rs文件在创建 rustup toolchain 之后可以直接rustc stage1 tests/ui/issue-1234.rs这快得多但并非总能行得通——例如某些测试包含指定编译器标志的指令directives或依赖其他 crate脱离这些选项后行为可能不一致。十二、在远程机器上运行测试测试可以在远程机器上执行例如为不同架构构建测试。机制是构建机上的remote-test-client把测试程序发送给运行在远程机器上的remote-test-server后者执行测试程序并把结果回传。remote-test-server提供的是未经认证的远程代码执行能力使用时必须谨慎。12.1 构建并部署 server先为远程机器构建remote-test-server以 RISC-V 为例./x build src/tools/remote-test-server --target riscv64gc-unknown-linux-gnu二进制产物位于./build/host/stage2-tools/$TARGET_ARCH/release/remote-test-server把它复制到远程机器上。在远程机器上运行$ ./remote-test-server --verbose --bind 0.0.0.0:12345 starting test server listening on 0.0.0.0:12345!这两个命令行参数--bind IP:PORT与-v/--verbose在 src/tools/remote-test-server/src/main.rs 中解析默认绑定地址为127.0.0.1:12345Android/Windows 平台默认0.0.0.0:12345默认端口 12345。安全警告把 server 绑定到0.0.0.0意味着所有能访问该机器的主机都可以在其上执行任意代码。强烈建议设置防火墙阻止外部访问 12345 端口或绑定更受限的 IP 地址。12.2 验证连通性用nc连接并发送ping\n应收到pong回复$ nc $REMOTE_IP 12345 ping pong这一协议同样在 src/tools/remote-test-server/src/main.rs 中实现收到ping时向 socket 写回pong。12.3 通过 x 运行远程测试设置TEST_DEVICE_ADDR环境变量后照常使用x。例如为 IP 为1.2.3.4的 RISC-V 机器运行ui测试export TEST_DEVICE_ADDR1.2.3.4:12345 ./x test tests/ui --target riscv64gc-unknown-linux-gnu如果 server 以--verbose启动测试机器上的输出大致如下[...] run /tmp/work/test1007/a run /tmp/work/test1008/a run /tmp/work/test1009/a [...]bootstrap 侧对remote-test-client的调用位于 src/bootstrap/src/core/build_steps/test.rs--remote-test-client参数传递工具路径。12.4 关键注意事项测试是在运行x的机器构建机上构建的而非远程机器无法成功构建的测试或ui测试产生错误构建输出可能在尚未运行于远程机器时就直接失败x无法连上remote-test-server时默认超时 30 分钟可通过环境变量TEST_DEVICE_CONNECT_TIMEOUT_SECONDS修改。十三、在模拟器/仿真环境中测试对于不易获取实机的架构部分平台通过模拟器测试。对标准库支持良好、且宿主机支持 TCP/IP 网络的架构可完全复用上文“远程机器测试”的流程——此时“远程机器”就是模拟器还有一组工具用于编排模拟器内的测试运行。arm-android、arm-unknown-linux-gnueabihf等平台已在 GitHub Actions 上配置为自动在仿真环境下跑测试。以 armhf-gnu 为例其 Docker 镜像见 src/ci/docker/host-x86_64/armhf-gnu/Dockerfile内置 QEMU 来模拟 ARM CPU。rust 源码树中自带的 remote-test-client 与 remote-test-server 负责把测试程序与库发送到模拟器、在模拟器内执行并读回结果。Docker 镜像启动remote-test-server构建工具用remote-test-client与之通信协调测试协调逻辑见 src/bootstrap/src/core/build_steps/test.rs。iOS/tvOS/watchOS/visionOS 模拟器可以把模拟器当作“远程”机器。一个有趣的细节是模拟器实例与宿主 macOS 共享网络因此可以使用回环地址127.0.0.1。完整流程如下# 为 iOS 模拟器构建测试服务端 ./x build src/tools/remote-test-server --target aarch64-apple-ios-sim # 若已有打开的模拟器实例从以下命令输出中复制设备 UUID xcrun simctl list devices booted UDID01234567-89AB-CDEF-0123-456789ABCDEF # 或者创建并启动新的模拟器实例 xcrun simctl list runtimes xcrun simctl list devicetypes UDID$(xcrun simctl create $CHOSEN_DEVICE_TYPE $CHOSEN_RUNTIME) xcrun simctl boot $UDID # 在 12345 端口启动运行器 xcrun simctl spawn $UDID ./build/host/stage2-tools/aarch64-apple-ios-sim/release/remote-test-server -v --bind 127.0.0.1:12345 # 在新终端中通过运行器执行测试 export TEST_DEVICE_ADDR127.0.0.1:12345 ./x test --host --target aarch64-apple-ios-sim --skip tests/debuginfo其中--skip tests/debuginfo是因为 debuginfo 测试可能需要在目标机上复制.dSYM目录才能工作目前尚未支持。十四、WASIwasm32-wasip1上的测试部分测试针对 wasm 目标。运行它们需要向x test传入目标./x test tests/ui --target wasm32-wasip1另外还需要wasi sdk按其官方说明安装以在本地获得 sysroot需确保 sdk 版本不低于 wasm32-wasip1 目标支持页 中指定的最低版本构建过程涉及一些耗时且产生大量 C 警告的 cmake 命令。然后在bootstrap.toml中指向 sysroot[target.wasm32-wasip1] wasi-root wasi-sdk location/build/sysroot/install/share/wasi-sysroot例如把 wasi-sdk git clone 到 rust 目录旁边时路径形如../wasi-sdk/build/....。配置完成后测试即可直接运行无需其他额外设置。十五、延伸阅读UI 测试详解测试结构、错误注解、rustfix、compare modescompiletest 测试框架总览测试套件、revisions、compare modes、并行前端测试代码的顶层定义TestMode / CompareMode 枚举远程测试服务端实现--bind、--verbose、ping/pong 协议远程测试客户端工具bootstrap 测试构建步骤remote-test-client 调用与测试套件编排测试运行相关配置项rust.verbose-tests【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考