Skip to content

Commit 81895c3

Browse files
committed
Speed up tests.
1 parent 48d9c2f commit 81895c3

File tree

3 files changed

+54
-29
lines changed

3 files changed

+54
-29
lines changed

Diff for: Sources/AsyncHTTPClient/ConnectionPool/HTTPConnectionPool+Factory.swift

+32-19
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,42 @@ extension HTTPConnectionPool {
2929
}
3030

3131
final class ConnectionFactory {
32+
33+
struct Timeouts {
34+
/// the `TimeAmount` waited before the TCP connection creation is failed with a timeout error
35+
var connect: TimeAmount = .seconds(10)
36+
37+
/// the `TimeAmount` waited before the SOCKS proxy connection creation is failed with a timeout error
38+
var socksProxyHandshake: TimeAmount = .seconds(10)
39+
40+
/// the `TimeAmount` waited before the HTTP proxy connection creation is failed with a timeout error
41+
var httpProxyHandshake: TimeAmount = .seconds(10)
42+
43+
/// the `TimeAmount` waited before we the TLS handshake is failed with a timeout error
44+
var tlsHandshake: TimeAmount = .seconds(10)
45+
}
46+
3247
let key: ConnectionPool.Key
3348
let clientConfiguration: HTTPClient.Configuration
3449
let tlsConfiguration: TLSConfiguration
3550
let sslContextCache: SSLContextCache
51+
let timeouts: Timeouts
3652

3753
init(key: ConnectionPool.Key,
3854
tlsConfiguration: TLSConfiguration?,
3955
clientConfiguration: HTTPClient.Configuration,
40-
sslContextCache: SSLContextCache) {
56+
sslContextCache: SSLContextCache,
57+
timeouts: Timeouts = .init()) {
4158
self.key = key
4259
self.clientConfiguration = clientConfiguration
4360
self.sslContextCache = sslContextCache
4461
self.tlsConfiguration = tlsConfiguration ?? clientConfiguration.tlsConfiguration ?? .forClient()
62+
63+
var timeouts = timeouts
64+
if let connect = clientConfiguration.timeout.connect {
65+
timeouts.connect = connect
66+
}
67+
self.timeouts = timeouts
4568
}
4669
}
4770
}
@@ -103,7 +126,7 @@ extension HTTPConnectionPool.ConnectionFactory {
103126
targetHost: self.key.host,
104127
targetPort: self.key.port,
105128
proxyAuthorization: proxy.authorization,
106-
deadline: .now() + .seconds(10)
129+
deadline: .now() + self.timeouts.httpProxyHandshake
107130
)
108131

