Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Closure-based reader-writer serde for JSON, FormURL #1439

Merged
merged 39 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
de363f2
Generated code builds
jbelkins Apr 5, 2024
214e5f7
Merge branch 'main' into jbe/readwrite
jbelkins Apr 10, 2024
e94c729
All readers/writers implemented, 74 test failures
jbelkins Apr 10, 2024
c192aaf
Lint cleanup, codegen test fixes
jbelkins Apr 11, 2024
9c738c3
Handle sparse collections in response
jbelkins Apr 11, 2024
2575369
Fix error protocol tests
jbelkins Apr 12, 2024
3316fab
Fix Swift & codegen tests
jbelkins Apr 15, 2024
b434813
Merge branch 'main' into jbe/readwrite
jbelkins Apr 15, 2024
2e148ce
Fix ktlint
jbelkins Apr 16, 2024
e312db9
Merge branch 'main' into jbe/readwrite
jbelkins Apr 16, 2024
62a2cd2
Renames
jbelkins Apr 17, 2024
6da7dca
Add protocol to base errors
jbelkins Apr 17, 2024
91d8a76
Fix codegen tests
jbelkins Apr 17, 2024
a7d0436
Fix ktlint
jbelkins Apr 17, 2024
078cbfe
Fix AWSClientRuntimeTests
jbelkins Apr 17, 2024
045fc32
Delete unused error type
jbelkins Apr 17, 2024
67df793
Refactoring
jbelkins Apr 18, 2024
a4a06cc
More refactoring & eliminating dead code
jbelkins Apr 18, 2024
3f75173
Fix ktlint
jbelkins Apr 18, 2024
9667f31
Eliminate document reading/writing closures
jbelkins Apr 19, 2024
05f3110
Eliminated document closures
jbelkins Apr 19, 2024
2a2382f
Fix tests
jbelkins Apr 19, 2024
f59f1f4
Merge branch 'main' into jbe/readwrite
jbelkins Apr 19, 2024
a48de94
Merge branch 'main' into jbe/readwrite
jbelkins Apr 22, 2024
075ae45
Add customization for S3 404 error
jbelkins Apr 22, 2024
37c4bd3
Fix S3 protocol test failure
jbelkins Apr 22, 2024
00e5feb
Fix ktlint
jbelkins Apr 22, 2024
0c8fbcc
Fix marshal/unmarshal, inherit common protocol generator implementations
jbelkins Apr 22, 2024
bd98fab
Merge remote-tracking branch 'origin/main' into jbe/readwrite
jbelkins Apr 22, 2024
8f39040
Code cleanup
jbelkins Apr 22, 2024
785af50
Merge remote-tracking branch 'origin/main' into jbe/readwrite
jbelkins Apr 23, 2024
2b4b3a5
Merge remote-tracking branch 'origin/main' into jbe/readwrite
jbelkins Apr 23, 2024
97d840d
Add protocol tests to build event stream support, update initial events
jbelkins Apr 24, 2024
7a379c7
Merge branch 'main' into jbe/readwrite
jbelkins Apr 26, 2024
3c39ef3
Merge remote-tracking branch 'origin/main' into jbe/readwrite
jbelkins Apr 26, 2024
32ee5c9
Merge branch 'main' into jbe/readwrite
jbelkins May 6, 2024
2268700
Merge remote-tracking branch 'origin/main' into jbe/readwrite
jbelkins May 9, 2024
82d1da2
Fix codegen tests
jbelkins May 10, 2024
6de7ab7
Fix initial event codegen test
jbelkins May 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Resources/Package.Base.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,13 @@ func addProtocolTests() {
let name: String
let sourcePath: String
let testPath: String?
let buildOnly: Bool

init(name: String, sourcePath: String, testPath: String? = nil) {
init(name: String, sourcePath: String, testPath: String? = nil, buildOnly: Bool = false) {
self.name = name
self.sourcePath = sourcePath
self.testPath = testPath
self.buildOnly = buildOnly
}
}

Expand All @@ -217,21 +219,22 @@ func addProtocolTests() {
.init(name: "S3TestSDK", sourcePath: "\(baseDir)/s3"),
.init(name: "rest_json_extras", sourcePath: "\(baseDirLocal)/rest_json_extras"),
.init(name: "AwsQueryExtras", sourcePath: "\(baseDirLocal)/AwsQueryExtras"),
.init(name: "EventStream", sourcePath: "\(baseDirLocal)/EventStream", buildOnly: true),
.init(name: "RPCEventStream", sourcePath: "\(baseDirLocal)/RPCEventStream", buildOnly: true),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the ability to add these two Smithy service definitions to local protocol tests.

These two Smithy services don't have any protocol tests, but at least this will build them & verify that the code compiles.

Had to add a little logic here to allow adding protocol test targets to the manifest that don't have actual test bundles.

.init(name: "Waiters", sourcePath: "\(baseDirLocal)/Waiters", testPath: "codegen/protocol-test-codegen-local/Tests"),
]
for protocolTest in protocolTests {
package.targets += [
.target(
name: protocolTest.name,
dependencies: [.clientRuntime, .awsClientRuntime],
path: "\(protocolTest.sourcePath)/swift-codegen/\(protocolTest.name)"
),
.testTarget(
name: "\(protocolTest.name)Tests",
dependencies: [.smithyTestUtils, .byNameItem(name: protocolTest.name, condition: nil)],
path: "\(protocolTest.testPath ?? protocolTest.sourcePath)/swift-codegen/\(protocolTest.name)Tests"
)
]
let target = Target.target(
name: protocolTest.name,
dependencies: [.clientRuntime, .awsClientRuntime],
path: "\(protocolTest.sourcePath)/swift-codegen/\(protocolTest.name)"
)
let testTarget = protocolTest.buildOnly ? nil : Target.testTarget(
name: "\(protocolTest.name)Tests",
dependencies: [.smithyTestUtils, .byNameItem(name: protocolTest.name, condition: nil)],
path: "\(protocolTest.testPath ?? protocolTest.sourcePath)/swift-codegen/\(protocolTest.name)Tests"
)
package.targets += [target, testTarget].compactMap { $0 }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class S3EmptyBody404Tests: S3XCTestCase {
_ = try await client.headObject(input: input)

// If an error was not thrown by the HeadObject call, fail the test.
XCTFail("Request should have thrown a service error with code NotFound, instead the request succeeded")
} catch let error as AWSServiceError & ClientRuntime.HTTPError where error.errorCode == "NotFound" {
XCTFail("Request should have thrown a NotFound modeled service error, instead the request succeeded")
} catch let error as AWSS3.NotFound {
Copy link
Contributor Author

@jbelkins jbelkins Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this error customization test so that it expects the genuine S3 NotFound modeled error instead of just matching the error code.


// The expected error has now been caught. Verify that the body is empty and the status code is 404.
XCTAssertTrue(error.httpResponse.body.isEmpty)
Expand Down
29 changes: 16 additions & 13 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,13 @@ func addProtocolTests() {
let name: String
let sourcePath: String
let testPath: String?
let buildOnly: Bool
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just generated from the Package.Base.swift above.


init(name: String, sourcePath: String, testPath: String? = nil) {
init(name: String, sourcePath: String, testPath: String? = nil, buildOnly: Bool = false) {
self.name = name
self.sourcePath = sourcePath
self.testPath = testPath
self.buildOnly = buildOnly
}
}

Expand All @@ -217,21 +219,22 @@ func addProtocolTests() {
.init(name: "S3TestSDK", sourcePath: "\(baseDir)/s3"),
.init(name: "rest_json_extras", sourcePath: "\(baseDirLocal)/rest_json_extras"),
.init(name: "AwsQueryExtras", sourcePath: "\(baseDirLocal)/AwsQueryExtras"),
.init(name: "EventStream", sourcePath: "\(baseDirLocal)/EventStream", buildOnly: true),
.init(name: "RPCEventStream", sourcePath: "\(baseDirLocal)/RPCEventStream", buildOnly: true),
.init(name: "Waiters", sourcePath: "\(baseDirLocal)/Waiters", testPath: "codegen/protocol-test-codegen-local/Tests"),
]
for protocolTest in protocolTests {
package.targets += [
.target(
name: protocolTest.name,
dependencies: [.clientRuntime, .awsClientRuntime],
path: "\(protocolTest.sourcePath)/swift-codegen/\(protocolTest.name)"
),
.testTarget(
name: "\(protocolTest.name)Tests",
dependencies: [.smithyTestUtils, .byNameItem(name: protocolTest.name, condition: nil)],
path: "\(protocolTest.testPath ?? protocolTest.sourcePath)/swift-codegen/\(protocolTest.name)Tests"
)
]
let target = Target.target(
name: protocolTest.name,
dependencies: [.clientRuntime, .awsClientRuntime],
path: "\(protocolTest.sourcePath)/swift-codegen/\(protocolTest.name)"
)
let testTarget = protocolTest.buildOnly ? nil : Target.testTarget(
name: "\(protocolTest.name)Tests",
dependencies: [.smithyTestUtils, .byNameItem(name: protocolTest.name, condition: nil)],
path: "\(protocolTest.testPath ?? protocolTest.sourcePath)/swift-codegen/\(protocolTest.name)Tests"
)
package.targets += [target, testTarget].compactMap { $0 }
}
}

Expand Down
28 changes: 0 additions & 28 deletions Sources/Core/AWSClientRuntime/Errors/RestXMLError+AWS.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -58,30 +58,31 @@ extension UnknownAWSHTTPServiceError {
/// - requestID2: The request ID2 associated with this error (ID2 used on S3 only.) Defaults to `nil`.
/// - typeName: The non-namespaced name of the error type for this error, or `nil`.
/// - Returns: An error that represents the response.
public static func makeError(
httpResponse: HttpResponse,
message: String?,
requestID: String?,
requestID2: String? = nil,
typeName: String?
) async throws -> Error {
public static func makeError<Base: BaseError>(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to take a BaseError as its param

baseError: Base
) throws -> Error {
let candidates: [UnknownAWSHTTPErrorCandidate.Type] = [
InvalidAccessKeyId.self
]
if let Candidate = candidates.first(where: { $0.errorCode == typeName }) {
if let Candidate = candidates.first(where: { $0.errorCode == baseError.code }) {
return Candidate.init(
httpResponse: httpResponse,
message: message,
requestID: requestID,
requestID2: requestID2
httpResponse: baseError.httpResponse,
message: baseError.message,
requestID: baseError.requestID,
requestID2: baseError.requestID2
)
}
return UnknownAWSHTTPServiceError(
httpResponse: httpResponse,
message: message,
requestID: requestID,
requestID2: requestID2,
typeName: typeName
httpResponse: baseError.httpResponse,
message: baseError.message,
requestID: baseError.requestID,
requestID2: baseError.requestID2,
typeName: baseError.code
)
}
}

extension ClientRuntime.BaseError {

var requestID2: String? { nil }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extends BaseError with a default implementation for requestID2. XML/S3 will provide a concrete implementation for this field.

}
4 changes: 0 additions & 4 deletions Sources/Core/AWSClientRuntime/HTTP/HttpResponse+AWS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
import ClientRuntime

public extension HttpResponse {
/// Returns true if the status code is `HttpStatusCode.notFound` and the body is empty.
var statusCodeIsNotFoundAndBodyIsEmpty: Bool {
return statusCode == .notFound && body.isEmpty
}

/// The value of the x-amz-request-id header.
var requestId: String? {
Expand Down
35 changes: 35 additions & 0 deletions Sources/Core/AWSClientRuntime/Protocols/AWSJSON/AWSJSONError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import protocol ClientRuntime.BaseError
import enum ClientRuntime.BaseErrorDecodeError
import class ClientRuntime.HttpResponse
import class SmithyJSON.Reader

public struct AWSJSONError: BaseError {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "base error" for use with AWS JSON 1.0 / 1.1. Provides values for the common error fields.

public let code: String
public let message: String?
public let requestID: String?
public var errorBodyReader: Reader { responseReader }

public let httpResponse: HttpResponse
private let responseReader: Reader

public init(httpResponse: HttpResponse, responseReader: Reader, noErrorWrapping: Bool) throws {
let code: String? = try httpResponse.headers.value(for: "X-Amzn-Errortype")
?? responseReader["code"].readIfPresent()
?? responseReader["__type"].readIfPresent()
let message: String? = try responseReader["Message"].readIfPresent()
let requestID: String? = try responseReader["RequestId"].readIfPresent()
guard let code else { throw BaseErrorDecodeError.missingRequiredData }
self.code = sanitizeErrorType(code)
self.message = message
self.requestID = requestID
self.httpResponse = httpResponse
self.responseReader = responseReader
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import protocol ClientRuntime.BaseError
import enum ClientRuntime.BaseErrorDecodeError
import class ClientRuntime.HttpResponse
import class SmithyXML.Reader

public struct AWSQueryError: BaseError {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "base error" for use with AWS Query. Provides values for the common error fields.

public let code: String
public let message: String?
public let requestID: String?
public let httpResponse: HttpResponse
public let responseReader: Reader
public let errorBodyReader: Reader

public init(httpResponse: HttpResponse, responseReader: Reader, noErrorWrapping: Bool) throws {
self.errorBodyReader = noErrorWrapping ? responseReader : responseReader["Error"]
let code: String? = try errorBodyReader["Code"].readIfPresent()
let message: String? = try errorBodyReader["Message"].readIfPresent()
let requestID: String? = try responseReader["RequestId"].readIfPresent()
guard let code else { throw BaseErrorDecodeError.missingRequiredData }
self.code = code
self.message = message
self.requestID = requestID
self.httpResponse = httpResponse
self.responseReader = responseReader
}
}

public enum AWSQueryDecodeError: Error {
case missingRequiredData
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import protocol ClientRuntime.BaseError
import enum ClientRuntime.BaseErrorDecodeError
import class ClientRuntime.HttpResponse
import class SmithyXML.Reader

public struct EC2QueryError: BaseError {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "base error" for use with EC2Query. Provides values for the common error fields.

public let code: String
public let message: String?
public let requestID: String?
public let errorBodyReader: Reader

public let httpResponse: HttpResponse
public let responseReader: Reader

public init(httpResponse: HttpResponse, responseReader: Reader, noErrorWrapping: Bool) throws {
self.httpResponse = httpResponse
self.responseReader = responseReader
self.errorBodyReader = responseReader["Errors"]["Error"]
let code: String? = try errorBodyReader["Code"].readIfPresent()
guard let code else { throw BaseErrorDecodeError.missingRequiredData }
let message: String? = try errorBodyReader["Message"].readIfPresent()
let requestID: String? = try responseReader["RequestId"].readIfPresent()
?? responseReader["RequestID"].readIfPresent()
self.code = code
self.message = message
self.requestID = requestID
}
}
23 changes: 0 additions & 23 deletions Sources/Core/AWSClientRuntime/Protocols/Ec2Query/Ec2Error.swift

This file was deleted.

21 changes: 0 additions & 21 deletions Sources/Core/AWSClientRuntime/Protocols/Ec2Query/Ec2Errors.swift

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading