From 1c39f444128c19ac4332f95ecd5c77794fcbebb5 Mon Sep 17 00:00:00 2001 From: Johannes Weiss Date: Thu, 21 Mar 2019 14:55:21 +0000 Subject: [PATCH] LineBasedFrameDecoder: Don't discard everything after EOF (#39) Motivation: LineBasedFrameDecoder discarded everything after EOF and delivered it in the left-over bytes error. For the real world however that doesn't make much sense, you'd want all previously received lines and only receive the partial lines as left-overs. Modifications: deliver lines until there are only partial lines left, even in case of EOF. Result: LineBasedFrameDecoder more useful --- Sources/NIOExtras/LineBasedFrameDecoder.swift | 1 + .../NIOExtrasTests/LineBasedFrameDecoderTest.swift | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Sources/NIOExtras/LineBasedFrameDecoder.swift b/Sources/NIOExtras/LineBasedFrameDecoder.swift index 8150aab..8485924 100644 --- a/Sources/NIOExtras/LineBasedFrameDecoder.swift +++ b/Sources/NIOExtras/LineBasedFrameDecoder.swift @@ -49,6 +49,7 @@ public class LineBasedFrameDecoder: ByteToMessageDecoder { } public func decodeLast(context: ChannelHandlerContext, buffer: inout ByteBuffer, seenEOF: Bool) throws -> DecodingState { + while try self.decode(context: context, buffer: &buffer) == .continue {} if buffer.readableBytes > 0 { context.fireErrorCaught(NIOExtrasErrors.LeftOverBytesError(leftOverBytes: buffer)) } diff --git a/Tests/NIOExtrasTests/LineBasedFrameDecoderTest.swift b/Tests/NIOExtrasTests/LineBasedFrameDecoderTest.swift index 53b6f42..e5e5598 100644 --- a/Tests/NIOExtrasTests/LineBasedFrameDecoderTest.swift +++ b/Tests/NIOExtrasTests/LineBasedFrameDecoderTest.swift @@ -25,7 +25,7 @@ class LineBasedFrameDecoderTest: XCTestCase { self.channel = EmbeddedChannel() self.decoder = LineBasedFrameDecoder() self.handler = ByteToMessageHandler(self.decoder) - try? self.channel.pipeline.addHandler(self.handler).wait() + XCTAssertNoThrow(try self.channel.pipeline.addHandler(self.handler).wait()) } override func tearDown() { @@ -141,6 +141,7 @@ class LineBasedFrameDecoderTest: XCTestCase { func channelRead(context: ChannelHandlerContext, data: NIOAny) { let buffer = self.unwrapInboundIn(data) + context.fireChannelRead(data) if buffer.readableBytes == 3 { context.close(promise: nil) @@ -159,9 +160,16 @@ class LineBasedFrameDecoderTest: XCTestCase { let handler = CloseWhenMyFavouriteMessageArrives(receivedLeftOversPromise: receivedLeftOversPromise) XCTAssertNoThrow(try self.channel.pipeline.addHandler(handler).wait()) var buffer = self.channel.allocator.buffer(capacity: 16) - buffer.writeString("a\nbb\nccc\ndddd\neeeee\nffffff\n") + buffer.writeString("a\nbb\nccc\ndddd\neeeee\nffffff\nXXX") XCTAssertNoThrow(try self.channel.writeInbound(buffer)) - XCTAssertNoThrow(try XCTAssertEqual("dddd\neeeee\nffffff\n", + for s in ["a", "bb", "ccc", "dddd", "eeeee", "ffffff"] { + XCTAssertNoThrow(XCTAssertEqual(s, + (try self.channel.readInbound(as: ByteBuffer.self)?.readableBytesView).map { + String(decoding: $0, as: Unicode.UTF8.self) + })) + } + XCTAssertNoThrow(XCTAssertNil(try self.channel.readInbound(as: ByteBuffer.self))) + XCTAssertNoThrow(try XCTAssertEqual("XXX", String(decoding: receivedLeftOversPromise.futureResult.wait().readableBytesView, as: UTF8.self))) }