失败问题排查

本指南概述了 排查 Fuchsia (CTF) 测试失败问题和行走问题 以及造成 CL 提交中断的一些原因。

CTF 测试会对版本分支上冻结的软件与 软件在 fuchsia.gitmain 分支上构建而成。如果这些断言失败 因为不兼容,将阻止提交 CL。

CTF 的目的不是禁止破坏兼容性的更改, 以便及时发现此类破坏情况 。

场景

每种情况都会带来真正的兼容性问题,导致 CTF 测试失败,并阻止 CL 提交。兼容性问题可能非常简单 因为更改测试所使用的现有 FIDL 协议的返回值。周三 假定每种场景都具有以下通用情境(如需了解详情,请参阅动机) 测试场景):

  • FIDL 客户端被冻结为 F19 上的 ctf_fuchsia_package 调用 echo-service-tests。这会连接到 FIDL 协议,并声明 响应。

  • generate_ctf_tests.gni 包含一条规则 template("generate_echo-service-tests"),用于合并传入客户端 包含基于 main 构建的服务器软件包。(请参阅用户指南 详情)。

  • 客户端在服务器上调用一个名为 Echo 的方法,该方法将 字符串并在输出中返回一个字符串,如下所示:

    auto server_proxy = connect_to_named_protocol("my_protocol.EchoService");
    ASSERT_EQ(
      server_proxy.echo("Hello"),
      "Hello"
    );
    

假设我们想将 echo 的行为改为返回小写的 其所传递的字符串的表示法。我们可以在 main 上将测试更新为 执行以下操作:

ASSERT_EQ(
  server_proxy.echo("Hello"),
  "hello"
);

这对于 ctf_in_development 测试来说会通过,但在具有 旧断言针对这个新服务器运行,测试将失败:

FAILURE: "hello" != "Hello"

CL 提交现已阻止,后续路径取决于 这个中断。

无意间的破坏性更改 - 软过渡

在这种情况下,我们无意破坏兼容性。这种情况就属于 预构建组件或树外组件依赖于旧行为。运行这些 针对包含 Echo 更改的平台运行组件会导致 意外行为。

在这种情况下,安全的做法是软过渡到新行为:

  1. 引入了具有新行为的新方法:

    protocol Echo {
     // ...
     @available(added=20)
     EchoLowercase(struct {input string}) -> (string);
    };
    
  2. 将旧方法标记为已弃用或已移除(可选):

    protocol Echo {
     @available(removed=20)
     Echo(/* ... */) -> (string);
     // ...
    };
    
  3. 在服务器中实现新方法。

  4. 更改 fuchsia.git 调用方以使用新方法而非旧方法。

服务器必须同时支持这两种方法,直到旧版 API 级别 方法不再受支持。在上面的示例中,这将是 F19 不受支持,因为在 F20 中旧的 Echo 方法已被移除(由于 @available(removed=20))。

故意的破坏性更改 - 版本分支中的更改测试

在这种情况下,兼容性中断是有意为之。对于 几个原因:

  • 我们想要改变 API 的行为,并且接受 预建或树外客户端中断。这是真正例 我们会明确确认

  • 发生变化的行为是测试内部的,不代表 对 SDK Surface 本身的破坏性变化这是一个假正例 测试失败,因为我们捕获的是不兼容的测试,而不是 SDK 不兼容。

无论哪种情况,解决方法都是修改版本分支,以便测试 针对更改前或更改后代码运行不再失败 日期:main

更改可按如下方式进行:

  1. 查看版本分支:

    fx sync-to refs/heads/releases/f19
    
  2. 修改断言,使其接受两个输出(或注释掉):

    EXPECT_THAT(
     server_proxy.echo("Hello"),
     AnyOf(Eq("Hello"), Eq("hello"))
    );
    
  3. 测试您的更改是否适用于 main(见下文)

  4. 提交并推送更改:

    git push origin HEAD:refs/for/releases/f19
    
  5. 提交 CL 进行审核并提交。

  6. 传递被阻止的 CL。

  7. 清理版本分支,仅接受新行为(可选)。

    EXPECT_EQ(
      server_proxy.echo("Hello"),
      "hello"
    );
    

