Repository: apple/swift-nio
File: Tests/NIOPosixTests/StreamChannelsTest.swift (Swift)

Code before:

            // Attempt to write a byte from chan1 to chan2 which should be refused after the close
            XCTAssertThrowsError(try chan1.write(self.buffer).wait()) { error in
                XCTAssertEqual(ChannelError.outputClosed, error as? ChannelError, "\(chan1)")
            }

            // wait for the write to complete
            XCTAssertNoThrow(try writeFuture.wait(), "chan1 write failed")

            // and wait for it to arrive
            XCTAssertNoThrow(try readPromise.futureResult.wait())

            // wait for the close to complete
            XCTAssertNoThrow(try closeFuture.wait(), "chan1 close failed")

            XCTAssertNoThrow(try chan1.syncCloseAcceptingAlreadyClosed())
            XCTAssertNoThrow(try chan2.syncCloseAcceptingAlreadyClosed())
        }
        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))
    }

    func testHalfCloseOwnOutputWithWritabilityChange() throws {
        final class BytesReadCountingHandler: ChannelInboundHandler, Sendable {
            typealias InboundIn = ByteBuffer

            private let numBytes: NIOLoopBoundBox<Int>

            init(_ numBytesLoopBound: NIOLoopBoundBox<Int>) {
                self.numBytes = numBytesLoopBound
            }

            func channelRead(context: ChannelHandlerContext, data: NIOAny) {
                let currentBuffer = Self.unwrapInboundIn(data)
                self.numBytes.value += currentBuffer.readableBytes
                context.fireChannelRead(data)
            }
        }

        final class BytesWrittenCountingHandler: ChannelInboundHandler, Sendable {
            typealias InboundIn = ByteBuffer

            public typealias OutboundIn = ByteBuffer
            public typealias OutboundOut = ByteBuffer

            private let numBytes: NIOLoopBoundBox<Int>

            init(_ numBytesLoopBound: NIOLoopBoundBox<Int>) {
                self.numBytes = numBytesLoopBound
            }

            func setup(_ context: ChannelHandlerContext) {

Review comment (suggestion):
No need to overcomplicate this, you can just use a `NIOLockedValueBox`.

Code after:
            chan1.flush()

            // Attempt to write a byte from chan1 to chan2 which should be refused after the close
            XCTAssertThrowsError(try chan1.write(self.buffer).wait()) { error in
                XCTAssertEqual(ChannelError.outputClosed, error as? ChannelError, "\(chan1)")
            }

            // wait for the write to complete
            XCTAssertNoThrow(try writeFuture.wait(), "chan1 write failed")

            // and wait for it to arrive
            XCTAssertNoThrow(try readPromise.futureResult.wait())

            // wait for the close to complete
            XCTAssertNoThrow(try closeFuture.wait(), "chan1 close failed")

            XCTAssertNoThrow(try chan1.syncCloseAcceptingAlreadyClosed())
            XCTAssertNoThrow(try chan2.syncCloseAcceptingAlreadyClosed())
        }
        XCTAssertNoThrow(try forEachCrossConnectedStreamChannelPair(runTest))
    }

    func testHalfCloseOwnOutputWithWritabilityChange() throws {
        final class BytesReadCountingHandler: ChannelInboundHandler, Sendable {
            typealias InboundIn = ByteBuffer

            private let numBytes = NIOLockedValueBox<Int>(0)
            private let numBytesReadAtInputClose = NIOLockedValueBox<Int>(0)

            var bytesRead: Int {
                self.numBytes.withLockedValue { $0 }
            }
            var bytesReadAtInputClose: Int {
                self.numBytesReadAtInputClose.withLockedValue { $0 }
            }

            func channelRead(context: ChannelHandlerContext, data: NIOAny) {
                let currentBuffer = Self.unwrapInboundIn(data)
                self.numBytes.withLockedValue { numBytes in
                    numBytes += currentBuffer.readableBytes
                }
                context.fireChannelRead(data)
            }

            func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {
                if event as? ChannelEvent == .some(.inputClosed) {
                    let numBytes = self.numBytes.withLockedValue { $0 }
                    self.numBytesReadAtInputClose.withLockedValue { $0 = numBytes }
                    context.close(mode: .all, promise: nil)
                }
                context.fireUserInboundEventTriggered(event)