@@ -41,7 +41,7 @@ final class TransactionTests: XCTestCase {
41
41
guard let preparedRequest = maybePreparedRequest else {
42
42
return XCTFail ( " Expected to have a request here. " )
43
43
}
44
- let ( transaction, responseTask) = Transaction . makeWithResultTask (
44
+ let ( transaction, responseTask) = await Transaction . makeWithResultTask (
45
45
request: preparedRequest,
46
46
preferredEventLoop: embeddedEventLoop
47
47
)
@@ -78,7 +78,7 @@ final class TransactionTests: XCTestCase {
78
78
guard let preparedRequest = maybePreparedRequest else {
79
79
return
80
80
}
81
- let ( transaction, responseTask) = Transaction . makeWithResultTask (
81
+ let ( transaction, responseTask) = await Transaction . makeWithResultTask (
82
82
request: preparedRequest,
83
83
preferredEventLoop: embeddedEventLoop
84
84
)
@@ -141,7 +141,7 @@ final class TransactionTests: XCTestCase {
141
141
guard let preparedRequest = maybePreparedRequest else {
142
142
return
143
143
}
144
- var tuple : ( Transaction , Task < HTTPClientResponse , Error > ) ! = Transaction . makeWithResultTask (
144
+ var tuple : ( Transaction , Task < HTTPClientResponse , Error > ) ! = await Transaction . makeWithResultTask (
145
145
request: preparedRequest,
146
146
preferredEventLoop: embeddedEventLoop
147
147
)
@@ -196,7 +196,7 @@ final class TransactionTests: XCTestCase {
196
196
guard let preparedRequest = maybePreparedRequest else {
197
197
return XCTFail ( " Expected to have a request here. " )
198
198
}
199
- let ( transaction, responseTask) = Transaction . makeWithResultTask (
199
+ let ( transaction, responseTask) = await Transaction . makeWithResultTask (
200
200
request: preparedRequest,
201
201
preferredEventLoop: embeddedEventLoop
202
202
)
@@ -282,7 +282,7 @@ final class TransactionTests: XCTestCase {
282
282
guard let preparedRequest = maybePreparedRequest else {
283
283
return XCTFail ( " Expected to have a request here. " )
284
284
}
285
- let ( transaction, responseTask) = Transaction . makeWithResultTask (
285
+ let ( transaction, responseTask) = await Transaction . makeWithResultTask (
286
286
request: preparedRequest,
287
287
preferredEventLoop: eventLoopGroup. next ( )
288
288
)
@@ -324,7 +324,7 @@ final class TransactionTests: XCTestCase {
324
324
guard let preparedRequest = maybePreparedRequest else {
325
325
return XCTFail ( " Expected to have a request here. " )
326
326
}
327
- let ( transaction, responseTask) = Transaction . makeWithResultTask (
327
+ let ( transaction, responseTask) = await Transaction . makeWithResultTask (
328
328
request: preparedRequest,
329
329
preferredEventLoop: embeddedEventLoop
330
330
)
@@ -366,7 +366,7 @@ final class TransactionTests: XCTestCase {
366
366
guard let preparedRequest = maybePreparedRequest else {
367
367
return XCTFail ( " Expected to have a request here. " )
368
368
}
369
- let ( transaction, responseTask) = Transaction . makeWithResultTask (
369
+ let ( transaction, responseTask) = await Transaction . makeWithResultTask (
370
370
request: preparedRequest,
371
371
preferredEventLoop: embeddedEventLoop
372
372
)
@@ -397,7 +397,7 @@ final class TransactionTests: XCTestCase {
397
397
func testResponseStreamFails( ) {
398
398
#if compiler(>=5.5.2) && canImport(_Concurrency)
399
399
guard #available( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * ) else { return }
400
- XCTAsyncTest {
400
+ XCTAsyncTest ( timeout : 30 ) {
401
401
let embeddedEventLoop = EmbeddedEventLoop ( )
402
402
defer { XCTAssertNoThrow ( try embeddedEventLoop. syncShutdownGracefully ( ) ) }
403
403
@@ -409,7 +409,7 @@ final class TransactionTests: XCTestCase {
409
409
guard let preparedRequest = maybePreparedRequest else {
410
410
return
411
411
}
412
- let ( transaction, responseTask) = Transaction . makeWithResultTask (
412
+ let ( transaction, responseTask) = await Transaction . makeWithResultTask (
413
413
request: preparedRequest,
414
414
preferredEventLoop: embeddedEventLoop
415
415
)
@@ -427,6 +427,7 @@ final class TransactionTests: XCTestCase {
427
427
transaction. receiveResponseHead ( responseHead)
428
428
429
429
let response = try await responseTask. value
430
+
430
431
XCTAssertEqual ( response. status, responseHead. status)
431
432
XCTAssertEqual ( response. headers, responseHead. headers)
432
433
XCTAssertEqual ( response. version, responseHead. version)
@@ -438,6 +439,7 @@ final class TransactionTests: XCTestCase {
438
439
XCTAssertNoThrow ( try executor. receiveResponseDemand ( ) )
439
440
executor. resetResponseStreamDemandSignal ( )
440
441
transaction. receiveResponseBodyParts ( [ ByteBuffer ( integer: 123 ) ] )
442
+
441
443
let result = try await part1
442
444
XCTAssertEqual ( result, ByteBuffer ( integer: 123 ) )
443
445
@@ -493,7 +495,7 @@ final class TransactionTests: XCTestCase {
493
495
guard let preparedRequest = maybePreparedRequest else {
494
496
return
495
497
}
496
- let ( transaction, responseTask) = Transaction . makeWithResultTask (
498
+ let ( transaction, responseTask) = await Transaction . makeWithResultTask (
497
499
request: preparedRequest,
498
500
preferredEventLoop: eventLoopGroup. next ( )
499
501
)
@@ -553,6 +555,45 @@ actor SharedIterator<Iterator: AsyncIteratorProtocol> {
553
555
}
554
556
}
555
557
558
+ /// non fail-able promise that only supports one observer
559
+ @available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
560
+ fileprivate actor Promise < Value> {
561
+ private enum State {
562
+ case initialised
563
+ case fulfilled( Value )
564
+ }
565
+
566
+ private var state : State = . initialised
567
+
568
+ private var observer : CheckedContinuation < Value , Never > ?
569
+
570
+ init ( ) { }
571
+
572
+ func fulfil( _ value: Value ) {
573
+ switch self . state {
574
+ case . initialised:
575
+ self . state = . fulfilled( value)
576
+ self . observer? . resume ( returning: value)
577
+ case . fulfilled:
578
+ preconditionFailure ( " \( Self . self) over fulfilled " )
579
+ }
580
+ }
581
+
582
+ var value : Value {
583
+ get async {
584
+ switch self . state {
585
+ case . initialised:
586
+ return await withCheckedContinuation { ( continuation: CheckedContinuation < Value , Never > ) in
587
+ precondition ( self . observer == nil , " \( Self . self) supports only one observer " )
588
+ self . observer = continuation
589
+ }
590
+ case . fulfilled( let value) :
591
+ return value
592
+ }
593
+ }
594
+ }
595
+ }
596
+
556
597
@available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
557
598
extension Transaction {
558
599
fileprivate static func makeWithResultTask(
@@ -561,9 +602,9 @@ extension Transaction {
561
602
logger: Logger = Logger ( label: " test " ) ,
562
603
connectionDeadline: NIODeadline = . distantFuture,
563
604
preferredEventLoop: EventLoop
564
- ) -> ( Transaction , _Concurrency . Task < HTTPClientResponse , Error > ) {
565
- let transactionPromise = preferredEventLoop . makePromise ( of : Transaction . self )
566
- let result = Task {
605
+ ) async -> ( Transaction , _Concurrency . Task < HTTPClientResponse , Error > ) {
606
+ let transactionPromise = Promise < Transaction > ( )
607
+ let task = Task {
567
608
try await withCheckedThrowingContinuation { ( continuation: CheckedContinuation < HTTPClientResponse , Error > ) in
568
609
let transaction = Transaction (
569
610
request: request,
@@ -573,13 +614,13 @@ extension Transaction {
573
614
preferredEventLoop: preferredEventLoop,
574
615
responseContinuation: continuation
575
616
)
576
- transactionPromise. succeed ( transaction)
617
+ Task {
618
+ await transactionPromise. fulfil ( transaction)
619
+ }
577
620
}
578
621
}
579
- // the promise can never fail and it is therefore safe to force unwrap
580
- let transaction = try ! transactionPromise. futureResult. wait ( )
581
622
582
- return ( transaction , result )
623
+ return ( await transactionPromise . value , task )
583
624
}
584
625
}
585
626
#endif
0 commit comments