您可以测试所做的更改在应用到 main 后是否有效。您需要两个 Fuchsia 的检出,一个同步到版本分支,另一个同步到 main。 请执行以下操作:

  1. 版本分支签出中,构建新的 CTF 软件包。

    fx set core.x64 --with-tests //sdk/ctf
    fx build
    
  2. main 结账时,构建 CTF 发布测试。

    fx set core.x64 --with-tests //sdk/ctf/release:tests
    fx build
    
  3. 版本分支的输出目录中,复制构建的 CTF 捆绑到 main 代码库。

    cp -fR \
    $RELEASE_BRANCH_FUCHSIA_OUT_DIR/cts/* \
    $MAIN_BRANCH_FUCHSIA_DIR/prebuilt/ctf/f19/linux-x64/cts/
    
  4. 重新构建 main 检出,重新分配设备或重启模拟器,然后运行 测试。

  5. 测试通过后,还原到 CIPD 的版本。

    jiri run-hooks
    

示例:SDK 兼容性中断(真正例)

此 CL 严重破坏了兼容性, fuchsia.ui.policy.MediaButtonsListener 协议。向 包含正确版本控制注释的 MediaButtonsEvent,但是, 更改上一个参数 实施。F19 的 CTF 测试发现了这种不兼容情况:

../../src/ui/tests/conformance_input_tests/media-button-validator.cc:243: Failure
Expected equality of these values:
  ToString(listener.events_received()[0])
    Which is: "\n    volume: 0\n    mic_mute: 0\n    pause: 0\n    camera_disable: 0\n    power: 0"
  ToString(MakePowerEvent())
    Which is: "\n    volume: 0\n    mic_mute: 0\n    pause: 0\n    camera_disable: 0\n    power: 1"

我们确定,此更改是可接受的,因为没有任何 以 API 级别 19 为目标平台的此协议的预构建客户端。

CL:10449941049612 为 F19 版本择优挑选 创建分支。这些更改在 CTF 中 版本发布日期为 main,因此原始 CL 是不经修改提交的。

示例:自动化测试框架兼容性损坏(假正例)

此 CLfuchsia.tracing.controller.Controller 协议。StopTracing 方法原为 已 flexible,并且将方法从 strict 更改为 flexible 不会 ABI 安全性。

WLAN hw-sim CTF 测试在此变更下会崩溃,因为它声明: 跟踪会在测试期间成功停止,即使这与 经过测试的 Wi-Fi 协议,对正确性而言不是必需的。这是一个假的 出现积极的兼容性失败,因为它只影响自动化测试框架本身。

此 CL 用于将跟踪故障转变为 警告而不是致命的断言,此更改是针对 F18 版本分支。将更改发布到用于 main - 提交原始 CL 时未做任何修改。

有意放弃特定测试对某个 API 级别的支持

在此场景中,我们想明确停止支持在 Google Cloud 上的某个 API 级别 测试基础。version_history.json 提供 规范的支持 API 级别列出,但出于以下原因,我们需要 特定 API 级别上特定协议的 Drop 兼容性保证。 例如,对某个非关键子系统进行了重大重构,其中破坏了旧系统 是否接受。

在本例中,我们可以修改解冻过程,以跳过针对 我们希望降低的 API 级别:

  1. 修改 main 分支上的 generate_ctf_tests.gni 有条件地跳过解冻测试。

    template("generate_my-service-tests") {
     forward_variables_from(invoker, [ "test_info" ])
     if (defined(invoker.api_level) && invoker.api_level == "15") {
       # Do not thaw this test for F15
       not_needed([ "test_info" ])
       group(target_name) {
       }
     } else {
       // ...
     }
    }
    
  2. 提交并提交此 CL。

上面的示例跳过了在 F15 时解冻整个工件。如果您不想 如需跳过所有测试,请参阅上一部分了解如何跳过单个测试 与版本分支相关的案例

示例:对诊断子系统进行重大重构

此 CL 删除了对 DirectoryReady 的支持 组件事件,该事件已不再使用。它的主要用途是 从组件获取诊断数据(现已使用 fuchsia.inspect.InspectSink) 协议。

遗憾的是,在 F15 中构建的组件仍然使用 DirectoryReady,并且此行为的所有诊断 CTF 测试都将在以下条件下失败: main

幸运的是,没有我们需要针对 F15 的预构建组件 来获取诊断数据。已提交 CL 以将其全部停用 源自 F15 的诊断 CTF 测试。