-
-
Notifications
You must be signed in to change notification settings - Fork 41
/
ApplicationTester.swift
95 lines (86 loc) · 3.04 KB
/
ApplicationTester.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
//===----------------------------------------------------------------------===//
//
// This source file is part of the Hummingbird server framework project
//
// Copyright (c) 2021-2021 the Hummingbird authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import HTTPTypes
import Hummingbird
import NIOCore
import ServiceLifecycle
/// Response structure returned by testing framework
public struct HBTestResponse: Sendable {
public let head: HTTPResponse
/// response status
public var status: HTTPResponse.Status { self.head.status }
/// response headers
public var headers: HTTPFields { self.head.headerFields }
/// response body
public let body: ByteBuffer
/// trailer headers
public let trailerHeaders: HTTPFields?
}
/// Errors thrown by testing framework.
struct HBTestError: Error, Equatable {
private enum _Internal {
case notStarted
case noHead
case illegalBody
case noEnd
case timeout
}
private let value: _Internal
private init(_ value: _Internal) {
self.value = value
}
static var notStarted: Self { .init(.notStarted) }
static var noHead: Self { .init(.noHead) }
static var illegalBody: Self { .init(.illegalBody) }
static var noEnd: Self { .init(.noEnd) }
static var timeout: Self { .init(.timeout) }
}
/// Protocol for client used by HummingbirdTesting
public protocol HBTestClientProtocol: Sendable {
/// Execute URL request and provide response
func executeRequest(
uri: String,
method: HTTPRequest.Method,
headers: HTTPFields,
body: ByteBuffer?
) async throws -> HBTestResponse
}
extension HBTestClientProtocol {
/// Send request to associated test framework and call test callback on the response returned
///
/// - Parameters:
/// - uri: Path of request
/// - method: Request method
/// - headers: Request headers
/// - body: Request body
/// - testCallback: closure to call on response returned by test framework
/// - Returns: Return value of test closure
@discardableResult public func execute<Return>(
uri: String,
method: HTTPRequest.Method,
headers: HTTPFields = [:],
body: ByteBuffer? = nil,
testCallback: @escaping (HBTestResponse) async throws -> Return = { $0 }
) async throws -> Return {
let response = try await executeRequest(uri: uri, method: method, headers: headers, body: body)
return try await testCallback(response)
}
}
/// Protocol for application test framework
protocol HBApplicationTestFramework {
/// Associated client for application test
associatedtype Client: HBTestClientProtocol
/// Run test server
func run<Value>(_ test: @escaping @Sendable (any HBTestClientProtocol) async throws -> Value) async throws -> Value
}