Skip to content

Commit 0032344

Browse files
committed
Introduce helper methods for test of ConnectionsState
Motivation: Issue swift-server#234 highlights that we directly manipulate ConnectionsState and this commit prepares tests to be refactored to manipulate the state by exposed APIs instead. Modifications: * introduce helper methods in ConnectionPoolTestsSupport.swift Result: * no observable changes
1 parent f01021e commit 0032344

File tree

2 files changed

+119
-2
lines changed

2 files changed

+119
-2
lines changed

Tests/AsyncHTTPClientTests/ConnectionPoolTests.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ class ConnectionPoolTests: XCTestCase {
2727
var eventLoop: EmbeddedEventLoop!
2828
var http1ConnectionProvider: HTTP1ConnectionProvider!
2929

30-
struct TempError: Error {}
31-
3230
func testPending() {
3331
var state = HTTP1ConnectionProvider.ConnectionsState(eventLoop: self.eventLoop)
3432

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the AsyncHTTPClient open source project
4+
//
5+
// Copyright (c) 2018-2019 Apple Inc. and the AsyncHTTPClient project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
@testable import AsyncHTTPClient
16+
import NIO
17+
import XCTest
18+
19+
extension ConnectionPoolTests {
20+
func buildState(count: Int, release: Bool = true, eventLoop: EventLoop? = nil) -> (HTTP1ConnectionProvider.ConnectionsState, [Connection]) {
21+
let eventLoop = eventLoop ?? self.eventLoop!
22+
23+
var state = HTTP1ConnectionProvider.ConnectionsState(eventLoop: eventLoop)
24+
var items: [Connection] = []
25+
26+
if count == 0 {
27+
return (state, items)
28+
}
29+
30+
let channel = ActiveChannel(eventLoop: self.eventLoop)
31+
32+
for _ in 1...count {
33+
// Set up connection pool to have one available connection
34+
do {
35+
let connection = Connection(channel: channel, provider: self.http1ConnectionProvider)
36+
items.append(connection)
37+
// First, we ask the empty pool for a connection, triggering connection creation
38+
XCTAssertTrue(state.enqueue())
39+
let action = state.acquire(waiter: .init(promise: eventLoop.makePromise(), setupComplete: eventLoop.makeSucceededFuture(()), preference: .indifferent))
40+
41+
switch action {
42+
case .create(let waiter):
43+
waiter.promise.succeed(connection)
44+
default:
45+
XCTFail("Unexpected action: \(action)")
46+
}
47+
48+
// We offer the connection to the pool so that it can be tracked
49+
_ = state.offer(connection: connection)
50+
}
51+
}
52+
53+
if release {
54+
for item in items {
55+
// No we release the connection, making it available for the next caller
56+
_ = state.release(connection: item, closing: false)
57+
}
58+
}
59+
return (state, items)
60+
}
61+
}
62+
63+
func XCTAssertState(_ state: HTTP1ConnectionProvider.ConnectionsState, available: Int, leased: Int, waiters: Int, pending: Int, opened: Int) {
64+
let snapshot = state.testsOnly_getInternalState()
65+
XCTAssertEqual(available, snapshot.availableConnections.count)
66+
XCTAssertEqual(leased, snapshot.leasedConnections.count)
67+
XCTAssertEqual(waiters, snapshot.waiters.count)
68+
XCTAssertEqual(pending, snapshot.pending)
69+
XCTAssertEqual(opened, snapshot.openedConnectionsCount)
70+
}
71+
72+
func XCTAssertState(_ state: HTTP1ConnectionProvider.ConnectionsState, available: Int, leased: Int, waiters: Int, pending: Int, opened: Int, isLeased connection: Connection) {
73+
let snapshot = state.testsOnly_getInternalState()
74+
XCTAssertEqual(available, snapshot.availableConnections.count)
75+
XCTAssertEqual(leased, snapshot.leasedConnections.count)
76+
XCTAssertEqual(waiters, snapshot.waiters.count)
77+
XCTAssertEqual(pending, snapshot.pending)
78+
XCTAssertEqual(opened, snapshot.openedConnectionsCount)
79+
XCTAssertTrue(snapshot.leasedConnections.contains(ConnectionKey(connection)))
80+
}
81+
82+
func XCTAssertState(_ state: HTTP1ConnectionProvider.ConnectionsState, available: Int, leased: Int, waiters: Int, pending: Int, opened: Int, isNotLeased connection: Connection) {
83+
let snapshot = state.testsOnly_getInternalState()
84+
XCTAssertEqual(available, snapshot.availableConnections.count)
85+
XCTAssertEqual(leased, snapshot.leasedConnections.count)
86+
XCTAssertEqual(waiters, snapshot.waiters.count)
87+
XCTAssertEqual(pending, snapshot.pending)
88+
XCTAssertEqual(opened, snapshot.openedConnectionsCount)
89+
XCTAssertFalse(snapshot.leasedConnections.contains(ConnectionKey(connection)))
90+
}
91+
92+
struct XCTEmptyError: Error {}
93+
94+
func XCTUnwrap<T>(_ value: T?) throws -> T {
95+
if let unwrapped = value {
96+
return unwrapped
97+
}
98+
throw XCTEmptyError()
99+
}
100+
101+
struct TempError: Error {}
102+
103+
func XCTAssertStateClose(_ state: HTTP1ConnectionProvider.ConnectionsState, available: Int, leased: Int, waiters: Int, clean: Bool) throws {
104+
var state = state
105+
106+
let (foundWaiters, foundAvailable, foundLeased, foundClean) = try XCTUnwrap(state.close())
107+
XCTAssertEqual(waiters, foundWaiters.count)
108+
XCTAssertEqual(available, foundAvailable.count)
109+
XCTAssertEqual(leased, foundLeased.count)
110+
XCTAssertEqual(clean, foundClean)
111+
112+
for waiter in foundWaiters {
113+
waiter.promise.fail(TempError())
114+
}
115+
116+
for lease in foundLeased {
117+
try lease.cancel().wait()
118+
}
119+
}

0 commit comments

Comments
 (0)