RFC-0015:Fuchsia (CTF) 的兼容性测试

RFC-0015:Fuchsia 兼容性测试 (CTF)
状态已接受
区域
  • 治理
  • 测试
说明

Fuchsia 兼容性测试 (CTF) 的要求、目标和背景信息。

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2020-11-13
审核日期(年-月-日)2020-12-09

摘要

本文档介绍了 Fuchsia 兼容性测试 (CTF) 的一组要求、设计和实现策略。CTF 将提供一种测试平台实现的方法,以确保它们按照 Fuchsia 的规范运行。Fuchsia 开发者将编写测试,以确保在平台源代码和行为发生变化时保持兼容性。如果这些测试通过,则可保证特定版本在特定设备上运行时,与 RFC-0002 中定义的目标 API 级别和目标 ABI 修订版本兼容。

就本文档而言,我们将 API 和 ABI 统称为平台表面积平台表面积元素是与平台表面积关联的已命名且已版本化的标识符(例如方法名称)。未来的 RFC 可能会正式确定这些定义。

设计初衷

目前(2020 年 12 月),所有针对 Fuchsia 平台行为的开源测试都是作为平台 build 的一部分进行构建和运行的。随着平台的发展,我们始终确保测试在 Head 分支上通过。因此,我们没有可保证向后兼容旧版平台的测试。

目前,我们使用多种产品测试来确保兼容性和稳定性。这些产品测试很难进行问题分类:由于它们依赖于产品的稳定性,并且针对平台的许多不同部分,平台工程师很难确定 bug 可能位于何处。

与此同时,开发者正在编写以旧版 Fuchsia 平台表面积为目标的代码。在本文档中,我们将此类开发者称为最终开发者

在推出会破坏 API 的更改时,我们没有采取任何措施来在破坏与最终开发者代码的兼容性时发出提醒。在项目过程中,我们经常发布未记录的 API 更改,导致外部代码停止构建。

此外,我们目前正在构建有关向后 ABI 兼容性的强大保证。自 2020 年 11 月 9 日起,我们要求提供 6 周的 ABI 兼容性窗口,但没有相应的强制执行机制。

我们需要一组可以独立于平台 build 执行的测试,以便在违反与最终开发者的合同条款时明确识别出来。这将有助于确保我们保持与外部开发的代码的兼容性,并为目前仅通过产品测试来执行的平台部分提供更易于分类、更有针对性的测试覆盖率。

从长远来看,我们还需要一套测试,供系统集成商执行,以了解他们是否在生成合规的 Fuchsia 实现。

Fuchsia 的 CTF 将提供一种测试平台实现的方法,以确保它们与特定平台版本兼容(如 RFC-0002 中所定义)。我们希望为平台界面区域中的每种已记录的行为都提供测试。

创建版本时,我们可以使用 CTF 来了解其表面区域与其他版本之间的兼容性。

如果有人正在开发运行 Fuchsia 的设备,并想知道该设备是否与给定的 SDK 兼容,他们可以获取 CTF 和想要展示兼容性的 SDK,通过测试,并确信其产品正确实现了 Fuchsia 的语义,那么该产品将“与 Fuchsia 兼容”。

当开发者想要了解如何针对特定 API 或使用特定 ABI 编写代码时,他们可以参考这些测试。

RFC-0002 允许平台实现提供对向后兼容性的部分支持。CTF 将提供一种测试部分兼容性的方法。

请注意,CTF 并非旨在作为平台演进和向后兼容性的完整解决方案。CTF 测试不太可能涵盖所有最终用例。API 和 ABI 仍必须在设计时考虑到未来的使用情形。如需了解更多相关讨论,请参阅缺点和替代方案部分。

设计

