Ensure that handlers added with first:true are in proper order. (#118)

Motivation:

Right now addHandlers(first:) does not actually add handlers at the
front of the pipeline: it just adds them *backwards* at the end of
the pipeline. That's definitely not right.

Modifications:

Pass the first: flag into the call to add each specific handler to
ensure they're actually put at the front of the pipeline.

Result:

Handlers added to the front of the pipeline actually are.
This commit is contained in:
Cory Benfield 2018-03-10 08:26:53 +09:00 committed by Norman Maurer
parent 684ae3d933
commit 43dd9c0b33
3 changed files with 56 additions and 1 deletions

View File

@ -697,7 +697,7 @@ extension ChannelPipeline {
handlers = handlers.reversed()
}
return EventLoopFuture<Void>.andAll(handlers.map { add(handler: $0) }, eventLoop: eventLoop)
return EventLoopFuture<Void>.andAll(handlers.map { add(handler: $0, first: first) }, eventLoop: eventLoop)
}
/// Adds the provided channel handlers to the pipeline in the order given, taking account

View File

@ -34,6 +34,7 @@ extension ChannelPipelineTest {
("testWriteAfterClose", testWriteAfterClose),
("testOutboundNextForInboundOnlyIsCorrect", testOutboundNextForInboundOnlyIsCorrect),
("testChannelInfrastructureIsNotLeaked", testChannelInfrastructureIsNotLeaked),
("testAddingHandlersFirstWorks", testAddingHandlersFirstWorks),
]
}
}

View File

@ -350,4 +350,58 @@ class ChannelPipelineTest: XCTestCase {
XCTAssertNoThrow(try loop.syncShutdownGracefully())
}()
}
func testAddingHandlersFirstWorks() throws {
final class ReceiveIntHandler: ChannelInboundHandler {
typealias InboundIn = Int
var intReadCount = 0
func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
if data.tryAs(type: Int.self) != nil {
self.intReadCount += 1
}
}
}
final class TransformStringToIntHandler: ChannelInboundHandler {
typealias InboundIn = String
typealias InboundOut = Int
func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
if let dataString = data.tryAs(type: String.self) {
ctx.fireChannelRead(self.wrapInboundOut(dataString.count))
}
}
}
final class TransformByteBufferToStringHandler: ChannelInboundHandler {
typealias InboundIn = ByteBuffer
typealias InboundOut = String
func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
if var buffer = data.tryAs(type: ByteBuffer.self) {
ctx.fireChannelRead(self.wrapInboundOut(buffer.readString(length: buffer.readableBytes)!))
}
}
}
let channel = EmbeddedChannel()
defer {
XCTAssertNoThrow(try channel.finish())
}
let countHandler = ReceiveIntHandler()
var buffer = channel.allocator.buffer(capacity: 12)
buffer.write(staticString: "hello, world")
XCTAssertNoThrow(try channel.pipeline.add(handler: countHandler).wait())
XCTAssertFalse(try channel.writeInbound(buffer))
XCTAssertEqual(countHandler.intReadCount, 0)
try channel.pipeline.addHandlers(TransformByteBufferToStringHandler(),
TransformStringToIntHandler(),
first: true).wait()
XCTAssertFalse(try channel.writeInbound(buffer))
XCTAssertEqual(countHandler.intReadCount, 1)
}
}