1313//===----------------------------------------------------------------------===//
1414
1515import Logging
16+ import NIOConcurrencyHelpers
1617import NIOCore
1718import NIOEmbedded
1819import NIOHTTP1
@@ -833,10 +834,11 @@ class HTTP1ClientChannelHandlerTests: XCTestCase {
833834 )
834835 try channel. connect ( to: . init( ipAddress: " 127.0.0.1 " , port: 80 ) ) . wait ( )
835836
836- let request = MockHTTPExecutableRequest ( )
837837 // non empty body is important to trigger this bug as we otherwise finish the request in a single flush
838- request. requestFramingMetadata. body = . fixedSize( 1 )
839- request. raiseErrorIfUnimplementedMethodIsCalled = false
838+ let request = MockHTTPExecutableRequest (
839+ framingMetadata: RequestFramingMetadata ( connectionClose: false , body: . fixedSize( 1 ) ) ,
840+ raiseErrorIfUnimplementedMethodIsCalled: false
841+ )
840842 channel. writeAndFlush ( request, promise: nil )
841843 XCTAssertEqual ( request. events. map ( \. kind) , [ . willExecuteRequest, . requestHeadSent] )
842844 }
@@ -897,34 +899,43 @@ class HTTP1ClientChannelHandlerTests: XCTestCase {
897899 }
898900}
899901
900- class TestBackpressureWriter {
902+ final class TestBackpressureWriter : Sendable {
901903 let eventLoop : EventLoop
902904
903905 let parts : Int
904906
905907 var finishFuture : EventLoopFuture < Void > { self . finishPromise. futureResult }
906908 private let finishPromise : EventLoopPromise < Void >
907- private( set) var written : Int = 0
908909
909- private var channelIsWritable : Bool = false
910+ private struct State {
911+ var written = 0
912+ var channelIsWritable = false
913+ }
914+
915+ var written : Int {
916+ self . state. value. written
917+ }
918+
919+ private let state : NIOLoopBoundBox < State >
910920
911921 init ( eventLoop: EventLoop , parts: Int ) {
912922 self . eventLoop = eventLoop
913923 self . parts = parts
914-
924+ self . state = . makeBoxSendingValue ( State ( ) , eventLoop : eventLoop )
915925 self . finishPromise = eventLoop. makePromise ( of: Void . self)
916926 }
917927
918928 func start( writer: HTTPClient . Body . StreamWriter , expectedErrors: [ HTTPClientError ] = [ ] ) -> EventLoopFuture < Void > {
929+ @Sendable
919930 func recursive( ) {
920931 XCTAssert ( self . eventLoop. inEventLoop)
921- XCTAssert ( self . channelIsWritable)
922- if self . written == self . parts {
932+ XCTAssert ( self . state . value . channelIsWritable)
933+ if self . state . value . written == self . parts {
923934 self . finishPromise. succeed ( ( ) )
924935 } else {
925936 self . eventLoop. execute {
926937 let future = writer. write ( . byteBuffer( . init( bytes: [ 0 , 1 ] ) ) )
927- self . written += 1
938+ self . state . value . written += 1
928939 future. whenComplete { result in
929940 switch result {
930941 case . success:
@@ -951,36 +962,35 @@ class TestBackpressureWriter {
951962 }
952963
953964 func writabilityChanged( _ newValue: Bool ) {
954- self . channelIsWritable = newValue
965+ self . state . value . channelIsWritable = newValue
955966 }
956967}
957968
958- class ResponseBackpressureDelegate : HTTPClientResponseDelegate {
969+ final class ResponseBackpressureDelegate : HTTPClientResponseDelegate {
959970 typealias Response = Void
960971
961- enum State {
972+ enum State : Sendable {
962973 case consuming( EventLoopPromise < Void > )
963974 case waitingForRemote( CircularBuffer < EventLoopPromise < ByteBuffer ? > > )
964975 case buffering( ( ByteBuffer ? , EventLoopPromise < Void > ) ? )
965976 case done
966977 }
967978
968979 let eventLoop : EventLoop
969- private var state : State = . buffering ( nil )
980+ private let state : NIOLoopBoundBox < State >
970981
971982 init ( eventLoop: EventLoop ) {
972983 self . eventLoop = eventLoop
973-
974- self . state = . consuming( self . eventLoop. makePromise ( of: Void . self) )
984+ self . state = . makeBoxSendingValue( . consuming( eventLoop. makePromise ( of: Void . self) ) , eventLoop: eventLoop)
975985 }
976986
977987 func next( ) -> EventLoopFuture < ByteBuffer ? > {
978- switch self . state {
988+ switch self . state. value {
979989 case . consuming( let backpressurePromise) :
980990 var promiseBuffer = CircularBuffer < EventLoopPromise < ByteBuffer ? > > ( )
981991 let newPromise = self . eventLoop. makePromise ( of: ByteBuffer ? . self)
982992 promiseBuffer. append ( newPromise)
983- self . state = . waitingForRemote( promiseBuffer)
993+ self . state. value = . waitingForRemote( promiseBuffer)
984994 backpressurePromise. succeed ( ( ) )
985995 return newPromise. futureResult
986996
@@ -991,18 +1001,18 @@ class ResponseBackpressureDelegate: HTTPClientResponseDelegate {
9911001 )
9921002 let promise = self . eventLoop. makePromise ( of: ByteBuffer ? . self)
9931003 promiseBuffer. append ( promise)
994- self . state = . waitingForRemote( promiseBuffer)
1004+ self . state. value = . waitingForRemote( promiseBuffer)
9951005 return promise. futureResult
9961006
9971007 case . buffering( . none) :
9981008 var promiseBuffer = CircularBuffer < EventLoopPromise < ByteBuffer ? > > ( )
9991009 let promise = self . eventLoop. makePromise ( of: ByteBuffer ? . self)
10001010 promiseBuffer. append ( promise)
1001- self . state = . waitingForRemote( promiseBuffer)
1011+ self . state. value = . waitingForRemote( promiseBuffer)
10021012 return promise. futureResult
10031013
10041014 case . buffering( . some( ( let buffer, let promise) ) ) :
1005- self . state = . buffering( nil )
1015+ self . state. value = . buffering( nil )
10061016 promise. succeed ( ( ) )
10071017 return self . eventLoop. makeSucceededFuture ( buffer)
10081018
@@ -1012,7 +1022,7 @@ class ResponseBackpressureDelegate: HTTPClientResponseDelegate {
10121022 }
10131023
10141024 func didReceiveHead( task: HTTPClient . Task < Void > , _ head: HTTPResponseHead ) -> EventLoopFuture < Void > {
1015- switch self . state {
1025+ switch self . state. value {
10161026 case . consuming( let backpressurePromise) :
10171027 return backpressurePromise. futureResult
10181028
@@ -1025,7 +1035,7 @@ class ResponseBackpressureDelegate: HTTPClientResponseDelegate {
10251035 }
10261036
10271037 func didReceiveBodyPart( task: HTTPClient . Task < Void > , _ buffer: ByteBuffer ) -> EventLoopFuture < Void > {
1028- switch self . state {
1038+ switch self . state. value {
10291039 case . waitingForRemote( var promiseBuffer) :
10301040 assert (
10311041 !promiseBuffer. isEmpty,
@@ -1034,18 +1044,18 @@ class ResponseBackpressureDelegate: HTTPClientResponseDelegate {
10341044 let promise = promiseBuffer. removeFirst ( )
10351045 if promiseBuffer. isEmpty {
10361046 let newBackpressurePromise = self . eventLoop. makePromise ( of: Void . self)
1037- self . state = . consuming( newBackpressurePromise)
1047+ self . state. value = . consuming( newBackpressurePromise)
10381048 promise. succeed ( buffer)
10391049 return newBackpressurePromise. futureResult
10401050 } else {
1041- self . state = . waitingForRemote( promiseBuffer)
1051+ self . state. value = . waitingForRemote( promiseBuffer)
10421052 promise. succeed ( buffer)
10431053 return self . eventLoop. makeSucceededVoidFuture ( )
10441054 }
10451055
10461056 case . buffering( . none) :
10471057 let promise = self . eventLoop. makePromise ( of: Void . self)
1048- self . state = . buffering( ( buffer, promise) )
1058+ self . state. value = . buffering( ( buffer, promise) )
10491059 return promise. futureResult
10501060
10511061 case . buffering( . some) :
@@ -1059,15 +1069,15 @@ class ResponseBackpressureDelegate: HTTPClientResponseDelegate {
10591069 }
10601070
10611071 func didFinishRequest( task: HTTPClient . Task < Void > ) throws {
1062- switch self . state {
1072+ switch self . state. value {
10631073 case . waitingForRemote( let promiseBuffer) :
10641074 for promise in promiseBuffer {
10651075 promise. succeed ( . none)
10661076 }
1067- self . state = . done
1077+ self . state. value = . done
10681078
10691079 case . buffering( . none) :
1070- self . state = . done
1080+ self . state. value = . done
10711081
10721082 case . done, . consuming:
10731083 preconditionFailure ( " Invalid state: \( self . state) " )
@@ -1093,7 +1103,7 @@ class ReadEventHitHandler: ChannelOutboundHandler {
10931103 }
10941104}
10951105
1096- final class FailEndHandler : ChannelOutboundHandler {
1106+ final class FailEndHandler : ChannelOutboundHandler , Sendable {
10971107 typealias OutboundIn = HTTPClientRequestPart
10981108 typealias OutboundOut = HTTPClientRequestPart
10991109
0 commit comments