CTF 设计需要在开发简易性与在 Fuchsia 代码库之外构建和运行 CTF 本身的需求之间取得平衡。要求如下:

  1. 每个平台表面区域元素的每个已记录行为都应有一个 CTF 测试。虽然我们预计这最终会成为一项硬性要求,但此 RFC 并未指定此类要求。

  2. CTF 测试不得依赖于特定系统映像的任何内部细节。 如果这些测试依赖于不受测试的其他平台代码,则必须将该代码捆绑为 CTF 的一部分,并且不得依赖于特定系统映像的任何内部细节。

  3. 添加或更改平台表面积的元素时,开发者必须更新 CTF 测试(即必须添加或修改测试)。

  4. 必须能够确定给定 CTF 制品所针对的 Fuchsia API 级别和 ABI 修订版本。

  5. 未作为预构建制品包含在测试套件中的 CTF 测试必须使用受用于测试的 SDK 支持的语言编写(如需了解详情,请参阅支持的语言文档和下方的语言部分)。

编写测试

我们会同时开发 CTF 测试及其对应的 SDK 元素。如今,这意味着我们在 fuchsia.git 中开发测试。虽然如果 CTF 开发者能获得与使用 SDK 的树外开发者相同的体验,那会很不错,但树内开发有太多优势,不容忽视:

  1. 由于功能开发与测试开发同时进行,因此在树内开发测试将允许测试作者使用他们熟悉的工作流程,并在同一 CL 中提交测试和功能。

  2. 由于功能将与测试同时提交,因此无需任何机制来对齐 CTF 和其符合条件的版本。

CTF 测试将使用 build-time enforcement 来确保 CTF 测试只能依赖于 SDK 元素或其他预先批准的 CTF 代码。在树内开发的一大风险在于,我们可能会意外依赖于未通过 SDK 公开的平台实现细节。CTF 测试只能访问平台的公开元素,以防止意外依赖于实现细节。CTF 测试可能会使用适合编写测试的平台代码(例如 zxtest);此类代码将作为 CTF 制品的一部分提供。

CTF 测试不得依赖于依赖 SDK 来实现 Fuchsia 支持的第三方库。需要 SDK 元素来支持 Fuchsia 的第三方库将基于特定 SDK 构建。我们必须确保测试尽可能与任何其他人的 SDK 依赖项分离,因为第三方代码可能依赖于我们需要从测试中排除的平台功能。例如,如果我们依赖于大量使用锁定的测试套件,那么该套件可能不适合用于测试 Zircon 中用于实现锁定的功能。由于存在此限制,我们将使用 zxtest 而不是 gtest。

包含与给定 SDK 相关的 CTF 测试的制品将与该 SDK 一起发布。此制品还将包含足够的构建系统支持,以便在树外构建和运行 CTF 测试。它不包含工具链。

测试必须充分利用语言支持。如需了解详情,请参阅语言支持部分。

实现

覆盖范围要求

对 Fuchsia 平台表面积元素的所有更新都应包含可测试已记录表面的测试。这包括但不限于 C/C++ 头文件、FIDL API、FIDL 有线格式以及 Fuchsia 系统接口文档中描述的任何表面。如果开发者可以通过 SDK 访问某个途径区域元素,则必须对其进行测试。

我们知道,目前要求进行测试可能不太实际。随着 CTF 和平台的发展,我们预计这项要求会变得更加严格。

几乎所有需要进行 API 审核的更改都应有 CTF 测试,API 审核人员应牢记这一点。最终审核将由可测试性审核人员进行,他们只有在平台表面积变更得到 CTF 测试的适当覆盖时,才能批准这些变更。

所有测试都必须满足与提交到树中的任何其他代码相同的审核要求。请注意,这并不意味着测试必须作为提交队列的一部分运行,尽管我们预计大多数测试都会如此。可能不会作为提交队列的一部分运行的测试示例包括手动测试和耗时超过提交队列允许时间的测试。

目录结构

