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