swift-nio-extras/Tests/NIOExtrasTests/LengthFieldBasedFrameDecoderTest.swift
Liam 97ffd10cae Removes integer backing from ByteLength enum.
Motivation:
To simplify the enum from the calling perspective.

Modifications:
Removed integer backing.
Removed a string addition from a test that wasn’t actually adding anything.

Result:
The integer for the enum can not be seen publicly.
2018-11-19 18:53:17 +00:00

297 lines
13 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import XCTest
import NIO
import NIOExtras
private let standardDataString = "abcde"
class LengthFieldBasedFrameDecoderTest: XCTestCase {
private var channel: EmbeddedChannel!
private var decoderUnderTest: LengthFieldBasedFrameDecoder!
override func setUp() {
self.channel = EmbeddedChannel()
}
func testDecodeWithUInt8HeaderWithData() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .one, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataBytes: [UInt8] = [10, 20, 30, 40]
let dataBytesLengthHeader = UInt8(dataBytes.count)
var buffer = self.channel.allocator.buffer(capacity: 5)
buffer.write(bytes: [dataBytesLengthHeader])
buffer.write(bytes: dataBytes)
XCTAssertTrue(try self.channel.writeInbound(buffer))
var outputBuffer: ByteBuffer? = self.channel.readInbound()
let outputData = outputBuffer?.readBytes(length: dataBytes.count)
XCTAssertEqual(dataBytes, outputData)
XCTAssertFalse(try self.channel.finish())
}
func testDecodeWithUInt16HeaderWithString() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .two, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataLength: UInt16 = 5
var buffer = self.channel.allocator.buffer(capacity: 7) // 2 byte header + 5 character string
buffer.write(integer: dataLength, endianness: .little, as: UInt16.self)
buffer.write(string: standardDataString)
XCTAssertTrue(try self.channel.writeInbound(buffer))
var outputBuffer: ByteBuffer? = self.channel.readInbound()
let outputData = outputBuffer?.readString(length: standardDataString.count)
XCTAssertEqual(standardDataString, outputData)
XCTAssertFalse(try self.channel.finish())
}
func testDecodeWithUInt32HeaderWithString() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .four, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataLength: UInt32 = 5
var buffer = self.channel.allocator.buffer(capacity: 9) // 4 byte header + 5 character string
buffer.write(integer: dataLength, endianness: .little, as: UInt32.self)
buffer.write(string: standardDataString)
XCTAssertTrue(try self.channel.writeInbound(buffer))
var outputBuffer: ByteBuffer? = self.channel.readInbound()
let outputData = outputBuffer?.readString(length: standardDataString.count)
XCTAssertEqual(standardDataString, outputData)
XCTAssertFalse(try self.channel.finish())
}
func testDecodeWithUInt64HeaderWithString() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .eight, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataLength: UInt64 = 5
var buffer = self.channel.allocator.buffer(capacity: 13) // 8 byte header + 5 character string
buffer.write(integer: dataLength, endianness: .little, as: UInt64.self)
buffer.write(string: standardDataString)
XCTAssertTrue(try self.channel.writeInbound(buffer))
var outputBuffer: ByteBuffer? = self.channel.readInbound()
let outputData = outputBuffer?.readString(length: standardDataString.count)
XCTAssertEqual(standardDataString, outputData)
XCTAssertFalse(try self.channel.finish())
}
func testDecodeWithInt64HeaderWithString() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .eight, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataLength: Int64 = 5
var buffer = self.channel.allocator.buffer(capacity: 13) // 8 byte header + 5 character string
buffer.write(integer: dataLength, endianness: .little, as: Int64.self)
buffer.write(string: standardDataString)
XCTAssertTrue(try self.channel.writeInbound(buffer))
var outputBuffer: ByteBuffer? = self.channel.readInbound()
let outputData = outputBuffer?.readString(length: standardDataString.count)
XCTAssertEqual(standardDataString, outputData)
XCTAssertFalse(try self.channel.finish())
}
func testDecodeWithInt64HeaderStringBigEndian() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .eight, lengthFieldEndianness: .big)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataLength: Int64 = 5
var buffer = self.channel.allocator.buffer(capacity: 13) // 8 byte header + 5 character string
buffer.write(integer: dataLength, endianness: .big, as: Int64.self)
buffer.write(string: standardDataString)
XCTAssertTrue(try self.channel.writeInbound(buffer))
var outputBuffer: ByteBuffer? = self.channel.readInbound()
let outputData = outputBuffer?.readString(length: standardDataString.count)
XCTAssertEqual(standardDataString, outputData)
XCTAssertFalse(try self.channel.finish())
}
func testDecodeWithInt64HeaderStringDefaultingToBigEndian() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .eight)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataLength: Int64 = 5
var buffer = self.channel.allocator.buffer(capacity: 13) // 8 byte header + 5 character string
buffer.write(integer: dataLength, endianness: .big, as: Int64.self)
buffer.write(string: standardDataString)
XCTAssertTrue(try self.channel.writeInbound(buffer))
var outputBuffer: ByteBuffer? = self.channel.readInbound()
let outputData = outputBuffer?.readString(length: standardDataString.count)
XCTAssertEqual(standardDataString, outputData)
XCTAssertFalse(try self.channel.finish())
}
func testDecodeWithUInt8HeaderTwoFrames() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .one, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let firstFrameDataLength: UInt8 = 5
let secondFrameDataLength: UInt8 = 3
let secondFrameString = "123"
var buffer = self.channel.allocator.buffer(capacity: 10) // 1 byte header + 5 character string + 1 byte header + 3 character string
buffer.write(integer: firstFrameDataLength, endianness: .little, as: UInt8.self)
buffer.write(string: standardDataString)
buffer.write(integer: secondFrameDataLength, endianness: .little, as: UInt8.self)
buffer.write(string: secondFrameString)
XCTAssertTrue(try self.channel.writeInbound(buffer))
var outputFirstFrameBuffer: ByteBuffer? = self.channel.readInbound()
let outputFirstFrameData = outputFirstFrameBuffer?.readString(length: standardDataString.count)
XCTAssertEqual(standardDataString, outputFirstFrameData)
var outputSecondFrameBuffer: ByteBuffer? = self.channel.readInbound()
let outputSecondFrameData = outputSecondFrameBuffer?.readString(length: secondFrameString.count)
XCTAssertEqual(secondFrameString, outputSecondFrameData)
XCTAssertFalse(try self.channel.finish())
}
func testEmptyBuffer() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .one, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
var buffer = self.channel.allocator.buffer(capacity: 1)
XCTAssertFalse(try self.channel.writeInbound(buffer))
XCTAssertFalse(try self.channel.finish())
}
func testDecodeWithUInt16HeaderWithPartialHeader() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .two, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataLength: UInt8 = 5 // 8 byte is only half the length required
var buffer = self.channel.allocator.buffer(capacity: 7) // 2 byte header + 5 character string
buffer.write(integer: dataLength, endianness: .little, as: UInt8.self)
XCTAssertFalse(try self.channel.writeInbound(buffer))
XCTAssertFalse(try self.channel.finish())
}
func testDecodeWithUInt16HeaderWithPartialBody() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .two, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataLength: UInt16 = 7
var buffer = self.channel.allocator.buffer(capacity: 9) // 2 byte header + 7 character string
buffer.write(integer: dataLength, endianness: .little, as: UInt16.self)
buffer.write(string: standardDataString) // 2 bytes short of the 7 required.
XCTAssertFalse(try self.channel.writeInbound(buffer))
XCTAssertFalse(try self.channel.finish())
}
func testRemoveHandlerWhenBufferIsEmpty() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .eight, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let dataLength: Int64 = 5
var buffer = self.channel.allocator.buffer(capacity: 13) // 8 byte header + 5 character string
buffer.write(integer: dataLength, endianness: .little, as: Int64.self)
buffer.write(string: standardDataString)
XCTAssertTrue(try self.channel.writeInbound(buffer))
var outputBuffer: ByteBuffer? = self.channel.readInbound()
let outputData = outputBuffer?.readString(length: standardDataString.count)
_ = try self.channel.pipeline.remove(handler: self.decoderUnderTest).wait()
XCTAssertEqual(standardDataString, outputData)
XCTAssertNoThrow(try self.channel.throwIfErrorCaught())
XCTAssertFalse(try self.channel.finish())
}
func testRemoveHandlerWhenBufferIsNotEmpty() throws {
self.decoderUnderTest = LengthFieldBasedFrameDecoder(lengthFieldLength: .eight, lengthFieldEndianness: .little)
try? self.channel.pipeline.add(handler: self.decoderUnderTest).wait()
let extraUnusedDataString = "fghi"
let dataLength: Int64 = 5
var buffer = self.channel.allocator.buffer(capacity: 17) // 8 byte header + 5 character string + 4 unused
buffer.write(integer: dataLength, endianness: .little, as: Int64.self)
buffer.write(string: standardDataString + extraUnusedDataString)
XCTAssertTrue(try channel.writeInbound(buffer))
var outputBuffer: ByteBuffer? = self.channel.readInbound()
let outputData = outputBuffer?.readString(length: standardDataString.count)
_ = try self.channel.pipeline.remove(handler: self.decoderUnderTest).wait()
XCTAssertThrowsError(try self.channel.throwIfErrorCaught()) { error in
guard let error = error as? NIOExtrasErrors.LeftOverBytesError else {
XCTFail()
return
}
var expectedBuffer = self.channel.allocator.buffer(capacity: 7)
expectedBuffer.write(string: extraUnusedDataString)
XCTAssertEqual(error.leftOverBytes, expectedBuffer)
}
XCTAssertEqual(standardDataString, outputData)
XCTAssertFalse(try self.channel.finish())
}
}