Skip to content

Commit 4e1128d

Browse files
committed
[WIP] CoreTransferable attachments
1 parent 1f2893c commit 4e1128d

File tree

7 files changed

+165
-0
lines changed

7 files changed

+165
-0
lines changed

Package.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ let package = Package(
162162
"_Testing_AppKit",
163163
"_Testing_CoreGraphics",
164164
"_Testing_CoreImage",
165+
"_Testing_CoreTransferable",
165166
"_Testing_Foundation",
166167
"_Testing_UIKit",
167168
"_Testing_WinSDK",
@@ -264,6 +265,15 @@ let package = Package(
264265
exclude: ["CMakeLists.txt"],
265266
swiftSettings: .packageSettings + .enableLibraryEvolution() + .moduleABIName("_Testing_CoreImage")
266267
),
268+
.target(
269+
name: "_Testing_CoreTransferable",
270+
dependencies: [
271+
"Testing",
272+
],
273+
path: "Sources/Overlays/_Testing_CoreTransferable",
274+
exclude: ["CMakeLists.txt"],
275+
swiftSettings: .packageSettings + .enableLibraryEvolution() + .moduleABIName("_Testing_CoreTransferable")
276+
),
267277
.target(
268278
name: "_Testing_Foundation",
269279
dependencies: [

Sources/Overlays/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
add_subdirectory(_Testing_AppKit)
1010
add_subdirectory(_Testing_CoreGraphics)
1111
add_subdirectory(_Testing_CoreImage)
12+
add_subdirectory(_Testing_CoreTransferable)
1213
add_subdirectory(_Testing_Foundation)
1314
add_subdirectory(_Testing_UIKit)
1415
add_subdirectory(_Testing_WinSDK)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// This source file is part of the Swift.org open source project
3+
//
4+
// Copyright (c) 2026 Apple Inc. and the Swift project authors
5+
// Licensed under Apache License v2.0 with Runtime Library Exception
6+
//
7+
// See https://swift.org/LICENSE.txt for license information
8+
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
//
10+
11+
#if canImport(CoreTransferable)
12+
public import Testing
13+
public import CoreTransferable
14+
15+
public import UniformTypeIdentifiers
16+
17+
@_spi(Experimental)
18+
@available(macOS 15.2, *)
19+
extension Attachment {
20+
/// Initialize an instance of this type that encloses the given transferable
21+
/// value.
22+
///
23+
/// - Parameters:
24+
/// - transferableValue: The value that will be attached to the output of
25+
/// the test run.
26+
/// - preferredName: The preferred name of the attachment to use when saving
27+
/// it. If `nil`, the testing library attempts to generate a reasonable
28+
/// filename for the attached value.
29+
/// - sourceLocation: The source location of the call to this initializer.
30+
/// This value is used when recording issues associated with the
31+
/// attachment.
32+
///
33+
/// - Throws: Any error that occurs while exporting `transferableValue`.
34+
///
35+
/// Use this initializer to create an instance of ``Attachment`` from a value
36+
/// that conforms to the [`Transferable`](https://developer.apple.com/documentation/coretransferable/transferable)
37+
/// protocol.
38+
public init<T>(
39+
transferring transferableValue: T,
40+
as contentType: UTType? = nil,
41+
named preferredName: String? = nil,
42+
sourceLocation: SourceLocation = #_sourceLocation
43+
) async throws where T: Transferable, AttachableValue == _AttachableTransferableWrapper<T> {
44+
let transferableWrapper = try await _AttachableTransferableWrapper(transferring: transferableValue, as: contentType)
45+
self.init(transferableWrapper, named: preferredName, sourceLocation: sourceLocation)
46+
}
47+
}
48+
#endif
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//
2+
// This source file is part of the Swift.org open source project
3+
//
4+
// Copyright (c) 2026 Apple Inc. and the Swift project authors
5+
// Licensed under Apache License v2.0 with Runtime Library Exception
6+
//
7+
// See https://swift.org/LICENSE.txt for license information
8+
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
//
10+
11+
#if canImport(CoreTransferable)
12+
public import Testing
13+
public import CoreTransferable
14+
15+
private import Foundation
16+
import UniformTypeIdentifiers
17+
18+
private enum TransferableAttachmentError: Error {
19+
case suitableContentTypeNotFound
20+
}
21+
22+
/// A wrapper type representing transferable values that can be attached
23+
/// indirectly.
24+
///
25+
/// You do not need to use this type directly. Instead, initialize an instance
26+
/// of ``Attachment`` using an instance of a type conforming to the [`Transferable`](https://developer.apple.com/documentation/coretransferable/transferable)
27+
/// protocol.
28+
@_spi(Experimental)
29+
@available(macOS 15.2, *)
30+
public struct _AttachableTransferableWrapper<T>: Sendable where T: Transferable {
31+
private var _transferableValue: T
32+
private var _contentType: UTType
33+
private var _bytes: Data
34+
35+
init(transferring transferableValue: T, as contentType: UTType?) async throws {
36+
_transferableValue = transferableValue
37+
38+
let contentType = contentType ?? transferableValue.exportedContentTypes()
39+
.first { $0.conforms(to: .data) }
40+
guard let contentType else {
41+
throw TransferableAttachmentError.suitableContentTypeNotFound
42+
}
43+
_contentType = contentType
44+
45+
_bytes = try await _transferableValue.exported(as: contentType)
46+
}
47+
}
48+
49+
// MARK: -
50+
51+
@_spi(Experimental)
52+
@available(macOS 15.2, *)
53+
extension _AttachableTransferableWrapper: AttachableWrapper {
54+
public var wrappedValue: T {
55+
_transferableValue
56+
}
57+
58+
public func withUnsafeBytes<R>(for attachment: borrowing Attachment<Self>, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R {
59+
try _bytes.withUnsafeBytes(body)
60+
}
61+
62+
public borrowing func preferredName(for attachment: borrowing Attachment<Self>, basedOn suggestedName: String) -> String {
63+
let baseName = _transferableValue.suggestedFilename ?? suggestedName
64+
return (baseName as NSString).appendingPathExtension(for: _contentType)
65+
}
66+
}
67+
#endif
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# This source file is part of the Swift.org open source project
2+
#
3+
# Copyright (c) 2026 Apple Inc. and the Swift project authors
4+
# Licensed under Apache License v2.0 with Runtime Library Exception
5+
#
6+
# See https://swift.org/LICENSE.txt for license information
7+
# See https://swift.org/CONTRIBUTORS.txt for Swift project authors
8+
9+
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
10+
include(ModuleABIName)
11+
add_library(_Testing_CoreTransferable
12+
Attachments/_AttachableTransferableWrapper.swift
13+
Attachments/Attachment+Transferable.swift
14+
ReexportTesting.swift)
15+
16+
target_link_libraries(_Testing_CoreTransferable PUBLIC
17+
Testing
18+
_Testing_CoreGraphics)
19+
20+
target_compile_options(_Testing_CoreTransferable PRIVATE
21+
-enable-library-evolution
22+
-emit-module-interface -emit-module-interface-path $<TARGET_PROPERTY:_Testing_CoreTransferable,Swift_MODULE_DIRECTORY>/_Testing_CoreTransferable.swiftinterface)
23+
24+
_swift_testing_install_target(_Testing_CoreTransferable)
25+
endif()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//
2+
// This source file is part of the Swift.org open source project
3+
//
4+
// Copyright (c) 2026 Apple Inc. and the Swift project authors
5+
// Licensed under Apache License v2.0 with Runtime Library Exception
6+
//
7+
// See https://swift.org/LICENSE.txt for license information
8+
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
//
10+
11+
@_exported @_spi(Experimental) @_spi(ForToolsIntegrationOnly) public import Testing
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version: 1
2+
modules:
3+
- name: _Testing_CoreTransferable

0 commit comments

Comments
 (0)