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>
- 可以看到
SetValue
和Encrypt
。 GetTimestamp
不存在,因为在 API 级别 19 时尚不存在。
- 可以看到
- 组件是以 API 级别 21 为目标构建的:
<ph type="x-smartling-placeholder">
- </ph>
- 可以看到
SetValue
和GetTimestamp
。 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 平台出现兼容性问题。
失败时间轴
我们来看一下导致破坏的完整时间轴。
在 SDK 变更之前:假设 FooWidget 团队希望 实现其适用于 Fuchsia 的 FooWidget。他们下载了 Fuchsia SDK 并构建了其以 API 级别 20 为目标平台的组件。这个 组件使用
Entry
协议并调用GetTimestamp
, 方法。此时,GetTimestamp
会返回秒数。这对他们来说很实用,因此,FooWidget 团队 名为
foo-widget
的软件包。经过检查,这个软件包的用户 可以看到它以 API 级别 20 为目标平台。FooWidget 包含在 Fuchsia 产品中:Fuchsia 产品 它包含
foo-widget
软件包和 Fuchsia 组件, 从 SDK 获取平台。foo-widget
软件包已作为 无需访问源代码的预构建二进制文件,但会进行产品组装 该软件包是针对 API 级别 20 构建的,并且 Fuchsia 平台映像支持 API 级别 20。发布 SDK 更改:此时,我们定义的更改
fuchsia.git
,系统会生成新的 SDK, 发布。产品与新 SDK 组合在一起:产品 将产品库推送到新 SDK,并使用 新的 Fuchsia 平台映像,并结合了现有的预构建
foo-widget
。FooWidget 在该产品上损坏:当
foo-widget
组件调用GetTimestamp()
,结果将以纳秒为单位 而不是几秒钟,这样可能会产生非常奇怪的结果。 例如,FooWidget 界面可能会以数百万次 因为它将纳秒视为 秒!更改平台功能的行为很危险 而现有软件依赖于旧行为。
捕获兼容性问题
CTF 测试利用 Fuchsia 的 版本分支过程。如果 CTF 测试失败, 针对旧 Fuchsia 平台实现的预构建组件 会失败。行之有效 如下所示:
- 每个 Fuchsia 里程碑版本都有一个
fuchsia.git
中关联的版本分支。这表示 Fuchsia 平台实现在发布时的状态。 - 该平台实现通过了该平台的一组测试, release 分支。
- 一组工件包含在 CTF Artifacts 软件包中, 发布分支。
- 创建和/或修改版本分支后,CTF 该分支的工件会被编译并上传到 CIPD。
- 每个受支持的 API 级别的 CTF 工件下载为
main
分支上的预构建组件,通过将它们解冻 转换为测试软件包 - 这些测试软件包针对最新的 Fuchsia 平台运行
针对
main
分支,如果提交失败,则会阻止 CL 提交。
这与构建组件的场景完全相同 旧版 Fuchsia SDK 和平台,然后作为 针对当前 Fuchsia 平台预构建的。
背景信息和历史
CTF 旨在防止对已实现的 Fuchsia 的破坏性更改 API 和 ABI。
CTF 最初设计的目的是确保 Fuchsia 系统为 特定的 ABI 修订版本。这意味着 可以在系统上运行,而且系统 相应修订版本的向后兼容性
CTF 目前的目的是提供一种 和“融化”测试工件
此机制可以确保当前的 Fuchsia 平台 支持每个版本的旧版 API 和 ABI 行为, 都应该受支持此外,冻结的测试 应用于任意 Fuchsia 图像,以实现原始目标 或 CTF。