let handler = HTTPHandler()
let channel = EmbeddedChannel(handler: handler)
try channel.writeInbound(HTTPServerRequestPart.head(HTTPRequestHead(version: http11, method: .GET, uri: "/testing/456")))
try channel.writeInbound(HTTPServerRequestPart.body(ByteBuffer()))
try channel.writeInbound(HTTPServerRequestPart.end(nil))
XCTAssertEqual(try channel.readInbound(), HTTPServerResponsePart.head(HTTPResponseHead(version: http11, status: .ok)))
XCTAssertEqual(try channel.readInbound(), HTTPServerResponsePart.body(IOData.byteBuffer(ByteBuffer(string: "The ID is 456"))))
XCTAssertEqual(try channel.readInbound(), HTTPServerResponsePart.end(nil))
XCTAssertNil(try channel.readInbound())
This test returns nil every time i call channel.readInbound(). I also threw in some asserts to see if the channel was active
XCTAssert(channel.isActive)
and these assertions always fail, no matter where in the test I put them.
I ended up getting around this by adding the RecordingHandler from the WG github, and asserting against that:
XCTAssertEqual(recorder.writes[0], HTTPServerResponsePart.head(HTTPResponseHead(version: http11, status: .ok)))
XCTAssertEqual(recorder.writes[1], HTTPServerResponsePart.body(IOData.byteBuffer(ByteBuffer(string: "The ID is 456"))))
XCTAssertEqual(recorder.writes[2], HTTPServerResponsePart.end(nil))
HTTPHandler is a ChannelInboundHandler reads 3 HTTPServerRequestPart objects from its InboundIn, and then writes out 3 HTTPServerResponsePart objects, flushing the last one, and then closing channel when the promises of all three writes are done.
// ------✂-------
let part = HTTPServerResponsePart.head(head)
let future = channel.write(part)
var buffer = channel.allocator.buffer(capacity: 100)
buffer.writeBytes(try! response.body())
let bodyPart = HTTPServerResponsePart.body(.byteBuffer(buffer))
let future2 = channel.write(bodyPart)
let endPart = HTTPServerResponsePart.end(nil)
let future3 = channel.writeAndFlush(endPart)
_ = future.and(future2).and(future3)
.flatMap({ (_) -> EventLoopFuture<Void> in
return channel.close()
})
So if you write out parts, you don’t want readInbound, you want readOutbound in your test. readInbound will show us any data that’s transformed by the handler, not data produced by it.
Ah, got it. So that makes it return a value instead of nil, but they now return IOData.byteBuffer objects where the inner byte buffer is always 0 bytes.
let part1: IOData? = try channel.readOutbound()
let part2: IOData? = try channel.readOutbound()
let part3: IOData? = try channel.readOutbound()
let part4: IOData? = try channel.readOutbound()
guard case let .byteBuffer(buffer1) = part1 else { XCTFail(); return }
guard case let .byteBuffer(buffer2) = part2 else { XCTFail(); return }
guard case let .byteBuffer(buffer3) = part3 else { XCTFail(); return }
XCTAssertEqual(buffer1.readableBytesView.count, 0)
XCTAssertEqual(buffer2.readableBytesView.count, 0)
XCTAssertEqual(buffer3.readableBytesView.count, 0)
XCTAssertNil(part4)
(All these assertions succeed.)
Is there a reason they're returning 0 length byte buffers instead of HTTPServerResponsePart?