From 2127f7c91fd60260c5e7e80ae26a4401bd93fad9 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Mon, 7 Oct 2024 16:41:22 +0200 Subject: [PATCH 1/6] Ensure Events still compiles --- Sources/AWSLambdaEvents/Utils/DateWrappers.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Sources/AWSLambdaEvents/Utils/DateWrappers.swift b/Sources/AWSLambdaEvents/Utils/DateWrappers.swift index afcd22a..11ea72f 100644 --- a/Sources/AWSLambdaEvents/Utils/DateWrappers.swift +++ b/Sources/AWSLambdaEvents/Utils/DateWrappers.swift @@ -12,11 +12,7 @@ // //===----------------------------------------------------------------------===// -#if canImport(FoundationEssentials) -import FoundationEssentials -#else import Foundation -#endif @propertyWrapper public struct ISO8601Coding: Decodable, Sendable { From 8458edf1b07f7cc997e799277c19629619d1ecb9 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Mon, 7 Oct 2024 16:48:24 +0200 Subject: [PATCH 2/6] Fix unacceptable language --- Sources/AWSLambdaEvents/ALB.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/AWSLambdaEvents/ALB.swift b/Sources/AWSLambdaEvents/ALB.swift index d45eb77..3fcdd9f 100644 --- a/Sources/AWSLambdaEvents/ALB.swift +++ b/Sources/AWSLambdaEvents/ALB.swift @@ -20,7 +20,7 @@ import FoundationEssentials import Foundation #endif -// https://github.com/aws/aws-lambda-go/blob/master/events/alb.go +// https://github.com/aws/aws-lambda-go/blob/main/events/alb.go /// `ALBTargetGroupRequest` contains data originating from the ALB Lambda target group integration. public struct ALBTargetGroupRequest: Codable, Sendable { /// `Context` contains information to identify the load balancer invoking the lambda. From a7a75707941bdd627b01b85afed83aef86b22bcb Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Mon, 7 Oct 2024 16:53:51 +0200 Subject: [PATCH 3/6] Fix more --- .github/workflows/pull_request.yml | 4 ++-- .licenseignore | 0 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 .licenseignore diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 503c0dc..c290ffb 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -11,8 +11,8 @@ jobs: with: license_header_check_project_name: "SwiftAWSLambdaEvents" shell_check_enabled: false - api_breakage_check_container_image: "swiftlang/swift:nightly-6.0-jammy" - docs_check_container_image: "swiftlang/swift:nightly-6.0-jammy" + api_breakage_check_container_image: "swift:6.0-jammy" + docs_check_container_image: "swift:6.0-focal" unit-tests: name: Unit tests diff --git a/.licenseignore b/.licenseignore new file mode 100644 index 0000000..e69de29 From 0e9f19884f53179443254272338d5e9a69da5c94 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Tue, 8 Oct 2024 12:03:33 +0200 Subject: [PATCH 4/6] swift-format --- Examples/Simple/Package.swift | 15 +- Package.swift | 6 +- .../APIGatewayLambdaAuthorizers.swift | 6 +- Sources/AWSLambdaEvents/AppSync.swift | 22 +- Sources/AWSLambdaEvents/Cognito.swift | 26 +- Sources/AWSLambdaEvents/DynamoDB.swift | 139 ++++--- Sources/AWSLambdaEvents/SNS.swift | 12 +- Sources/AWSLambdaEvents/SQS.swift | 12 +- Sources/AWSLambdaEvents/Utils/Base64.swift | 115 +++--- .../AWSLambdaEvents/Utils/DateWrappers.swift | 23 +- Sources/AWSLambdaEvents/Utils/HTTP.swift | 7 +- Tests/AWSLambdaEventsTests/ALBTests.swift | 53 +-- .../APIGateway+V2IAMTests.swift | 211 +++++----- .../APIGateway+V2Tests.swift | 233 +++++------ .../APIGatewayLambdaAuthorizerTest.swift | 270 +++++++------ .../APIGatewayTests.swift | 24 +- Tests/AWSLambdaEventsTests/AppSyncTests.swift | 363 +++++++++--------- .../BedrockAgentTests.swift | 3 +- .../CloudFormationTests.swift | 3 +- .../CloudwatchTests.swift | 29 +- Tests/AWSLambdaEventsTests/CognitoTests.swift | 329 +++++++++------- .../AWSLambdaEventsTests/DynamoDBTests.swift | 232 ++++++----- .../FunctionURLTests.swift | 189 ++++----- .../LambdaGatewayProxyEventTests.swift | 191 ++++----- Tests/AWSLambdaEventsTests/S3Tests.swift | 141 +++---- Tests/AWSLambdaEventsTests/SESTests.swift | 130 ++++--- Tests/AWSLambdaEventsTests/SNSTests.swift | 79 ++-- Tests/AWSLambdaEventsTests/SQSTests.swift | 92 ++--- .../Utils/Base64Tests.swift | 13 +- .../Utils/DateWrapperTests.swift | 33 +- 30 files changed, 1620 insertions(+), 1381 deletions(-) diff --git a/Examples/Simple/Package.swift b/Examples/Simple/Package.swift index 461e21d..8eaf80f 100644 --- a/Examples/Simple/Package.swift +++ b/Examples/Simple/Package.swift @@ -5,11 +5,11 @@ import PackageDescription let package = Package( name: "swift-aws-lambda-events-samples", platforms: [ - .macOS(.v12), + .macOS(.v12) ], products: [ // demonstrate how to integrate with AWS API Gateway - .executable(name: "APIGateway", targets: ["APIGateway"]), + .executable(name: "APIGateway", targets: ["APIGateway"]) ], dependencies: [ // this is the dependency on the swift-aws-lambda-runtime library @@ -21,9 +21,12 @@ let package = Package( .package(name: "swift-aws-lambda-events", path: "../.."), ], targets: [ - .executableTarget(name: "APIGateway", dependencies: [ - .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"), - .product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events"), - ]), + .executableTarget( + name: "APIGateway", + dependencies: [ + .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"), + .product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events"), + ] + ) ] ) diff --git a/Package.swift b/Package.swift index f95c2a3..36b37d0 100644 --- a/Package.swift +++ b/Package.swift @@ -7,7 +7,7 @@ let swiftSettings: [SwiftSetting] = [.enableExperimentalFeature("StrictConcurren let package = Package( name: "swift-aws-lambda-events", products: [ - .library(name: "AWSLambdaEvents", targets: ["AWSLambdaEvents"]), + .library(name: "AWSLambdaEvents", targets: ["AWSLambdaEvents"]) ], dependencies: [ .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), @@ -17,14 +17,14 @@ let package = Package( .target( name: "AWSLambdaEvents", dependencies: [ - .product(name: "HTTPTypes", package: "swift-http-types"), + .product(name: "HTTPTypes", package: "swift-http-types") ], swiftSettings: swiftSettings ), .testTarget( name: "AWSLambdaEventsTests", dependencies: [ - "AWSLambdaEvents", + "AWSLambdaEvents" ], swiftSettings: swiftSettings ), diff --git a/Sources/AWSLambdaEvents/APIGatewayLambdaAuthorizers.swift b/Sources/AWSLambdaEvents/APIGatewayLambdaAuthorizers.swift index fab1679..d7f9ce0 100644 --- a/Sources/AWSLambdaEvents/APIGatewayLambdaAuthorizers.swift +++ b/Sources/AWSLambdaEvents/APIGatewayLambdaAuthorizers.swift @@ -60,8 +60,10 @@ public struct APIGatewayLambdaAuthorizerSimpleResponse: Codable, Sendable { public let isAuthorized: Bool public let context: LambdaAuthorizerContext? - public init(isAuthorized: Bool, - context: LambdaAuthorizerContext?) { + public init( + isAuthorized: Bool, + context: LambdaAuthorizerContext? + ) { self.isAuthorized = isAuthorized self.context = context } diff --git a/Sources/AWSLambdaEvents/AppSync.swift b/Sources/AWSLambdaEvents/AppSync.swift index 2896e1e..b228071 100644 --- a/Sources/AWSLambdaEvents/AppSync.swift +++ b/Sources/AWSLambdaEvents/AppSync.swift @@ -29,10 +29,13 @@ public struct AppSyncEvent: Decodable, Sendable { } else if let dictionaryValue = try? container.decode([String: String].self) { self = .dictionary(dictionaryValue) } else { - throw DecodingError.dataCorruptedError(in: container, debugDescription: """ - Unexpected AppSync argument. - Expected a String or a Dictionary. - """) + throw DecodingError.dataCorruptedError( + in: container, + debugDescription: """ + Unexpected AppSync argument. + Expected a String or a Dictionary. + """ + ) } } @@ -127,10 +130,13 @@ public struct AppSyncEvent: Decodable, Sendable { } else if let cognitoIdentity = try? container.decode(CognitoUserPoolIdentity.self) { self = .cognitoUserPools(cognitoIdentity) } else { - throw DecodingError.dataCorruptedError(in: container, debugDescription: """ - Unexpected Identity argument. - Expected a IAM Identity or a Cognito User Pool Identity. - """) + throw DecodingError.dataCorruptedError( + in: container, + debugDescription: """ + Unexpected Identity argument. + Expected a IAM Identity or a Cognito User Pool Identity. + """ + ) } } diff --git a/Sources/AWSLambdaEvents/Cognito.swift b/Sources/AWSLambdaEvents/Cognito.swift index 379aff1..e42b9ff 100644 --- a/Sources/AWSLambdaEvents/Cognito.swift +++ b/Sources/AWSLambdaEvents/Cognito.swift @@ -189,7 +189,14 @@ extension CognitoEvent: Codable { let userName = try container.decode(String.self, forKey: .userName) let callerContext = try container.decode(CallerContext.self, forKey: .callerContext) - let params = CognitoEvent.Parameters(version: version, triggerSource: triggerSource, region: region, userPoolId: userPoolId, userName: userName, callerContext: callerContext) + let params = CognitoEvent.Parameters( + version: version, + triggerSource: triggerSource, + region: region, + userPoolId: userPoolId, + userName: userName, + callerContext: callerContext + ) switch triggerSource { case .preSignUp_SignUp, .preSignUp_ExternalProvider, .preSignUp_AdminCreateUser: @@ -204,7 +211,9 @@ extension CognitoEvent: Codable { let value = try container.decode(CognitoEvent.PostAuthentication.self, forKey: .request) self = .postAuthentication(params, value) - case .customMessage_SignUp, .customMessage_AdminCreateUser, .customMessage_ResendCode, .customMessage_ForgotPassword, .customMessage_UpdateUserAttribute, .customMessage_VerifyUserAttribute, .customMessage_Authentication: + case .customMessage_SignUp, .customMessage_AdminCreateUser, .customMessage_ResendCode, + .customMessage_ForgotPassword, .customMessage_UpdateUserAttribute, .customMessage_VerifyUserAttribute, + .customMessage_Authentication: let value = try container.decode(CognitoEvent.CustomMessage.self, forKey: .request) self = .customMessage(params, value) @@ -317,7 +326,14 @@ extension CognitoEventResponse: Codable { let userName = try container.decode(String.self, forKey: .userName) let callerContext = try container.decode(CognitoEvent.CallerContext.self, forKey: .callerContext) - let params = CognitoEvent.Parameters(version: version, triggerSource: triggerSource, region: region, userPoolId: userPoolId, userName: userName, callerContext: callerContext) + let params = CognitoEvent.Parameters( + version: version, + triggerSource: triggerSource, + region: region, + userPoolId: userPoolId, + userName: userName, + callerContext: callerContext + ) switch triggerSource { case .preSignUp_SignUp, .preSignUp_AdminCreateUser, .preSignUp_ExternalProvider: @@ -338,7 +354,9 @@ extension CognitoEventResponse: Codable { self = .postAuthentication(params, request, response) - case .customMessage_SignUp, .customMessage_AdminCreateUser, .customMessage_ResendCode, .customMessage_ForgotPassword, .customMessage_UpdateUserAttribute, .customMessage_VerifyUserAttribute, .customMessage_Authentication: + case .customMessage_SignUp, .customMessage_AdminCreateUser, .customMessage_ResendCode, + .customMessage_ForgotPassword, .customMessage_UpdateUserAttribute, .customMessage_VerifyUserAttribute, + .customMessage_Authentication: let request = try container.decode(CognitoEvent.CustomMessage.self, forKey: .request) let response = try container.decode(CognitoEventResponse.CustomMessage.self, forKey: .response) diff --git a/Sources/AWSLambdaEvents/DynamoDB.swift b/Sources/AWSLambdaEvents/DynamoDB.swift index df27642..ab5fca9 100644 --- a/Sources/AWSLambdaEvents/DynamoDB.swift +++ b/Sources/AWSLambdaEvents/DynamoDB.swift @@ -312,13 +312,17 @@ extension DynamoDBEvent { public init() {} - @inlinable public func decode(_ type: T.Type, from image: [String: AttributeValue]) - throws -> T { + @inlinable public func decode( + _ type: T.Type, + from image: [String: AttributeValue] + ) throws -> T { try self.decode(type, from: .map(image)) } - @inlinable public func decode(_ type: T.Type, from value: AttributeValue) - throws -> T { + @inlinable public func decode( + _ type: T.Type, + from value: AttributeValue + ) throws -> T { let decoder = _DecoderImpl(userInfo: userInfo, from: value, codingPath: []) return try decoder.decode(T.self) } @@ -340,13 +344,17 @@ extension DynamoDBEvent { try T(from: self) } - @usableFromInline func container(keyedBy type: Key.Type) throws -> - KeyedDecodingContainer where Key: CodingKey { + @usableFromInline func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer + where Key: CodingKey { guard case .map(let dictionary) = self.value else { - throw DecodingError.typeMismatch([String: AttributeValue].self, DecodingError.Context( - codingPath: self.codingPath, - debugDescription: "Expected to decode \([String: AttributeValue].self) but found \(self.value.debugDataTypeDescription) instead." - )) + throw DecodingError.typeMismatch( + [String: AttributeValue].self, + DecodingError.Context( + codingPath: self.codingPath, + debugDescription: + "Expected to decode \([String: AttributeValue].self) but found \(self.value.debugDataTypeDescription) instead." + ) + ) } let container = _KeyedDecodingContainer( @@ -359,10 +367,14 @@ extension DynamoDBEvent { @usableFromInline func unkeyedContainer() throws -> UnkeyedDecodingContainer { guard case .list(let array) = self.value else { - throw DecodingError.typeMismatch([AttributeValue].self, DecodingError.Context( - codingPath: self.codingPath, - debugDescription: "Expected to decode \([AttributeValue].self) but found \(self.value.debugDataTypeDescription) instead." - )) + throw DecodingError.typeMismatch( + [AttributeValue].self, + DecodingError.Context( + codingPath: self.codingPath, + debugDescription: + "Expected to decode \([AttributeValue].self) but found \(self.value.debugDataTypeDescription) instead." + ) + ) } return _UnkeyedDecodingContainer( @@ -509,8 +521,12 @@ extension DynamoDBEvent { return try T(from: decoder) } - func nestedContainer(keyedBy type: NestedKey.Type, forKey key: K) throws - -> KeyedDecodingContainer where NestedKey: CodingKey { + func nestedContainer( + keyedBy type: NestedKey.Type, + forKey key: K + ) throws + -> KeyedDecodingContainer where NestedKey: CodingKey + { try self.decoderForKey(key).container(keyedBy: type) } @@ -540,24 +556,38 @@ extension DynamoDBEvent { @inline(__always) private func getValue(forKey key: K) throws -> AttributeValue { guard let value = self.dictionary[key.stringValue] else { - throw DecodingError.keyNotFound(key, .init( - codingPath: self.codingPath, - debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")." - )) + throw DecodingError.keyNotFound( + key, + .init( + codingPath: self.codingPath, + debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")." + ) + ) } return value } - @inline(__always) private func createTypeMismatchError(type: Any.Type, forKey key: K, value: AttributeValue) -> DecodingError { + @inline(__always) private func createTypeMismatchError( + type: Any.Type, + forKey key: K, + value: AttributeValue + ) -> DecodingError { let codingPath = self.codingPath + [key] - return DecodingError.typeMismatch(type, .init( - codingPath: codingPath, debugDescription: "Expected to decode \(type) but found \(value.debugDataTypeDescription) instead." - )) + return DecodingError.typeMismatch( + type, + .init( + codingPath: codingPath, + debugDescription: "Expected to decode \(type) but found \(value.debugDataTypeDescription) instead." + ) + ) } - @inline(__always) private func decodeFixedWidthInteger(key: Self.Key) - throws -> T { + @inline(__always) private func decodeFixedWidthInteger( + key: Self.Key + ) + throws -> T + { let value = try getValue(forKey: key) guard case .number(let number) = value else { @@ -576,7 +606,8 @@ extension DynamoDBEvent { } @inline(__always) private func decodeLosslessStringConvertible( - key: Self.Key) throws -> T { + key: Self.Key + ) throws -> T { let value = try getValue(forKey: key) guard case .number(let number) = value else { @@ -679,14 +710,18 @@ extension DynamoDBEvent { } @inline(__always) private func createTypeMismatchError(type: Any.Type, value: AttributeValue) -> DecodingError { - DecodingError.typeMismatch(type, .init( - codingPath: self.codingPath, - debugDescription: "Expected to decode \(type) but found \(value.debugDataTypeDescription) instead." - )) + DecodingError.typeMismatch( + type, + .init( + codingPath: self.codingPath, + debugDescription: "Expected to decode \(type) but found \(value.debugDataTypeDescription) instead." + ) + ) } @inline(__always) private func decodeFixedWidthInteger() throws - -> T { + -> T + { guard case .number(let number) = self.value else { throw self.createTypeMismatchError(type: T.self, value: self.value) } @@ -702,7 +737,8 @@ extension DynamoDBEvent { } @inline(__always) private func decodeLosslessStringConvertible() - throws -> T { + throws -> T + { guard case .number(let number) = self.value else { throw self.createTypeMismatchError(type: T.self, value: self.value) } @@ -723,7 +759,7 @@ extension DynamoDBEvent { let codingPath: [CodingKey] let array: [AttributeValue] - let count: Int? // protocol requirement to be optional + let count: Int? // protocol requirement to be optional var isAtEnd = false var currentIndex = 0 @@ -844,8 +880,11 @@ extension DynamoDBEvent { return try T(from: decoder) } - mutating func nestedContainer(keyedBy type: NestedKey.Type) throws - -> KeyedDecodingContainer where NestedKey: CodingKey { + mutating func nestedContainer( + keyedBy type: NestedKey.Type + ) throws + -> KeyedDecodingContainer where NestedKey: CodingKey + { try self.impl.container(keyedBy: type) } @@ -859,13 +898,18 @@ extension DynamoDBEvent { @inline(__always) private func createTypeMismatchError(type: Any.Type, value: AttributeValue) -> DecodingError { let codingPath = self.codingPath + [ArrayKey(index: self.currentIndex)] - return DecodingError.typeMismatch(type, .init( - codingPath: codingPath, debugDescription: "Expected to decode \(type) but found \(value.debugDataTypeDescription) instead." - )) + return DecodingError.typeMismatch( + type, + .init( + codingPath: codingPath, + debugDescription: "Expected to decode \(type) but found \(value.debugDataTypeDescription) instead." + ) + ) } @inline(__always) private mutating func decodeFixedWidthInteger() throws - -> T { + -> T + { defer { currentIndex += 1 if currentIndex == count { @@ -878,15 +922,18 @@ extension DynamoDBEvent { } guard let integer = T(number) else { - throw DecodingError.dataCorruptedError(in: self, - debugDescription: "Parsed JSON number <\(number)> does not fit in \(T.self).") + throw DecodingError.dataCorruptedError( + in: self, + debugDescription: "Parsed JSON number <\(number)> does not fit in \(T.self)." + ) } return integer } @inline(__always) private mutating func decodeLosslessStringConvertible() - throws -> T { + throws -> T + { defer { currentIndex += 1 if currentIndex == count { @@ -899,8 +946,10 @@ extension DynamoDBEvent { } guard let float = T(number) else { - throw DecodingError.dataCorruptedError(in: self, - debugDescription: "Parsed JSON number <\(number)> does not fit in \(T.self).") + throw DecodingError.dataCorruptedError( + in: self, + debugDescription: "Parsed JSON number <\(number)> does not fit in \(T.self)." + ) } return float diff --git a/Sources/AWSLambdaEvents/SNS.swift b/Sources/AWSLambdaEvents/SNS.swift index 31fa291..a3deb0b 100644 --- a/Sources/AWSLambdaEvents/SNS.swift +++ b/Sources/AWSLambdaEvents/SNS.swift @@ -101,10 +101,14 @@ extension SNSEvent.Message.Attribute: Decodable { let bytes = try base64encoded.base64decoded() self = .binary(bytes) default: - throw DecodingError.dataCorruptedError(forKey: .dataType, in: container, debugDescription: """ - Unexpected value \"\(dataType)\" for key \(CodingKeys.dataType). - Expected `String` or `Binary`. - """) + throw DecodingError.dataCorruptedError( + forKey: .dataType, + in: container, + debugDescription: """ + Unexpected value \"\(dataType)\" for key \(CodingKeys.dataType). + Expected `String` or `Binary`. + """ + ) } } } diff --git a/Sources/AWSLambdaEvents/SQS.swift b/Sources/AWSLambdaEvents/SQS.swift index 9b745c6..5a6f3b7 100644 --- a/Sources/AWSLambdaEvents/SQS.swift +++ b/Sources/AWSLambdaEvents/SQS.swift @@ -86,10 +86,14 @@ extension SQSEvent.Message.Attribute: Decodable { let bytes = try base64encoded.base64decoded() self = .binary(bytes) default: - throw DecodingError.dataCorruptedError(forKey: .dataType, in: container, debugDescription: """ - Unexpected value \"\(dataType)\" for key \(CodingKeys.dataType). - Expected `String`, `Binary` or `Number`. - """) + throw DecodingError.dataCorruptedError( + forKey: .dataType, + in: container, + debugDescription: """ + Unexpected value \"\(dataType)\" for key \(CodingKeys.dataType). + Expected `String`, `Binary` or `Number`. + """ + ) } } } diff --git a/Sources/AWSLambdaEvents/Utils/Base64.swift b/Sources/AWSLambdaEvents/Utils/Base64.swift index 310a6aa..df6d535 100644 --- a/Sources/AWSLambdaEvents/Utils/Base64.swift +++ b/Sources/AWSLambdaEvents/Utils/Base64.swift @@ -36,9 +36,12 @@ extension Base64 { } @inlinable - static func decode(encoded: Buffer, options: DecodingOptions = []) - throws -> [UInt8] where Buffer.Element == UInt8 { - let alphabet = options.contains(.base64UrlAlphabet) + static func decode( + encoded: Buffer, + options: DecodingOptions = [] + ) throws -> [UInt8] where Buffer.Element == UInt8 { + let alphabet = + options.contains(.base64UrlAlphabet) ? Base64.decodeBase64Url : Base64.decodeBase64 @@ -58,7 +61,7 @@ extension Base64 { outputBytes.reserveCapacity(outputLength) // fast loop. we don't expect any padding in here. - for _ in 0 ..< fullQualified { + for _ in 0.. String { """ @@ -52,11 +53,15 @@ class CloudwatchTests: XCTestCase { } func testEC2InstanceStateChangeNotificationEventFromJSON() { - let eventBody = CloudwatchTests.eventBody(type: CloudwatchDetails.EC2.InstanceStateChangeNotification.name, - details: "{ \"instance-id\": \"0\", \"state\": \"stopping\" }") + let eventBody = CloudwatchTests.eventBody( + type: CloudwatchDetails.EC2.InstanceStateChangeNotification.name, + details: "{ \"instance-id\": \"0\", \"state\": \"stopping\" }" + ) let data = eventBody.data(using: .utf8)! var maybeEvent: CloudwatchEC2InstanceStateChangeNotificationEvent? - XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(CloudwatchEC2InstanceStateChangeNotificationEvent.self, from: data)) + XCTAssertNoThrow( + maybeEvent = try JSONDecoder().decode(CloudwatchEC2InstanceStateChangeNotificationEvent.self, from: data) + ) guard let event = maybeEvent else { return XCTFail("Expected to have an event") @@ -73,11 +78,15 @@ class CloudwatchTests: XCTestCase { } func testEC2SpotInstanceInterruptionNoticeEventFromJSON() { - let eventBody = CloudwatchTests.eventBody(type: CloudwatchDetails.EC2.SpotInstanceInterruptionNotice.name, - details: "{ \"instance-id\": \"0\", \"instance-action\": \"terminate\" }") + let eventBody = CloudwatchTests.eventBody( + type: CloudwatchDetails.EC2.SpotInstanceInterruptionNotice.name, + details: "{ \"instance-id\": \"0\", \"instance-action\": \"terminate\" }" + ) let data = eventBody.data(using: .utf8)! var maybeEvent: CloudwatchEC2SpotInstanceInterruptionNoticeEvent? - XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(CloudwatchEC2SpotInstanceInterruptionNoticeEvent.self, from: data)) + XCTAssertNoThrow( + maybeEvent = try JSONDecoder().decode(CloudwatchEC2SpotInstanceInterruptionNoticeEvent.self, from: data) + ) guard let event = maybeEvent else { return XCTFail("Expected to have an event") @@ -127,8 +136,10 @@ class CloudwatchTests: XCTestCase { } func testTypeMismatch() { - let eventBody = CloudwatchTests.eventBody(type: CloudwatchDetails.EC2.InstanceStateChangeNotification.name, - details: "{ \"instance-id\": \"0\", \"state\": \"stopping\" }") + let eventBody = CloudwatchTests.eventBody( + type: CloudwatchDetails.EC2.InstanceStateChangeNotification.name, + details: "{ \"instance-id\": \"0\", \"state\": \"stopping\" }" + ) let data = eventBody.data(using: .utf8)! XCTAssertThrowsError(try JSONDecoder().decode(CloudwatchScheduledEvent.self, from: data)) { error in XCTAssert(error is CloudwatchDetails.TypeMismatch, "expected DetailTypeMismatch but received \(error)") diff --git a/Tests/AWSLambdaEventsTests/CognitoTests.swift b/Tests/AWSLambdaEventsTests/CognitoTests.swift index 3d5bd4a..d356a6c 100644 --- a/Tests/AWSLambdaEventsTests/CognitoTests.swift +++ b/Tests/AWSLambdaEventsTests/CognitoTests.swift @@ -12,37 +12,38 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + final class CognitoTests: XCTestCase { func testPreSignUpRequest() throws { let json = """ - { - "version": "1", - "triggerSource": "PreSignUp_SignUp", - "region": "us-east-1", - "userPoolId": "abc", - "userName": "blob", - "callerContext": { - "awsSdkVersion": "1", - "clientId": "abc", - }, - "request": { - "userAttributes": { - "string": "string" - }, - "validationData": { - "string": "string" - }, - "clientMetadata": { - "string": "string" - } - }, - - "response": {} - } - """ + { + "version": "1", + "triggerSource": "PreSignUp_SignUp", + "region": "us-east-1", + "userPoolId": "abc", + "userName": "blob", + "callerContext": { + "awsSdkVersion": "1", + "clientId": "abc", + }, + "request": { + "userAttributes": { + "string": "string" + }, + "validationData": { + "string": "string" + }, + "clientMetadata": { + "string": "string" + } + }, + + "response": {} + } + """ let event = try JSONDecoder().decode(CognitoEvent.self, from: json.data(using: .utf8)!) guard case .preSignUp(let params, let request) = event else { @@ -52,26 +53,34 @@ final class CognitoTests: XCTestCase { XCTAssertEqual(params.triggerSource, .preSignUp_SignUp) - let signUp = CognitoEvent.PreSignUp(userAttributes: ["string": "string"], - validationData: ["string": "string"], - clientMetadata: ["string": "string"]) + let signUp = CognitoEvent.PreSignUp( + userAttributes: ["string": "string"], + validationData: ["string": "string"], + clientMetadata: ["string": "string"] + ) XCTAssertEqual(request, signUp) } func testPreSignUpResponse() throws { - let params = CognitoEvent.Parameters(version: "1", - triggerSource: .preSignUp_SignUp, - region: .us_east_1, - userPoolId: "abc", - userName: "blob", - callerContext: .init(awsSdkVersion: "1", clientId: "abc")) - let request = CognitoEvent.PreSignUp(userAttributes: ["string": "string"], - validationData: ["string": "string"], - clientMetadata: ["string": "string"]) - - let signUpResponse = CognitoEventResponse.PreSignUp(autoConfirmUser: true, - autoVerifyPhone: true, - autoVerifyEmail: true) + let params = CognitoEvent.Parameters( + version: "1", + triggerSource: .preSignUp_SignUp, + region: .us_east_1, + userPoolId: "abc", + userName: "blob", + callerContext: .init(awsSdkVersion: "1", clientId: "abc") + ) + let request = CognitoEvent.PreSignUp( + userAttributes: ["string": "string"], + validationData: ["string": "string"], + clientMetadata: ["string": "string"] + ) + + let signUpResponse = CognitoEventResponse.PreSignUp( + autoConfirmUser: true, + autoVerifyPhone: true, + autoVerifyEmail: true + ) let response = CognitoEventResponse.preSignUp(params, request, signUpResponse) @@ -91,27 +100,27 @@ final class CognitoTests: XCTestCase { func testPostConfirmationRequest() throws { let json = """ - { - "version": "1", - "triggerSource": "PostConfirmation_ConfirmSignUp", - "region": "us-east-1", - "userPoolId": "abc", - "userName": "blob", - "callerContext": { - "awsSdkVersion": "1", - "clientId": "abc", - }, - "request": { - "userAttributes": { - "string": "string" - }, - "clientMetadata": { - "string": "string" - } - }, - "response": {} - } - """ + { + "version": "1", + "triggerSource": "PostConfirmation_ConfirmSignUp", + "region": "us-east-1", + "userPoolId": "abc", + "userName": "blob", + "callerContext": { + "awsSdkVersion": "1", + "clientId": "abc", + }, + "request": { + "userAttributes": { + "string": "string" + }, + "clientMetadata": { + "string": "string" + } + }, + "response": {} + } + """ let event = try JSONDecoder().decode(CognitoEvent.self, from: json.data(using: .utf8)!) guard case .postConfirmation(let params, let request) = event else { @@ -121,20 +130,26 @@ final class CognitoTests: XCTestCase { XCTAssertEqual(params.triggerSource, .postConfirmation_ConfirmSignUp) - let postConfirmation = CognitoEvent.PostConfirmation(userAttributes: ["string": "string"], - clientMetadata: ["string": "string"]) + let postConfirmation = CognitoEvent.PostConfirmation( + userAttributes: ["string": "string"], + clientMetadata: ["string": "string"] + ) XCTAssertEqual(request, postConfirmation) } func testPostConfirmationResponse() throws { - let params = CognitoEvent.Parameters(version: "1", - triggerSource: .postConfirmation_ConfirmSignUp, - region: .us_east_1, - userPoolId: "abc", - userName: "blob", - callerContext: .init(awsSdkVersion: "1", clientId: "abc")) - let request = CognitoEvent.PostConfirmation(userAttributes: ["string": "string"], - clientMetadata: ["string": "string"]) + let params = CognitoEvent.Parameters( + version: "1", + triggerSource: .postConfirmation_ConfirmSignUp, + region: .us_east_1, + userPoolId: "abc", + userName: "blob", + callerContext: .init(awsSdkVersion: "1", clientId: "abc") + ) + let request = CognitoEvent.PostConfirmation( + userAttributes: ["string": "string"], + clientMetadata: ["string": "string"] + ) let postConfirmationResponse = CognitoEventResponse.EmptyResponse() @@ -144,7 +159,8 @@ final class CognitoTests: XCTestCase { let decodedResponse = try JSONDecoder().decode(CognitoEventResponse.self, from: data) - guard case .postConfirmation(let decodedParams, let decodedRequest, let decodedResponse) = decodedResponse else { + guard case .postConfirmation(let decodedParams, let decodedRequest, let decodedResponse) = decodedResponse + else { XCTFail() return } @@ -156,28 +172,28 @@ final class CognitoTests: XCTestCase { func testPostAuthenticationRequest() throws { let json = """ - { - "version": "1", - "triggerSource": "PostAuthentication_Authentication", - "region": "us-east-1", - "userPoolId": "abc", - "userName": "blob", - "callerContext": { - "awsSdkVersion": "1", - "clientId": "abc", - }, - "request": { - "newDeviceUsed": false, - "userAttributes": { - "string": "string" - }, - "clientMetadata": { - "string": "string" - } - }, - "response": {} - } - """ + { + "version": "1", + "triggerSource": "PostAuthentication_Authentication", + "region": "us-east-1", + "userPoolId": "abc", + "userName": "blob", + "callerContext": { + "awsSdkVersion": "1", + "clientId": "abc", + }, + "request": { + "newDeviceUsed": false, + "userAttributes": { + "string": "string" + }, + "clientMetadata": { + "string": "string" + } + }, + "response": {} + } + """ let event = try JSONDecoder().decode(CognitoEvent.self, from: json.data(using: .utf8)!) guard case .postAuthentication(let params, let request) = event else { @@ -187,22 +203,28 @@ final class CognitoTests: XCTestCase { XCTAssertEqual(params.triggerSource, .postAuthentication_Authentication) - let postAuthentication = CognitoEvent.PostAuthentication(newDeviceUsed: false, - userAttributes: ["string": "string"], - clientMetadata: ["string": "string"]) + let postAuthentication = CognitoEvent.PostAuthentication( + newDeviceUsed: false, + userAttributes: ["string": "string"], + clientMetadata: ["string": "string"] + ) XCTAssertEqual(request, postAuthentication) } func testPostAuthenticationResponse() throws { - let params = CognitoEvent.Parameters(version: "1", - triggerSource: .postAuthentication_Authentication, - region: .us_east_1, - userPoolId: "abc", - userName: "blob", - callerContext: .init(awsSdkVersion: "1", clientId: "abc")) - let request = CognitoEvent.PostAuthentication(newDeviceUsed: false, - userAttributes: ["string": "string"], - clientMetadata: ["string": "string"]) + let params = CognitoEvent.Parameters( + version: "1", + triggerSource: .postAuthentication_Authentication, + region: .us_east_1, + userPoolId: "abc", + userName: "blob", + callerContext: .init(awsSdkVersion: "1", clientId: "abc") + ) + let request = CognitoEvent.PostAuthentication( + newDeviceUsed: false, + userAttributes: ["string": "string"], + clientMetadata: ["string": "string"] + ) let postAuthenticationResponse = CognitoEventResponse.EmptyResponse() @@ -212,7 +234,8 @@ final class CognitoTests: XCTestCase { let decodedResponse = try JSONDecoder().decode(CognitoEventResponse.self, from: data) - guard case .postAuthentication(let decodedParams, let decodedRequest, let decodedResponse) = decodedResponse else { + guard case .postAuthentication(let decodedParams, let decodedRequest, let decodedResponse) = decodedResponse + else { XCTFail() return } @@ -224,29 +247,29 @@ final class CognitoTests: XCTestCase { func testCustomMessageRequest() throws { let json = """ - { - "version": "1", - "triggerSource": "CustomMessage_AdminCreateUser", - "region": "us-east-1", - "userPoolId": "abc", - "userName": "blob", - "callerContext": { - "awsSdkVersion": "1", - "clientId": "abc", - }, - "request": { - "codeParameter": "######", - "usernameParameter": "user123", - "userAttributes": { - "string": "string" - }, - "clientMetadata": { - "string": "string" - } - }, - "response": {} - } - """ + { + "version": "1", + "triggerSource": "CustomMessage_AdminCreateUser", + "region": "us-east-1", + "userPoolId": "abc", + "userName": "blob", + "callerContext": { + "awsSdkVersion": "1", + "clientId": "abc", + }, + "request": { + "codeParameter": "######", + "usernameParameter": "user123", + "userAttributes": { + "string": "string" + }, + "clientMetadata": { + "string": "string" + } + }, + "response": {} + } + """ let event = try JSONDecoder().decode(CognitoEvent.self, from: json.data(using: .utf8)!) guard case .customMessage(let params, let request) = event else { @@ -256,26 +279,36 @@ final class CognitoTests: XCTestCase { XCTAssertEqual(params.triggerSource, .customMessage_AdminCreateUser) - let postAuthentication = CognitoEvent.CustomMessage(codeParameter: "######", - usernameParameter: "user123", - userAttributes: ["string": "string"], - clientMetadata: ["string": "string"]) + let postAuthentication = CognitoEvent.CustomMessage( + codeParameter: "######", + usernameParameter: "user123", + userAttributes: ["string": "string"], + clientMetadata: ["string": "string"] + ) XCTAssertEqual(request, postAuthentication) } func testCustomMessageResponse() throws { - let params = CognitoEvent.Parameters(version: "1", - triggerSource: .customMessage_AdminCreateUser, - region: .us_east_1, - userPoolId: "abc", - userName: "blob", - callerContext: .init(awsSdkVersion: "1", clientId: "abc")) - let request = CognitoEvent.CustomMessage(codeParameter: "######", - usernameParameter: "user123", - userAttributes: ["string": "string"], - clientMetadata: ["string": "string"]) - - let customMessageResponse = CognitoEventResponse.CustomMessage(smsMessage: nil, emailMessage: "Your code is ######", emailSubject: "Sign up code") + let params = CognitoEvent.Parameters( + version: "1", + triggerSource: .customMessage_AdminCreateUser, + region: .us_east_1, + userPoolId: "abc", + userName: "blob", + callerContext: .init(awsSdkVersion: "1", clientId: "abc") + ) + let request = CognitoEvent.CustomMessage( + codeParameter: "######", + usernameParameter: "user123", + userAttributes: ["string": "string"], + clientMetadata: ["string": "string"] + ) + + let customMessageResponse = CognitoEventResponse.CustomMessage( + smsMessage: nil, + emailMessage: "Your code is ######", + emailSubject: "Sign up code" + ) let response = CognitoEventResponse.customMessage(params, request, customMessageResponse) diff --git a/Tests/AWSLambdaEventsTests/DynamoDBTests.swift b/Tests/AWSLambdaEventsTests/DynamoDBTests.swift index cd6ac50..5d2db43 100644 --- a/Tests/AWSLambdaEventsTests/DynamoDBTests.swift +++ b/Tests/AWSLambdaEventsTests/DynamoDBTests.swift @@ -12,105 +12,106 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + class DynamoDBTests: XCTestCase { static let streamEventBody = """ - { - "Records": [ { - "eventID": "1", - "eventVersion": "1.0", - "dynamodb": { - "ApproximateCreationDateTime": 1.578648338E9, - "Keys": { - "Id": { - "N": "101" - } - }, - "NewImage": { - "Message": { - "S": "New item!" + "Records": [ + { + "eventID": "1", + "eventVersion": "1.0", + "dynamodb": { + "ApproximateCreationDateTime": 1.578648338E9, + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "StreamViewType": "NEW_AND_OLD_IMAGES", + "SequenceNumber": "111", + "SizeBytes": 26 }, - "Id": { - "N": "101" - } + "awsRegion": "eu-central-1", + "eventName": "INSERT", + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:account-id:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", + "eventSource": "aws:dynamodb" }, - "StreamViewType": "NEW_AND_OLD_IMAGES", - "SequenceNumber": "111", - "SizeBytes": 26 - }, - "awsRegion": "eu-central-1", - "eventName": "INSERT", - "eventSourceARN": "arn:aws:dynamodb:eu-central-1:account-id:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", - "eventSource": "aws:dynamodb" - }, - { - "eventID": "2", - "eventVersion": "1.0", - "dynamodb": { - "ApproximateCreationDateTime": 1.578648338E9, - "OldImage": { - "Message": { - "S": "New item!" + { + "eventID": "2", + "eventVersion": "1.0", + "dynamodb": { + "ApproximateCreationDateTime": 1.578648338E9, + "OldImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "SequenceNumber": "222", + "Keys": { + "Id": { + "N": "101" + } + }, + "SizeBytes": 59, + "NewImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "StreamViewType": "NEW_AND_OLD_IMAGES" }, - "Id": { - "N": "101" - } - }, - "SequenceNumber": "222", - "Keys": { - "Id": { - "N": "101" - } + "awsRegion": "eu-central-1", + "eventName": "MODIFY", + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:account-id:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", + "eventSource": "aws:dynamodb" }, - "SizeBytes": 59, - "NewImage": { - "Message": { - "S": "This item has changed" + { + "eventID": "3", + "eventVersion": "1.0", + "dynamodb": { + "ApproximateCreationDateTime":1.578648338E9, + "Keys": { + "Id": { + "N": "101" + } + }, + "SizeBytes": 38, + "SequenceNumber": "333", + "OldImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "StreamViewType": "NEW_AND_OLD_IMAGES" }, - "Id": { - "N": "101" - } - }, - "StreamViewType": "NEW_AND_OLD_IMAGES" - }, - "awsRegion": "eu-central-1", - "eventName": "MODIFY", - "eventSourceARN": "arn:aws:dynamodb:eu-central-1:account-id:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", - "eventSource": "aws:dynamodb" - }, - { - "eventID": "3", - "eventVersion": "1.0", - "dynamodb": { - "ApproximateCreationDateTime":1.578648338E9, - "Keys": { - "Id": { - "N": "101" - } - }, - "SizeBytes": 38, - "SequenceNumber": "333", - "OldImage": { - "Message": { - "S": "This item has changed" - }, - "Id": { - "N": "101" - } - }, - "StreamViewType": "NEW_AND_OLD_IMAGES" - }, - "awsRegion": "eu-central-1", - "eventName": "REMOVE", - "eventSourceARN": "arn:aws:dynamodb:eu-central-1:account-id:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", - "eventSource": "aws:dynamodb" + "awsRegion": "eu-central-1", + "eventName": "REMOVE", + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:account-id:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", + "eventSource": "aws:dynamodb" + } + ] } - ] - } - """ + """ func testEventFromJSON() { let data = DynamoDBTests.streamEventBody.data(using: .utf8)! @@ -125,79 +126,104 @@ class DynamoDBTests: XCTestCase { func testAttributeValueBoolDecoding() { let json = "{\"BOOL\": true}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) XCTAssertEqual(value, .boolean(true)) } func testAttributeValueBinaryDecoding() { let json = "{\"B\": \"YmFzZTY0\"}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) XCTAssertEqual(value, .binary([UInt8]("base64".utf8))) } func testAttributeValueBinarySetDecoding() { let json = "{\"BS\": [\"YmFzZTY0\", \"YWJjMTIz\"]}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) XCTAssertEqual(value, .binarySet([[UInt8]("base64".utf8), [UInt8]("abc123".utf8)])) } func testAttributeValueStringDecoding() { let json = "{\"S\": \"huhu\"}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) XCTAssertEqual(value, .string("huhu")) } func testAttributeValueStringSetDecoding() { let json = "{\"SS\": [\"huhu\", \"haha\"]}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) XCTAssertEqual(value, .stringSet(["huhu", "haha"])) } func testAttributeValueNullDecoding() { let json = "{\"NULL\": true}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) XCTAssertEqual(value, .null) } func testAttributeValueNumberDecoding() { let json = "{\"N\": \"1.2345\"}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) XCTAssertEqual(value, .number("1.2345")) } func testAttributeValueNumberSetDecoding() { let json = "{\"NS\": [\"1.2345\", \"-19\"]}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) XCTAssertEqual(value, .numberSet(["1.2345", "-19"])) } func testAttributeValueListDecoding() { let json = "{\"L\": [{\"NS\": [\"1.2345\", \"-19\"]}, {\"S\": \"huhu\"}]}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) XCTAssertEqual(value, .list([.numberSet(["1.2345", "-19"]), .string("huhu")])) } func testAttributeValueMapDecoding() { let json = "{\"M\": {\"numbers\": {\"NS\": [\"1.2345\", \"-19\"]}, \"string\": {\"S\": \"huhu\"}}}" var value: DynamoDBEvent.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) - XCTAssertEqual(value, .map([ - "numbers": .numberSet(["1.2345", "-19"]), - "string": .string("huhu"), - ])) + XCTAssertNoThrow( + value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) + XCTAssertEqual( + value, + .map([ + "numbers": .numberSet(["1.2345", "-19"]), + "string": .string("huhu"), + ]) + ) } func testAttributeValueEmptyDecoding() { let json = "{\"haha\": 1}" - XCTAssertThrowsError(_ = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) { error in + XCTAssertThrowsError( + _ = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!) + ) { error in guard case DecodingError.dataCorrupted = error else { XCTFail("Unexpected error: \(String(describing: error))") return diff --git a/Tests/AWSLambdaEventsTests/FunctionURLTests.swift b/Tests/AWSLambdaEventsTests/FunctionURLTests.swift index 67e49f0..eb70c67 100644 --- a/Tests/AWSLambdaEventsTests/FunctionURLTests.swift +++ b/Tests/AWSLambdaEventsTests/FunctionURLTests.swift @@ -12,112 +12,113 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + class FunctionURLTests: XCTestCase { /// Example event body pulled from [AWS documentation](https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-request-payload). static let documentationExample = """ - { - "version": "2.0", - "routeKey": "$default", - "rawPath": "/my/path", - "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", - "cookies": [ - "cookie1", - "cookie2" - ], - "headers": { - "header1": "value1", - "header2": "value1,value2" - }, - "queryStringParameters": { - "parameter1": "value1,value2", - "parameter2": "value" - }, - "requestContext": { - "accountId": "123456789012", - "apiId": "", - "authentication": null, - "authorizer": { - "iam": { - "accessKey": "AKIA...", - "accountId": "111122223333", - "callerId": "AIDA...", - "cognitoIdentity": null, - "principalOrgId": null, - "userArn": "arn:aws:iam::111122223333:user/example-user", - "userId": "AIDA..." - } + { + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "header1": "value1", + "header2": "value1,value2" }, - "domainName": ".lambda-url.us-west-2.on.aws", - "domainPrefix": "", - "http": { - "method": "POST", - "path": "/my/path", - "protocol": "HTTP/1.1", - "sourceIp": "123.123.123.123", - "userAgent": "agent" + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" }, - "requestId": "id", - "routeKey": "$default", - "stage": "$default", - "time": "12/Mar/2020:19:03:58 +0000", - "timeEpoch": 1583348638390 - }, - "body": "Hello from client!", - "pathParameters": null, - "isBase64Encoded": false, - "stageVariables": null - } - """ + "requestContext": { + "accountId": "123456789012", + "apiId": "", + "authentication": null, + "authorizer": { + "iam": { + "accessKey": "AKIA...", + "accountId": "111122223333", + "callerId": "AIDA...", + "cognitoIdentity": null, + "principalOrgId": null, + "userArn": "arn:aws:iam::111122223333:user/example-user", + "userId": "AIDA..." + } + }, + "domainName": ".lambda-url.us-west-2.on.aws", + "domainPrefix": "", + "http": { + "method": "POST", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "123.123.123.123", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "$default", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "body": "Hello from client!", + "pathParameters": null, + "isBase64Encoded": false, + "stageVariables": null + } + """ /// Example event body pulled from an an actual Lambda invocation. static let realWorldExample = """ - { - "headers": { - "x-amzn-tls-cipher-suite": "ECDHE-RSA-AES128-GCM-SHA256", - "x-amzn-tls-version": "TLSv1.2", - "x-amzn-trace-id": "Root=0-12345678-9abcdef0123456789abcdef0", - "cookie": "test", - "x-forwarded-proto": "https", - "host": "0123456789abcdefghijklmnopqrstuv.lambda-url.us-west-2.on.aws", - "x-forwarded-port": "443", - "x-forwarded-for": "1.2.3.4", - "accept": "*/*", - "user-agent": "curl" - }, - "isBase64Encoded": false, - "rawPath": "/", - "routeKey": "$default", - "requestContext": { - "accountId": "anonymous", - "timeEpoch": 1667192002044, + { + "headers": { + "x-amzn-tls-cipher-suite": "ECDHE-RSA-AES128-GCM-SHA256", + "x-amzn-tls-version": "TLSv1.2", + "x-amzn-trace-id": "Root=0-12345678-9abcdef0123456789abcdef0", + "cookie": "test", + "x-forwarded-proto": "https", + "host": "0123456789abcdefghijklmnopqrstuv.lambda-url.us-west-2.on.aws", + "x-forwarded-port": "443", + "x-forwarded-for": "1.2.3.4", + "accept": "*/*", + "user-agent": "curl" + }, + "isBase64Encoded": false, + "rawPath": "/", "routeKey": "$default", - "stage": "$default", - "domainPrefix": "0123456789abcdefghijklmnopqrstuv", - "requestId": "01234567-89ab-cdef-0123-456789abcdef", - "domainName": "0123456789abcdefghijklmnopqrstuv.lambda-url.us-west-2.on.aws", - "http": { - "path": "/", - "protocol": "HTTP/1.1", - "method": "GET", - "sourceIp": "1.2.3.4", - "userAgent": "curl" + "requestContext": { + "accountId": "anonymous", + "timeEpoch": 1667192002044, + "routeKey": "$default", + "stage": "$default", + "domainPrefix": "0123456789abcdefghijklmnopqrstuv", + "requestId": "01234567-89ab-cdef-0123-456789abcdef", + "domainName": "0123456789abcdefghijklmnopqrstuv.lambda-url.us-west-2.on.aws", + "http": { + "path": "/", + "protocol": "HTTP/1.1", + "method": "GET", + "sourceIp": "1.2.3.4", + "userAgent": "curl" + }, + "time": "31/Oct/2022:04:53:22 +0000", + "apiId": "0123456789abcdefghijklmnopqrstuv" }, - "time": "31/Oct/2022:04:53:22 +0000", - "apiId": "0123456789abcdefghijklmnopqrstuv" - }, - "queryStringParameters": { - "test": "2" - }, - "version": "2.0", - "rawQueryString": "test=2", - "cookies": [ - "test" - ] - } - """ + "queryStringParameters": { + "test": "2" + }, + "version": "2.0", + "rawQueryString": "test=2", + "cookies": [ + "test" + ] + } + """ // MARK: - Request - diff --git a/Tests/AWSLambdaEventsTests/LambdaGatewayProxyEventTests.swift b/Tests/AWSLambdaEventsTests/LambdaGatewayProxyEventTests.swift index 6950031..91e5240 100644 --- a/Tests/AWSLambdaEventsTests/LambdaGatewayProxyEventTests.swift +++ b/Tests/AWSLambdaEventsTests/LambdaGatewayProxyEventTests.swift @@ -12,105 +12,106 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + class LambdaGatewayProxyEventTests: XCTestCase { static let exampleLambdaProxyEvent = """ - { - "resource": "/hello", - "path": "/hello", - "httpMethod": "GET", - "headers": { - "x-forwarded-proto":"https", - "x-forwarded-for":"91.64.117.86", - "x-forwarded-port":"443", - "authorization":"Bearer abc123", - "host":"hello.test.com", - "x-amzn-trace-id":"Root=1-5ea3263d-07c5d5ddfd0788bed7dad831", - "user-agent":"Paw/3.1.10 (Macintosh; OS X/10.15.4) GCDHTTPRequest", - "content-length":"0" - }, - "multiValueHeaders": { - "header1": [ - "value1" - ], - "header2": [ - "value1", - "value2" - ] - }, - "queryStringParameters": { - "foo":"bar" - }, - "multiValueQueryStringParameters": { - "parameter1": [ - "value1", - "value2" - ], - "parameter2": [ - "value" - ] - }, - "requestContext": { - "accountId": "123456789012", - "apiId":"pb5dg6g3rg", - "authorizer": { - "scopes":[ - "hello" - ], - "claims":{ - "aud":"customers", - "iss":"https://hello.test.com/", - "iat":"1587749276", - "exp":"1587756476" - } - }, - "domainName": "id.execute-api.us-east-1.amazonaws.com", - "domainPrefix": "id", - "extendedRequestId": "request-id", - "httpMethod": "GET", - "identity": { - "accessKey": null, - "accountId": null, - "caller": null, - "cognitoAuthenticationProvider": null, - "cognitoAuthenticationType": null, - "cognitoIdentityId": null, - "cognitoIdentityPoolId": null, - "principalOrgId": null, - "sourceIp":"91.64.117.86", - "user": null, - "userAgent":"Paw/3.1.10 (Macintosh; OS X/10.15.4) GCDHTTPRequest", - "userArn": null, - "clientCert": { - "clientCertPem": "CERT_CONTENT", - "subjectDN": "www.example.com", - "issuerDN": "Example issuer", - "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", - "validity": { - "notBefore": "May 28 12:30:02 2019 GMT", - "notAfter": "Aug 5 09:36:04 2021 GMT" - } - } - }, - "path": "/hello", - "protocol": "HTTP/1.1", - "requestId":"LgLpnibOFiAEPCA=", - "requestTime": "04/Mar/2020:19:15:17 +0000", - "requestTimeEpoch": 1587750461466, - "resourceId": null, - "resourcePath": "/my/path", - "stage": "$default" - }, - "pathParameters": null, - "stageVariables":{ - "foo":"bar" - }, - "body": "Hello from Lambda!", - "isBase64Encoded": false - } - """ + { + "resource": "/hello", + "path": "/hello", + "httpMethod": "GET", + "headers": { + "x-forwarded-proto":"https", + "x-forwarded-for":"91.64.117.86", + "x-forwarded-port":"443", + "authorization":"Bearer abc123", + "host":"hello.test.com", + "x-amzn-trace-id":"Root=1-5ea3263d-07c5d5ddfd0788bed7dad831", + "user-agent":"Paw/3.1.10 (Macintosh; OS X/10.15.4) GCDHTTPRequest", + "content-length":"0" + }, + "multiValueHeaders": { + "header1": [ + "value1" + ], + "header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "foo":"bar" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId":"pb5dg6g3rg", + "authorizer": { + "scopes":[ + "hello" + ], + "claims":{ + "aud":"customers", + "iss":"https://hello.test.com/", + "iat":"1587749276", + "exp":"1587756476" + } + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp":"91.64.117.86", + "user": null, + "userAgent":"Paw/3.1.10 (Macintosh; OS X/10.15.4) GCDHTTPRequest", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/hello", + "protocol": "HTTP/1.1", + "requestId":"LgLpnibOFiAEPCA=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1587750461466, + "resourceId": null, + "resourcePath": "/my/path", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables":{ + "foo":"bar" + }, + "body": "Hello from Lambda!", + "isBase64Encoded": false + } + """ // MARK: - Request - diff --git a/Tests/AWSLambdaEventsTests/S3Tests.swift b/Tests/AWSLambdaEventsTests/S3Tests.swift index 217a934..0d3e2da 100644 --- a/Tests/AWSLambdaEventsTests/S3Tests.swift +++ b/Tests/AWSLambdaEventsTests/S3Tests.swift @@ -12,91 +12,92 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + class S3Tests: XCTestCase { static let eventBodyObjectCreated = """ - { - "Records": [ { - "eventVersion":"2.1", - "eventSource":"aws:s3", - "awsRegion":"eu-central-1", - "eventTime":"2020-01-13T09:25:40.621Z", - "eventName":"ObjectCreated:Put", - "userIdentity":{ - "principalId":"AWS:AAAAAAAJ2MQ4YFQZ7AULJ" - }, - "requestParameters":{ - "sourceIPAddress":"123.123.123.123" - }, - "responseElements":{ - "x-amz-request-id":"01AFA1430E18C358", - "x-amz-id-2":"JsbNw6sHGFwgzguQjbYcew//bfAeZITyTYLfjuu1U4QYqCq5CPlSyYLtvWQS+gw0RxcroItGwm8=" - }, - "s3":{ - "s3SchemaVersion":"1.0", - "configurationId":"98b55bc4-3c0c-4007-b727-c6b77a259dde", - "bucket":{ - "name":"eventsources", - "ownerIdentity":{ - "principalId":"AAAAAAAAAAAAAA" + "Records": [ + { + "eventVersion":"2.1", + "eventSource":"aws:s3", + "awsRegion":"eu-central-1", + "eventTime":"2020-01-13T09:25:40.621Z", + "eventName":"ObjectCreated:Put", + "userIdentity":{ + "principalId":"AWS:AAAAAAAJ2MQ4YFQZ7AULJ" + }, + "requestParameters":{ + "sourceIPAddress":"123.123.123.123" + }, + "responseElements":{ + "x-amz-request-id":"01AFA1430E18C358", + "x-amz-id-2":"JsbNw6sHGFwgzguQjbYcew//bfAeZITyTYLfjuu1U4QYqCq5CPlSyYLtvWQS+gw0RxcroItGwm8=" }, - "arn":"arn:aws:s3:::eventsources" - }, - "object":{ - "key":"Hi.md", - "size":2880, - "eTag":"91a7f2c3ae81bcc6afef83979b463f0e", - "sequencer":"005E1C37948E783A6E" + "s3":{ + "s3SchemaVersion":"1.0", + "configurationId":"98b55bc4-3c0c-4007-b727-c6b77a259dde", + "bucket":{ + "name":"eventsources", + "ownerIdentity":{ + "principalId":"AAAAAAAAAAAAAA" + }, + "arn":"arn:aws:s3:::eventsources" + }, + "object":{ + "key":"Hi.md", + "size":2880, + "eTag":"91a7f2c3ae81bcc6afef83979b463f0e", + "sequencer":"005E1C37948E783A6E" + } + } } - } + ] } - ] - } - """ + """ // A S3 ObjectRemoved:* event does not contain the object size static let eventBodyObjectRemoved = """ - { - "Records": [ { - "eventVersion":"2.1", - "eventSource":"aws:s3", - "awsRegion":"eu-central-1", - "eventTime":"2020-01-13T09:25:40.621Z", - "eventName":"ObjectRemoved:DeleteMarkerCreated", - "userIdentity":{ - "principalId":"AWS:AAAAAAAJ2MQ4YFQZ7AULJ" - }, - "requestParameters":{ - "sourceIPAddress":"123.123.123.123" - }, - "responseElements":{ - "x-amz-request-id":"01AFA1430E18C358", - "x-amz-id-2":"JsbNw6sHGFwgzguQjbYcew//bfAeZITyTYLfjuu1U4QYqCq5CPlSyYLtvWQS+gw0RxcroItGwm8=" - }, - "s3":{ - "s3SchemaVersion":"1.0", - "configurationId":"98b55bc4-3c0c-4007-b727-c6b77a259dde", - "bucket":{ - "name":"eventsources", - "ownerIdentity":{ - "principalId":"AAAAAAAAAAAAAA" + "Records": [ + { + "eventVersion":"2.1", + "eventSource":"aws:s3", + "awsRegion":"eu-central-1", + "eventTime":"2020-01-13T09:25:40.621Z", + "eventName":"ObjectRemoved:DeleteMarkerCreated", + "userIdentity":{ + "principalId":"AWS:AAAAAAAJ2MQ4YFQZ7AULJ" + }, + "requestParameters":{ + "sourceIPAddress":"123.123.123.123" }, - "arn":"arn:aws:s3:::eventsources" - }, - "object":{ - "key":"Hi.md", - "eTag":"91a7f2c3ae81bcc6afef83979b463f0e", - "sequencer":"005E1C37948E783A6E" + "responseElements":{ + "x-amz-request-id":"01AFA1430E18C358", + "x-amz-id-2":"JsbNw6sHGFwgzguQjbYcew//bfAeZITyTYLfjuu1U4QYqCq5CPlSyYLtvWQS+gw0RxcroItGwm8=" + }, + "s3":{ + "s3SchemaVersion":"1.0", + "configurationId":"98b55bc4-3c0c-4007-b727-c6b77a259dde", + "bucket":{ + "name":"eventsources", + "ownerIdentity":{ + "principalId":"AAAAAAAAAAAAAA" + }, + "arn":"arn:aws:s3:::eventsources" + }, + "object":{ + "key":"Hi.md", + "eTag":"91a7f2c3ae81bcc6afef83979b463f0e", + "sequencer":"005E1C37948E783A6E" + } + } } - } + ] } - ] - } - """ + """ func testSimpleEventFromJSON() { let data = S3Tests.eventBodyObjectCreated.data(using: .utf8)! diff --git a/Tests/AWSLambdaEventsTests/SESTests.swift b/Tests/AWSLambdaEventsTests/SESTests.swift index 3a838e1..ceb5ce1 100644 --- a/Tests/AWSLambdaEventsTests/SESTests.swift +++ b/Tests/AWSLambdaEventsTests/SESTests.swift @@ -12,78 +12,79 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + class SESTests: XCTestCase { static let eventBody = """ - { - "Records": [ { - "eventSource": "aws:ses", - "eventVersion": "1.0", - "ses": { - "mail": { - "commonHeaders": { - "date": "Wed, 7 Oct 2015 12:34:56 -0700", - "from": [ - "Jane Doe " - ], - "messageId": "<0123456789example.com>", - "returnPath": "janedoe@example.com", - "subject": "Test Subject", - "to": [ - "johndoe@example.com" - ] - }, - "destination": [ - "johndoe@example.com" - ], - "headers": [ - { - "name": "Return-Path", - "value": "" + "Records": [ + { + "eventSource": "aws:ses", + "eventVersion": "1.0", + "ses": { + "mail": { + "commonHeaders": { + "date": "Wed, 7 Oct 2015 12:34:56 -0700", + "from": [ + "Jane Doe " + ], + "messageId": "<0123456789example.com>", + "returnPath": "janedoe@example.com", + "subject": "Test Subject", + "to": [ + "johndoe@example.com" + ] + }, + "destination": [ + "johndoe@example.com" + ], + "headers": [ + { + "name": "Return-Path", + "value": "" + }, + { + "name": "Received", + "value": "from mailer.example.com (mailer.example.com [203.0.113.1]) by inbound-smtp.eu-west-1.amazonaws.com with SMTP id o3vrnil0e2ic28trm7dfhrc2v0cnbeccl4nbp0g1 for johndoe@example.com; Wed, 07 Oct 2015 12:34:56 +0000 (UTC)" + } + ], + "headersTruncated": true, + "messageId": "5h5auqp1oa1bg49b2q8f8tmli1oju8pcma2haao1", + "source": "janedoe@example.com", + "timestamp": "1970-01-01T00:00:00.000Z" }, - { - "name": "Received", - "value": "from mailer.example.com (mailer.example.com [203.0.113.1]) by inbound-smtp.eu-west-1.amazonaws.com with SMTP id o3vrnil0e2ic28trm7dfhrc2v0cnbeccl4nbp0g1 for johndoe@example.com; Wed, 07 Oct 2015 12:34:56 +0000 (UTC)" + "receipt": { + "action": { + "functionArn": "arn:aws:lambda:eu-west-1:123456789012:function:Example", + "invocationType": "Event", + "type": "Lambda" + }, + "dkimVerdict": { + "status": "PASS" + }, + "processingTimeMillis": 574, + "recipients": [ + "test@swift-server.com", + "test2@swift-server.com" + ], + "spamVerdict": { + "status": "PASS" + }, + "spfVerdict": { + "status": "PROCESSING_FAILED" + }, + "timestamp": "1970-01-01T00:00:00.000Z", + "virusVerdict": { + "status": "FAIL" + } } - ], - "headersTruncated": true, - "messageId": "5h5auqp1oa1bg49b2q8f8tmli1oju8pcma2haao1", - "source": "janedoe@example.com", - "timestamp": "1970-01-01T00:00:00.000Z" - }, - "receipt": { - "action": { - "functionArn": "arn:aws:lambda:eu-west-1:123456789012:function:Example", - "invocationType": "Event", - "type": "Lambda" - }, - "dkimVerdict": { - "status": "PASS" - }, - "processingTimeMillis": 574, - "recipients": [ - "test@swift-server.com", - "test2@swift-server.com" - ], - "spamVerdict": { - "status": "PASS" - }, - "spfVerdict": { - "status": "PROCESSING_FAILED" - }, - "timestamp": "1970-01-01T00:00:00.000Z", - "virusVerdict": { - "status": "FAIL" } } - } + ] } - ] - } - """ + """ func testSimpleEventFromJSON() { let data = Data(SESTests.eventBody.utf8) @@ -107,7 +108,10 @@ class SESTests: XCTestCase { XCTAssertEqual(record.ses.mail.headers[0].name, "Return-Path") XCTAssertEqual(record.ses.mail.headers[0].value, "") XCTAssertEqual(record.ses.mail.headers[1].name, "Received") - XCTAssertEqual(record.ses.mail.headers[1].value, "from mailer.example.com (mailer.example.com [203.0.113.1]) by inbound-smtp.eu-west-1.amazonaws.com with SMTP id o3vrnil0e2ic28trm7dfhrc2v0cnbeccl4nbp0g1 for johndoe@example.com; Wed, 07 Oct 2015 12:34:56 +0000 (UTC)") + XCTAssertEqual( + record.ses.mail.headers[1].value, + "from mailer.example.com (mailer.example.com [203.0.113.1]) by inbound-smtp.eu-west-1.amazonaws.com with SMTP id o3vrnil0e2ic28trm7dfhrc2v0cnbeccl4nbp0g1 for johndoe@example.com; Wed, 07 Oct 2015 12:34:56 +0000 (UTC)" + ) XCTAssertEqual(record.ses.mail.headersTruncated, true) XCTAssertEqual(record.ses.mail.messageId, "5h5auqp1oa1bg49b2q8f8tmli1oju8pcma2haao1") XCTAssertEqual(record.ses.mail.source, "janedoe@example.com") diff --git a/Tests/AWSLambdaEventsTests/SNSTests.swift b/Tests/AWSLambdaEventsTests/SNSTests.swift index a6b5781..0e81ded 100644 --- a/Tests/AWSLambdaEventsTests/SNSTests.swift +++ b/Tests/AWSLambdaEventsTests/SNSTests.swift @@ -12,43 +12,44 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + class SNSTests: XCTestCase { static let eventBody = """ - { - "Records": [ { - "EventSource": "aws:sns", - "EventVersion": "1.0", - "EventSubscriptionArn": "arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5:6fabdb7f-b27e-456d-8e8a-14679db9e40c", - "Sns": { - "Type": "Notification", - "MessageId": "bdb6900e-1ae9-5b4b-b7fc-c681fde222e3", - "TopicArn": "arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5", - "Subject": null, - "Message": "{\\\"hello\\\": \\\"world\\\"}", - "Timestamp": "2020-01-08T14:18:51.203Z", - "SignatureVersion": "1", - "Signature": "LJMF/xmMH7A1gNy2unLA3hmzyf6Be+zS/Yeiiz9tZbu6OG8fwvWZeNOcEZardhSiIStc0TF7h9I+4Qz3omCntaEfayzTGmWN8itGkn2mfn/hMFmPbGM8gEUz3+jp1n6p+iqP3XTx92R0LBIFrU3ylOxSo8+SCOjA015M93wfZzwj0WPtynji9iAvvtf15d8JxPUu1T05BRitpFd5s6ZXDHtVQ4x/mUoLUN8lOVp+rs281/ZdYNUG/V5CwlyUDTOERdryTkBJ/GO1NNPa+6m04ywJFa5d+BC8mDcUcHhhXXjpTEbt8AHBmswK3nudHrVMRO/G4zmssxU2P7ii5+gCfA==", - "SigningCertUrl": "https://sns.eu-central-1.amazonaws.com/SimpleNotificationService-6aad65c2f9911b05cd53efda11f913f9.pem", - "UnsubscribeUrl": "https://sns.eu-central-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5:6fabdb7f-b27e-456d-8e8a-14679db9e40c", - "MessageAttributes": { - "binary":{ - "Type": "Binary", - "Value": "YmFzZTY0" - }, - "string":{ - "Type": "String", - "Value": "abc123" + "Records": [ + { + "EventSource": "aws:sns", + "EventVersion": "1.0", + "EventSubscriptionArn": "arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5:6fabdb7f-b27e-456d-8e8a-14679db9e40c", + "Sns": { + "Type": "Notification", + "MessageId": "bdb6900e-1ae9-5b4b-b7fc-c681fde222e3", + "TopicArn": "arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5", + "Subject": null, + "Message": "{\\\"hello\\\": \\\"world\\\"}", + "Timestamp": "2020-01-08T14:18:51.203Z", + "SignatureVersion": "1", + "Signature": "LJMF/xmMH7A1gNy2unLA3hmzyf6Be+zS/Yeiiz9tZbu6OG8fwvWZeNOcEZardhSiIStc0TF7h9I+4Qz3omCntaEfayzTGmWN8itGkn2mfn/hMFmPbGM8gEUz3+jp1n6p+iqP3XTx92R0LBIFrU3ylOxSo8+SCOjA015M93wfZzwj0WPtynji9iAvvtf15d8JxPUu1T05BRitpFd5s6ZXDHtVQ4x/mUoLUN8lOVp+rs281/ZdYNUG/V5CwlyUDTOERdryTkBJ/GO1NNPa+6m04ywJFa5d+BC8mDcUcHhhXXjpTEbt8AHBmswK3nudHrVMRO/G4zmssxU2P7ii5+gCfA==", + "SigningCertUrl": "https://sns.eu-central-1.amazonaws.com/SimpleNotificationService-6aad65c2f9911b05cd53efda11f913f9.pem", + "UnsubscribeUrl": "https://sns.eu-central-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5:6fabdb7f-b27e-456d-8e8a-14679db9e40c", + "MessageAttributes": { + "binary":{ + "Type": "Binary", + "Value": "YmFzZTY0" + }, + "string":{ + "Type": "String", + "Value": "abc123" + } + } } } - } + ] } - ] - } - """ + """ func testSimpleEventFromJSON() { let data = SNSTests.eventBody.data(using: .utf8)! @@ -62,7 +63,10 @@ class SNSTests: XCTestCase { XCTAssertEqual(record.eventSource, "aws:sns") XCTAssertEqual(record.eventVersion, "1.0") - XCTAssertEqual(record.eventSubscriptionArn, "arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5:6fabdb7f-b27e-456d-8e8a-14679db9e40c") + XCTAssertEqual( + record.eventSubscriptionArn, + "arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5:6fabdb7f-b27e-456d-8e8a-14679db9e40c" + ) XCTAssertEqual(record.sns.type, "Notification") XCTAssertEqual(record.sns.messageId, "bdb6900e-1ae9-5b4b-b7fc-c681fde222e3") @@ -70,9 +74,18 @@ class SNSTests: XCTestCase { XCTAssertEqual(record.sns.message, "{\"hello\": \"world\"}") XCTAssertEqual(record.sns.timestamp, Date(timeIntervalSince1970: 1_578_493_131.203)) XCTAssertEqual(record.sns.signatureVersion, "1") - XCTAssertEqual(record.sns.signature, "LJMF/xmMH7A1gNy2unLA3hmzyf6Be+zS/Yeiiz9tZbu6OG8fwvWZeNOcEZardhSiIStc0TF7h9I+4Qz3omCntaEfayzTGmWN8itGkn2mfn/hMFmPbGM8gEUz3+jp1n6p+iqP3XTx92R0LBIFrU3ylOxSo8+SCOjA015M93wfZzwj0WPtynji9iAvvtf15d8JxPUu1T05BRitpFd5s6ZXDHtVQ4x/mUoLUN8lOVp+rs281/ZdYNUG/V5CwlyUDTOERdryTkBJ/GO1NNPa+6m04ywJFa5d+BC8mDcUcHhhXXjpTEbt8AHBmswK3nudHrVMRO/G4zmssxU2P7ii5+gCfA==") - XCTAssertEqual(record.sns.signingCertURL, "https://sns.eu-central-1.amazonaws.com/SimpleNotificationService-6aad65c2f9911b05cd53efda11f913f9.pem") - XCTAssertEqual(record.sns.unsubscribeURL, "https://sns.eu-central-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5:6fabdb7f-b27e-456d-8e8a-14679db9e40c") + XCTAssertEqual( + record.sns.signature, + "LJMF/xmMH7A1gNy2unLA3hmzyf6Be+zS/Yeiiz9tZbu6OG8fwvWZeNOcEZardhSiIStc0TF7h9I+4Qz3omCntaEfayzTGmWN8itGkn2mfn/hMFmPbGM8gEUz3+jp1n6p+iqP3XTx92R0LBIFrU3ylOxSo8+SCOjA015M93wfZzwj0WPtynji9iAvvtf15d8JxPUu1T05BRitpFd5s6ZXDHtVQ4x/mUoLUN8lOVp+rs281/ZdYNUG/V5CwlyUDTOERdryTkBJ/GO1NNPa+6m04ywJFa5d+BC8mDcUcHhhXXjpTEbt8AHBmswK3nudHrVMRO/G4zmssxU2P7ii5+gCfA==" + ) + XCTAssertEqual( + record.sns.signingCertURL, + "https://sns.eu-central-1.amazonaws.com/SimpleNotificationService-6aad65c2f9911b05cd53efda11f913f9.pem" + ) + XCTAssertEqual( + record.sns.unsubscribeURL, + "https://sns.eu-central-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-central-1:079477498937:EventSources-SNSTopic-1NHENSE2MQKF5:6fabdb7f-b27e-456d-8e8a-14679db9e40c" + ) XCTAssertEqual(record.sns.messageAttributes?.count, 2) diff --git a/Tests/AWSLambdaEventsTests/SQSTests.swift b/Tests/AWSLambdaEventsTests/SQSTests.swift index cd28972..06ed0f3 100644 --- a/Tests/AWSLambdaEventsTests/SQSTests.swift +++ b/Tests/AWSLambdaEventsTests/SQSTests.swift @@ -12,52 +12,53 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + class SQSTests: XCTestCase { static let eventBody = """ - { - "Records": [ { - "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78", - "receiptHandle": "MessageReceiptHandle", - "body": "Hello from SQS!", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1523232000000", - "SenderId": "123456789012", - "ApproximateFirstReceiveTimestamp": "1523232000001" - }, - "messageAttributes": { - "number":{ - "stringValue":"123", - "stringListValues":[], - "binaryListValues":[], - "dataType":"Number" - }, - "string":{ - "stringValue":"abc123", - "stringListValues":[], - "binaryListValues":[], - "dataType":"String" - }, - "binary":{ - "dataType": "Binary", - "stringListValues":[], - "binaryListValues":[], - "binaryValue":"YmFzZTY0" - }, + "Records": [ + { + "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78", + "receiptHandle": "MessageReceiptHandle", + "body": "Hello from SQS!", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1523232000000", + "SenderId": "123456789012", + "ApproximateFirstReceiveTimestamp": "1523232000001" + }, + "messageAttributes": { + "number":{ + "stringValue":"123", + "stringListValues":[], + "binaryListValues":[], + "dataType":"Number" + }, + "string":{ + "stringValue":"abc123", + "stringListValues":[], + "binaryListValues":[], + "dataType":"String" + }, + "binary":{ + "dataType": "Binary", + "stringListValues":[], + "binaryListValues":[], + "binaryValue":"YmFzZTY0" + }, - }, - "md5OfBody": "7b270e59b47ff90a553787216d55d91d", - "eventSource": "aws:sqs", - "eventSourceARN": "arn:aws:sqs:us-east-1:123456789012:MyQueue", - "awsRegion": "us-east-1" + }, + "md5OfBody": "7b270e59b47ff90a553787216d55d91d", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:us-east-1:123456789012:MyQueue", + "awsRegion": "us-east-1" + } + ] } - ] - } - """ + """ func testSimpleEventFromJSON() { let data = SQSTests.eventBody.data(using: .utf8)! @@ -74,11 +75,14 @@ class SQSTests: XCTestCase { XCTAssertEqual(message.body, "Hello from SQS!") XCTAssertEqual(message.attributes.count, 4) - XCTAssertEqual(message.messageAttributes, [ - "number": .number("123"), - "string": .string("abc123"), - "binary": .binary([UInt8]("base64".utf8)), - ]) + XCTAssertEqual( + message.messageAttributes, + [ + "number": .number("123"), + "string": .string("abc123"), + "binary": .binary([UInt8]("base64".utf8)), + ] + ) XCTAssertEqual(message.md5OfBody, "7b270e59b47ff90a553787216d55d91d") XCTAssertEqual(message.eventSource, "aws:sqs") XCTAssertEqual(message.eventSourceArn, "arn:aws:sqs:us-east-1:123456789012:MyQueue") diff --git a/Tests/AWSLambdaEventsTests/Utils/Base64Tests.swift b/Tests/AWSLambdaEventsTests/Utils/Base64Tests.swift index 59e300c..ed62ef1 100644 --- a/Tests/AWSLambdaEventsTests/Utils/Base64Tests.swift +++ b/Tests/AWSLambdaEventsTests/Utils/Base64Tests.swift @@ -12,9 +12,10 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + class Base64Tests: XCTestCase { // MARK: - Decoding - @@ -32,9 +33,10 @@ class Base64Tests: XCTestCase { } func testBase64DecodingAllTheBytesSequentially() { - let base64 = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==" + let base64 = + "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==" - let expected = Array(UInt8(0) ... UInt8(255)) + let expected = Array(UInt8(0)...UInt8(255)) var decoded: [UInt8]? XCTAssertNoThrow(decoded = try base64.base64decoded()) @@ -42,9 +44,10 @@ class Base64Tests: XCTestCase { } func testBase64UrlDecodingAllTheBytesSequentially() { - let base64 = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w==" + let base64 = + "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w==" - let expected = Array(UInt8(0) ... UInt8(255)) + let expected = Array(UInt8(0)...UInt8(255)) var decoded: [UInt8]? XCTAssertNoThrow(decoded = try base64.base64decoded(options: .base64UrlAlphabet)) diff --git a/Tests/AWSLambdaEventsTests/Utils/DateWrapperTests.swift b/Tests/AWSLambdaEventsTests/Utils/DateWrapperTests.swift index a1a9593..cacc2e8 100644 --- a/Tests/AWSLambdaEventsTests/Utils/DateWrapperTests.swift +++ b/Tests/AWSLambdaEventsTests/Utils/DateWrapperTests.swift @@ -12,9 +12,10 @@ // //===----------------------------------------------------------------------===// -@testable import AWSLambdaEvents import XCTest +@testable import AWSLambdaEvents + class DateWrapperTests: XCTestCase { func testISO8601CodingWrapperSuccess() { struct TestEvent: Decodable { @@ -35,15 +36,19 @@ class DateWrapperTests: XCTestCase { var date: Date } - let date = "2020-03-26T16:53:05" // missing Z at end + let date = "2020-03-26T16:53:05" // missing Z at end let json = #"{"date":"\#(date)"}"# XCTAssertThrowsError(_ = try JSONDecoder().decode(TestEvent.self, from: json.data(using: .utf8)!)) { error in guard case DecodingError.dataCorrupted(let context) = error else { - XCTFail("Unexpected error: \(error)"); return + XCTFail("Unexpected error: \(error)") + return } XCTAssertEqual(context.codingPath.map(\.stringValue), ["date"]) - XCTAssertEqual(context.debugDescription, "Expected date to be in ISO8601 date format, but `\(date)` is not in the correct format") + XCTAssertEqual( + context.debugDescription, + "Expected date to be in ISO8601 date format, but `\(date)` is not in the correct format" + ) XCTAssertNil(context.underlyingError) } } @@ -67,15 +72,19 @@ class DateWrapperTests: XCTestCase { var date: Date } - let date = "2020-03-26T16:53:05Z" // missing fractional seconds + let date = "2020-03-26T16:53:05Z" // missing fractional seconds let json = #"{"date":"\#(date)"}"# XCTAssertThrowsError(_ = try JSONDecoder().decode(TestEvent.self, from: json.data(using: .utf8)!)) { error in guard case DecodingError.dataCorrupted(let context) = error else { - XCTFail("Unexpected error: \(error)"); return + XCTFail("Unexpected error: \(error)") + return } XCTAssertEqual(context.codingPath.map(\.stringValue), ["date"]) - XCTAssertEqual(context.debugDescription, "Expected date to be in ISO8601 date format with fractional seconds, but `\(date)` is not in the correct format") + XCTAssertEqual( + context.debugDescription, + "Expected date to be in ISO8601 date format with fractional seconds, but `\(date)` is not in the correct format" + ) XCTAssertNil(context.underlyingError) } } @@ -138,15 +147,19 @@ class DateWrapperTests: XCTestCase { var date: Date } - let date = "Thu, 5 Apr 2012 23:47 +0200" // missing seconds + let date = "Thu, 5 Apr 2012 23:47 +0200" // missing seconds let json = #"{"date":"\#(date)"}"# XCTAssertThrowsError(_ = try JSONDecoder().decode(TestEvent.self, from: json.data(using: .utf8)!)) { error in guard case DecodingError.dataCorrupted(let context) = error else { - XCTFail("Unexpected error: \(error)"); return + XCTFail("Unexpected error: \(error)") + return } XCTAssertEqual(context.codingPath.map(\.stringValue), ["date"]) - XCTAssertEqual(context.debugDescription, "Expected date to be in RFC5322 date-time format, but `\(date)` is not in the correct format") + XCTAssertEqual( + context.debugDescription, + "Expected date to be in RFC5322 date-time format, but `\(date)` is not in the correct format" + ) XCTAssertNil(context.underlyingError) } } From aa9ad631850bf6cf235853554b31236c02f40a43 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Tue, 8 Oct 2024 12:04:41 +0200 Subject: [PATCH 5/6] Fix docs? --- .github/workflows/pull_request.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index c290ffb..5bcbaf0 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -11,8 +11,8 @@ jobs: with: license_header_check_project_name: "SwiftAWSLambdaEvents" shell_check_enabled: false - api_breakage_check_container_image: "swift:6.0-jammy" - docs_check_container_image: "swift:6.0-focal" + api_breakage_check_container_image: "swift:6.0-noble" + docs_check_container_image: "swift:6.0-noble" unit-tests: name: Unit tests From 6385baca7427eca638972a8f1356813dadf321c3 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Tue, 8 Oct 2024 12:34:32 +0200 Subject: [PATCH 6/6] Fix license check --- .github/workflows/pull_request.yml | 2 +- .licenseignore | 32 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 5bcbaf0..89116fd 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -9,7 +9,7 @@ jobs: name: Soundness uses: apple/swift-nio/.github/workflows/soundness.yml@main with: - license_header_check_project_name: "SwiftAWSLambdaEvents" + license_header_check_project_name: "SwiftAWSLambdaRuntime" shell_check_enabled: false api_breakage_check_container_image: "swift:6.0-noble" docs_check_container_image: "swift:6.0-noble" diff --git a/.licenseignore b/.licenseignore index e69de29..c535d3f 100644 --- a/.licenseignore +++ b/.licenseignore @@ -0,0 +1,32 @@ +.gitignore +.licenseignore +.swiftformatignore +.spi.yml +.swift-format +.github/* +*.md +**/*.md +CONTRIBUTORS.txt +LICENSE.txt +NOTICE.txt +Package.swift +Package@swift-*.swift +Package.resolved +**/*.docc/* +**/.gitignore +**/Package.swift +**/Package.resolved +**/docker-compose*.yaml +**/docker/* +**/.dockerignore +**/Dockerfile +**/Makefile +**/*.html +**/*-template.yml +**/*.xcworkspace/* +**/*.xcodeproj/* +**/*.xcassets/* +**/*.appiconset/* +**/ResourcePackaging/hello.txt +.mailmap +.swiftformat