Fuchsia 兼容性测试

Fuchsia 兼容性测试 (CTF) 是一种 与 Fuchsia 对比发布不同版本的预构建 Fuchsia 软件 检测兼容性问题。

CTF 测试可确保客户端在之前的发布里程碑处冻结 与应用编程接口 (API) 兼容,并且 通过 。它会模拟 搭载的 Fuchsia 平台会破坏预编译的客户端。

CTF 基本上由以下几个部分组成:

  • 一种机制,用于冻结版本分支上的工件并使用 测试这些工件
  • 一组用于选择要冻结的制品的构建规则,以及一组 简化构建规则的解冻过程, main 中。
  • 一组测试使用这些构建规则来测试 具有最新平台 surface 的旧客户端代码。
  • 这套测试的覆盖率 系统会测试 FIDL 方法和系统调用,以确保 版本。

CTF 最初提议为 RFC 0015, 代码位于 //sdk/ctf

设计初衷

Fuchsia 平台定义了一个表面区域,由许多 Fuchsia SDK 中提供的 FIDL 协议。开发者可以 下载并使用 Fuchsia SDK 来编写针对 Fuchsia 系统的软件 在特定 API 级别使用。

随着 Fuchsia 平台平台的不断演变, 通过 FIDL 协议中的可用性注释表示:

protocol Entry {
  @available(added=12)
  SetValue(struct { value string; });

  @available(added=20)
  GetTimestamp() -> (struct { timestamp int64; });

  @available(added=13, removed=20)
  Encrypt();
};

在上面的示例中,协议 Entry 有三个方法:

  • SetValue:在 API 级别 12 中添加
  • GetTimestamp,在 API 级别 20 中添加
  • Encrypt:在 API 级别 13 中添加,但在 API 级别移除 20。

使用 Fuchsia SDK 构建的组件必须声明 API 级别 它们是目标,这会影响可见的定义。请考虑以下事项 场景:

  • 组件是以 API 级别 19 为目标构建的: <ph type="x-smartling-placeholder">
      </ph>
    • 可以看到SetValueEncrypt
    • GetTimestamp 不存在,因为在 API 级别 19 时尚不存在。
  • 组件是以 API 级别 21 为目标构建的: <ph type="x-smartling-placeholder">
      </ph>
    • 可以看到SetValueGetTimestamp
    • Encrypt 不存在,因为它已在 API 级别 20 中移除。

目前,并非所有 API 级别都受 Fuchsia 平台支持。 已选中支持的 API 级别的规范化列表 添加到 fuchsia.git 代码库中,用于确定使用哪个 API 级别在 Fuchsia SDK 版本中受支持。

以支持的 API 级别为目标平台可确保客户端能够连接 只向受支持且能保证实现的协议 但并不能保证平台的行为 将与针对该 API 的预构建组件保持一致 。

确保一致的行为对于支持组件非常重要 在 fuchsia.git 代码库之外构建的应用,尤其是在 这些组件会下载为预构建的二进制文件,然后汇编到 商品图片。

示例:兼容性问题

请参考上述 Entry 协议的简化版本:

protocol Entry {
  @available(added=20)
  GetTimestamp() -> (struct { timestamp int64; });
};

GetTimestamp 方法会返回 Entry 的时间戳(以秒为单位)。

我们可以按如下方式对其进行测试:

TEST(Timestamp) {
  EntrySyncPtr entry = CreateEntryAtMidnightJan1stUTC();
  ASSERT_EQ(entry.GetTimestamp(), 1704067200);
}

假设我们决定实际需要的是纳秒粒度。周三 会将 GetTimestamp实现更改为返回 但请注意,FIDL 定义不会改变。

我们将按如下方式更新测试:

TEST(Timestamp) {
  EntrySyncPtr entry = CreateEntryAtMidnightJan1stUTC();
- ASSERT_EQ(entry.GetTimestamp(), 17040672000);
+ ASSERT_EQ(entry.GetTimestamp(), 17040672000000000);
}

这将通过 fuchsia.git 中的所有检查并提交,但现在 导致 Fuchsia 平台出现兼容性问题

失败时间轴

我们来看一下导致破坏的完整时间轴。

  1. 在 SDK 变更之前:假设 FooWidget 团队希望 实现其适用于 Fuchsia 的 FooWidget。他们下载了 Fuchsia SDK 并构建了其以 API 级别 20 为目标平台的组件。这个 组件使用 Entry 协议并调用 GetTimestamp, 方法。此时,GetTimestamp 会返回秒数。

    这对他们来说很实用,因此,FooWidget 团队 名为 foo-widget 的软件包。经过检查,这个软件包的用户 可以看到它以 API 级别 20 为目标平台。

  2. FooWidget 包含在 Fuchsia 产品中:Fuchsia 产品 它包含 foo-widget 软件包和 Fuchsia 组件, 从 SDK 获取平台。foo-widget 软件包已作为 无需访问源代码的预构建二进制文件,但会进行产品组装 该软件包是针对 API 级别 20 构建的,并且 Fuchsia 平台映像支持 API 级别 20。

  3. 发布 SDK 更改:此时,我们定义的更改 fuchsia.git,系统会生成新的 SDK, 发布。

  4. 产品与新 SDK 组合在一起:产品 将产品库推送到新 SDK,并使用 新的 Fuchsia 平台映像,并结合了现有的预构建 foo-widget

  5. FooWidget 在该产品上损坏:当 foo-widget 组件调用 GetTimestamp(),结果将以纳秒为单位 而不是几秒钟,这样可能会产生非常奇怪的结果。 例如,FooWidget 界面可能会以数百万次 因为它将纳秒视为 秒!

    更改平台功能的行为很危险 而现有软件依赖于旧行为。

捕获兼容性问题

CTF 测试利用 Fuchsia 的 版本分支过程。如果 CTF 测试失败, 针对旧 Fuchsia 平台实现的预构建组件 会失败。行之有效 如下所示:

  1. 每个 Fuchsia 里程碑版本都有一个 fuchsia.git 中关联的版本分支。这表示 Fuchsia 平台实现在发布时的状态。
  2. 该平台实现通过了该平台的一组测试, release 分支。
  3. 一组工件包含在 CTF Artifacts 软件包中, 发布分支。
  4. 创建和/或修改版本分支后,CTF 该分支的工件会被编译并上传到 CIPD。
  5. 每个受支持的 API 级别的 CTF 工件下载为 main 分支上的预构建组件,通过将它们解冻 转换为测试软件包
  6. 这些测试软件包针对最新的 Fuchsia 平台运行 针对 main 分支,如果提交失败,则会阻止 CL 提交。

这与构建组件的场景完全相同 旧版 Fuchsia SDK 和平台,然后作为 针对当前 Fuchsia 平台预构建的。

背景信息和历史

CTF 旨在防止对已实现的 Fuchsia 的破坏性更改 API 和 ABI。

CTF 最初设计的目的是确保 Fuchsia 系统为 特定的 ABI 修订版本。这意味着 可以在系统上运行,而且系统 相应修订版本的向后兼容性

CTF 目前的目的是提供一种 和“融化”测试工件

此机制可以确保当前的 Fuchsia 平台 支持每个版本的旧版 API 和 ABI 行为, 都应该受支持此外,冻结的测试 应用于任意 Fuchsia 图像,以实现原始目标 或 CTF。