测试和调试 Rust 代码

此页面说明如何在 Firefox 中测试和调试 Rust 代码。

构建文档 解释了如何将新的 Rust 代码添加到 Firefox。该 代码文档 解释了如何在 Firefox 中编写和使用 Rust 代码。

测试 Mozilla crate

Rust 代码将自然地作为系统测试(例如 Mochitests)的一部分进行测试。本节介绍了单元测试单个 Rust crate 的两种方法。应根据具体情况选择使用哪种方法。

Rust 测试

如果一个 Mozilla crate 具有“普通”Rust 测试(即 #[test] 使用 cargo test 运行的函数),您可以将 crate 的名称添加到 toolkit/library/rust/moz.build 中的 RUST_TESTS 中。(可以通过将 Cargo 特性添加到同一文件中的 RUST_TEST_FEATURES 中来为 Rust 测试激活它们。)

Rust 测试使用 ./mach rusttests 运行。它们在几个 rusttests 作业的自动化中运行,但并非在所有平台上都运行。

Rust 测试有一个主要限制:它们不能链接到 Gecko 符号。因此,Rust 测试不能用于使用 Gecko crate(如 nsstringxpcom)的 crate。

也可以在不同的 moz.build 文件中使用 RUST_TESTS。请参阅 testing/geckodriver/moz.buildgeckodriver 测试文档 以了解示例。

GTests

单元测试 Mozilla crate 的另一种方法是编写一个 GTest,它使用 FFI 调用 Rust 代码。这需要以下步骤。

  • 创建一个新的测试 crate,其名称与正在测试的 crate 的名称相同,并在末尾添加 -gtest 后缀。

  • 向测试 crate 中添加一个 Rust 文件、一个包含 GTest TEST() 函数的 C++ 文件(这些函数使用 FFI 调用 Rust 文件)、一个引用 Rust 文件的 Cargo.toml 文件和一个引用 C++ 文件的 moz.build 文件。

  • toolkit/library/gtest/rust/Cargo.toml 中的 [dependencies] 部分添加一个条目。

  • toolkit/library/gtest/rust/lib.rs 中添加一个 extern crate 条目。

请参阅 xpcom/rust/gtest/nsstring/ 以了解一个简单的示例。(请注意,该 moz.build 文件位于该 crate 的父目录中。)

Rust GTest 可以像任何其他 GTest 一样通过 ./mach gtest 运行,使用 C++ TEST() 函数作为起点。

与 Rust 测试不同,当需要链接到 Gecko 符号时,可以使用 GTests。

测试第三方 crate

通常我们不会运行第三方 crate 的测试。假设这些 crate 在其他地方已经得到了充分的测试。

调试 Rust 代码

理论上,Rust 代码的调试方式与 C++ 代码非常相似,可以使用标准工具(如 gdbrr 和 Microsoft Visual Studio 调试器)。实际上,体验可能会更差,因为可能会出现以下缺点。

  • 无法打印局部变量,即使在非优化构建中。

  • 无法调用泛型函数。

  • 缺少行号和堆栈帧。

  • 诸如 OptionVec 之类的基本类型的打印有时不是最佳的。如果在启动 gdb 时看到警告“Missing auto-load script at offset 0 in section .debug_gdb_scripts”,则 rust-gdb 包装器可能会提供更好的结果。

从 Rust 代码记录日志

Rust 日志记录

可以使用 RUST_LOG 环境变量(来自 env_logger crate)来启用从 Firefox 中的 Rust 代码到 stderr 的日志记录。可以使用 log crate 中的日志记录宏。按重要性排序,它们是:error!warn!info!debug!trace!

例如,要显示所有 info 级别或更高的日志消息,请运行

RUST_LOG=info firefox

还可以指定模块级日志记录,请参阅 文档,了解 env_logger crate 的详细信息。

要将日志记录限制为子进程,请使用 RUST_LOG_CHILD 而不是 RUST_LOG

Gecko 日志记录

Rust 日志记录也可以转发到 Gecko 日志记录器,以便通过 MOZ_LOGMOZ_LOG_FILE 进行捕获。

  • 在从 MOZ_LOG 解析模块时,包含 :: 的模块被认为是 Rust 模块。要记录顶级模块(如 neqo_transport)中的所有内容,请将其指定为 neqo_transport::*。例如

MOZ_LOG=timestamp,sync,nsHostResolver:5,neqo_transport::*:5,proxy:5 firefox
  • 从子模块记录日志时,允许使用 ::*,但不是必需的。因此,这两行是等效的

MOZ_LOG=timestamp,sync,neqo_transport::recovery:5 firefox
MOZ_LOG=timestamp,sync,neqo_transport::recovery::*:5 firefox
  • debug!trace! 日志不会出现在非调试构建中。这是由于我们在 log crate 中使用了 release_max_level_info 特性。

  • 同时使用 MOZ_LOGRUST_LOG 时,在 MOZ_LOG 中指定的模块不会出现在 RUST_LOG 中。