Skip to content

Commit 24cbf5d

Browse files
committed
Merge branch 'main' into jgrynspan/162-redesign-value-capture
2 parents 1a117ef + cacb295 commit 24cbf5d

File tree

56 files changed

+1429
-317
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1429
-317
lines changed

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
# See https://swift.org/CONTRIBUTORS.txt for Swift project authors
99
#
1010

11-
* @stmontgomery @grynspan @briancroom @SeanROlszewski @suzannaratcliff
11+
* @stmontgomery @grynspan @briancroom @suzannaratcliff

Documentation/ABI/JSON.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,24 @@ sufficient information to display the event in a human-readable format.
188188
"kind": <event-kind>,
189189
"instant": <instant>, ; when the event occurred
190190
["issue": <issue>,] ; the recorded issue (if "kind" is "issueRecorded")
191+
["attachment": <attachment>,] ; the attachment (if kind is "valueAttached")
191192
"messages": <array:message>,
192193
["testID": <test-id>,]
193194
}
194195
195196
<event-kind> ::= "runStarted" | "testStarted" | "testCaseStarted" |
196197
"issueRecorded" | "testCaseEnded" | "testEnded" | "testSkipped" |
197-
"runEnded" ; additional event kinds may be added in the future
198+
"runEnded" | "valueAttached"; additional event kinds may be added in the future
198199
199200
<issue> ::= {
200201
"isKnown": <bool>, ; is this a known issue or not?
201202
["sourceLocation": <source-location>,] ; where the issue occurred, if known
202203
}
203204
205+
<attachment> ::= {
206+
"path": <string>, ; the absolute path to the attachment on disk
207+
}
208+
204209
<message> ::= {
205210
"symbol": <message-symbol>,
206211
"text": <string>, ; the human-readable text of this message

Documentation/ABI/TestContent.md

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,10 @@ record's kind is a 32-bit unsigned value. The following kinds are defined:
100100
| `0x00000000` | &ndash; | Reserved (**do not use**) |
101101
| `0x74657374` | `'test'` | Test or suite declaration |
102102
| `0x65786974` | `'exit'` | Exit test |
103+
| `0x706c6179` | `'play'` | [Playground](https://github.com/apple/swift-play-experimental) |
103104

104-
<!-- When adding cases to this enumeration, be sure to also update the
105-
corresponding enumeration in TestContentGeneration.swift. -->
105+
<!-- The kind values listed in this table should be a superset of the cases in
106+
the `TestContentKind` enumeration. -->
106107

107108
If a test content record's `kind` field equals `0x00000000`, the values of all
108109
other fields in that record are undefined.
@@ -149,25 +150,12 @@ The fourth argument to this function, `reserved`, is reserved for future use.
149150
Accessor functions should assume it is `0` and must not access it.
150151

151152
The concrete Swift type of the value written to `outValue`, the type pointed to
152-
by `type`, and the value pointed to by `hint` depend on the kind of record:
153+
by `type`, and the value pointed to by `hint` depend on the kind of record.
153154

154-
- For test or suite declarations (kind `0x74657374`), the accessor produces a
155-
structure of type `Testing.Test.Generator` that the testing library can use
156-
to generate the corresponding test[^notAccessorSignature].
157-
158-
[^notAccessorSignature]: This level of indirection is necessary because
159-
loading a test or suite declaration is an asynchronous operation, but C
160-
functions cannot be `async`.
161-
162-
Test content records of this kind do not specify a type for `hint`. Always
163-
pass `nil`.
164-
165-
- For exit test declarations (kind `0x65786974`), the accessor produces a
166-
structure describing the exit test (of type `Testing.ExitTest`.)
167-
168-
Test content records of this kind accept a `hint` of type `Testing.ExitTest.ID`.
169-
They only produce a result if they represent an exit test declared with the
170-
same ID (or if `hint` is `nil`.)
155+
The record kinds defined by Swift Testing (kinds `0x74657374` and `0x65786974`)
156+
make use of the `DiscoverableAsTestContent` protocol in the `_TestDiscovery`
157+
module and do not publicly expose the types of their accessor functions'
158+
arguments. Do not call the accessor functions for these records directly.
171159

172160
> [!WARNING]
173161
> Calling code should use [`withUnsafeTemporaryAllocation(of:capacity:_:)`](https://developer.apple.com/documentation/swift/withunsafetemporaryallocation(of:capacity:_:))
@@ -274,7 +262,8 @@ extension FoodTruckDiagnostic: DiscoverableAsTestContent {
274262
```
275263

276264
If you customize `TestContentContext`, be aware that the type you specify must
277-
have the same stride and alignment as `UInt`.
265+
have the same stride as `UInt` and must have an alignment less than or equal to
266+
that of `UInt`.
278267

279268
When you are done configuring your type's protocol conformance, you can then
280269
enumerate all test content records matching it as instances of

Package.swift

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// swift-tools-version: 6.0
1+
// swift-tools-version: 6.1
22

33
//
44
// This source file is part of the Swift.org open source project
55
//
6-
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Copyright (c) 2023–2025 Apple Inc. and the Swift project authors
77
// Licensed under Apache License v2.0 with Runtime Library Exception
88
//
99
// See https://swift.org/LICENSE.txt for license information
@@ -95,8 +95,15 @@ let package = Package(
9595
return result
9696
}(),
9797

98+
traits: [
99+
.trait(
100+
name: "ExperimentalExitTestValueCapture",
101+
description: "Enable experimental support for capturing values in exit tests"
102+
),
103+
],
104+
98105
dependencies: [
99-
.package(url: "https://github.com/swiftlang/swift-syntax.git", from: "601.0.0-latest"),
106+
.package(url: "https://github.com/swiftlang/swift-syntax.git", from: "602.0.0-latest"),
100107
],
101108

102109
targets: [
@@ -171,7 +178,7 @@ let package = Package(
171178
dependencies: ["_TestingInternals",],
172179
exclude: ["CMakeLists.txt"],
173180
cxxSettings: .packageSettings,
174-
swiftSettings: .packageSettings
181+
swiftSettings: .packageSettings + .enableLibraryEvolution()
175182
),
176183

177184
// Cross-import overlays (not supported by Swift Package Manager)
@@ -239,8 +246,9 @@ extension BuildSettingCondition {
239246
if let nonEmbeddedCondition = nonEmbeddedCondition() {
240247
nonEmbeddedCondition
241248
} else {
242-
// The caller did not supply a fallback.
243-
.when(platforms: [])
249+
// The caller did not supply a fallback. Specify a non-existent platform
250+
// to ensure this condition never matches.
251+
.when(platforms: [.custom("DoesNotExist")])
244252
}
245253
} else {
246254
// Enable unconditionally because the target is Embedded Swift.
@@ -277,6 +285,17 @@ extension Array where Element == PackageDescription.SwiftSetting {
277285
// proposal via Swift Evolution.
278286
.enableExperimentalFeature("SymbolLinkageMarkers"),
279287

288+
// This setting is no longer needed when building with a 6.2 or later
289+
// toolchain now that SE-0458 has been accepted and implemented, but it is
290+
// needed in order to preserve support for building with 6.1 development
291+
// snapshot toolchains. (Production 6.1 toolchains can build the testing
292+
// library even without this setting since this experimental feature is
293+
// _suppressible_.) This setting can be removed once the minimum supported
294+
// toolchain for building the testing library is ≥ 6.2. It is not needed
295+
// in the CMake settings since that is expected to build using a
296+
// new-enough toolchain.
297+
.enableExperimentalFeature("AllowUnsafeAttribute"),
298+
280299
// When building as a package, the macro plugin always builds as an
281300
// executable rather than a library.
282301
.define("SWT_NO_LIBRARY_MACRO_PLUGINS"),
@@ -293,6 +312,14 @@ extension Array where Element == PackageDescription.SwiftSetting {
293312
.define("SWT_NO_LIBDISPATCH", .whenEmbedded()),
294313
]
295314

315+
// Unconditionally enable 'ExperimentalExitTestValueCapture' when building
316+
// for development.
317+
if buildingForDevelopment {
318+
result += [
319+
.define("ExperimentalExitTestValueCapture")
320+
]
321+
}
322+
296323
return result
297324
}
298325

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,15 @@ very best ideas, from anywhere, can help shape the future of testing in Swift.
9393
The table below describes the current level of support that Swift Testing has
9494
for various platforms:
9595

96-
| **Platform** | **CI Status (6.0)** | **CI Status (main)** | **Support Status** |
96+
| **Platform** | **CI Status (6.1)** | **CI Status (main)** | **Support Status** |
9797
|---|:-:|:-:|---|
98-
| **macOS** | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-6.0-macos)](https://ci.swift.org/job/swift-testing-main-swift-6.0-macos/) | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-main-macos)](https://ci.swift.org/view/Swift%20Packages/job/swift-testing-main-swift-main-macos/) | Supported |
98+
| **macOS** | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-6.1-macos)](https://ci.swift.org/job/swift-testing-main-swift-6.1-macos/) | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-main-macos)](https://ci.swift.org/view/Swift%20Packages/job/swift-testing-main-swift-main-macos/) | Supported |
9999
| **iOS** | | | Supported |
100100
| **watchOS** | | | Supported |
101101
| **tvOS** | | | Supported |
102102
| **visionOS** | | | Supported |
103-
| **Ubuntu 22.04** | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-6.0-linux)](https://ci.swift.org/job/swift-testing-main-swift-6.0-linux/) | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-main-linux)](https://ci.swift.org/view/Swift%20Packages/job/swift-testing-main-swift-main-linux/) | Supported |
104-
| **Windows** | | [![Build Status](https://ci-external.swift.org/buildStatus/icon?job=swift-testing-main-swift-main-windows)](https://ci-external.swift.org/job/swift-testing-main-swift-main-windows/) | Supported |
103+
| **Ubuntu 22.04** | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-6.1-linux)](https://ci.swift.org/job/swift-testing-main-swift-6.1-linux/) | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-main-linux)](https://ci.swift.org/view/Swift%20Packages/job/swift-testing-main-swift-main-linux/) | Supported |
104+
| **Windows** | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-6.1-windows)](https://ci-external.swift.org/view/all/job/swift-testing-main-swift-6.1-windows/) | [![Build Status](https://ci-external.swift.org/buildStatus/icon?job=swift-testing-main-swift-main-windows)](https://ci-external.swift.org/job/swift-testing-main-swift-main-windows/) | Supported |
105105
| **Wasm** | | | Experimental |
106106

107107
### Works with XCTest

Sources/Overlays/_Testing_CoreGraphics/Attachments/Attachment+AttachableAsCGImage.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ extension Attachment {
4242
contentType: (any Sendable)?,
4343
encodingQuality: Float,
4444
sourceLocation: SourceLocation
45-
) where AttachableValue == _AttachableImageContainer<T> {
46-
let imageContainer = _AttachableImageContainer(image: attachableValue, encodingQuality: encodingQuality, contentType: contentType)
47-
self.init(imageContainer, named: preferredName, sourceLocation: sourceLocation)
45+
) where AttachableValue == _AttachableImageWrapper<T> {
46+
let imageWrapper = _AttachableImageWrapper(image: attachableValue, encodingQuality: encodingQuality, contentType: contentType)
47+
self.init(imageWrapper, named: preferredName, sourceLocation: sourceLocation)
4848
}
4949

5050
/// Initialize an instance of this type that encloses the given image.
@@ -79,7 +79,7 @@ extension Attachment {
7979
as contentType: UTType?,
8080
encodingQuality: Float = 1.0,
8181
sourceLocation: SourceLocation = #_sourceLocation
82-
) where AttachableValue == _AttachableImageContainer<T> {
82+
) where AttachableValue == _AttachableImageWrapper<T> {
8383
self.init(attachableValue: attachableValue, named: preferredName, contentType: contentType, encodingQuality: encodingQuality, sourceLocation: sourceLocation)
8484
}
8585

@@ -109,7 +109,7 @@ extension Attachment {
109109
named preferredName: String? = nil,
110110
encodingQuality: Float = 1.0,
111111
sourceLocation: SourceLocation = #_sourceLocation
112-
) where AttachableValue == _AttachableImageContainer<T> {
112+
) where AttachableValue == _AttachableImageWrapper<T> {
113113
self.init(attachableValue: attachableValue, named: preferredName, contentType: nil, encodingQuality: encodingQuality, sourceLocation: sourceLocation)
114114
}
115115
}

Sources/Overlays/_Testing_CoreGraphics/Attachments/_AttachableImageContainer.swift renamed to Sources/Overlays/_Testing_CoreGraphics/Attachments/_AttachableImageWrapper.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//
1010

1111
#if SWT_TARGET_OS_APPLE && canImport(CoreGraphics)
12-
@_spi(Experimental) public import Testing
12+
public import Testing
1313
private import CoreGraphics
1414

1515
private import ImageIO
@@ -48,7 +48,7 @@ import UniformTypeIdentifiers
4848
///
4949
/// - [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage)
5050
@_spi(Experimental)
51-
public struct _AttachableImageContainer<Image>: Sendable where Image: AttachableAsCGImage {
51+
public struct _AttachableImageWrapper<Image>: Sendable where Image: AttachableAsCGImage {
5252
/// The underlying image.
5353
///
5454
/// `CGImage` and `UIImage` are sendable, but `NSImage` is not. `NSImage`
@@ -127,8 +127,8 @@ public struct _AttachableImageContainer<Image>: Sendable where Image: Attachable
127127

128128
// MARK: -
129129

130-
extension _AttachableImageContainer: AttachableContainer {
131-
public var attachableValue: Image {
130+
extension _AttachableImageWrapper: AttachableWrapper {
131+
public var wrappedValue: Image {
132132
image
133133
}
134134

Sources/Overlays/_Testing_Foundation/Attachments/Attachable+Encodable+NSSecureCoding.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//
1010

1111
#if canImport(Foundation)
12-
@_spi(Experimental) public import Testing
12+
public import Testing
1313
public import Foundation
1414

1515
// This implementation is necessary to let the compiler disambiguate when a type
@@ -18,7 +18,9 @@ public import Foundation
1818
// (which explicitly document what happens when a type conforms to both
1919
// protocols.)
2020

21-
@_spi(Experimental)
21+
/// @Metadata {
22+
/// @Available(Swift, introduced: 6.2)
23+
/// }
2224
extension Attachable where Self: Encodable & NSSecureCoding {
2325
@_documentation(visibility: private)
2426
public func withUnsafeBytes<R>(for attachment: borrowing Attachment<Self>, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R {

Sources/Overlays/_Testing_Foundation/Attachments/Attachable+Encodable.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//
1010

1111
#if canImport(Foundation)
12-
@_spi(Experimental) public import Testing
12+
public import Testing
1313
private import Foundation
1414

1515
/// A common implementation of ``withUnsafeBytes(for:_:)`` that is used when a
@@ -53,7 +53,10 @@ func withUnsafeBytes<E, R>(encoding attachableValue: borrowing E, for attachment
5353
// Implement the protocol requirements generically for any encodable value by
5454
// encoding to JSON. This lets developers provide trivial conformance to the
5555
// protocol for types that already support Codable.
56-
@_spi(Experimental)
56+
57+
/// @Metadata {
58+
/// @Available(Swift, introduced: 6.2)
59+
/// }
5760
extension Attachable where Self: Encodable {
5861
/// Encode this value into a buffer using either [`PropertyListEncoder`](https://developer.apple.com/documentation/foundation/propertylistencoder)
5962
/// or [`JSONEncoder`](https://developer.apple.com/documentation/foundation/jsonencoder),
@@ -86,6 +89,10 @@ extension Attachable where Self: Encodable {
8689
/// _and_ [`NSSecureCoding`](https://developer.apple.com/documentation/foundation/nssecurecoding),
8790
/// the default implementation of this function uses the value's conformance
8891
/// to `Encodable`.
92+
///
93+
/// @Metadata {
94+
/// @Available(Swift, introduced: 6.2)
95+
/// }
8996
public func withUnsafeBytes<R>(for attachment: borrowing Attachment<Self>, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R {
9097
try _Testing_Foundation.withUnsafeBytes(encoding: self, for: attachment, body)
9198
}

Sources/Overlays/_Testing_Foundation/Attachments/Attachable+NSSecureCoding.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
//
1010

1111
#if canImport(Foundation)
12-
@_spi(Experimental) public import Testing
12+
public import Testing
1313
public import Foundation
1414

1515
// As with Encodable, implement the protocol requirements for
1616
// NSSecureCoding-conformant classes by default. The implementation uses
1717
// NSKeyedArchiver for encoding.
18-
@_spi(Experimental)
18+
19+
/// @Metadata {
20+
/// @Available(Swift, introduced: 6.2)
21+
/// }
1922
extension Attachable where Self: NSSecureCoding {
2023
/// Encode this object using [`NSKeyedArchiver`](https://developer.apple.com/documentation/foundation/nskeyedarchiver)
2124
/// into a buffer, then call a function and pass that buffer to it.
@@ -46,6 +49,10 @@ extension Attachable where Self: NSSecureCoding {
4649
/// _and_ [`NSSecureCoding`](https://developer.apple.com/documentation/foundation/nssecurecoding),
4750
/// the default implementation of this function uses the value's conformance
4851
/// to `Encodable`.
52+
///
53+
/// @Metadata {
54+
/// @Available(Swift, introduced: 6.2)
55+
/// }
4956
public func withUnsafeBytes<R>(for attachment: borrowing Attachment<Self>, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R {
5057
let format = try EncodingFormat(for: attachment)
5158

Sources/Overlays/_Testing_Foundation/Attachments/Attachment+URL.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//
1010

1111
#if canImport(Foundation)
12-
@_spi(Experimental) public import Testing
12+
public import Testing
1313
public import Foundation
1414

1515
#if !SWT_NO_PROCESS_SPAWNING && os(Windows)
@@ -32,8 +32,7 @@ extension URL {
3232
}
3333
}
3434

35-
@_spi(Experimental)
36-
extension Attachment where AttachableValue == _AttachableURLContainer {
35+
extension Attachment where AttachableValue == _AttachableURLWrapper {
3736
#if SWT_TARGET_OS_APPLE
3837
/// An operation queue to use for asynchronously reading data from disk.
3938
private static let _operationQueue = OperationQueue()
@@ -51,6 +50,10 @@ extension Attachment where AttachableValue == _AttachableURLContainer {
5150
/// attachment.
5251
///
5352
/// - Throws: Any error that occurs attempting to read from `url`.
53+
///
54+
/// @Metadata {
55+
/// @Available(Swift, introduced: 6.2)
56+
/// }
5457
public init(
5558
contentsOf url: URL,
5659
named preferredName: String? = nil,
@@ -91,8 +94,8 @@ extension Attachment where AttachableValue == _AttachableURLContainer {
9194
}
9295
#endif
9396

94-
let urlContainer = _AttachableURLContainer(url: url, data: data, isCompressedDirectory: isDirectory)
95-
self.init(urlContainer, named: preferredName, sourceLocation: sourceLocation)
97+
let urlWrapper = _AttachableURLWrapper(url: url, data: data, isCompressedDirectory: isDirectory)
98+
self.init(urlWrapper, named: preferredName, sourceLocation: sourceLocation)
9699
}
97100
}
98101

Sources/Overlays/_Testing_Foundation/Attachments/Data+Attachable.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,16 @@
99
//
1010

1111
#if canImport(Foundation)
12-
@_spi(Experimental) public import Testing
12+
public import Testing
1313
public import Foundation
1414

15-
@_spi(Experimental)
15+
/// @Metadata {
16+
/// @Available(Swift, introduced: 6.2)
17+
/// }
1618
extension Data: Attachable {
19+
/// @Metadata {
20+
/// @Available(Swift, introduced: 6.2)
21+
/// }
1722
public func withUnsafeBytes<R>(for attachment: borrowing Attachment<Self>, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R {
1823
try withUnsafeBytes(body)
1924
}

Sources/Overlays/_Testing_Foundation/Attachments/EncodingFormat.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//
1010

1111
#if canImport(Foundation)
12-
@_spi(Experimental) import Testing
12+
import Testing
1313
import Foundation
1414

1515
/// An enumeration describing the encoding formats we support for `Encodable`

0 commit comments

Comments
 (0)