mirror of
https://github.com/swift-server/swift-aws-lambda-runtime.git
synced 2026-06-02 07:27:33 +00:00
This allows Xcode 13 to still compile on macOS 11 which does not have symbols for Concurrency yet See swift-server/swift-service-lifecycle#110
324 lines
12 KiB
Swift
324 lines
12 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the SwiftAWSLambdaRuntime open source project
|
|
//
|
|
// Copyright (c) 2017-2018 Apple Inc. and the SwiftAWSLambdaRuntime project authors
|
|
// Licensed under Apache License v2.0
|
|
//
|
|
// See LICENSE.txt for license information
|
|
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@testable import AWSLambdaRuntimeCore
|
|
import NIO
|
|
import XCTest
|
|
|
|
class LambdaHandlerTest: XCTestCase {
|
|
// MARK: - Callback
|
|
|
|
func testCallbackSuccess() {
|
|
let server = MockLambdaServer(behavior: Behavior())
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: LambdaHandler {
|
|
typealias In = String
|
|
typealias Out = String
|
|
|
|
func handle(context: Lambda.Context, event: String, callback: (Result<String, Error>) -> Void) {
|
|
callback(.success(event))
|
|
}
|
|
}
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration, handler: Handler())
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
func testVoidCallbackSuccess() {
|
|
let server = MockLambdaServer(behavior: Behavior(result: .success(nil)))
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: LambdaHandler {
|
|
typealias In = String
|
|
typealias Out = Void
|
|
|
|
func handle(context: Lambda.Context, event: String, callback: (Result<Void, Error>) -> Void) {
|
|
callback(.success(()))
|
|
}
|
|
}
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration, handler: Handler())
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
func testCallbackFailure() {
|
|
let server = MockLambdaServer(behavior: Behavior(result: .failure(TestError("boom"))))
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: LambdaHandler {
|
|
typealias In = String
|
|
typealias Out = String
|
|
|
|
func handle(context: Lambda.Context, event: String, callback: (Result<String, Error>) -> Void) {
|
|
callback(.failure(TestError("boom")))
|
|
}
|
|
}
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration, handler: Handler())
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
#if compiler(>=5.5) && canImport(_Concurrency)
|
|
|
|
// MARK: - AsyncLambdaHandler
|
|
|
|
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
|
|
func testAsyncHandlerSuccess() {
|
|
let server = MockLambdaServer(behavior: Behavior())
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: AsyncLambdaHandler {
|
|
typealias In = String
|
|
typealias Out = String
|
|
|
|
init(context: Lambda.InitializationContext) {}
|
|
|
|
func handle(event: String, context: Lambda.Context) async throws -> String {
|
|
event
|
|
}
|
|
}
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration, factory: Handler.init)
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
|
|
func testVoidAsyncHandlerSuccess() {
|
|
let server = MockLambdaServer(behavior: Behavior(result: .success(nil)))
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: AsyncLambdaHandler {
|
|
typealias In = String
|
|
typealias Out = Void
|
|
|
|
init(context: Lambda.InitializationContext) {}
|
|
|
|
func handle(event: String, context: Lambda.Context) async throws {}
|
|
}
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration, factory: Handler.init)
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
|
|
func testAsyncHandlerFailure() {
|
|
let server = MockLambdaServer(behavior: Behavior(result: .failure(TestError("boom"))))
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: AsyncLambdaHandler {
|
|
typealias In = String
|
|
typealias Out = String
|
|
|
|
init(context: Lambda.InitializationContext) {}
|
|
|
|
func handle(event: String, context: Lambda.Context) async throws -> String {
|
|
throw TestError("boom")
|
|
}
|
|
}
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration, factory: Handler.init)
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
#endif
|
|
|
|
// MARK: - EventLoop
|
|
|
|
func testEventLoopSuccess() {
|
|
let server = MockLambdaServer(behavior: Behavior())
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: EventLoopLambdaHandler {
|
|
typealias In = String
|
|
typealias Out = String
|
|
|
|
func handle(context: Lambda.Context, event: String) -> EventLoopFuture<String> {
|
|
context.eventLoop.makeSucceededFuture(event)
|
|
}
|
|
}
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration, handler: Handler())
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
func testVoidEventLoopSuccess() {
|
|
let server = MockLambdaServer(behavior: Behavior(result: .success(nil)))
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: EventLoopLambdaHandler {
|
|
typealias In = String
|
|
typealias Out = Void
|
|
|
|
func handle(context: Lambda.Context, event: String) -> EventLoopFuture<Void> {
|
|
context.eventLoop.makeSucceededFuture(())
|
|
}
|
|
}
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration, handler: Handler())
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
func testEventLoopFailure() {
|
|
let server = MockLambdaServer(behavior: Behavior(result: .failure(TestError("boom"))))
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: EventLoopLambdaHandler {
|
|
typealias In = String
|
|
typealias Out = String
|
|
|
|
func handle(context: Lambda.Context, event: String) -> EventLoopFuture<String> {
|
|
context.eventLoop.makeFailedFuture(TestError("boom"))
|
|
}
|
|
}
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration, handler: Handler())
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
// MARK: - Closure
|
|
|
|
func testClosureSuccess() {
|
|
let server = MockLambdaServer(behavior: Behavior())
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration) { (_, event: String, callback) in
|
|
callback(.success(event))
|
|
}
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
func testVoidClosureSuccess() {
|
|
let server = MockLambdaServer(behavior: Behavior(result: .success(nil)))
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result = Lambda.run(configuration: configuration) { (_, _: String, callback) in
|
|
callback(.success(()))
|
|
}
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
func testClosureFailure() {
|
|
let server = MockLambdaServer(behavior: Behavior(result: .failure(TestError("boom"))))
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
let maxTimes = Int.random(in: 1 ... 10)
|
|
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
|
|
let result: Result<Int, Error> = Lambda.run(configuration: configuration) { (_, _: String, callback: (Result<String, Error>) -> Void) in
|
|
callback(.failure(TestError("boom")))
|
|
}
|
|
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
|
|
}
|
|
|
|
func testBootstrapFailure() {
|
|
let server = MockLambdaServer(behavior: FailedBootstrapBehavior())
|
|
XCTAssertNoThrow(try server.start().wait())
|
|
defer { XCTAssertNoThrow(try server.stop().wait()) }
|
|
|
|
struct Handler: LambdaHandler {
|
|
typealias In = String
|
|
typealias Out = String
|
|
|
|
init(context: Lambda.InitializationContext) throws {
|
|
throw TestError("kaboom")
|
|
}
|
|
|
|
func handle(context: Lambda.Context, event: String, callback: (Result<String, Error>) -> Void) {
|
|
callback(.failure(TestError("should not be called")))
|
|
}
|
|
}
|
|
|
|
let result = Lambda.run(factory: Handler.init)
|
|
assertLambdaLifecycleResult(result, shouldFailWithError: TestError("kaboom"))
|
|
}
|
|
}
|
|
|
|
private struct Behavior: LambdaServerBehavior {
|
|
let requestId: String
|
|
let event: String
|
|
let result: Result<String?, TestError>
|
|
|
|
init(requestId: String = UUID().uuidString, event: String = "hello", result: Result<String?, TestError> = .success("hello")) {
|
|
self.requestId = requestId
|
|
self.event = event
|
|
self.result = result
|
|
}
|
|
|
|
func getInvocation() -> GetInvocationResult {
|
|
.success((requestId: self.requestId, event: self.event))
|
|
}
|
|
|
|
func processResponse(requestId: String, response: String?) -> Result<Void, ProcessResponseError> {
|
|
XCTAssertEqual(self.requestId, requestId, "expecting requestId to match")
|
|
switch self.result {
|
|
case .success(let expected):
|
|
XCTAssertEqual(expected, response, "expecting response to match")
|
|
return .success(())
|
|
case .failure:
|
|
XCTFail("unexpected to fail, but succeeded with: \(response ?? "undefined")")
|
|
return .failure(.internalServerError)
|
|
}
|
|
}
|
|
|
|
func processError(requestId: String, error: ErrorResponse) -> Result<Void, ProcessErrorError> {
|
|
XCTAssertEqual(self.requestId, requestId, "expecting requestId to match")
|
|
switch self.result {
|
|
case .success:
|
|
XCTFail("unexpected to succeed, but failed with: \(error)")
|
|
return .failure(.internalServerError)
|
|
case .failure(let expected):
|
|
XCTAssertEqual(expected.description, error.errorMessage, "expecting error to match")
|
|
return .success(())
|
|
}
|
|
}
|
|
|
|
func processInitError(error: ErrorResponse) -> Result<Void, ProcessErrorError> {
|
|
XCTFail("should not report init error")
|
|
return .failure(.internalServerError)
|
|
}
|
|
}
|