编写和运行 Starnix 测试

本指南提供了有关如何针对 Starnix 运行和编写自动化测试的说明。

1. 运行现有测试

在 Starnix 中验证功能或重现 bug 的推荐方法是编写并运行 C++ 系统调用测试。这些测试位于 //src/starnix/tests/syscalls/cpp/ 中。

如需运行现有测试,请配置包含 Starnix 测试目标的 Fuchsia build:

  1. 配置 build:

    fx set workbench_eng.x64 \
        --with-test //src/starnix/tests/syscalls/cpp:starnix_syscalls_cpp_tests
  2. 构建 Fuchsia:

    fx build
  3. 启动模拟器(或连接 Fuchsia 设备)。例如,如需启动没有图形界面的模拟器,请执行以下操作:

    ffx emu start --headless

    如需了解更多选项,请参阅 Fuchsia 模拟器说明

  4. 运行测试:

    fx test starnix_syscalls_cpp_tests

2. 编写新测试

添加新的系统调用或内核功能时,请在 //src/starnix/tests/syscalls/cpp/ 目录中添加相应的测试。

以下部分介绍了如何编写这些测试:

针对 Linux 内核进行测试

Starnix 系统调用测试套件的目的是针对 Linux 内核对 Starnix 进行交叉测试。由于 Starnix 实现的是 Linux UAPI,因此在 Linux 宿主机上编译并运行完全相同的测试二进制文件,以验证对 Linux 行为的理解。然后,在 Fuchsia 上运行这些测试二进制文件,以验证 Starnix 的实现。

如果测试在针对宿主 Linux 内核运行时失败,则表明测试本身不正确或对 Linux 行为的假设有误。您必须先修复该测试,使其在 Linux 上通过,然后才能使用该测试来验证 Starnix。

如需编写新测试,请执行以下操作:

  1. 开发测试并针对主机 Linux 内核运行测试。确保您的 build 已配置为包含测试:

    fx set workbench_eng.x64 \
        --with-test //src/starnix/tests/syscalls/cpp:tests

    然后,在 Linux 主机上运行测试。主机测试目标名称与目标测试名称相同,但以 starnix_ 为前缀,以 _host 为后缀。例如,如需运行 hello_starnix_test,请执行以下操作:

    fx test starnix_hello_starnix_test_host

    反复运行测试,直到在主机 Linux 内核上通过率为 100%。

  2. 提交预期会失败的测试。如果 Starnix 中尚未完全实现该系统调用,则 Starnix 测试目标会失败。您应该使用测试预期添加预期失败(请参阅使用测试预期),并将测试套件作为基准提交,而不是等待系统调用完成。

  3. 在 Starnix 中实现相应功能。在 Linux 上通过测试后,开始在 Starnix 内核中实现系统调用。如需有关编写 Starnix 系统调用的指南,请参阅 Starnix 系统调用评分标准常见编码模式

  4. 针对 Starnix 运行测试。在连接 Fuchsia 设备或运行模拟器的情况下,运行测试:

    fx test hello_starnix_test

    迭代 Starnix 实现,直到测试通过。如果确实如此,请更新测试预期结果(请参阅使用测试预期结果),以移除预期失败。

使用测试预期

您在 Linux 宿主机上测试的某些系统调用可能尚未在 Starnix 中完全实现。如果测试在 Linux 上成功运行,但在 Starnix 上失败,则 Fuchsia build 将变为红色。Starnix 不会删除测试或等待系统调用完全构建完成,而是使用测试预期来明确记录哪些测试预期会失败。

  1. 找到预期文件:预期在 .json5 文件中定义(例如://src/starnix/tests/syscalls/cpp/expectations/syscalls_cpp_test.json5)。
  2. 添加失败预期:将失败测试块的名称添加到 expect_failure 列表中。

    // expectations/syscalls_cpp_test.json5
    {
        actions: [
            {
                type: "expect_failure",
                matchers: [
                    // TODO(https://fxbug.dev/12345): Implement new sys_xyz
                    "HelloStarnixTest.FailingTest",
                ],
            },
        ],
    }
    
  3. 提交测试套件:提交并提交包含失败预期结果的测试套件。这会将 Linux 行为确立为基准。

  4. 实现系统调用:在后续 CL 中,在 Starnix 中实现系统调用。

  5. 移除预期:当您的 Starnix 实现允许测试通过时,请从 .json5 文件中删除相应条目。现在,该测试将充当未来的回归防护措施。

示例:创建新测试

例如,如需创建名为 hello_starnix_test.cc 的新测试文件,以测试 Starnix 中尚未实现的系统调用,请执行以下操作:

  1. 创建 //src/starnix/tests/syscalls/cpp/hello_starnix_test.cc

    #include <gtest/gtest.h>
    
    namespace {
    
    TEST(HelloStarnixTest, Basic) {
      EXPECT_TRUE(true);
    }
    
    }  // namespace
    
  2. //src/starnix/tests/syscalls/cpp/expectations/syscalls_cpp_test.json5 中的测试添加失败预期:

    // ... inside the file's `expect_failure` block:
    {
        type: "expect_failure",
        matchers: [
            // ... existing expectations ...
            "HelloStarnixTest.Basic",
        ],
    }
    
  3. "hello_starnix_test" 添加到 //src/starnix/tests/syscalls/cpp/BUILD.gn 中的 syscall_tests 列表:

    syscall_tests = [
      # ... other tests ...
      "hello_starnix_test",
      # ...
    ]
    
  4. 构建更新后的测试软件包:

    fx build
  5. 在 Fuchsia 设备或模拟器运行的情况下,执行新测试:

    fx test hello_starnix_test

由于在 .json5 文件中添加了预期结果,因此测试运行程序预期测试会在 Starnix 上失败。构建将成功,并且测试运行将报告为通过。在 Starnix 中实现缺少的系统调用后,您可以从 .json5 文件中移除相应预期。

后续操作