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: test-suite #651

Merged
merged 60 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
81a5043
chore: Require Swift 5.7, fix deprecation warnings (#600)
jbelkins Oct 11, 2023
b759e19
feat: support initial-response in RPC based event streams (#597)
dayaffe Oct 12, 2023
e7f1d28
chore: Updates version to 0.32.0
aws-sdk-swift-automation Oct 12, 2023
f6c8bc8
chore: Add newline to README.md (#602)
jbelkins Oct 13, 2023
62ad3a2
feat: add limited support in smithy-swift for visionOS (#606)
dayaffe Oct 20, 2023
818a5c7
feat: add support for requiresLength trait and Transfer-Encoding: Chu…
dayaffe Oct 23, 2023
e0b4f25
chore: Update to aws-crt-swift 0.15.0 (#607)
jbelkins Oct 24, 2023
31d7652
fix: content-length middleware should not error on event streams (#608)
dayaffe Oct 25, 2023
4d965ac
chore: Updates version to 0.33.0
aws-sdk-swift-automation Oct 25, 2023
53fbde2
chore: Improved downstream task (#568)
jbelkins Oct 25, 2023
ef962dd
chore: Convert idempotency token middleware from closure to reusable …
jbelkins Oct 30, 2023
a35c983
fix: Update aws-crt-swift dependency to 0.17.0 (#612)
sichanyoo Oct 31, 2023
6037a81
chore: Updates version to 0.34.0
aws-sdk-swift-automation Oct 31, 2023
96b95c1
fix: Endpoint url should be nil if host or scheme is missing (#614)
dayaffe Oct 31, 2023
a03eedc
fix: Pool HTTP connections based on scheme, host, and port (#615)
jbelkins Nov 2, 2023
c19f585
add default log level to initialize method (#616)
CyprienRicque Nov 6, 2023
c2ab0a5
feat: add utility method for converting SdkHttpRequest to URLRequest.…
sichanyoo Nov 6, 2023
ab999a9
chore: Updates version to 0.35.0
aws-sdk-swift-automation Nov 7, 2023
1d9c963
Add customizations to auth resolve process.
Oct 4, 2023
a54a9de
Add signEvent API to Signer protocol, and rename sign to signRequest.
Nov 14, 2023
4f346f8
Add mock auth scheme resolver, mock auth schemes, mock identity, mock…
Nov 14, 2023
856ae3c
Add unit tests for AuthSchemeMiddleware and SignerMiddleware.
Nov 14, 2023
de25f6e
Update MockSigner to conform to modified Signer API with signEvent.
Nov 14, 2023
10a9a3e
Rename directory containing mocks for auth tests from AuthTest to Aut…
Nov 14, 2023
8d05731
fix: Add a header to operation doc comments (#621)
jbelkins Nov 22, 2023
2658d06
remove unnecessary TODOs (#622)
dayaffe Nov 27, 2023
b1a0cf4
fix: Codegen issues re: recursion, Swift keywords in unions (#623)
jbelkins Nov 28, 2023
34aecef
feat!: Replace the XML encoder with a custom Smithy implementation (#…
jbelkins Nov 29, 2023
af13f00
feat!: Use closures for processing HTTP response (#624)
jbelkins Nov 30, 2023
794b36b
feat: add custom trait PaginationTruncationMember (#625)
dayaffe Dec 1, 2023
2550e03
allow isTruncated to be optional bool (#626)
dayaffe Dec 4, 2023
ca28bf2
chore: Updates version to 0.36.0
aws-sdk-swift-automation Dec 5, 2023
39638f3
chore: Run tvOS old & new in CI (#628)
jbelkins Dec 6, 2023
562a8cc
fix: Fix Package.swift warning on Mac (#629)
jbelkins Dec 7, 2023
460e51c
chore: refactor HttpBody and ByteStream to be a single class ByteStre…
dayaffe Dec 7, 2023
d51e9a6
chore: remove sync read in unused data extension (#630)
dayaffe Dec 12, 2023
3254b1f
update smithy to 1.42.0 (#631)
dayaffe Dec 13, 2023
77b100f
chore: Updates version to 0.37.0
aws-sdk-swift-automation Dec 20, 2023
d222378
chore: Update to aws-crt-swift 0.20.0 (#633)
dayaffe Dec 22, 2023
f11e2e8
fix: add back from method with fileHandle (#635)
dayaffe Dec 22, 2023
f9046ac
fix!: Add no-op behavior for initialize methods of logging system. (#…
sichanyoo Jan 9, 2024
922d066
feat!: URLSession-based HTTP Client (#636)
jbelkins Jan 9, 2024
29f734a
bump up CRT version to 0.22.0 (#639)
dayaffe Jan 11, 2024
4ccc50e
chore: Update version to 0.38.0 (#641)
jbelkins Jan 11, 2024
98018ec
chore: Empty commit (#643)
jbelkins Jan 11, 2024
4332319
feat: add wrapper for checksums + unit tests (#642)
dayaffe Jan 12, 2024
af30f38
Merge old test suite branch to new test suite branch.
Jan 16, 2024
2632677
Update to reflect midleware generics change.
Jan 16, 2024
dcf4f82
Delete unnessary line from test case.
Jan 16, 2024
d033143
Add CloudFront KeyValueStore as one of the services that use rules ba…
Jan 17, 2024
9a25887
feat: Use the Foundation HTTP client by default on Mac (#646)
jbelkins Jan 18, 2024
a89f313
chore: Updates version to 0.39.0
aws-sdk-swift-automation Jan 18, 2024
e812418
Fix auth scheme middleware to save the selected auth scheme to middle…
Jan 24, 2024
6aabf23
chore: Change MyURLQueryItem to SDKURLQueryItem (#652)
sichanyoo Jan 26, 2024
ea1b674
feat!: Provide HTTP request components by closure instead of protocol…
jbelkins Jan 26, 2024
a084a20
fix: Don't retry modeled errors by default (#653)
jbelkins Jan 26, 2024
3322748
Merge main into feat/test-suite.
Jan 26, 2024
8fb7ab4
Merge branch 'feat/sra-identity-and-auth' into feat/test-suite
Feb 6, 2024
4b3c4b2
Address Josh's PR comments.
Feb 7, 2024
f48d844
Merge updated CRT version from main into feat/test-suite.
Feb 8, 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
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ let package = Package(
.library(name: "SmithyTestUtil", targets: ["SmithyTestUtil"]),
],
dependencies: [
.package(url: "https://github.com/awslabs/aws-crt-swift.git", exact: "0.20.0"),
.package(url: "https://github.com/awslabs/aws-crt-swift.git", exact: "0.22.0"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
.package(url: "https://github.com/MaxDesiatov/XMLCoder.git", exact: "0.17.0")
],
Expand Down
2 changes: 1 addition & 1 deletion Package.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.37.0
0.39.0
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public extension DefaultSDKRuntimeConfiguration {
/// - Parameter httpClientConfiguration: The configuration for the HTTP client.
/// - Returns: The `CRTClientEngine` client on Mac & Linux platforms, returns `URLSessionHttpClient` on non-Mac Apple platforms.
static func makeClient(httpClientConfiguration: HttpClientConfiguration) -> HTTPClient {
#if os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
#if os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) || os(macOS)
return URLSessionHTTPClient(httpClientConfiguration: httpClientConfiguration)
#else
let connectTimeoutMs = httpClientConfiguration.connectTimeout.map { UInt32($0 * 1_000_000) }
Expand Down
4 changes: 2 additions & 2 deletions Sources/ClientRuntime/Networking/Endpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Foundation

public struct Endpoint: Hashable {
public let path: String
public let queryItems: [URLQueryItem]?
public let queryItems: [SDKURLQueryItem]?
public let protocolType: ProtocolType?
public let host: String
public let port: Int16
Expand Down Expand Up @@ -43,7 +43,7 @@ public struct Endpoint: Hashable {
public init(host: String,
path: String = "/",
port: Int16 = 443,
queryItems: [URLQueryItem]? = nil,
queryItems: [SDKURLQueryItem]? = nil,
protocolType: ProtocolType? = .https,
headers: Headers? = nil,
properties: [String: AnyHashable] = [:]) {
Expand Down
83 changes: 83 additions & 0 deletions Sources/ClientRuntime/Networking/HashFunction.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

import AwsCommonRuntimeKit

enum HashResult {
case data(Data)
case integer(UInt32)
}

enum HashError: Error {
case invalidInput
case hashingFailed(reason: String)
}

enum HashFunction {
case crc32, crc32c, sha1, sha256, md5

static func from(string: String) -> HashFunction? {
switch string.lowercased() {
case "crc32": return .crc32
case "crc32c": return .crc32c
case "sha1": return .sha1
case "sha256": return .sha256
case "md5": return .md5 // md5 is not a valid flexible checksum algorithm
default: return nil
}
}

var isSupported: Bool {
switch self {
case .crc32, .crc32c, .sha256, .sha1:
return true
default:
return false
}
}

func computeHash(of data: Data) throws -> HashResult {
switch self {
case .crc32:
return .integer(data.computeCRC32())
case .crc32c:
return .integer(data.computeCRC32C())
case .sha1:
do {
let hashed = try data.computeSHA1()
return .data(hashed)
} catch {
throw HashError.hashingFailed(reason: "Error computing SHA1: \(error)")
}
case .sha256:
do {
let hashed = try data.computeSHA256()
return .data(hashed)
} catch {
throw HashError.hashingFailed(reason: "Error computing SHA256: \(error)")
}
case .md5:
do {
let hashed = try data.computeMD5()
return .data(hashed)
} catch {
throw HashError.hashingFailed(reason: "Error computing MD5: \(error)")
}
}
}
}

extension HashResult {

// Convert a HashResult to a hexadecimal String
func toHexString() -> String {
switch self {
case .data(let data):
return data.map { String(format: "%02x", $0) }.joined()
case .integer(let integer):
return String(format: "%08x", integer)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public class CRTClientEngine: HTTPClient {
clientBootstrap: sharedDefaultIO.clientBootstrap,
hostName: endpoint.host,
initialWindowSize: windowSize,
port: UInt16(endpoint.port),
port: UInt32(endpoint.port),
proxyOptions: nil,
socketOptions: socketOptions,
tlsOptions: tlsConnectionOptions,
Expand Down Expand Up @@ -118,7 +118,7 @@ public class CRTClientEngine: HTTPClient {
let options = HTTP2StreamManagerOptions(
clientBootstrap: sharedDefaultIO.clientBootstrap,
hostName: endpoint.host,
port: UInt16(endpoint.port),
port: UInt32(endpoint.port),
maxConnections: maxConnectionsPerEndpoint,
socketOptions: socketOptions,
tlsOptions: tlsConnectionOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ extension HTTP2Stream {
func write(body: ByteStream) async throws {
switch body {
case .data(let data):
try await writeData(data: data ?? .init(), endOfStream: true)
try await writeChunk(chunk: data ?? .init(), endOfStream: true)
case .stream(let stream):
while let data = try await stream.readAsync(upToCount: manualWriteBufferSize) {
try await writeData(data: data, endOfStream: false)
try await writeChunk(chunk: data, endOfStream: false)
}
try await writeData(data: .init(), endOfStream: true)
try await writeChunk(chunk: .init(), endOfStream: true)
case .noStream:
try await writeData(data: .init(), endOfStream: true)
try await writeChunk(chunk: .init(), endOfStream: true)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ public struct AuthSchemeMiddleware<OperationStackOutput: HttpResponseBinding,
}

// Set the selected auth scheme in context for subsequent middleware access, then pass to next middleware in chain
return try await next.handle(
context: context.toBuilder().withSelectedAuthScheme(value: selectedAuthScheme).build(), input: input
)
context.attributes.set(key: AttributeKeys.selectedAuthScheme, value: selectedAuthScheme)
return try await next.handle(context: context, input: input)
jbelkins marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,11 @@ public struct ContentMD5Middleware<OperationStackOutput>: Middleware {

switch input.body {
case .data(let data):
guard
let data = data,
let bodyString = String(data: data, encoding: .utf8)
else {
guard let data = data else {
jbelkins marked this conversation as resolved.
Show resolved Hide resolved
return try await next.handle(context: context, input: input)
}
let base64Encoded = try bodyString.base64EncodedMD5()
let md5Hash = try data.computeMD5()
let base64Encoded = md5Hash.base64EncodedString()
input.headers.update(name: "Content-MD5", value: base64Encoded)
case .stream:
guard let logger = context.getLogger() else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
// SPDX-License-Identifier: Apache-2.0
//

public struct HeaderMiddleware<OperationStackInput: HeaderProvider, OperationStackOutput>: Middleware {
public struct HeaderMiddleware<OperationStackInput, OperationStackOutput>: Middleware {
public let id: String = "\(String(describing: OperationStackInput.self))HeadersMiddleware"

public init() {}
let headerProvider: HeaderProvider<OperationStackInput>

public init(_ headerProvider: @escaping HeaderProvider<OperationStackInput>) {
self.headerProvider = headerProvider
}

public func handle<H>(context: Context,
input: MInput,
Expand All @@ -17,8 +21,7 @@ public struct HeaderMiddleware<OperationStackInput: HeaderProvider, OperationSta
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context {
input.builder.withHeaders(input.operationInput.headers)

input.builder.withHeaders(headerProvider(input.operationInput))
return try await next.handle(context: context, input: input)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@
// SPDX-License-Identifier: Apache-2.0
//

public protocol HeaderProvider {
var headers: Headers { get }
}
public typealias HeaderProvider<T> = (T) -> Headers
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@
// SPDX-License-Identifier: Apache-2.0
//

public protocol QueryItemProvider {
var queryItems: [URLQueryItem] { get throws }
}
public typealias QueryItemProvider<T> = (T) throws -> [SDKURLQueryItem]
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@
// SPDX-License-Identifier: Apache-2.0
//

public protocol URLPathProvider {
var urlPath: String? { get }
}
public typealias URLPathProvider<T> = (T) -> String?
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
// SPDX-License-Identifier: Apache-2.0
//

public struct QueryItemMiddleware<OperationStackInput: QueryItemProvider, OperationStackOutput>: Middleware {
public struct QueryItemMiddleware<OperationStackInput, OperationStackOutput>: Middleware {
public let id: String = "\(String(describing: OperationStackInput.self))QueryItemMiddleware"

public init() {}
let queryItemProvider: QueryItemProvider<OperationStackInput>

public init(_ queryItemProvider: @escaping QueryItemProvider<OperationStackInput>) {
self.queryItemProvider = queryItemProvider
}

public func handle<H>(context: Context,
input: MInput,
Expand All @@ -17,7 +21,7 @@ public struct QueryItemMiddleware<OperationStackInput: QueryItemProvider, Operat
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context {
for queryItem in try input.operationInput.queryItems {
for queryItem in try queryItemProvider(input.operationInput) {
input.builder.withQueryItem(queryItem)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
// SPDX-License-Identifier: Apache-2.0
//

public struct URLPathMiddleware<OperationStackInput: URLPathProvider, OperationStackOutput>: Middleware {
public struct URLPathMiddleware<OperationStackInput, OperationStackOutput>: Middleware {
public let id: Swift.String = "\(String(describing: OperationStackInput.self))URLPathMiddleware"

let urlPrefix: Swift.String?
let urlPathProvider: URLPathProvider<OperationStackInput>

public init(urlPrefix: Swift.String? = nil) {
public init(urlPrefix: Swift.String? = nil, _ urlPathProvider: @escaping URLPathProvider<OperationStackInput>) {
self.urlPrefix = urlPrefix
self.urlPathProvider = urlPathProvider
}

public func handle<H>(context: Context,
Expand All @@ -21,7 +23,7 @@ public struct URLPathMiddleware<OperationStackInput: URLPathProvider, OperationS
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context {
guard var urlPath = input.urlPath else {
guard var urlPath = urlPathProvider(input) else {
let message = "Creating the url path failed, a required property in the path was nil"
throw ClientError.pathCreationFailed(message)
}
Expand Down
14 changes: 7 additions & 7 deletions Sources/ClientRuntime/Networking/Http/SdkHttpRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class SdkHttpRequest {
}
public var path: String { endpoint.path }
public var host: String { endpoint.host }
public var queryItems: [URLQueryItem]? { endpoint.queryItems }
public var queryItems: [SDKURLQueryItem]? { endpoint.queryItems }

public init(method: HttpMethodType,
endpoint: Endpoint,
Expand Down Expand Up @@ -146,8 +146,8 @@ extension SdkHttpRequestBuilder {
host = originalRequest.host
if let crtRequest = crtRequest as? HTTPRequest, let components = URLComponents(string: crtRequest.path) {
path = components.percentEncodedPath
queryItems = components.percentEncodedQueryItems?.map { URLQueryItem(name: $0.name, value: $0.value) }
?? [URLQueryItem]()
queryItems = components.percentEncodedQueryItems?.map { SDKURLQueryItem(name: $0.name, value: $0.value) }
?? [SDKURLQueryItem]()
} else if crtRequest as? HTTP2Request != nil {
assertionFailure("HTTP2Request not supported")
} else {
Expand All @@ -170,11 +170,11 @@ public class SdkHttpRequestBuilder {
var host: String = ""
var path: String = "/"
var body: ByteStream = .noStream
var queryItems: [URLQueryItem]?
var queryItems: [SDKURLQueryItem]?
var port: Int16 = 443
var protocolType: ProtocolType = .https

public var currentQueryItems: [URLQueryItem]? {
public var currentQueryItems: [SDKURLQueryItem]? {
return queryItems
}

Expand Down Expand Up @@ -225,14 +225,14 @@ public class SdkHttpRequestBuilder {
}

@discardableResult
public func withQueryItems(_ value: [URLQueryItem]) -> SdkHttpRequestBuilder {
public func withQueryItems(_ value: [SDKURLQueryItem]) -> SdkHttpRequestBuilder {
self.queryItems = self.queryItems ?? []
self.queryItems?.append(contentsOf: value)
return self
}

@discardableResult
public func withQueryItem(_ value: URLQueryItem) -> SdkHttpRequestBuilder {
public func withQueryItem(_ value: SDKURLQueryItem) -> SdkHttpRequestBuilder {
withQueryItems([value])
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ public typealias URL = Foundation.URL

extension URL {

func toQueryItems() -> [URLQueryItem]? {
func toQueryItems() -> [SDKURLQueryItem]? {
URLComponents(url: self, resolvingAgainstBaseURL: false)?
.queryItems?
.map { URLQueryItem(name: $0.name, value: $0.value) }
.map { SDKURLQueryItem(name: $0.name, value: $0.value) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
* SPDX-License-Identifier: Apache-2.0.
*/

public typealias URLQueryItem = MyURLQueryItem

public struct MyURLQueryItem: Hashable {
public struct SDKURLQueryItem: Hashable {
public var name: String
public var value: String?

Expand Down
17 changes: 6 additions & 11 deletions Sources/ClientRuntime/Retries/DefaultRetryErrorInfoProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,12 @@ public enum DefaultRetryErrorInfoProvider: RetryErrorInfoProvider {
hint = TimeInterval(retryAfterString)
}
if let modeledError = error as? ModeledError {
switch type(of: modeledError).isThrottling {
case true:
return .init(errorType: .throttling, retryAfterHint: hint, isTimeout: false)
case false:
let errorType = type(of: modeledError).fault.retryErrorType
return .init(errorType: errorType, retryAfterHint: hint, isTimeout: false)
}
} else if let httpError = error as? HTTPError {
if retryableStatusCodes.contains(httpError.httpResponse.statusCode) {
return .init(errorType: .serverError, retryAfterHint: hint, isTimeout: false)
}
let type = type(of: modeledError)
guard type.isRetryable else { return nil }
let errorType: RetryErrorType = type.isThrottling ? .throttling : type.fault.retryErrorType
return .init(errorType: errorType, retryAfterHint: hint, isTimeout: false)
} else if let code = (error as? HTTPError)?.httpResponse.statusCode, retryableStatusCodes.contains(code) {
return .init(errorType: .serverError, retryAfterHint: hint, isTimeout: false)
}
return nil
}
Expand Down
Loading
Loading