Skip to content

Commit 7e5cc8f

Browse files
committed
Refine docs around ExitCondition and rebase on a feature branch we're not ready to merge yet
1 parent 1df58de commit 7e5cc8f

File tree

1 file changed

+83
-50
lines changed

1 file changed

+83
-50
lines changed

Documentation/Proposals/NNNN-exit-tests.md

Lines changed: 83 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ and would improve code coverage for existing test targets that adopt them.
4747

4848
## Proposed solution
4949

50-
This proposal introduces a new variant of the `#expect()` and `#require()`
50+
This proposal introduces new overloads of the `#expect()` and `#require()`
5151
macros that take, as an argument, a closure to be executed in a child process.
5252
When called, these macros spawn a new process using the relevant
5353
platform-specific interface (`posix_spawn()`, `CreateProcessW()`, etc.), call
@@ -57,7 +57,76 @@ value passed to the macro, allowing the test to pass or fail as appropriate.
5757

5858
## Detailed design
5959

60-
We will introduce the following new interfaces to the testing library:
60+
### New expectations
61+
62+
We will introduce the following new overloads of `#expect()` and `#require()` to
63+
the testing library:
64+
65+
```swift
66+
/// Check that an expression causes the process to terminate in a given fashion.
67+
///
68+
/// - Parameters:
69+
/// - exitCondition: The expected exit condition.
70+
/// - comment: A comment describing the expectation.
71+
/// - sourceLocation: The source location to which recorded expectations and
72+
/// issues should be attributed.
73+
/// - expression: The expression to be evaluated.
74+
///
75+
/// Use this overload of `#expect()` when an expression will cause the current
76+
/// process to terminate and the nature of that termination will determine if
77+
/// the test passes or fails.
78+
#if SWT_NO_EXIT_TESTS
79+
@available(*, unavailable, message: "Exit tests are not available on this platform.")
80+
#endif
81+
@freestanding(expression) public macro expect(
82+
exitsWith exitCondition: ExitCondition,
83+
_ comment: @autoclosure () -> Comment? = nil,
84+
sourceLocation: SourceLocation = SourceLocation(),
85+
performing expression: @convention(thin) () async -> Void
86+
)
87+
88+
/// Check that an expression causes the process to terminate in a given fashion.
89+
///
90+
/// - Parameters:
91+
/// - exitCondition: The expected exit condition.
92+
/// - comment: A comment describing the expectation.
93+
/// - sourceLocation: The source location to which recorded expectations and
94+
/// issues should be attributed.
95+
/// - expression: The expression to be evaluated.
96+
///
97+
/// Use this overload of `#require()` when an expression will cause the current
98+
/// process to terminate and the nature of that termination will determine if
99+
/// the test passes or fails.
100+
#if SWT_NO_EXIT_TESTS
101+
@available(*, unavailable, message: "Exit tests are not available on this platform.")
102+
#endif
103+
@freestanding(expression) public macro require(
104+
exitsWith exitCondition: ExitCondition,
105+
_ comment: @autoclosure () -> Comment? = nil,
106+
sourceLocation: SourceLocation = SourceLocation(),
107+
performing expression: @convention(thin) () async -> Void
108+
)
109+
```
110+
111+
> [!NOTE]
112+
> `SWT_NO_EXIT_TESTS` is defined by the testing library when building for
113+
> platforms that do not have the ability to spawn child processes (including
114+
> iOS, watchOS, tvOS, visionOS, and WASI.) In other words, these interfaces are
115+
> available on **macOS**, **Linux**, and **Windows**. `SWT_NO_EXIT_TESTS` is not
116+
> defined during test target builds.
117+
118+
### Exit conditions
119+
120+
These macros take an argument of the new enumeration `ExitCondition`. This type
121+
describes how the child process is expected to have exited:
122+
123+
- With a specific exit code (as passed to the C standard function `exit()` or a
124+
platform equivalent;
125+
- With a specific signal (on POSIX-like platforms that support signal handling;
126+
- With any successful status; or
127+
- With any failure status.
128+
129+
The enumeration is declared as:
61130

62131
```swift
63132
/// An enumeration describing possible conditions under which an exit test will
@@ -67,6 +136,10 @@ We will introduce the following new interfaces to the testing library:
67136
/// ``expect(exitsWith:_:sourceLocation:performing:)`` or
68137
/// ``require(exitsWith:_:sourceLocation:performing:)`` to configure which exit
69138
/// statuses should be considered successful.
139+
///
140+
/// Two instances of this type can be compared; if either instance is equal to
141+
/// ``failure``, it will compare equal to any instance except ``success``. To
142+
/// check if two instances are exactly equal, use the `===` operator:
70143
#if SWT_NO_EXIT_TESTS
71144
@available(*, unavailable, message: "Exit tests are not available on this platform.")
72145
#endif
@@ -122,57 +195,16 @@ public enum ExitCondition: Sendable {
122195
case signal(_ signal: CInt)
123196
}
124197

