-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Store test content in a custom metadata section.
See also: swiftlang/swift#76698 Resolves #735.
- Loading branch information
Showing
18 changed files
with
662 additions
and
441 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# Runtime-discoverable test content | ||
|
||
<!-- | ||
This source file is part of the Swift.org open source project | ||
Copyright (c) 2024 Apple Inc. and the Swift project authors | ||
Licensed under Apache License v2.0 with Runtime Library Exception | ||
See https://swift.org/LICENSE.txt for license information | ||
See https://swift.org/CONTRIBUTORS.txt for Swift project authors | ||
--> | ||
|
||
This document describes the format and location of test content that the testing | ||
library emits at compile time and can discover at runtime. | ||
|
||
## Basic format | ||
|
||
Swift Testing uses the [ELF Note format](https://man7.org/linux/man-pages/man5/elf.5.html) | ||
to store individual records of test content. Records created and discoverable by | ||
the testing library are stored in dedicated platform-specific sections: | ||
|
||
| Platform | Binary Format | Section Name | | ||
|-|:-:|-| | ||
| macOS | Mach-O | `__DATA_CONST,__swift5_tests` | | ||
| iOS | Mach-O | `__DATA_CONST,__swift5_tests` | | ||
| watchOS | Mach-O | `__DATA_CONST,__swift5_tests` | | ||
| tvOS | Mach-O | `__DATA_CONST,__swift5_tests` | | ||
| visionOS | Mach-O | `__DATA_CONST,__swift5_tests` | | ||
| Linux | ELF | `PT_NOTE`[^1] | | ||
| FreeBSD | ELF | `PT_NOTE`[^1] | | ||
| Android | ELF | `PT_NOTE`[^1] | | ||
| WASI | Statically Linked | `swift5_tests` | | ||
| Windows | PE/COFF | `.sw5test` | | ||
|
||
[^1]: On platforms that use the ELF binary format natively, test content records | ||
are stored in ELF program headers of type `PT_NOTE`. Take care not to | ||
remove these program headers (for example, by invoking [`strip(1)`](https://www.man7.org/linux/man-pages/man1/strip.1.html).) | ||
|
||
### Determining the type of test content | ||
Regardless of platform, all test content records created and discoverable by the | ||
testing library start have the name `"Swift Testing"` stored in the implied | ||
`n_name` field of their underlying ELF Notes. Each record's _type_ (stored in | ||
the underlying ELF Note's `n_type` field) determines how the record will be | ||
interpreted at runtime: | ||
|
||
| Type Value | Interpretation | | ||
|-:|-| | ||
| < `0` | Undefined (**do not use**) | | ||
| `0` ... `99` | Reserved | | ||
| `100` | Test or suite declaration | | ||
| `101` | Exit test | | ||
|
||
<!-- When adding cases to this enumeration, be sure to also update the | ||
corresponding enumeration in Discovery.h and TestContentGeneration.swift. --> | ||
|
||
### Loading test content from a record | ||
|
||
For all currently-defined record types, the header and name are followed by a | ||
structure of the following form: | ||
|
||
```c | ||
struct SWTTestContent { | ||
bool (* _Nonnull accessor)(void *); | ||
uint64_t flags; | ||
}; | ||
``` | ||
|
||
#### The accessor field | ||
|
||
The function `accessor` is a C function whose signature in Swift can be restated | ||
as: | ||
|
||
```swift | ||
@convention(c) (_ outValue: UnsafeMutableRawPointer) -> Bool | ||
``` | ||
|
||
When called, it initializes the memory at `outValue` to an instance of some | ||
Swift type and returns `true`, or returns `false` if it could not generate the | ||
relevant content. On successful return, the caller is responsible for | ||
deinitializing the memory at `outValue` when done with it. | ||
|
||
The concrete Swift type of `accessor`'s result depends on the type of record: | ||
|
||
| Type Value | Return Type | | ||
|-:|-| | ||
| < `0` | Undefined (**do not use**) | | ||
| `0` ... `99` | `nil` | | ||
| `100` | `@Sendable () async -> Test`[^2] | | ||
| `101` | `ExitTest` (owned by caller) | | ||
|
||
[^2]: This signature is not the signature of `accessor`, but of the Swift | ||
function reference it returns. This level of indirection is necessary | ||
because loading a test or suite declaration is an asynchronous operation, | ||
but C functions cannot be `async`. | ||
|
||
#### The flags field | ||
|
||
For test or suite declarations (type `100`), the following flags are defined: | ||
|
||
| Bit | Description | | ||
|-:|-| | ||
| `1 << 0` | This record contains a suite declaration | | ||
| `1 << 1` | This record contains a parameterized test function declaration | | ||
|
||
For exit test declarations (type `101`), no flags are currently defined. | ||
|
||
## Third-party test content | ||
|
||
TODO: elaborate how tools can reuse the same `n_name` and `n_type` fields to | ||
supplement Swift Testing's data, or use a different `n_name` field to store | ||
arbitrary other data in the test content section that Swift Testing will ignore. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.