Skip to content

Commit ea667ec

Browse files
committed
Some improvements
1 parent 6b8acb3 commit ea667ec

File tree

3 files changed

+112
-53
lines changed

3 files changed

+112
-53
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ let package = Package(
3333
// testing helper
3434
.target(name: "AWSLambdaTesting", dependencies: [
3535
"AWSLambdaRuntime",
36-
.product(name: "NIOHTTP1", package: "swift-nio"),
36+
.product(name: "NIO", package: "swift-nio"),
3737
]),
3838
.testTarget(name: "AWSLambdaTestingTests", dependencies: ["AWSLambdaTesting"]),
3939
// samples

Sources/AWSLambdaTesting/Lambda+Testing.swift

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,43 +19,70 @@ import Logging
1919
import NIO
2020

2121
extension Lambda {
22+
public struct TestConfig {
23+
public var requestId: String
24+
public var traceId: String
25+
public var invokedFunctionArn: String
26+
public var timeout: Double
27+
28+
public init(requestId: String = "\(DispatchTime.now().uptimeNanoseconds)",
29+
traceId: String = "Root=\(DispatchTime.now().uptimeNanoseconds);Parent=\(DispatchTime.now().uptimeNanoseconds);Sampled=1",
30+
invokedFunctionArn: String = "arn:aws:lambda:us-west-1:\(DispatchTime.now().uptimeNanoseconds):function:custom-runtime",
31+
timeout: Double = 5) {
32+
self.requestId = requestId
33+
self.traceId = traceId
34+
self.invokedFunctionArn = invokedFunctionArn
35+
self.timeout = timeout
36+
}
37+
}
38+
2239
public static func test(_ closure: @escaping StringLambdaClosure,
23-
with payload: String,
24-
_ body: @escaping (Result<String, Error>) -> Void) {
25-
Self.test(StringLambdaClosureWrapper(closure), with: payload, body)
40+
config: TestConfig = .init(),
41+
with payload: String) throws -> String {
42+
try Self.test(StringLambdaClosureWrapper(closure), config: config, with: payload)
2643
}
2744

2845
public static func test(_ closure: @escaping StringVoidLambdaClosure,
29-
with payload: String,
30-
_ body: @escaping (Result<Void, Error>) -> Void) {
31-
Self.test(StringVoidLambdaClosureWrapper(closure), with: payload, body)
46+
config: TestConfig = .init(),
47+
with payload: String) throws {
48+
_ = try Self.test(StringVoidLambdaClosureWrapper(closure), config: config, with: payload)
3249
}
3350

34-
public static func test<In: Decodable, Out: Encodable>(_ closure: @escaping CodableLambdaClosure<In, Out>,
35-
with payload: In,
36-
_ body: @escaping (Result<Out, Error>) -> Void) {
37-
Self.test(CodableLambdaClosureWrapper(closure), with: payload, body)
51+
public static func test<In: Decodable, Out: Encodable>(
52+
_ closure: @escaping CodableLambdaClosure<In, Out>,
53+
config: TestConfig = .init(),
54+
with payload: In
55+
) throws -> Out {
56+
try Self.test(CodableLambdaClosureWrapper(closure), config: config, with: payload)
3857
}
3958

4059
public static func test<In: Decodable>(_ closure: @escaping CodableVoidLambdaClosure<In>,
41-
with payload: In,
42-
_ body: @escaping (Result<Void, Error>) -> Void) {
43-
Self.test(CodableVoidLambdaClosureWrapper(closure), with: payload, body)
60+
config: TestConfig = .init(),
61+
with payload: In) throws {
62+
_ = try Self.test(CodableVoidLambdaClosureWrapper(closure), config: config, with: payload)
4463
}
4564

46-
public static func test<In, Out, Handler: EventLoopLambdaHandler>(_ handler: Handler,
47-
with payload: In,
48-
_ body: @escaping (Result<Out, Error>) -> Void) where Handler.In == In, Handler.Out == Out {
65+
public static func test<In, Out, Handler: EventLoopLambdaHandler>(
66+
_ handler: Handler,
67+
config: TestConfig = .init(),
68+
with payload: In
69+
) throws -> Out where Handler.In == In, Handler.Out == Out {
4970
let logger = Logger(label: "test")
5071
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
51-
let context = Context(requestId: "\(DispatchTime.now().uptimeNanoseconds)",
52-
traceId: "Root=\(DispatchTime.now().uptimeNanoseconds);Parent=\(DispatchTime.now().uptimeNanoseconds);Sampled=1",
53-
invokedFunctionArn: "arn:aws:lambda:us-west-1:\(DispatchTime.now().uptimeNanoseconds):function:custom-runtime",
54-
deadline: .now() + 5,
72+
let eventLoop = eventLoopGroup.next()
73+
74+
let context = Context(requestId: config.requestId,
75+
traceId: config.traceId,
76+
invokedFunctionArn: config.invokedFunctionArn,
77+
deadline: .now() + config.timeout,
5578
logger: logger,
56-
eventLoop: eventLoopGroup.next())
57-
handler.handle(context: context, payload: payload).whenComplete { result in
58-
body(result)
59-
}
79+
eventLoop: eventLoop)
80+
81+
let result = try eventLoop.flatSubmit {
82+
handler.handle(context: context, payload: payload)
83+
}.wait()
84+
85+
try eventLoopGroup.syncShutdownGracefully()
86+
return result
6087
}
6188
}

Tests/AWSLambdaTestingTests/Tests.swift

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import AWSLambdaRuntime
1616
import AWSLambdaTesting
17+
import NIO
1718
import XCTest
1819

1920
class LambdaTestingTests: XCTestCase {
@@ -31,14 +32,9 @@ class LambdaTestingTests: XCTestCase {
3132
}
3233

3334
let request = Request(name: UUID().uuidString)
34-
Lambda.test(myLambda, with: request) { result in
35-
switch result {
36-
case .failure(let error):
37-
XCTFail("expected to succeed but failed with \(error)")
38-
case .success(let response):
39-
XCTAssertEqual(response.message, "echo" + request.name)
40-
}
41-
}
35+
var response: Response?
36+
XCTAssertNoThrow(response = try Lambda.test(myLambda, with: request))
37+
XCTAssertEqual(response?.message, "echo" + request.name)
4238
}
4339

4440
func testCodableVoidClosure() {
@@ -51,14 +47,7 @@ class LambdaTestingTests: XCTestCase {
5147
}
5248

5349
let request = Request(name: UUID().uuidString)
54-
Lambda.test(myLambda, with: request) { result in
55-
switch result {
56-
case .failure(let error):
57-
XCTFail("expected to succeed but failed with \(error)")
58-
case .success:
59-
break
60-
}
61-
}
50+
XCTAssertNoThrow(try Lambda.test(myLambda, with: request))
6251
}
6352

6453
func testLambdaHandler() {
@@ -75,19 +64,32 @@ class LambdaTestingTests: XCTestCase {
7564
typealias Out = Response
7665

7766
func handle(context: Lambda.Context, payload: In, callback: @escaping (Result<Out, Error>) -> Void) {
67+
XCTAssertFalse(context.eventLoop.inEventLoop)
7868
callback(.success(Response(message: "echo" + payload.name)))
7969
}
8070
}
8171

8272
let request = Request(name: UUID().uuidString)
83-
Lambda.test(MyLambda(), with: request) { result in
84-
switch result {
85-
case .failure(let error):
86-
XCTFail("expected to succeed but failed with \(error)")
87-
case .success(let response):
88-
XCTAssertEqual(response.message, "echo" + request.name)
73+
var response: Response?
74+
XCTAssertNoThrow(response = try Lambda.test(MyLambda(), with: request))
75+
XCTAssertEqual(response?.message, "echo" + request.name)
76+
}
77+
78+
func testEventLoopLambdaHandler() {
79+
struct MyLambda: EventLoopLambdaHandler {
80+
typealias In = String
81+
typealias Out = String
82+
83+
func handle(context: Lambda.Context, payload: String) -> EventLoopFuture<String> {
84+
XCTAssertTrue(context.eventLoop.inEventLoop)
85+
return context.eventLoop.makeSucceededFuture("echo" + payload)
8986
}
9087
}
88+
89+
let input = UUID().uuidString
90+
var result: String?
91+
XCTAssertNoThrow(result = try Lambda.test(MyLambda(), with: input))
92+
XCTAssertEqual(result, "echo" + input)
9193
}
9294

9395
func testFailure() {
@@ -102,13 +104,43 @@ class LambdaTestingTests: XCTestCase {
102104
}
103105
}
104106

105-
Lambda.test(MyLambda(), with: UUID().uuidString) { result in
106-
switch result {
107-
case .failure(let error):
108-
XCTAssert(error is MyError)
109-
case .success:
110-
XCTFail("expected to fail but succeeded")
107+
XCTAssertThrowsError(try Lambda.test(MyLambda(), with: UUID().uuidString)) { error in
108+
XCTAssert(error is MyError)
109+
}
110+
}
111+
112+
func testAsyncLongRunning() {
113+
var executed: Bool = false
114+
let myLambda = { (_: Lambda.Context, _: String, callback: @escaping (Result<Void, Error>) -> Void) in
115+
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 0.5) {
116+
executed = true
117+
callback(.success(()))
111118
}
112119
}
120+
121+
XCTAssertNoThrow(try Lambda.test(myLambda, with: UUID().uuidString))
122+
XCTAssertTrue(executed)
123+
}
124+
125+
func testConfigValues() {
126+
let config = Lambda.TestConfig(
127+
requestId: "abc123",
128+
traceId: "hahahihi",
129+
invokedFunctionArn: "arn:hihi",
130+
timeout: 4
131+
)
132+
133+
let myLambda = { (ctx: Lambda.Context, _: String, callback: @escaping (Result<Void, Error>) -> Void) in
134+
XCTAssertEqual(ctx.requestId, config.requestId)
135+
XCTAssertEqual(ctx.traceId, config.traceId)
136+
XCTAssertEqual(ctx.invokedFunctionArn, config.invokedFunctionArn)
137+
138+
let secondsSinceEpoch = Double(Int64(bitPattern: ctx.deadline.rawValue)) / -1_000_000_000
139+
XCTAssertLessThanOrEqual(Date(timeIntervalSince1970: secondsSinceEpoch).timeIntervalSinceNow, config.timeout)
140+
141+
callback(.success(()))
142+
}
143+
144+
XCTAssertNoThrow(try Lambda.test(myLambda, config: config, with: UUID().uuidString))
113145
}
114146
}

0 commit comments

Comments
 (0)