//sdk/ctf/tests 目录的结构与已发布的 SDK 的结构相同。测试位于与 SDK 中被测接口所在的目录相对应的目录中。例如:

  • 主机工具的测试应放在 //sdk/ctf/tests/tools
  • FIDL 接口的测试应放在 //sdk/ctf/tests/fidl 的相应子目录中。例如,针对 fuchsia.sysmem 的测试应放在 //sdk/ctf/tests/fidl/fuchsia.sysmem 中。
  • 库的测试应放在 //sdk/ctf/tests/pkg 的相应子目录中。例如,针对 async-loop 的测试应放在 //sdk/ctf/tests/pkg/async-loop 中。

如果 Fuchsia 开发者不清楚应将测试放在何处,则应咨询相关目录的 OWNERS。

构建支持

CTF 测试针对的是通过外部可用的 SDK 提供的 API 和 ABI。构建支持可确保测试仅依赖于通过 SDK 提供的 API 元素,或允许在 CTF 中使用的 API 元素。所有未列入许可名单的 build 目标都必须使用 //sdk/ctf/build 中的 cts_ 规则变体,而不是标准的 fuchsia.git 规则(即使用 ctf_fuchsia_componentctf_executable 等)。

非 SDK 代码的许可名单可在 //sdk/ctf/build/allowed_ctf_deps.gni 中找到。如果测试作者认为需要额外纳入某个文件,应与相应目录的 OWNERS 联系。

语言

目标端测试

所有 API 测试都必须使用其所测试的 SDK 支持的语言编写。在大多数情况下,这意味着 C++。ABI 测试可以用任何语言编写;为了避免必须为我们不支持的语言构建外部支持(通过 SDK),如果 ABI 测试需要使用其他语言,我们会将其作为预构建的二进制文件或软件包(以更合适的方式)包含在内。

特定标头的测试必须以支持该标头的语言编写。截至撰写本文时,C 头文件面向 C11 和 C++11 及更高版本,而 C++ 头文件面向 C++14 及更高版本。

CTF 测试可能会将自己限制为特定语言版本。例如,我们可能会决定将特定测试限制为 C++14,以确保标头保持 C++14 兼容性。

主机端测试

目标端测试的语言限制不适用于宿主端测试。主机端测试的语言是特定于测试的。如果需要 CTF 依赖于新的工具链,则应与 CTF 团队协商做出决定。对于在主机上运行的端到端测试和脚本,截至撰写本文时,我们支持使用 Dart(尤其是 sl4f)。随着支持的语言发生变化,我们会提供相关文档,说明哪些语言支持主机端测试。

测试要求

测试应包含针对特定 API 或 ABI 的每项已记录断言的检查。例如,如果我们有一个类 fit::basic_string_view,并且它有一个方法 size,该方法记录为返回 string_view 的大小,那么我们会有一个测试来创建 string_view、调用 size 方法,并断言返回值是正确的。

我们知道,在某些情况下,这可能很难做到,而且有些测试可能需要特定的设备设置,而这些设置可能很难复制。我们建议开发者在开发周期的早期阶段就开始进行测试。长期目标是让 CTF 测试成为对平台表面区域的所有更改的必要要求。

测试应反映有关特定 API 用法的最佳实践。简单来说,如果最终开发者复制了测试对 API 的使用,测试作者会认为该开发者正在正确使用 API。测试应尽可能不依赖于未记录的应用特定不变量。未来,如果未记录的行为在 Fuchsia 树之外得到广泛使用,我们可能需要针对不遵循建议用法的用例添加测试。

测试应尽可能避免为目标设备的内部状态创建测试替身(例如,模拟对象和伪对象)。CTF 的目的是确保整个设备的行为正确,而不是确保特定组件的行为正确。

不过,这并不意味着 CTF 测试在某些环境中无法从伪对象中受益。例如,为了使用 CTF 测试来确保平台稳定性,我们可能会发现在没有这些功能的自动化环境中执行需要真实硬件或手动输入的测试(例如音频或连接测试)很有用。虽然 CTF 测试本身应避免使用测试替身,但被测设备可以使用向测试提供虚假数据的虚假驱动程序。在无法使用真实硬件的情况下,CTF 测试可以依赖此类驱动程序。

