Skip to content

Commit

Permalink
use B2MD verifier (#52)
Browse files Browse the repository at this point in the history
Motivation:

Use B2MDVerifier for the B2MDs in NIOExtras. Already found one bug,
separetely fixed in #51.

Modifications:

Write a basic validation test for all B2MDs.

Result:

Better test coverage.
  • Loading branch information
weissi authored May 28, 2019
1 parent 3a9ddca commit 66f9a50
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 29 deletions.
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var targets: [PackageDescription.Target] = [
linkerSettings: [
.linkedLibrary("z")
]),
.testTarget(name: "NIOExtrasTests", dependencies: ["NIOExtras"]),
.testTarget(name: "NIOExtrasTests", dependencies: ["NIOExtras", "NIOTestUtils"]),
.testTarget(name: "NIOHTTPCompressionTests", dependencies: ["NIOHTTPCompression"]),
]

Expand All @@ -38,7 +38,7 @@ let package = Package(
.library(name: "NIOHTTPCompression", targets: ["NIOHTTPCompression"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.0.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.2.0"),
],
targets: targets
)
3 changes: 1 addition & 2 deletions Sources/NIOExtras/LengthFieldBasedFrameDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ public final class LengthFieldBasedFrameDecoder: ByteToMessageDecoder {
case four
case eight

fileprivate var length: Int {

var length: Int {
switch self {
case .one:
return 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extension FixedLengthFrameDecoderTest {
("testDecodeIfMoreBytesAreSent", testDecodeIfMoreBytesAreSent),
("testRemoveHandlerWhenBufferIsNotEmpty", testRemoveHandlerWhenBufferIsNotEmpty),
("testRemoveHandlerWhenBufferIsEmpty", testRemoveHandlerWhenBufferIsEmpty),
("testCloseInChannelRead", testCloseInChannelRead),
("testBasicValidation", testBasicValidation),
]
}
}
Expand Down
39 changes: 16 additions & 23 deletions Tests/NIOExtrasTests/FixedLengthFrameDecoderTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import XCTest
import NIO
import NIOExtras
import NIOTestUtils

class FixedLengthFrameDecoderTest: XCTestCase {
public func testDecodeIfFewerBytesAreSent() throws {
Expand Down Expand Up @@ -115,30 +116,22 @@ class FixedLengthFrameDecoderTest: XCTestCase {
XCTAssertTrue(try channel.finish().isClean)
}

func testCloseInChannelRead() {
let channel = EmbeddedChannel(handler: ByteToMessageHandler(LengthFieldBasedFrameDecoder(lengthFieldLength: .four)))
class CloseInReadHandler: ChannelInboundHandler {
typealias InboundIn = ByteBuffer

private var numberOfReads = 0

func channelRead(context: ChannelHandlerContext, data: NIOAny) {
self.numberOfReads += 1
XCTAssertEqual(1, self.numberOfReads)
XCTAssertEqual([UInt8(100)], Array(self.unwrapInboundIn(data).readableBytesView))
context.close().whenFailure { error in
XCTFail("unexpected error: \(error)")
}
context.fireChannelRead(data)
func testBasicValidation() {
for length in 1 ... 20 {
let inputs = [
String(decoding: Array(repeating: UInt8(ascii: "a"), count: length), as: Unicode.UTF8.self),
String(decoding: Array(repeating: UInt8(ascii: "b"), count: length), as: Unicode.UTF8.self),
String(decoding: Array(repeating: UInt8(ascii: "c"), count: length), as: Unicode.UTF8.self),
]
func byteBuffer(_ string: String) -> ByteBuffer {
var buffer = ByteBufferAllocator().buffer(capacity: string.utf8.count)
buffer.writeString(string)
return buffer
}
let inputOutputPairs: [(String, [ByteBuffer])] = inputs.map { ($0, [byteBuffer($0)]) }
XCTAssertNoThrow(try ByteToMessageDecoderVerifier.verifyDecoder(stringInputOutputPairs: inputOutputPairs) {
FixedLengthFrameDecoder(frameLength: length)
})
}
XCTAssertNoThrow(try channel.pipeline.addHandler(CloseInReadHandler()).wait())

var buf = channel.allocator.buffer(capacity: 1024)
buf.writeBytes([UInt8(0), 0, 0, 1, 100])
XCTAssertNoThrow(try channel.writeInbound(buf))
XCTAssertNoThrow(XCTAssertEqual([100], Array((try channel.readInbound() as ByteBuffer?)!.readableBytesView)))
XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ extension LengthFieldBasedFrameDecoderTest {
("testDecodeWithUInt16HeaderWithPartialBody", testDecodeWithUInt16HeaderWithPartialBody),
("testRemoveHandlerWhenBufferIsEmpty", testRemoveHandlerWhenBufferIsEmpty),
("testRemoveHandlerWhenBufferIsNotEmpty", testRemoveHandlerWhenBufferIsNotEmpty),
("testCloseInChannelRead", testCloseInChannelRead),
("testBasicVerification", testBasicVerification),
]
}
}
Expand Down
82 changes: 81 additions & 1 deletion Tests/NIOExtrasTests/LengthFieldBasedFrameDecoderTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@

import XCTest
import NIO
import NIOExtras
@testable import NIOExtras
import NIOTestUtils

private let standardDataString = "abcde"

Expand Down Expand Up @@ -375,4 +376,83 @@ class LengthFieldBasedFrameDecoderTest: XCTestCase {
}))
XCTAssertTrue(try self.channel.finish().isClean)
}

func testCloseInChannelRead() {
let channel = EmbeddedChannel(handler: ByteToMessageHandler(LengthFieldBasedFrameDecoder(lengthFieldLength: .four)))
class CloseInReadHandler: ChannelInboundHandler {
typealias InboundIn = ByteBuffer

private var numberOfReads = 0

func channelRead(context: ChannelHandlerContext, data: NIOAny) {
self.numberOfReads += 1
XCTAssertEqual(1, self.numberOfReads)
XCTAssertEqual([UInt8(100)], Array(self.unwrapInboundIn(data).readableBytesView))
context.close().whenFailure { error in
XCTFail("unexpected error: \(error)")
}
context.fireChannelRead(data)
}
}
XCTAssertNoThrow(try channel.pipeline.addHandler(CloseInReadHandler()).wait())

var buf = channel.allocator.buffer(capacity: 1024)
buf.writeBytes([UInt8(0), 0, 0, 1, 100])
XCTAssertNoThrow(try channel.writeInbound(buf))
XCTAssertNoThrow(XCTAssertEqual([100], Array((try channel.readInbound() as ByteBuffer?)!.readableBytesView)))
XCTAssertNoThrow(XCTAssertNil(try channel.readInbound()))
}

func testBasicVerification() {
let inputs: [(LengthFieldBasedFrameDecoder.ByteLength, [(Int, String)])] = [
(.one, [
(6, "abcdef"),
(0, ""),
(9, "123456789"),
(Int(UInt8.max),
String(decoding: Array(repeating: UInt8(ascii: "X"), count: Int(UInt8.max)), as: Unicode.UTF8.self)),
]),
(.two, [
(1, "a"),
(0, ""),
(9, "123456789"),
(307,
String(decoding: Array(repeating: UInt8(ascii: "X"), count: 307), as: Unicode.UTF8.self)),
]),
(.four, [
(1, "a"),
(0, ""),
(3, "333"),
(307,
String(decoding: Array(repeating: UInt8(ascii: "X"), count: 307), as: Unicode.UTF8.self)),
]),
(.eight, [
(1, "a"),
(0, ""),
(4, "aaaa"),
(307,
String(decoding: Array(repeating: UInt8(ascii: "X"), count: 307), as: Unicode.UTF8.self)),
]),
]

for input in inputs {
let (lenBytes, inputData) = input

func byteBuffer(length: Int, string: String) -> ByteBuffer {
var buf = self.channel.allocator.buffer(capacity: string.utf8.count + 8)
buf.writeInteger(length)
buf.moveReaderIndex(forwardBy: 8 - lenBytes.length)
buf.writeString(string)
return buf
}

let inputOutputPairs = inputData.map { (input: (Int, String)) -> (ByteBuffer, [ByteBuffer]) in
let bytes = byteBuffer(length: input.0, string: input.1)
return (bytes, [bytes.getSlice(at: bytes.readerIndex + lenBytes.length, length: input.0)!])
}
XCTAssertNoThrow(try ByteToMessageDecoderVerifier.verifyDecoder(inputOutputPairs: inputOutputPairs) {
LengthFieldBasedFrameDecoder(lengthFieldLength: lenBytes)
})
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extension LineBasedFrameDecoderTest {
("testChannelInactiveWithLeftOverBytes", testChannelInactiveWithLeftOverBytes),
("testMoreDataAvailableWhenChannelBecomesInactive", testMoreDataAvailableWhenChannelBecomesInactive),
("testDripFedCRLN", testDripFedCRLN),
("testBasicValidation", testBasicValidation),
]
}
}
Expand Down
27 changes: 27 additions & 0 deletions Tests/NIOExtrasTests/LineBasedFrameDecoderTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import XCTest
@testable import NIO // to inspect the cumulationBuffer
import NIOExtras
import NIOTestUtils

class LineBasedFrameDecoderTest: XCTestCase {
private var channel: EmbeddedChannel!
Expand Down Expand Up @@ -186,4 +187,30 @@ class LineBasedFrameDecoderTest: XCTestCase {
buffer.writeString("a")
XCTAssertNoThrow(XCTAssertEqual(buffer, try self.channel.readInbound()))
}

func testBasicValidation() {
func byteBuffer(_ string: String) -> ByteBuffer {
var buffer = self.channel.allocator.buffer(capacity: string.utf8.count)
buffer.writeString(string)
return buffer
}

do {
try ByteToMessageDecoderVerifier.verifyDecoder(stringInputOutputPairs: [
("\n", [byteBuffer("")]),
("\r\n", [byteBuffer("")]),
("a\r\n", [byteBuffer("a")]),
("a\n", [byteBuffer("a")]),
("a\rb\n", [byteBuffer("a\rb")]),
("Content-Length: 17\r\nConnection: close\r\n\r\n", [byteBuffer("Content-Length: 17"),
byteBuffer("Connection: close"),
byteBuffer("")])
]) {
return LineBasedFrameDecoder()
}
} catch {
print(error)
XCTFail()
}
}
}

0 comments on commit 66f9a50

Please sign in to comment.