@@ -15,19 +15,12 @@ private import _TestingInternals
15
15
struct AttachmentTests {
16
16
@Test func saveValue( ) {
17
17
let attachableValue = MyAttachable ( string: " <!doctype html> " )
18
- Test . Attachment ( attachableValue, named: " AttachmentTests.saveValue.html " ) . attach ( )
18
+ let attachment = Test . Attachment ( attachableValue, named: " AttachmentTests.saveValue.html " )
19
+ attachment. attach ( )
19
20
}
20
21
21
22
#if !SWT_NO_FILE_IO
22
- @Test func writeAttachment( ) throws {
23
- let attachableValue = MyAttachable ( string: " <!doctype html> " )
24
- let attachment = Test . Attachment ( attachableValue, named: " loremipsum.html " )
25
-
26
- // Write the attachment to disk, then read it back.
27
- let filePath = try attachment. write ( toFileInDirectoryAtPath: temporaryDirectoryPath ( ) )
28
- defer {
29
- remove ( filePath)
30
- }
23
+ func compare( _ attachableValue: borrowing MyAttachable , toContentsOfFileAtPath filePath: String ) throws {
31
24
let file = try FileHandle ( forReadingAtPath: filePath)
32
25
let bytes = try file. readToEnd ( )
33
26
@@ -39,6 +32,18 @@ struct AttachmentTests {
39
32
#expect( decodedValue == attachableValue. string)
40
33
}
41
34
35
+ @Test func writeAttachment( ) throws {
36
+ let attachableValue = MyAttachable ( string: " <!doctype html> " )
37
+ let attachment = Test . Attachment ( attachableValue, named: " loremipsum.html " )
38
+
39
+ // Write the attachment to disk, then read it back.
40
+ let filePath = try attachment. write ( toFileInDirectoryAtPath: temporaryDirectoryPath ( ) )
41
+ defer {
42
+ remove ( filePath)
43
+ }
44
+ try compare ( attachableValue, toContentsOfFileAtPath: filePath)
45
+ }
46
+
42
47
@Test func writeAttachmentWithNameConflict( ) throws {
43
48
// A sequence of suffixes that are guaranteed to cause conflict.
44
49
let randomBaseValue = UInt64 . random ( in: 0 ..< ( . max - 10 ) )
@@ -67,15 +72,7 @@ struct AttachmentTests {
67
72
} else {
68
73
#expect( fileName != baseFileName)
69
74
}
70
- let file = try FileHandle ( forReadingAtPath: filePath)
71
- let bytes = try file. readToEnd ( )
72
-
73
- let decodedValue = if #available( macOS 15 . 0 , iOS 18 . 0 , watchOS 11 . 0 , tvOS 18 . 0 , visionOS 2 . 0 , * ) {
74
- try #require( String ( validating: bytes, as: UTF8 . self) )
75
- } else {
76
- String ( decoding: bytes, as: UTF8 . self)
77
- }
78
- #expect( decodedValue == attachableValue. string)
75
+ try compare ( attachableValue, toContentsOfFileAtPath: filePath)
79
76
}
80
77
}
81
78
@@ -98,6 +95,32 @@ struct AttachmentTests {
98
95
}
99
96
let fileName = try #require( filePath. split { $0 == " / " || $0 == #"\"# } . last)
100
97
#expect( fileName == " loremipsum- \( suffix) .tar.gz.gif.jpeg.html " )
98
+ try compare ( attachableValue, toContentsOfFileAtPath: filePath)
99
+ }
100
+
101
+ #if os(Windows)
102
+ static let maximumNameCount = Int ( _MAX_FNAME)
103
+ static let reservedNames = [ " CON " , " COM0 " , " LPT2 " ]
104
+ #else
105
+ static let maximumNameCount = Int ( NAME_MAX)
106
+ static let reservedNames : [ String ] = [ ]
107
+ #endif
108
+
109
+ @Test ( arguments: [
110
+ #"/\:"# ,
111
+ String ( repeating: " a " , count: maximumNameCount) ,
112
+ String ( repeating: " a " , count: maximumNameCount + 1 ) ,
113
+ String ( repeating: " a " , count: maximumNameCount + 2 ) ,
114
+ ] + reservedNames) func writeAttachmentWithBadName( name: String ) throws {
115
+ let attachableValue = MyAttachable ( string: " <!doctype html> " )
116
+ let attachment = Test . Attachment ( attachableValue, named: name)
117
+
118
+ // Write the attachment to disk, then read it back.
119
+ let filePath = try attachment. write ( toFileInDirectoryAtPath: temporaryDirectoryPath ( ) )
120
+ defer {
121
+ remove ( filePath)
122
+ }
123
+ try compare ( attachableValue, toContentsOfFileAtPath: filePath)
101
124
}
102
125
#endif
103
126
@@ -132,14 +155,82 @@ struct AttachmentTests {
132
155
}
133
156
}
134
157
}
158
+
159
+ @Test func issueRecordedWhenAttachingNonSendableValueThatThrows( ) async {
160
+ await confirmation ( " Attachment detected " ) { valueAttached in
161
+ await confirmation ( " Issue recorded " ) { issueRecorded in
162
+ await Test {
163
+ var attachableValue = MyAttachable ( string: " <!doctype html> " )
164
+ attachableValue. errorToThrow = MyError ( )
165
+ Test . Attachment ( attachableValue, named: " loremipsum " ) . attach ( )
166
+ } . run { event, _ in
167
+ if case . valueAttached = event. kind {
168
+ valueAttached ( )
169
+ } else if case let . issueRecorded( issue) = event. kind,
170
+ case let . errorCaught( error) = issue. kind,
171
+ error is MyError {
172
+ issueRecorded ( )
173
+ }
174
+ }
175
+ }
176
+ }
177
+ }
178
+ }
179
+
180
+ extension AttachmentTests {
181
+ @Suite ( " Built-in conformances " )
182
+ struct BuiltInConformances {
183
+ func test( _ value: borrowing some Test . Attachable & ~ Copyable) throws {
184
+ #expect( value. estimatedAttachmentByteCount == 6 )
185
+ let attachment = Test . Attachment ( value)
186
+ try attachment. attachableValue. withUnsafeBufferPointer ( for: attachment) { buffer in
187
+ #expect( buffer. elementsEqual ( " abc123 " . utf8) )
188
+ #expect( buffer. count == 6 )
189
+ }
190
+ }
191
+
192
+ @Test func uint8Array( ) throws {
193
+ let value : [ UInt8 ] = Array ( " abc123 " . utf8)
194
+ try test ( value)
195
+ }
196
+
197
+ @Test func uint8UnsafeBufferPointer( ) throws {
198
+ let value : [ UInt8 ] = Array ( " abc123 " . utf8)
199
+ try value. withUnsafeBufferPointer { value in
200
+ try test ( value)
201
+ }
202
+ }
203
+
204
+ @Test func unsafeRawBufferPointer( ) throws {
205
+ let value : [ UInt8 ] = Array ( " abc123 " . utf8)
206
+ try value. withUnsafeBytes { value in
207
+ try test ( value)
208
+ }
209
+ }
210
+
211
+ @Test func string( ) throws {
212
+ let value = " abc123 "
213
+ try test ( value)
214
+ }
215
+
216
+ @Test func substring( ) throws {
217
+ let value : Substring = " abc123 " [ ... ]
218
+ try test ( value)
219
+ }
220
+ }
135
221
}
136
222
137
223
// MARK: - Fixtures
138
224
139
225
struct MyAttachable : Test . Attachable , ~ Copyable {
140
226
var string : String
227
+ var errorToThrow : ( any Error ) ?
141
228
142
229
func withUnsafeBufferPointer< R> ( for attachment: borrowing Testing . Test . Attachment , _ body: ( UnsafeRawBufferPointer ) throws -> R ) throws -> R {
230
+ if let errorToThrow {
231
+ throw errorToThrow
232
+ }
233
+
143
234
var string = string
144
235
return try string. withUTF8 { buffer in
145
236
try body ( . init( buffer) )
@@ -160,3 +251,14 @@ struct MySendableAttachable: Test.Attachable, Sendable {
160
251
}
161
252
}
162
253
}
254
+
255
+ struct MySendableAttachableWithDefaultByteCount : Test . Attachable , Sendable {
256
+ var string : String
257
+
258
+ func withUnsafeBufferPointer< R> ( for attachment: borrowing Testing . Test . Attachment , _ body: ( UnsafeRawBufferPointer ) throws -> R ) throws -> R {
259
+ var string = string
260
+ return try string. withUTF8 { buffer in
261
+ try body ( . init( buffer) )
262
+ }
263
+ }
264
+ }
0 commit comments