blob: 9d35ed102ea213388d3a4530eeb8a0887dc927ac [file] [log] [blame] [view]
{% set rfcid = "RFC-0015" %}
{% include "docs/contribute/governance/rfcs/_common/_rfc_header.md" %}
# {{ rfc.name }}: {{ rfc.title }}
<!-- SET the `rfcid` VAR ABOVE. DO NOT EDIT ANYTHING ELSE ABOVE THIS LINE. -->
## Summary
This document presents requirements, design, and implementation strategy for a
set of Compatibility Tests for Fuchsia (CTF). The CTF will offer a way
of testing platform implementations to make sure that they behave according to
Fuchsia's specifications. Fuchsia developers will write tests that guarantee
compatibility across changes to both the source and behavior of the platform.
When these tests pass, they will guarantee that a particular release, when
run on a particular device, is compatible with a target API level and target ABI
revision, as defined in [RFC-0002].
For the purposes of this document, we refer to API and ABI jointly as the
_platform surface area_. A _platform surface area element_ is a named and
versioned identifier associated with the platform surface area (e.g., a method
name). Future RFCs may formalize these definitions.
## Motivation
All of the open-source tests for Fuchsia platform behavior are currently
(December 2020) built and run as part of the platform build. As the platform
evolves, we keep the tests passing at head. As a result, we have no tests that
guarantee backwards compatibility with older versions of the platform.
Currently, we use a number of product tests to ensure compatibility and
stability. These product tests are difficult to triage: because they rely on
the stability of the product, and target many different parts of the platform,
it is difficult for platform engineers to determine where the bug may be.
At the same time, developers are writing code that targets older versions of the
Fuchsia platform surface area. In this document, we refer to such developers as
_end developers_.
As we roll out API breaking changes, we have no safeguards in place that raise a
flag when we break compatibility with end developers' code. Over the course of
the project, undocumented API changes have frequently been released that cause
external code to stop building.
Furthermore, we are currently building out strong guarantees about backwards ABI
compatibility. As of 9 November 2020, we require a six-week ABI compatibility
window, but have no enforcement mechanism for it.
We need a set of tests that we can execute independently from the platform build
that identify clearly when we break our contracts with end developers. This
will help ensure that we maintain compatibility with externally developed code,
and provide more easily triaged, targeted test coverage for the parts of the
platform that are currently only exercised by product tests.
In the long term, we will also need a set of tests that system integrators can
execute to know if they are producing a compliant Fuchsia implementation.
Fuchsia's CTF will offer a way of testing platform implementations to make sure
that they are compatible with particular platform releases (as defined in
[RFC-0002]). We aspire to have a test for each documented behavior in the
platform surface area.
When we create a release, we can use the CTF to tell us about the compatibility
of its surface area with that of other release versions.
When someone is developing a device running Fuchsia, and wants to see if it is
compatible with a given SDK, they can take the CTF and the SDK with which it
wants to demonstrate compatibility, pass the tests, and have confidence that
their product correctly implements Fuchsia's semantics - it will be "Fuchsia
compatible".
When a developer wants to understand how to write code against a particular API,
or using a particular ABI, they will be able to use these tests as reference.
[RFC-0002] allows a platform implementation to provide partial support for
backwards compatibility. CTF will provide a way to test partial compatibility.
Note that the CTF is not intended as a complete solution for platform evolution
and backwards compatibility. It's not likely that CTF tests will cover every
last use case. API and ABI will still have to be designed with future use cases
in mind. See the section on [drawbacks and
alternatives](#drawbacks_alternatives_and-unknowns) for additional discussion.
## Design
The CTF design involves balancing ease of development with the need to build and
run the CTF itself outside of the Fuchsia repository. The requirements are as
follows:
1. There should be a CTF test for every documented behavior of every platform
surface area element. Although we expect this to become a hard requirement
eventually, this RFC does not specify such a requirement.
1. CTF tests may not rely on any internal details of a particular system image.
To the extent that they rely on other platform code that is not itself
subject to test, that code must be bundled as part of the CTF and also not
rely on any internal details of a particular system image.
1. CTF tests must be updated by developers (that is, tests must be added or
modified) when adding or changing elements of the platform surface area.
1. It must be possible to determine the API level and ABI revision of Fuchsia
that a given CTF artifact targets.
1. CTF tests that are not included in the test suite as prebuilt artifacts must
be written in languages supported by the SDK being used to test (see the
[supported languages document] and the [Language](#Language) section below
for more details).
### Authoring the Tests
We develop CTF tests alongside their corresponding SDK elements. Today, that
means we develop the tests in fuchsia.git. While it would be nice if CTF
developers had the same experience as the out of tree developers who use the
SDK, there are too many advantages to in-tree development to ignore:
1. Because feature development is done alongside test development, in-tree
development of the tests will allow test authors to use a workflow with which
they are familiar, as well as submit the test in the same CL as the feature.
1. Because the feature will be submitted at the same time as the test, there is
no need for any machinery to align the CTF and the version that it qualifies.
CTF tests will use build-time enforcement to ensure that CTF tests can only
depend on SDK elements or other pre-approved CTF code. One of the dangers of
developing in-tree is that we may accidentally take on dependencies on platform
implementation details that are not exposed via the SDK. CTF tests must only
access publicly facing elements of the platform to prevent accidentally relying
on implementation details. CTF tests may use platform code that is appropriate
for writing tests (e.g., zxtest); such code will ship as part of the CTF
artifact.
CTF tests must not take dependencies on third party libraries that rely on the
SDK for their Fuchsia support. Third party libraries that require SDK elements
to support Fuchsia are going to be built against a particular SDK. We must make
sure that our tests are as decoupled as possible from anyone else's SDK
dependencies, as third party code may rely on platform features that we need to
exclude from the tests. For example, if we rely on a test suite that heavily
uses locking, it may be inappropriate for testing features of Zircon used to
implement locking. Because of this restriction, we will use zxtest rather than
gtest.
An artifact containing the CTF tests relevant to a given SDK will be published
alongside that SDK. This artifact will also contain build system support
sufficient to build and run the CTF tests outside of the tree. It will not
contain a toolchain.
The tests must exercise language support thoroughly. See the section on
[Language Support](#language) for more details.
## Implementation
### Coverage Requirements
All updates to Fuchsia platform surface area elements should include tests that
exercise the documented surface. This includes, but is not limited to, C/C++
headers, FIDL API, the FIDL wire format, and any surface described by the
[Fuchsia System Interface] document. If the surface area element can be
accessed by developers via an SDK, it must be tested.
We recognize that it may not be practical to require tests at this point. As
the CTF and platform grows, we expect this requirement will become more strict.
Almost all changes that require API review should have CTF tests, and API
reviewers should review with that in mind. The final review will be made by
testability reviewers, who should only approve platform surface area changes if
they are appropriately covered by CTF tests.
All tests are subject to the same review requirements as any other code
submitted to the tree. Note that this does not mean that tests must be run as
part of the commit queue, although we expect most will be. Examples of tests
that might not be run as part of the commit queue include manual tests and tests
that take longer than the commit queue allows.
#### Directory structure
The structure of the `//sdk/ctf/tests` directory mirrors the structure of
released SDKs. Tests go in the directory that mirrors the one where the
interface under test is found in an SDK. For example:
* Tests for host tools should go in `//sdk/ctf/tests/tools`
* Tests for FIDL interfaces should go in the appropriate
subdirectory of `//sdk/ctf/tests/fidl`. For example, tests for
`fuchsia.sysmem` should go in `//sdk/ctf/tests/fidl/fuchsia.sysmem`.
* Tests for libraries should go in the appropriate subdirectory of
`//sdk/ctf/tests/pkg`. For example, tests for `async-loop` should go in
`//sdk/ctf/tests/pkg/async-loop`.
If Fuchsia developers are not clear on where to put their tests, they should
consult the OWNERS of the relevant directory.
#### Build support
CTF tests target API and ABI that are available through externally-available
SDKs. Build support ensures that tests only depend on API elements that are
either available via an SDK, or allowlisted for use within the CTF. All build
targets that are not allowlisted must use the `cts_` rule variants found in
`//sdk/ctf/build` instead of the standard fuchsia.git rules (i.e., use
`ctf_fuchsia_component`, `ctf_executable`, and so on).
The allowlist for non-SDK code can be found in
`//sdk/ctf/build/allowed_ctf_deps.gni`. Test authors who believe they need an
additional inclusion should reach out to the OWNERS of this directory.
#### Language
##### Target-side tests
All API tests must be written in languages supported by the SDK they test. In
most cases, this implies C++. ABI tests may be written in any language; in
order to avoid having to build external support for languages we do not support
via the SDK, if an ABI test needs to be in another language, we will include it
as a prebuilt binary or package (whichever is more appropriate).
Tests for particular headers must be written in a language that supports that
header. As of this writing, C headers target C11 and C++11 and above, and C++
headers target C++14 and above.
CTF tests may restrict themselves to a particular language version. For
example, we may decide that particular tests are restricted to C++14 in order to
guarantee that headers maintain C++14 compatibility.
##### Host-side tests
Language restrictions for target-side tests are not applicable to host-side
tests. The language for host-side tests is test-specific. If it will require
the CTF to depend on a new toolchain, the decision should be made in
consultation with the CTF team. For end-to-end tests and scripts that run on
the host, as of this writing, we support the use of Dart (and, specifically
`sl4f`). As supported languages change, documentation will be made available
about which languages are supported for host-side testing.
#### Test Requirements
Tests should contain a check for every documented assertion about a particular
API or ABI. For example, if we have a class `fit::basic_string_view`, and it
has a method `size` that is documented to return the size of the string_view, we
would have a test that creates a string_view, calls the `size` method, and
asserts that the return value is correct.
We recognize that it may be difficult to do this in some cases, and that some
tests may require specific device setup that may be hard to replicate. We
recommend that developers start working on testing early in the development
cycle. The long-term goal is to make CTF testing a requirement for all changes
to the platform surface area.
Tests should reflect best practices about the usage of a given API. Informally,
if an end developer copies a test's usage of the API, the test author would
believe that developer is using the API correctly. Tests should, to the extent
possible, not depend on undocumented, application-specific invariants. In the
future, in the case of widespread use of undocumented behaviors outside of the
Fuchsia tree, we may need to add tests for use cases that do not follow
recommended usages.
Wherever possible, tests should avoid creating test doubles (e.g., mocks and
fakes) for the internal state of the target device. The intent of the CTF is to
make sure the entire device behaves correctly, not to make sure that a
particular component behaves correctly in isolation.
However, this does not mean that CTF tests cannot benefit from fakes in some
environments. For example, for the purposes of using CTF tests to ensure
platform stability, we may find it useful to exercise tests that require real
hardware or manual input, such audio or connectivity tests, in an automated
environment that does not have those features available. While a CTF test
itself should avoid the use of test doubles, the device under test can use fake
drivers that feed the test fake data. CTF tests can rely on such drivers in
cases where using real hardware is not practical.
In addition, CTF tests should maintain isolation from each other. If one test
fails, or if one aspect of the system under test misbehaves, then ideally this
failure should be localized rather than affect other tests. Lack of isolation
between tests is sometimes referred to as "test cross-talk". For instance
consider a test that changes global state in a device settings component. If
the test fails to restore the original state before it terminates, or if
another component on the system changes the global state during test execution,
then cross-talk may occur. For such a test to be isolated, the test author
might consider creating an affordance for locally-scoped settings rather than
mutating global state.
If necessary, tests may require manual intervention to pass. We recommend that
developers thoroughly investigate the possibility of automation.
### Deployment
CTF artifacts will be generated alongside the SDK artifacts that contain the
relevant platform surface elements. Because of the soft transition requirements
of RFC-0002, we expect that every SDK build will successfully execute the CTF
associated with the previous build of the same SDK. As a proof of concept, we
will implement infrastructure to guarantee this.
CTF artifacts will contain a test harness and build rules for gn. They will not
contain a build system or toolchain; this must be supplied in the test execution
environment. We will document which toolchains are known to be compatible with
a given CTF.
### Examples
Test examples can be found in fuchsia.git at `//sdk/ctf/`.
## Performance
This change will have the following performance impact:
* An increase in time to run all platform tests, stemming from an increased
number of tests.
* No impact on production performance, because the changes are test-only.
## Security considerations
Because changes associated with this RFC are test-only, they are a low security
risk. Tests are not expected to interact with untrusted data from external
sources.
## Privacy considerations
Because changes associated with this RFC are test-only, they are a low privacy
risk. Tests are not expected to interact with user data.
## Testing
This proposal will increase the testing matrix for the platform. For example,
given the six-week ABI stability guarantee, all ABI tests from the CTF generated
six weeks earlier than a given build should be run and complete successfully
against that build.
The new requirements in this proposal will also increase the overall number of
platform tests.
As many required properties of the test framework as is practical will be
enforced automatically; for example, the framework will automatically check that
only allowed dependencies are included.
## Documentation
Documentation on how to write CTF tests will be included in `//docs`. There
will be updates to testability and API process documents to reflect new CTF test
authorship requirements. The steps needed to run CTF out of tree will be
documented, so that end developers and system integrators can do them
independently.
## Drawbacks, alternatives, and unknowns
The chief drawback of this proposal is that it creates a significant new testing
requirement for all changes to the platform surface area.
It is not a goal of the CTF effort to provide a complete solution to evolution
and backwards compatibility issues. APIs and ABIs will have to be designed
carefully to ensure that developers can migrate their code at a reasonable cost.
For example, the FIDL team evolves language bindings with extreme care: they
have a [clear specification for how bindings ought to
work](/docs/reference/fidl/language/bindings-spec.md), and actively [tracks how
conformant the various bindings
are](/docs/development/languages/fidl/guides/compatibility/README.md).
The CTF approach is a standard industry approach to maintaining backwards
compatibility. Other approaches include:
* Simply being careful. We know empirically that this does not work by itself.
* Not evolving the platform. Obviously, simply never making changes is not
practical. Most scaled down versions of this (for example, shipping most of
an application's dependencies with it, or providing a virtual environment for
every application) are at odds with Fuchsia's design principles and product
goals.
* Formal verification. We do not consider formal verification to be a scalable
alternative to testing.
## Prior art and references
Android solves this problem by releasing a
[CTF](https://source.android.com/compatibility/cts) with their product.
Developers of new Android devices must ensure that their devices pass the CTF.
As part of its [Windows Hardware Compatibility
Program](https://docs.microsoft.com/en-us/windows-hardware/design/compatibility/),
Microsoft produces a [Windows Hardware Lab
Kit](https://docs.microsoft.com/en-us/windows-hardware/test/hlk/) that they
distribute to developers of new Windows hardware.
<!-- xrefs -->
[RFC-0002]: /docs/contribute/governance/rfcs/0002_platform_versioning.md
[supported languages document]: /docs/contribute/governance/policy/programming_languages.md
[Fuchsia System Interface]: /docs/concepts/packages/system.md
[Fuchsia language policy]: /docs/contribute/governance/policy/programming_languages.md