@@ -609,6 +609,69 @@ final class AsyncChannelBootstrapTests: XCTestCase {
609
609
}
610
610
}
611
611
612
+ func testServerClientBootstrap_withAsyncChannel_clientConnectedSocket( ) async throws {
613
+ let eventLoopGroup = MultiThreadedEventLoopGroup ( numberOfThreads: 3 )
614
+ defer {
615
+ try ! eventLoopGroup. syncShutdownGracefully ( )
616
+ }
617
+
618
+ let channel = try await ServerBootstrap ( group: eventLoopGroup)
619
+ . serverChannelOption ( . socketOption( . so_reuseaddr) , value: 1 )
620
+ . childChannelOption ( . autoRead, value: true )
621
+ . bind (
622
+ host: " 127.0.0.1 " ,
623
+ port: 0
624
+ ) { channel in
625
+ channel. eventLoop. makeCompletedFuture { ( ) -> NIOAsyncChannel < String , String > in
626
+ try channel. pipeline. syncOperations. addHandler ( ByteToMessageHandler ( LineDelimiterCoder ( ) ) )
627
+ try channel. pipeline. syncOperations. addHandler ( MessageToByteHandler ( LineDelimiterCoder ( ) ) )
628
+ try channel. pipeline. syncOperations. addHandler ( ByteBufferToStringHandler ( ) )
629
+ return try NIOAsyncChannel (
630
+ wrappingChannelSynchronously: channel,
631
+ configuration: . init(
632
+ inboundType: String . self,
633
+ outboundType: String . self
634
+ )
635
+ )
636
+ }
637
+ }
638
+
639
+ try await withThrowingTaskGroup ( of: Void . self) { group in
640
+ let ( stream, continuation) = AsyncStream< StringOrByte> . makeStream( )
641
+ var iterator = stream. makeAsyncIterator ( )
642
+
643
+ group. addTask {
644
+ try await withThrowingTaskGroup ( of: Void . self) { _ in
645
+ try await channel. executeThenClose { inbound in
646
+ for try await childChannel in inbound {
647
+ try await childChannel. executeThenClose { childChannelInbound, _ in
648
+ for try await value in childChannelInbound {
649
+ continuation. yield ( . string( value) )
650
+ }
651
+ }
652
+ }
653
+ }
654
+ }
655
+ }
656
+
657
+ let s = try Socket ( protocolFamily: . inet, type: . stream)
658
+ XCTAssert ( try s. connect ( to: channel. channel. localAddress!) )
659
+ let fd = try s. takeDescriptorOwnership ( )
660
+
661
+ let stringChannel = try await self . makeClientChannel (
662
+ eventLoopGroup: eventLoopGroup,
663
+ fileDescriptor: fd
664
+ )
665
+ try await stringChannel. executeThenClose { _, outbound in
666
+ try await outbound. write ( " hello " )
667
+ }
668
+
669
+ await XCTAsyncAssertEqual ( await iterator. next ( ) , . string( " hello " ) )
670
+
671
+ group. cancelAll ( )
672
+ }
673
+ }
674
+
612
675
// MARK: Datagram Bootstrap
613
676
614
677
func testDatagramBootstrap_withAsyncChannel_andHostPort( ) async throws {
@@ -1280,6 +1343,22 @@ final class AsyncChannelBootstrapTests: XCTestCase {
1280
1343
}
1281
1344
}
1282
1345
1346
+ private func makeClientChannel(
1347
+ eventLoopGroup: EventLoopGroup,
1348
+ fileDescriptor: CInt
1349
+ ) async throws -> NIOAsyncChannel< String, String> {
1350
+ try await ClientBootstrap ( group: eventLoopGroup)
1351
+ . withConnectedSocket ( fileDescriptor) { channel in
1352
+ channel. eventLoop. makeCompletedFuture {
1353
+ try channel. pipeline. syncOperations. addHandler ( AddressedEnvelopingHandler ( ) )
1354
+ try channel. pipeline. syncOperations. addHandler ( ByteToMessageHandler ( LineDelimiterCoder ( ) ) )
1355
+ try channel. pipeline. syncOperations. addHandler ( MessageToByteHandler ( LineDelimiterCoder ( ) ) )
1356
+ try channel. pipeline. syncOperations. addHandler ( ByteBufferToStringHandler ( ) )
1357
+ return try NIOAsyncChannel ( wrappingChannelSynchronously: channel)
1358
+ }
1359
+ }
1360
+ }
1361
+
1283
1362
private func makeClientChannelWithProtocolNegotiation(
1284
1363
eventLoopGroup: EventLoopGroup,
1285
1364
port: Int,
0 commit comments