109132
do {
@@ -138,7 +161,7 @@ extension HTTPConnectionPool.ConnectionFactory {
138161
let bootstrap = self.makePlainBootstrap(eventLoop: eventLoop)
139162
return bootstrap.connect(host: proxy.host, port: proxy.port).flatMap { channel in
140163
let socksConnectHandler = SOCKSClientHandler(targetAddress: .domain(self.key.host, port: self.key.port))
141-
let socksEventHandler = SOCKSEventsHandler(deadline: .now() + .seconds(10))
164+
let socksEventHandler = SOCKSEventsHandler(deadline: .now() + self.timeouts.socksProxyHandshake)
142165

143166
do {
144167
try channel.pipeline.syncOperations.addHandler(socksConnectHandler)
@@ -167,7 +190,7 @@ extension HTTPConnectionPool.ConnectionFactory {
167190
var tlsConfig = self.tlsConfiguration
168191
// since we can support h2, we need to advertise this in alpn
169192
tlsConfig.applicationProtocols = ["http/1.1" /* , "h2" */ ]
170-
let tlsEventHandler = TLSEventsHandler(deadline: .now() + .seconds(10))
193+
let tlsEventHandler = TLSEventsHandler(deadline: .now() + self.timeouts.tlsHandshake)
171194

172195
let sslContextFuture = self.sslContextCache.sslContext(
173196
tlsConfiguration: tlsConfig,
@@ -204,7 +227,7 @@ extension HTTPConnectionPool.ConnectionFactory {
204227
#if canImport(Network)
205228
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *), let tsBootstrap = NIOTSConnectionBootstrap(validatingGroup: eventLoop) {
206229
return tsBootstrap
207-
.addTimeoutIfNeeded(self.clientConfiguration.timeout)
230+
.connectTimeout(self.timeouts.connect)
208231
.channelInitializer { channel in
209232
do {
210233
try channel.pipeline.syncOperations.addHandler(HTTPClient.NWErrorHandler())
@@ -218,7 +241,7 @@ extension HTTPConnectionPool.ConnectionFactory {
218241

219242
if let nioBootstrap = ClientBootstrap(validatingGroup: eventLoop) {
220243
return nioBootstrap
221-
.addTimeoutIfNeeded(self.clientConfiguration.timeout)
244+
.connectTimeout(self.timeouts.connect)
222245
}
223246

224247
preconditionFailure("No matching bootstrap found")
@@ -269,7 +292,7 @@ extension HTTPConnectionPool.ConnectionFactory {
269292
options -> NIOClientTCPBootstrapProtocol in
270293

271294
tsBootstrap
272-
.addTimeoutIfNeeded(self.clientConfiguration.timeout)
295+
.connectTimeout(self.timeouts.connect)
273296
.tlsOptions(options)
274297
.channelInitializer { channel in
275298
do {
@@ -298,7 +321,7 @@ extension HTTPConnectionPool.ConnectionFactory {
298321
)
299322

300323
let bootstrap = ClientBootstrap(group: eventLoop)
301-
.addTimeoutIfNeeded(self.clientConfiguration.timeout)
324+
.connectTimeout(self.timeouts.connect)
302325
.channelInitializer { channel in
303326
sslContextFuture.flatMap { (sslContext) -> EventLoopFuture<Void> in
304327
do {
@@ -307,7 +330,7 @@ extension HTTPConnectionPool.ConnectionFactory {
307330
context: sslContext,
308331
serverHostname: hostname
309332
)
310-
let tlsEventHandler = TLSEventsHandler(deadline: .now() + .seconds(10))
333+
let tlsEventHandler = TLSEventsHandler(deadline: .now() + self.timeouts.tlsHandshake)
311334

312335
try sync.addHandler(sslHandler)
313336
try sync.addHandler(tlsEventHandler)
@@ -333,16 +356,6 @@ extension ConnectionPool.Key.Scheme {
333356
}
334357
}
335358

336-
extension NIOClientTCPBootstrapProtocol {
337-
func addTimeoutIfNeeded(_ config: HTTPClient.Configuration.Timeout?) -> Self {
338-
guard let connectTimeamount = config?.connect else {
339-
return self
340-
}
341-
342-
return self.connectTimeout(connectTimeamount)
343-
}
344-
}
345-
346359
private extension String {
347360
var isIPAddress: Bool {
348361
var ipv4Addr = in_addr()

Diff for: Tests/AsyncHTTPClientTests/HTTP1ProxyConnectHandlerTests.swift

+16-7
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,15 @@ class HTTP1ProxyConnectHandlerTests: XCTestCase {
112112
XCTAssertEqual(try embedded.readOutbound(as: HTTPClientRequestPart.self), .end(nil))
113113

114114
let responseHead = HTTPResponseHead(version: .http1_1, status: .internalServerError)
115-
XCTAssertNoThrow(try embedded.writeInbound(HTTPClientResponsePart.head(responseHead)))
116-
XCTAssertEqual(embedded.isActive, false)
115+
// answering with 500 should lead to a triggered error in pipeline
116+
XCTAssertThrowsError(try embedded.writeInbound(HTTPClientResponsePart.head(responseHead))) {
117+
XCTAssertEqual($0 as? HTTPClientError, .invalidProxyResponse)
118+
}
119+
XCTAssertFalse(embedded.isActive, "Channel should be closed in response to the error")
117120
XCTAssertNoThrow(try embedded.writeInbound(HTTPClientResponsePart.end(nil)))
118121

119-
XCTAssertThrowsError(try proxyConnectHandler.proxyEstablishedFuture.wait()) { error in
120-
XCTAssertEqual(error as? HTTPClientError, .invalidProxyResponse)
122+
XCTAssertThrowsError(try proxyConnectHandler.proxyEstablishedFuture.wait()) {
123+
XCTAssertEqual($0 as? HTTPClientError, .invalidProxyResponse)
121124
}
122125
}
123126

@@ -148,8 +151,11 @@ class HTTP1ProxyConnectHandlerTests: XCTestCase {
148151
XCTAssertEqual(try embedded.readOutbound(as: HTTPClientRequestPart.self), .end(nil))
149152

150153
let responseHead = HTTPResponseHead(version: .http1_1, status: .proxyAuthenticationRequired)
151-
XCTAssertNoThrow(try embedded.writeInbound(HTTPClientResponsePart.head(responseHead)))
152-
XCTAssertEqual(embedded.isActive, false)
154+
// answering with 500 should lead to a triggered error in pipeline
155+
XCTAssertThrowsError(try embedded.writeInbound(HTTPClientResponsePart.head(responseHead))) {
156+
XCTAssertEqual($0 as? HTTPClientError, .proxyAuthenticationRequired)
157+
}
158+
XCTAssertFalse(embedded.isActive, "Channel should be closed in response to the error")
153159
XCTAssertNoThrow(try embedded.writeInbound(HTTPClientResponsePart.end(nil)))
154160

155161
XCTAssertThrowsError(try proxyConnectHandler.proxyEstablishedFuture.wait()) { error in
@@ -184,7 +190,10 @@ class HTTP1ProxyConnectHandlerTests: XCTestCase {
184190

185191
let responseHead = HTTPResponseHead(version: .http1_1, status: .ok)
186192
XCTAssertNoThrow(try embedded.writeInbound(HTTPClientResponsePart.head(responseHead)))
187-
XCTAssertNoThrow(try embedded.writeInbound(HTTPClientResponsePart.body(ByteBuffer(bytes: [0, 1, 2, 3]))))
193+
// answering with a body should lead to a triggered error in pipeline
194+
XCTAssertThrowsError(try embedded.writeInbound(HTTPClientResponsePart.body(ByteBuffer(bytes: [0, 1, 2, 3])))) {
195+
XCTAssertEqual($0 as? HTTPClientError, .invalidProxyResponse)
196+
}
188197
XCTAssertEqual(embedded.isActive, false)
189198
XCTAssertNoThrow(try embedded.writeInbound(HTTPClientResponsePart.end(nil)))
190199

Diff for: Tests/AsyncHTTPClientTests/HTTPConnectionPool+FactoryTests.swift

+6-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ class HTTPConnectionPool_FactoryTests: XCTestCase {
4040
key: .init(request),
4141
tlsConfiguration: nil,
4242
clientConfiguration: .init(proxy: .socksServer(host: "127.0.0.1", port: server!.localAddress!.port!)),
43-
sslContextCache: .init()
43+
sslContextCache: .init(),
44+
timeouts: .init(socksProxyHandshake: .milliseconds(30))
4445
)
4546

4647
XCTAssertThrowsError(try factory.makeChannel(connectionID: 1, eventLoop: group.next(), logger: .init(label: "test")).wait()) {
@@ -69,7 +70,8 @@ class HTTPConnectionPool_FactoryTests: XCTestCase {
6970
key: .init(request),
7071
tlsConfiguration: nil,
7172
clientConfiguration: .init(proxy: .server(host: "127.0.0.1", port: server!.localAddress!.port!)),
72-
sslContextCache: .init()
73+
sslContextCache: .init(),
74+
timeouts: .init(httpProxyHandshake: .milliseconds(30))
7375
)
7476

7577
XCTAssertThrowsError(try factory.makeChannel(connectionID: 1, eventLoop: group.next(), logger: .init(label: "test")).wait()) {
@@ -98,7 +100,8 @@ class HTTPConnectionPool_FactoryTests: XCTestCase {
98100
key: .init(request),
99101
tlsConfiguration: nil,
100102
clientConfiguration: .init(tlsConfiguration: .forClient(certificateVerification: .none)),
101-
sslContextCache: .init()
103+
sslContextCache: .init(),
104+
timeouts: .init(tlsHandshake: .milliseconds(30))
102105
)
103106

104107
XCTAssertThrowsError(try factory.makeChannel(connectionID: 1, eventLoop: group.next(), logger: .init(label: "test")).wait()) {

0 commit comments

Comments
 (0)