mirror of
https://github.com/apple/swift-nio-extras.git
synced 2025-06-01 18:53:35 +08:00
use B2MD verifier (#52)
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.
This commit is contained in:
parent
3a9ddcaf3e
commit
66f9a509ed
@ -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"]),
|
||||
]
|
||||
|
||||
@ -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
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -30,7 +30,7 @@ extension FixedLengthFrameDecoderTest {
|
||||
("testDecodeIfMoreBytesAreSent", testDecodeIfMoreBytesAreSent),
|
||||
("testRemoveHandlerWhenBufferIsNotEmpty", testRemoveHandlerWhenBufferIsNotEmpty),
|
||||
("testRemoveHandlerWhenBufferIsEmpty", testRemoveHandlerWhenBufferIsEmpty),
|
||||
("testCloseInChannelRead", testCloseInChannelRead),
|
||||
("testBasicValidation", testBasicValidation),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
import XCTest
|
||||
import NIO
|
||||
import NIOExtras
|
||||
import NIOTestUtils
|
||||
|
||||
class FixedLengthFrameDecoderTest: XCTestCase {
|
||||
public func testDecodeIfFewerBytesAreSent() throws {
|
||||
@ -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()))
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ extension LengthFieldBasedFrameDecoderTest {
|
||||
("testDecodeWithUInt16HeaderWithPartialBody", testDecodeWithUInt16HeaderWithPartialBody),
|
||||
("testRemoveHandlerWhenBufferIsEmpty", testRemoveHandlerWhenBufferIsEmpty),
|
||||
("testRemoveHandlerWhenBufferIsNotEmpty", testRemoveHandlerWhenBufferIsNotEmpty),
|
||||
("testCloseInChannelRead", testCloseInChannelRead),
|
||||
("testBasicVerification", testBasicVerification),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,8 @@
|
||||
|
||||
import XCTest
|
||||
import NIO
|
||||
import NIOExtras
|
||||
@testable import NIOExtras
|
||||
import NIOTestUtils
|
||||
|
||||
private let standardDataString = "abcde"
|
||||
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ extension LineBasedFrameDecoderTest {
|
||||
("testChannelInactiveWithLeftOverBytes", testChannelInactiveWithLeftOverBytes),
|
||||
("testMoreDataAvailableWhenChannelBecomesInactive", testMoreDataAvailableWhenChannelBecomesInactive),
|
||||
("testDripFedCRLN", testDripFedCRLN),
|
||||
("testBasicValidation", testBasicValidation),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
import XCTest
|
||||
@testable import NIO // to inspect the cumulationBuffer
|
||||
import NIOExtras
|
||||
import NIOTestUtils
|
||||
|
||||
class LineBasedFrameDecoderTest: XCTestCase {
|
||||
private var channel: EmbeddedChannel!
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user