@@ -21,28 +21,38 @@ the testing library are stored in dedicated platform-specific sections:
21
21
22
22
| Platform | Binary Format | Section Name |
23
23
| -| :-:| -|
24
- | macOS | Mach-O | ` __DATA_CONST,__swift5_tests ` |
25
- | iOS | Mach-O | ` __DATA_CONST,__swift5_tests ` |
26
- | watchOS | Mach-O | ` __DATA_CONST,__swift5_tests ` |
27
- | tvOS | Mach-O | ` __DATA_CONST,__swift5_tests ` |
28
- | visionOS | Mach-O | ` __DATA_CONST,__swift5_tests ` |
29
- | Linux | ELF | ` PT_NOTE ` [ ^ 1 ] |
30
- | FreeBSD | ELF | ` PT_NOTE ` [ ^ 1 ] |
31
- | Android | ELF | ` PT_NOTE ` [ ^ 1 ] |
24
+ | macOS, iOS, watchOS, tvOS, visionOS | Mach-O | ` __DATA_CONST,__swift5_tests ` |
25
+ | Linux, FreeBSD, Android | ELF | ` PT_NOTE ` [ ^ 1 ] |
32
26
| WASI | Statically Linked | ` swift5_tests ` |
33
27
| Windows | PE/COFF | ` .sw5test ` |
34
28
35
29
[ ^ 1 ] : On platforms that use the ELF binary format natively, test content records
36
30
are stored in ELF program headers of type ` PT_NOTE ` . Take care not to
37
31
remove these program headers (for example, by invoking [ ` strip(1) ` ] ( https://www.man7.org/linux/man-pages/man1/strip.1.html ) .)
38
32
39
- ### Determining the type of test content
33
+ ### Record headers
40
34
41
35
Regardless of platform, all test content records created and discoverable by the
42
- testing library start have the name ` "Swift Testing" ` stored in the implied
43
- ` n_name ` field of their underlying ELF Notes. Each record's _ type_ (stored in
44
- the underlying ELF Note's ` n_type ` field) determines how the record will be
45
- interpreted at runtime:
36
+ testing library have the following structure:
37
+
38
+ ``` c
39
+ struct SWTTestContentHeader {
40
+ int32_t n_namesz;
41
+ int32_t n_descsz;
42
+ int32_t n_type;
43
+ char n_name[ n_namesz] ;
44
+ // ...
45
+ };
46
+
47
+ The size of `n_name` is dynamic and cannot be statically computed. The testing
48
+ library always generates the name `" Swift Testing" ` and specifies an `n_namesz`
49
+ value of `20 ` (the string being null-padded to the correct length), but other
50
+ content may be present in the same section whose header content differs. For
51
+ more information about this structure such as its alignment requirements, see
52
+ the documentation for the [ELF format](https:// man7.org/linux/man-pages/man5/elf.5.html).
53
+
54
+ Each record' s _kind_ (stored in the `n_type` field) determines how the record
55
+ will be interpreted at runtime:
46
56
47
57
| Type Value | Interpretation |
48
58
|-:|-|
@@ -54,18 +64,27 @@ interpreted at runtime:
54
64
<!-- When adding cases to this enumeration, be sure to also update the
55
65
corresponding enumeration in Discovery.h and TestContentGeneration.swift. -->
56
66
57
- ### Loading test content from a record
67
+ ### Record contents
58
68
59
- For all currently-defined record types, the header and name are followed by a
60
- structure of the following form:
69
+ For all currently-defined record types, the header structure is immediately
70
+ followed by the actual content of the record. A test content record currently
71
+ contains an `accessor` function to load the corresponding Swift content and a
72
+ `flags` field whose value depends on the type of record. The overall structure
73
+ of a record therefore looks like:
61
74
62
75
```c
63
76
struct SWTTestContent {
77
+ SWTTestContentHeader header;
64
78
bool (* accessor)(void *);
65
79
uint64_t flags;
66
80
};
67
81
```
68
82
83
+ This structure may grow in the future as needed. Check the `header.n_descsz`
84
+ field to determine if there are additional fields present. Do not assume that
85
+ the size of this structure will remain fixed over time or that all discovered
86
+ test content records are the same size.
87
+
69
88
#### The accessor field
70
89
71
90
The function `accessor` is a C function whose signature in Swift can be restated
@@ -80,19 +99,20 @@ Swift type and returns `true`, or returns `false` if it could not generate the
80
99
relevant content. On successful return, the caller is responsible for
81
100
deinitializing the memory at `outValue` when done with it.
82
101
83
- The concrete Swift type of ` accessor ` 's result depends on the type of record:
102
+ The concrete Swift type of the value written to `outValue` depends on the type
103
+ of record:
84
104
85
105
| Type Value | Return Type |
86
106
|-:|-|
87
107
| < `0` | Undefined (**do not use**) |
88
- | ` 0 ` ... ` 99 ` | ` nil ` |
108
+ | `0` ... `99` | Reserved (**do not use**) |
89
109
| `100` | `@Sendable () async -> Test`[^2] |
90
- | ` 101 ` | ` ExitTest ` (owned by caller) |
110
+ | `101` | `ExitTest` (consumed by caller) |
91
111
92
112
[^2]: This signature is not the signature of `accessor`, but of the Swift
93
- function reference it returns . This level of indirection is necessary
94
- because loading a test or suite declaration is an asynchronous operation,
95
- but C functions cannot be ` async ` .
113
+ function reference it writes to `outValue` . This level of indirection is
114
+ necessary because loading a test or suite declaration is an asynchronous
115
+ operation, but C functions cannot be `async`.
96
116
97
117
#### The flags field
98
118
0 commit comments