mirror of
https://github.com/apple/swift-nio.git
synced 2026-05-20 20:30:36 +00:00
Speed up the tests (#3601)
### Motivation We want our tests to pass in reasonable time. ### Changes - Disable test `ByteBufferCrashTests.setBytesWithoutContigiousStorageMoreThanUInt32maxBytes` - Do not initialize data in `ByteBufferCrashTests. takingOwnershipOfPointerThatsToLarge` ### Result Tests are faster again.
This commit is contained in:
@@ -31,7 +31,9 @@ public final class NIOHTTPRequestHeadersValidator: ChannelOutboundHandler, Remov
|
|||||||
public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
|
public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
|
||||||
switch NIOHTTPRequestHeadersValidator.unwrapOutboundIn(data) {
|
switch NIOHTTPRequestHeadersValidator.unwrapOutboundIn(data) {
|
||||||
case .head(let head):
|
case .head(let head):
|
||||||
guard Self.uriOnlyContainsAllowedCharacters(head.uri), head.method.isValidToSend, head.headers.areValidToSend else {
|
guard Self.uriOnlyContainsAllowedCharacters(head.uri), head.method.isValidToSend,
|
||||||
|
head.headers.areValidToSend
|
||||||
|
else {
|
||||||
promise?.fail(HTTPParserError.invalidHeaderToken)
|
promise?.fail(HTTPParserError.invalidHeaderToken)
|
||||||
context.fireErrorCaught(HTTPParserError.invalidHeaderToken)
|
context.fireErrorCaught(HTTPParserError.invalidHeaderToken)
|
||||||
return
|
return
|
||||||
@@ -98,10 +100,9 @@ public final class NIOHTTPRequestHeadersValidator: ChannelOutboundHandler, Remov
|
|||||||
|
|
||||||
uri.utf8.allSatisfy { byte in
|
uri.utf8.allSatisfy { byte in
|
||||||
switch byte {
|
switch byte {
|
||||||
case
|
case // unreserved
|
||||||
// unreserved
|
// - ALPHA
|
||||||
// - ALPHA
|
UInt8(ascii: "A")...UInt8(ascii: "Z"), UInt8(ascii: "a")...UInt8(ascii: "z"),
|
||||||
UInt8(ascii: "A")...UInt8(ascii: "Z"), UInt8(ascii: "a")...UInt8(ascii: "z"),
|
|
||||||
// - DIGIT
|
// - DIGIT
|
||||||
UInt8(ascii: "0")...UInt8(ascii: "9"),
|
UInt8(ascii: "0")...UInt8(ascii: "9"),
|
||||||
// - extra characters
|
// - extra characters
|
||||||
@@ -225,7 +226,7 @@ extension HTTPMethod {
|
|||||||
.SOURCE:
|
.SOURCE:
|
||||||
true
|
true
|
||||||
|
|
||||||
case .RAW(value: let value):
|
case .RAW(let value):
|
||||||
// The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#method.overview) defines the valid
|
// The spec in [RFC 9110](https://httpwg.org/specs/rfc9110.html#method.overview) defines the valid
|
||||||
// characters as the following:
|
// characters as the following:
|
||||||
//
|
//
|
||||||
@@ -241,9 +242,8 @@ extension HTTPMethod {
|
|||||||
|
|
||||||
value.utf8.allSatisfy { byte in
|
value.utf8.allSatisfy { byte in
|
||||||
switch byte {
|
switch byte {
|
||||||
case
|
case // ALPHA
|
||||||
// ALPHA
|
UInt8(ascii: "A")...UInt8(ascii: "Z"), UInt8(ascii: "a")...UInt8(ascii: "z"),
|
||||||
UInt8(ascii: "A")...UInt8(ascii: "Z"), UInt8(ascii: "a")...UInt8(ascii: "z"),
|
|
||||||
// DIGIT
|
// DIGIT
|
||||||
UInt8(ascii: "0")...UInt8(ascii: "9"),
|
UInt8(ascii: "0")...UInt8(ascii: "9"),
|
||||||
// token
|
// token
|
||||||
@@ -337,11 +337,10 @@ extension HTTPResponseStatus {
|
|||||||
|
|
||||||
reasonPhrase.utf8.allSatisfy { byte in
|
reasonPhrase.utf8.allSatisfy { byte in
|
||||||
switch byte {
|
switch byte {
|
||||||
case
|
case 9, // HTAB
|
||||||
9, // HTAB
|
32, // SP
|
||||||
32, // SP
|
|
||||||
33...126, // VCHAR
|
33...126, // VCHAR
|
||||||
128...255: // obs-text
|
128...255: // obs-text
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ extension ChannelPipeline {
|
|||||||
/// - enableOutboundHeaderValidation: Whether the pipeline should confirm that outbound headers are well-formed.
|
/// - enableOutboundHeaderValidation: Whether the pipeline should confirm that outbound headers are well-formed.
|
||||||
/// Defaults to `true`.
|
/// Defaults to `true`.
|
||||||
/// - encoderConfiguration: The configuration for the ``HTTPRequestEncoder``.
|
/// - encoderConfiguration: The configuration for the ``HTTPRequestEncoder``.
|
||||||
|
/// - decoderLimitConfiguration: The limit configuration for the ``HTTPDecoder``.
|
||||||
/// - upgrade: Add a ``NIOHTTPClientUpgradeHandler`` to the pipeline, configured for
|
/// - upgrade: Add a ``NIOHTTPClientUpgradeHandler`` to the pipeline, configured for
|
||||||
/// HTTP upgrade. Should be a tuple of an array of ``NIOHTTPClientUpgradeHandler`` and
|
/// HTTP upgrade. Should be a tuple of an array of ``NIOHTTPClientUpgradeHandler`` and
|
||||||
/// the upgrade completion handler. See the documentation on ``NIOHTTPClientUpgradeHandler``
|
/// the upgrade completion handler. See the documentation on ``NIOHTTPClientUpgradeHandler``
|
||||||
@@ -389,7 +390,6 @@ extension ChannelPipeline {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private func _configureHTTPServerPipeline(
|
private func _configureHTTPServerPipeline(
|
||||||
position: ChannelPipeline.Position = .last,
|
position: ChannelPipeline.Position = .last,
|
||||||
withPipeliningAssistance pipelining: Bool = true,
|
withPipeliningAssistance pipelining: Bool = true,
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
@_spi(CustomByteBufferAllocator) import NIOCore
|
@_spi(CustomByteBufferAllocator) import NIOCore
|
||||||
import Testing
|
import Testing
|
||||||
import Foundation
|
|
||||||
|
|
||||||
#if compiler(>=6.2)
|
#if compiler(>=6.2)
|
||||||
@Suite struct ByteBufferCrashTests {
|
@Suite struct ByteBufferCrashTests {
|
||||||
@@ -91,7 +91,11 @@ import Foundation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test func setBytesWithoutContigiousStorageMoreThanUInt32maxBytes() async {
|
@Test(
|
||||||
|
.disabled(
|
||||||
|
"This test is taking too long, as it needs to allocate 4GB of memory. It doesn't work on 32bit machines."
|
||||||
|
)
|
||||||
|
) func setBytesWithoutContigiousStorageMoreThanUInt32maxBytes() async {
|
||||||
await #expect(processExitsWith: .failure) {
|
await #expect(processExitsWith: .failure) {
|
||||||
let circularBuffer = CircularBuffer<UInt8>(repeating: 0, count: Int(UInt32.max) + 1)
|
let circularBuffer = CircularBuffer<UInt8>(repeating: 0, count: Int(UInt32.max) + 1)
|
||||||
var bb = ByteBuffer()
|
var bb = ByteBuffer()
|
||||||
@@ -138,12 +142,6 @@ import Foundation
|
|||||||
let capacity = Int(UInt32.max) + 1
|
let capacity = Int(UInt32.max) + 1
|
||||||
let ptr = malloc(capacity)!
|
let ptr = malloc(capacity)!
|
||||||
|
|
||||||
// Initialize some data in the external memory
|
|
||||||
let boundPtr = ptr.bindMemory(to: UInt8.self, capacity: capacity)
|
|
||||||
for i in 0..<capacity {
|
|
||||||
boundPtr[i] = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
let allocator = ByteBufferCustomAllocatorTest.makeTrackedAllocator()
|
let allocator = ByteBufferCustomAllocatorTest.makeTrackedAllocator()
|
||||||
|
|
||||||
// this should crash
|
// this should crash
|
||||||
|
|||||||
@@ -613,7 +613,12 @@ import Testing
|
|||||||
try channel.pipeline.syncOperations.addHTTPClientHandlers()
|
try channel.pipeline.syncOperations.addHTTPClientHandlers()
|
||||||
|
|
||||||
let headers = HTTPHeaders([("Host", "example.com")])
|
let headers = HTTPHeaders([("Host", "example.com")])
|
||||||
let goodRequest = HTTPRequestHead(version: .http1_1, method: .RAW(value: weirdAllowedMethodName), uri: "/", headers: headers)
|
let goodRequest = HTTPRequestHead(
|
||||||
|
version: .http1_1,
|
||||||
|
method: .RAW(value: weirdAllowedMethodName),
|
||||||
|
uri: "/",
|
||||||
|
headers: headers
|
||||||
|
)
|
||||||
let goodRequestBytes = ByteBuffer(
|
let goodRequestBytes = ByteBuffer(
|
||||||
string: "\(weirdAllowedMethodName) / HTTP/1.1\r\nHost: example.com\r\n\r\n"
|
string: "\(weirdAllowedMethodName) / HTTP/1.1\r\nHost: example.com\r\n\r\n"
|
||||||
)
|
)
|
||||||
@@ -638,7 +643,12 @@ import Testing
|
|||||||
try channel.pipeline.syncOperations.addHTTPClientHandlers()
|
try channel.pipeline.syncOperations.addHTTPClientHandlers()
|
||||||
|
|
||||||
let headers = HTTPHeaders([("Host", "example.com")])
|
let headers = HTTPHeaders([("Host", "example.com")])
|
||||||
let badRequest = HTTPRequestHead(version: .http1_1, method: .RAW(value: forbiddenFieldName), uri: "/", headers: headers)
|
let badRequest = HTTPRequestHead(
|
||||||
|
version: .http1_1,
|
||||||
|
method: .RAW(value: forbiddenFieldName),
|
||||||
|
uri: "/",
|
||||||
|
headers: headers
|
||||||
|
)
|
||||||
|
|
||||||
let error = #expect(
|
let error = #expect(
|
||||||
throws: HTTPParserError.self,
|
throws: HTTPParserError.self,
|
||||||
@@ -662,9 +672,9 @@ import Testing
|
|||||||
// ```
|
// ```
|
||||||
|
|
||||||
let allowedRanges: [ClosedRange<UInt8>] = [
|
let allowedRanges: [ClosedRange<UInt8>] = [
|
||||||
9...9, // HTAB
|
9...9, // HTAB
|
||||||
32...32, // SP
|
32...32, // SP
|
||||||
33...126, // VCHAR
|
33...126, // VCHAR
|
||||||
128...255, // obs-text
|
128...255, // obs-text
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -693,7 +703,9 @@ import Testing
|
|||||||
|
|
||||||
switch allowed {
|
switch allowed {
|
||||||
case true:
|
case true:
|
||||||
let goodRequestBytes = ByteBuffer(string: "HTTP/1.1 600 \(testReason)\r\ntransfer-encoding: chunked\r\n\r\n")
|
let goodRequestBytes = ByteBuffer(
|
||||||
|
string: "HTTP/1.1 600 \(testReason)\r\ntransfer-encoding: chunked\r\n\r\n"
|
||||||
|
)
|
||||||
let goodEnd = ByteBuffer(string: "0\r\n\r\n")
|
let goodEnd = ByteBuffer(string: "0\r\n\r\n")
|
||||||
#expect(throws: Never.self, "Rejected reason phrase with byte: \(byte)") {
|
#expect(throws: Never.self, "Rejected reason phrase with byte: \(byte)") {
|
||||||
try channel.writeOutbound(HTTPServerResponsePart.head(response))
|
try channel.writeOutbound(HTTPServerResponsePart.head(response))
|
||||||
@@ -829,7 +841,7 @@ import Testing
|
|||||||
return String(Unicode.Scalar(byte))
|
return String(Unicode.Scalar(byte))
|
||||||
|
|
||||||
case 0xC0, 0xC1:
|
case 0xC0, 0xC1:
|
||||||
return nil // forbidden in UTF-8
|
return nil // forbidden in UTF-8
|
||||||
|
|
||||||
case 0xC2...0xDF:
|
case 0xC2...0xDF:
|
||||||
// Lead of 2-byte seq. Smallest scalar with this lead:
|
// Lead of 2-byte seq. Smallest scalar with this lead:
|
||||||
@@ -844,7 +856,7 @@ import Testing
|
|||||||
let base = UInt32(byte & 0x0F) << 12
|
let base = UInt32(byte & 0x0F) << 12
|
||||||
let scalar = (byte == 0xE0) ? 0x0800 : base
|
let scalar = (byte == 0xE0) ? 0x0800 : base
|
||||||
// Skip surrogates if we land in D800–DFFF (byte == 0xED)
|
// Skip surrogates if we land in D800–DFFF (byte == 0xED)
|
||||||
if byte == 0xED { return String(Unicode.Scalar(0xD000 - 0x0800 + base)!) } // simple pick
|
if byte == 0xED { return String(Unicode.Scalar(0xD000 - 0x0800 + base)!) } // simple pick
|
||||||
return Unicode.Scalar(scalar).map { String($0) }
|
return Unicode.Scalar(scalar).map { String($0) }
|
||||||
|
|
||||||
case 0xF0...0xF4:
|
case 0xF0...0xF4:
|
||||||
@@ -856,12 +868,12 @@ import Testing
|
|||||||
switch byte {
|
switch byte {
|
||||||
case 0xF0: scalar = 0x10000
|
case 0xF0: scalar = 0x10000
|
||||||
case 0xF4: scalar = 0x100000
|
case 0xF4: scalar = 0x100000
|
||||||
default: scalar = UInt32(byte & 0x07) << 18
|
default: scalar = UInt32(byte & 0x07) << 18
|
||||||
}
|
}
|
||||||
return Unicode.Scalar(scalar).map { String($0) }
|
return Unicode.Scalar(scalar).map { String($0) }
|
||||||
|
|
||||||
default: // 0xF5...0xFF
|
default: // 0xF5...0xFF
|
||||||
return nil // forbidden in UTF-8
|
return nil // forbidden in UTF-8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -872,4 +884,3 @@ extension EmbeddedChannel {
|
|||||||
try self.writeInbound(request)
|
try self.writeInbound(request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user