125-
/// Check that an expression causes the process to terminate in a given fashion.
126-
///
127-
/// - Parameters:
128-
/// - exitCondition: The expected exit condition.
129-
/// - comment: A comment describing the expectation.
130-
/// - sourceLocation: The source location to which recorded expectations and
131-
/// issues should be attributed.
132-
/// - expression: The expression to be evaluated.
133-
///
134-
/// Use this overload of `#expect()` when an expression will cause the current
135-
/// process to terminate and the nature of that termination will determine if
136-
/// the test passes or fails.
137-
#if SWT_NO_EXIT_TESTS
138-
@available(*, unavailable, message: "Exit tests are not available on this platform.")
139-
#endif
140-
@freestanding(expression) public macro expect(
141-
exitsWith exitCondition: ExitCondition,
142-
_ comment: @autoclosure () -> Comment? = nil,
143-
sourceLocation: SourceLocation = SourceLocation(),
144-
performing expression: @convention(thin) () async -> Void
145-
)
198+
extension ExitCondition: Equatable {
199+
public static func ===(lhs: Self, rhs: Self) -> Bool
200+
public static func !==(lhs: Self, rhs: Self) -> Bool
201+
}
146202

147-
/// Check that an expression causes the process to terminate in a given fashion.
148-
///
149-
/// - Parameters:
150-
/// - exitCondition: The expected exit condition.
151-
/// - comment: A comment describing the expectation.
152-
/// - sourceLocation: The source location to which recorded expectations and
153-
/// issues should be attributed.
154-
/// - expression: The expression to be evaluated.
155-
///
156-
/// Use this overload of `#require()` when an expression will cause the current
157-
/// process to terminate and the nature of that termination will determine if
158-
/// the test passes or fails.
159-
#if SWT_NO_EXIT_TESTS
160-
@available(*, unavailable, message: "Exit tests are not available on this platform.")
161-
#endif
162-
@freestanding(expression) public macro require(
163-
exitsWith exitCondition: ExitCondition,
164-
_ comment: @autoclosure () -> Comment? = nil,
165-
sourceLocation: SourceLocation = SourceLocation(),
166-
performing expression: @convention(thin) () async -> Void
167-
)
203+
@available(*, unavailable, message: "ExitCondition does not conform to Hashable.")
204+
extension ExitCondition: Hashable {}
168205
```
169206

170-
> [!NOTE]
171-
> `SWT_NO_EXIT_TESTS` is defined by the testing library when building for
172-
> platforms that do not have the ability to spawn child processes (including
173-
> iOS, watchOS, tvOS, visionOS, and WASI.) In other words, these interfaces are
174-
> available on **macOS**, **Linux**, and **Windows**. `SWT_NO_EXIT_TESTS` is not
175-
> defined during test target builds.
207+
### Usage
176208

177209
These macros can be used within a test function:
178210

@@ -447,3 +479,4 @@ can expand upon in the future if it proves to be important to exit test authors.
447479
## Acknowledgments
448480

449481
Many thanks to the XCTest and swift-testing team.
482+

0 commit comments

Comments
 (0)