此外,CTF 测试应保持相互隔离。如果一项测试失败,或者被测系统的某个方面出现异常行为,那么理想情况下,此失败应是局部性的,而不是影响其他测试。测试之间缺乏隔离有时称为“测试串扰”。例如,假设某个测试会更改设备设置组件中的全局状态。如果测试在终止之前未能恢复原始状态,或者系统上的其他组件在测试执行期间更改了全局状态,则可能会发生串扰。为了隔离此类测试,测试作者可能会考虑为本地范围的设置创建功能,而不是改变全局状态。

如有必要,测试可能需要人工干预才能通过。我们建议开发者彻底调查自动化的可能性。

部署

CTF 制品将与包含相关平台表面元素的 SDK 制品一起生成。根据 RFC-0002 的软过渡要求,我们预计每个 SDK build 都能成功执行与同一 SDK 的上一个 build 关联的 CTF。作为概念验证,我们将实现可保证这一点的基础设施。

CTF 制品将包含测试框架和 gn 的构建规则。它们不会包含 build 系统或工具链;这必须在测试执行环境中提供。我们将记录已知与特定 CTF 兼容的工具链。

示例

您可以在 fuchsia.git 中的 //sdk/ctf/ 找到测试示例。

性能

此项变更会对效果产生以下影响:

  • 运行所有平台测试的时间增加,这是因为测试数量增加了。
  • 由于这些更改仅用于测试,因此不会对生产性能产生影响。

安全注意事项

由于与此 RFC 关联的更改仅用于测试,因此安全风险较低。测试不应与来自外部来源的不受信任的数据进行交互。

隐私注意事项

由于与此 RFC 关联的更改仅用于测试,因此隐私风险较低。测试不应与用户数据互动。

测试

此提案将增加平台的测试矩阵。例如,假设 ABI 稳定性保证期为 6 周,那么在给定 build 之前 6 周生成的 CTF 中的所有 ABI 测试都应针对该 build 运行并成功完成。

此提案中的新要求还将增加平台测试的总数。

系统会自动强制执行测试框架的尽可能多的必需属性;例如,框架会自动检查是否仅包含允许的依赖项。

文档

有关如何编写 CTF 测试的文档将包含在 //docs 中。我们将更新可测试性和 API 流程文档,以反映新的 CTF 测试作者身份要求。我们将记录运行树外 CTF 所需的步骤,以便最终开发者和系统集成商可以独立完成这些步骤。

缺点、替代方案和未知因素

此提案的主要缺点是,它对平台表面区域的所有更改都提出了新的重大测试要求。

CTF 工作的目标不是为演变和向后兼容性问题提供完整的解决方案。必须精心设计 API 和 ABI,以确保开发者能够以合理的成本迁移其代码。例如,FIDL 团队非常谨慎地改进语言绑定:他们明确规定了绑定的运作方式,并积极跟踪各种绑定的合规性

CTF 方法是一种用于保持向后兼容性的标准行业方法。其他方法包括:

  • 只是小心谨慎。我们根据经验知道,仅靠这一点是不够的。
  • 不发展平台。显然,永远不进行更改是不切实际的。此方法的多数缩减版本(例如,随应用一起提供应用的大部分依赖项,或为每个应用提供虚拟环境)都与 Fuchsia 的设计原则和产品目标相悖。
  • 形式化验证。我们认为,形式化验证并非可扩展的测试替代方案。

在先技术和参考资料

Android 通过随产品发布 CTF 来解决此问题。新 Android 设备的开发者必须确保其设备通过 CTF。

作为 Windows 硬件兼容性计划的一部分,Microsoft 制作了 Windows 硬件实验室套件,并将其分发给新 Windows 硬件的开发者。