Skip to content

Commit

Permalink
2.x.x Rename HummingbirdXCT to HummingbirdTesting (#392)
Browse files Browse the repository at this point in the history
* Rename HummingbirdXCT to HummingbirdTesting

* Remove XCT from all symbols

* XCTExecute -> execute
  • Loading branch information
adam-fowler committed Mar 7, 2024
1 parent 4df02df commit 3e73381
Show file tree
Hide file tree
Showing 34 changed files with 324 additions and 324 deletions.
2 changes: 1 addition & 1 deletion Benchmarks/Benchmarks/Router/RouterBenchmarks.swift
Expand Up @@ -16,7 +16,7 @@ import Benchmark
import HTTPTypes
import Hummingbird
import NIOHTTPTypes
@_spi(HBXCT) import HummingbirdCore
@_spi(HBInternal) import HummingbirdCore
import Logging
import NIOCore
import NIOPosix
Expand Down
12 changes: 6 additions & 6 deletions Package.swift
Expand Up @@ -15,7 +15,7 @@ let package = Package(
.library(name: "HummingbirdTLS", targets: ["HummingbirdTLS"]),
.library(name: "HummingbirdJobs", targets: ["HummingbirdJobs"]),
.library(name: "HummingbirdRouter", targets: ["HummingbirdRouter"]),
.library(name: "HummingbirdXCT", targets: ["HummingbirdXCT"]),
.library(name: "HummingbirdTesting", targets: ["HummingbirdTesting"]),
.executable(name: "PerformanceTest", targets: ["PerformanceTest"]),
],
dependencies: [
Expand Down Expand Up @@ -89,7 +89,7 @@ let package = Package(
swiftSettings: swiftSettings
),
.target(
name: "HummingbirdXCT",
name: "HummingbirdTesting",
dependencies: [
.byName(name: "Hummingbird"),
.product(name: "AsyncHTTPClient", package: "async-http-client"),
Expand Down Expand Up @@ -138,16 +138,16 @@ let package = Package(
.byName(name: "Hummingbird"),
.byName(name: "HummingbirdTLS"),
.byName(name: "HummingbirdHTTP2"),
.byName(name: "HummingbirdXCT"),
.byName(name: "HummingbirdTesting"),
]),
.testTarget(name: "HummingbirdJobsTests", dependencies: [
.byName(name: "HummingbirdJobs"),
.byName(name: "HummingbirdXCT"),
.byName(name: "HummingbirdTesting"),
.product(name: "Atomics", package: "swift-atomics"),
]),
.testTarget(name: "HummingbirdRouterTests", dependencies: [
.byName(name: "HummingbirdRouter"),
.byName(name: "HummingbirdXCT"),
.byName(name: "HummingbirdTesting"),
]),
.testTarget(
name: "HummingbirdCoreTests",
Expand All @@ -156,7 +156,7 @@ let package = Package(
.byName(name: "HummingbirdCore"),
.byName(name: "HummingbirdHTTP2"),
.byName(name: "HummingbirdTLS"),
.byName(name: "HummingbirdXCT"),
.byName(name: "HummingbirdTesting"),
.product(name: "AsyncHTTPClient", package: "async-http-client"),
],
resources: [.process("Certificates")]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -49,7 +49,7 @@ Hummingbird is designed to require the least number of dependencies possible, bu
- `HummingbirdRouter`: an alternative router that uses a resultbuilder.
- `HummingbirdTLS`: TLS support.
- `HummingbirdHTTP2`: Support for HTTP2 upgrades.
- `HummingbirdXCT`: helper functions to aid testing Hummingbird projects.
- `HummingbirdTesting`: helper functions to aid testing Hummingbird projects.

And also the following are available in other repositories in this organisation

Expand Down
Expand Up @@ -17,27 +17,27 @@ import HummingbirdCore
import NIOCore

/// HTTP Scheme to use with AsyncHTTPClient test framework
public enum XCTScheme: String {
public enum HBTestHTTPScheme: String {
case http
case https
}

/// Type of test framework
public struct XCTTestingSetup {
public struct HBTestingSetup {
enum Internal {
case router
case live
case ahc(XCTScheme)
case ahc(HBTestHTTPScheme)
}

let value: Internal

/// Test writing requests directly to router.
public static var router: XCTTestingSetup { .init(value: .router) }
public static var router: HBTestingSetup { .init(value: .router) }
/// Sets up a live server and execute tests using a HTTP client. Only supports HTTP1
public static var live: XCTTestingSetup { .init(value: .live) }
public static var live: HBTestingSetup { .init(value: .live) }
/// Sets up a live server and execute tests using a HTTP client. Does not support trailer headers
public static func ahc(_ scheme: XCTScheme) -> XCTTestingSetup { .init(value: .ahc(scheme)) }
public static func ahc(_ scheme: HBTestHTTPScheme) -> HBTestingSetup { .init(value: .ahc(scheme)) }
}

/// Extends `HBApplicationProtocol` to support testing of applications
Expand All @@ -46,7 +46,7 @@ extension HBApplicationProtocol where Responder.Context: HBRequestContext {

/// Test `HBApplication`
///
/// You use `test` and `XCTExecute` to test applications. You can either test using
/// You use `test` and `execute` to test applications. You can either test using
/// the `.router` test framework which sends requests directly to the router for testing your code or
/// the `.live` or `.ahc` frameworks which both run live servers to pass requests to, but provide
/// a single connection HTTP client or AsyncHTTPClient as a client respectively . The `.router` test
Expand All @@ -62,7 +62,7 @@ extension HBApplicationProtocol where Responder.Context: HBRequestContext {
/// let app = HBApplication(router: router)
/// app.test(.router) { client in
/// // does my app return "hello" in the body for this route
/// client.XCTExecute(uri: "/hello", method: .GET) { response in
/// client.execute(uri: "/hello", method: .GET) { response in
/// XCTAssertEqual(String(buffer: response.body), "hello")
/// }
/// }
Expand All @@ -72,13 +72,13 @@ extension HBApplicationProtocol where Responder.Context: HBRequestContext {
/// - testing: indicates which type of testing framework we want
/// - configuration: configuration of application
public func test<Value>(
_ testingSetup: XCTTestingSetup,
_ test: @escaping @Sendable (any HBXCTClientProtocol) async throws -> Value
_ testingSetup: HBTestingSetup,
_ test: @escaping @Sendable (any HBTestClientProtocol) async throws -> Value
) async throws -> Value {
let app: any HBXCTApplication = switch testingSetup.value {
case .router: try await HBXCTRouter(app: self)
case .live: HBXCTLive(app: self)
case .ahc(let scheme): HBXCTAsyncHTTPClient(app: self, scheme: scheme)
let app: any HBApplicationTestFramework = switch testingSetup.value {
case .router: try await HBRouterTestFramework(app: self)
case .live: HBLiveTestFramework(app: self)
case .ahc(let scheme): HBAsyncHTTPClientTestFramework(app: self, scheme: scheme)
}
return try await app.run(test)
}
Expand Down
Expand Up @@ -17,8 +17,8 @@ import Hummingbird
import NIOCore
import ServiceLifecycle

/// Response structure returned by XCT testing framework
public struct HBXCTResponse: Sendable {
/// Response structure returned by testing framework
public struct HBTestResponse: Sendable {
public let head: HTTPResponse
/// response status
public var status: HTTPResponse.Status { self.head.status }
Expand All @@ -30,8 +30,8 @@ public struct HBXCTResponse: Sendable {
public let trailerHeaders: HTTPFields?
}

/// Errors thrown by XCT framework.
struct HBXCTError: Error, Equatable {
/// Errors thrown by testing framework.
struct HBTestError: Error, Equatable {
private enum _Internal {
case notStarted
case noHead
Expand All @@ -52,18 +52,18 @@ struct HBXCTError: Error, Equatable {
static var timeout: Self { .init(.timeout) }
}

/// Protocol for client used by HummingbirdXCT
public protocol HBXCTClientProtocol: Sendable {
/// Protocol for client used by HummingbirdTesting
public protocol HBTestClientProtocol: Sendable {
/// Execute URL request and provide response
func execute(
func executeRequest(
uri: String,
method: HTTPRequest.Method,
headers: HTTPFields,
body: ByteBuffer?
) async throws -> HBXCTResponse
) async throws -> HBTestResponse
}

extension HBXCTClientProtocol {
extension HBTestClientProtocol {
/// Send request to associated test framework and call test callback on the response returned
///
/// - Parameters:
Expand All @@ -73,23 +73,23 @@ extension HBXCTClientProtocol {
/// - body: Request body
/// - testCallback: closure to call on response returned by test framework
/// - Returns: Return value of test closure
@discardableResult public func XCTExecute<Return>(
@discardableResult public func execute<Return>(
uri: String,
method: HTTPRequest.Method,
headers: HTTPFields = [:],
body: ByteBuffer? = nil,
testCallback: @escaping (HBXCTResponse) async throws -> Return = { $0 }
testCallback: @escaping (HBTestResponse) async throws -> Return = { $0 }
) async throws -> Return {
let response = try await execute(uri: uri, method: method, headers: headers, body: body)
let response = try await executeRequest(uri: uri, method: method, headers: headers, body: body)
return try await testCallback(response)
}
}

/// Protocol for Test application.
protocol HBXCTApplication {
/// Associated client with XCT server type
associatedtype Client: HBXCTClientProtocol
/// Protocol for application test framework
protocol HBApplicationTestFramework {
/// Associated client for application test
associatedtype Client: HBTestClientProtocol

/// Run XCT server
func run<Value>(_ test: @escaping @Sendable (any HBXCTClientProtocol) async throws -> Value) async throws -> Value
/// Run test server
func run<Value>(_ test: @escaping @Sendable (any HBTestClientProtocol) async throws -> Value) async throws -> Value
}
Expand Up @@ -25,19 +25,19 @@ import ServiceLifecycle
import XCTest

/// Test using a live server and AsyncHTTPClient as a client
final class HBXCTAsyncHTTPClient<App: HBApplicationProtocol>: HBXCTApplication {
struct Client: HBXCTClientProtocol {
final class HBAsyncHTTPClientTestFramework<App: HBApplicationProtocol>: HBApplicationTestFramework {
struct Client: HBTestClientProtocol {
let client: HTTPClient
let urlPrefix: String
let timeout: TimeAmount

/// Send request and call test callback on the response returned
func execute(
func executeRequest(
uri: String,
method: HTTPRequest.Method,
headers: HTTPFields = [:],
body: ByteBuffer? = nil
) async throws -> HBXCTResponse {
) async throws -> HBTestResponse {
let url = "\(self.urlPrefix)\(uri.first == "/" ? "" : "/")\(uri)"
var request = HTTPClientRequest(url: url)
request.method = .init(method)
Expand All @@ -49,14 +49,14 @@ final class HBXCTAsyncHTTPClient<App: HBApplicationProtocol>: HBXCTApplication {
}
}

init(app: App, scheme: XCTScheme) {
init(app: App, scheme: HBTestHTTPScheme) {
self.timeout = .seconds(15)
self.application = TestApplication(base: app)
self.scheme = scheme
}

/// Start tests
func run<Value>(_ test: @escaping @Sendable (HBXCTClientProtocol) async throws -> Value) async throws -> Value {
func run<Value>(_ test: @escaping @Sendable (HBTestClientProtocol) async throws -> Value) async throws -> Value {
try await withThrowingTaskGroup(of: Void.self) { group in
let serviceGroup = ServiceGroup(
configuration: .init(
Expand Down Expand Up @@ -90,7 +90,7 @@ final class HBXCTAsyncHTTPClient<App: HBApplicationProtocol>: HBXCTApplication {
}

let application: TestApplication<App>
let scheme: XCTScheme
let scheme: HBTestHTTPScheme
let timeout: TimeAmount
}

Expand Down
Expand Up @@ -23,20 +23,20 @@ import ServiceLifecycle
import XCTest

/// Test using a live server
final class HBXCTLive<App: HBApplicationProtocol>: HBXCTApplication {
struct Client: HBXCTClientProtocol {
let client: HBXCTClient
final class HBLiveTestFramework<App: HBApplicationProtocol>: HBApplicationTestFramework {
struct Client: HBTestClientProtocol {
let client: HBTestClient

/// Send request and call test callback on the response returned
func execute(
func executeRequest(
uri: String,
method: HTTPRequest.Method,
headers: HTTPFields = [:],
body: ByteBuffer? = nil
) async throws -> HBXCTResponse {
) async throws -> HBTestResponse {
var headers = headers
headers[.connection] = "keep-alive"
let request = HBXCTClient.Request(uri, method: method, authority: "localhost", headers: headers, body: body)
let request = HBTestClient.Request(uri, method: method, authority: "localhost", headers: headers, body: body)
let response = try await client.execute(request)
return .init(head: response.head, body: response.body ?? ByteBuffer(), trailerHeaders: response.trailerHeaders)
}
Expand All @@ -48,7 +48,7 @@ final class HBXCTLive<App: HBApplicationProtocol>: HBXCTApplication {
}

/// Start tests
func run<Value>(_ test: @escaping @Sendable (HBXCTClientProtocol) async throws -> Value) async throws -> Value {
func run<Value>(_ test: @escaping @Sendable (HBTestClientProtocol) async throws -> Value) async throws -> Value {
try await withThrowingTaskGroup(of: Void.self) { group in
let serviceGroup = ServiceGroup(
configuration: .init(
Expand All @@ -61,7 +61,7 @@ final class HBXCTLive<App: HBApplicationProtocol>: HBXCTApplication {
try await serviceGroup.run()
}
let port = await self.application.portPromise.wait()
let client = HBXCTClient(
let client = HBTestClient(
host: "localhost",
port: port,
configuration: .init(timeout: self.timeout),
Expand Down
Expand Up @@ -15,8 +15,8 @@
import Atomics
import HTTPTypes
import NIOEmbedded
@_spi(HBXCT) import Hummingbird
@_spi(HBXCT) import HummingbirdCore
@_spi(HBInternal) import Hummingbird
@_spi(HBInternal) import HummingbirdCore
import Logging
import NIOConcurrencyHelpers
import NIOCore
Expand All @@ -25,7 +25,7 @@ import NIOPosix
import ServiceLifecycle

/// Test sending requests directly to router. This does not setup a live server
struct HBXCTRouter<Responder: HBResponder>: HBXCTApplication where Responder.Context: HBBaseRequestContext {
struct HBRouterTestFramework<Responder: HBResponder>: HBApplicationTestFramework where Responder.Context: HBBaseRequestContext {
let responder: Responder
let makeContext: @Sendable (Logger) -> Responder.Context
let services: [any Service]
Expand All @@ -46,7 +46,7 @@ struct HBXCTRouter<Responder: HBResponder>: HBXCTApplication where Responder.Con
}

/// Run test
func run<Value>(_ test: @escaping @Sendable (HBXCTClientProtocol) async throws -> Value) async throws -> Value {
func run<Value>(_ test: @escaping @Sendable (HBTestClientProtocol) async throws -> Value) async throws -> Value {
let client = Client(
responder: self.responder,
logger: self.logger,
Expand Down Expand Up @@ -88,15 +88,15 @@ struct HBXCTRouter<Responder: HBResponder>: HBXCTApplication where Responder.Con
}
}

/// HBXCTRouter client. Constructs an `HBRequest` sends it to the router and then converts
/// resulting response back to XCT response type
struct Client: HBXCTClientProtocol {
/// HBRouterTestFramework client. Constructs an `HBRequest` sends it to the router and then converts
/// resulting response back to test response type
struct Client: HBTestClientProtocol {
let responder: Responder
let logger: Logger
let makeContext: @Sendable (Logger) -> Responder.Context

func execute(uri: String, method: HTTPRequest.Method, headers: HTTPFields, body: ByteBuffer?) async throws -> HBXCTResponse {
return try await withThrowingTaskGroup(of: HBXCTResponse.self) { group in
func executeRequest(uri: String, method: HTTPRequest.Method, headers: HTTPFields, body: ByteBuffer?) async throws -> HBTestResponse {
return try await withThrowingTaskGroup(of: HBTestResponse.self) { group in
let (stream, source) = HBRequestBody.makeStream()
let request = HBRequest(
head: .init(method: method, scheme: "http", authority: "localhost", path: uri, headerFields: headers),
Expand All @@ -118,7 +118,7 @@ struct HBXCTRouter<Responder: HBResponder>: HBXCTApplication where Responder.Con
let responseWriter = RouterResponseWriter()
let trailerHeaders = try await response.body.write(responseWriter)
return responseWriter.collated.withLockedValue { collated in
HBXCTResponse(head: response.head, body: collated, trailerHeaders: trailerHeaders)
HBTestResponse(head: response.head, body: collated, trailerHeaders: trailerHeaders)
}
}

Expand Down
Expand Up @@ -21,7 +21,7 @@ import ServiceLifecycle
/// TestApplication used to wrap HBApplication being tested.
///
/// This is needed to override the `onServerRunning` function
struct TestApplication<BaseApp: HBApplicationProtocol>: HBApplicationProtocol, Service {
internal struct TestApplication<BaseApp: HBApplicationProtocol>: HBApplicationProtocol, Service {
typealias Responder = BaseApp.Responder
typealias ChildChannel = BaseApp.ChildChannel

Expand Down
Expand Up @@ -17,7 +17,7 @@ import HTTPTypes
import NIOCore

/// HTTP client types
extension HBXCTClient {
extension HBTestClient {
public enum Error: Swift.Error {
case invalidURL
case malformedResponse
Expand Down

0 comments on commit 3e73381

Please sign in to comment.