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!: Standalone integration test package #1585

Merged
merged 20 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
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
15 changes: 11 additions & 4 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,13 @@ jobs:
TOKEN_ESCAPED=`echo -n "$AWS_SESSION_TOKEN" | jq -Rsa .`
# Insert the credentials into the .xctestplan file, write the modified JSON
# to a temp file, then move the temp over the original.
jq ".defaultOptions.environmentVariableEntries += [{\"key\": \"AWS_ACCESS_KEY_ID\", \"value\": $AKID_ESCAPED}, {\"key\": \"AWS_SECRET_ACCESS_KEY\", \"value\": $SECRET_ESCAPED}, {\"key\": \"AWS_DEFAULT_REGION\", \"value\": $REGION_ESCAPED}, {\"key\": \"AWS_SESSION_TOKEN\", \"value\": $TOKEN_ESCAPED}]" XCTestPlans/AWSIntegrationTestsOnCI.xctestplan > testplan.tmp
mv testplan.tmp XCTestPlans/AWSIntegrationTestsOnCI.xctestplan
jq ".defaultOptions.environmentVariableEntries += [{\"key\": \"AWS_ACCESS_KEY_ID\", \"value\": $AKID_ESCAPED}, {\"key\": \"AWS_SECRET_ACCESS_KEY\", \"value\": $SECRET_ESCAPED}, {\"key\": \"AWS_DEFAULT_REGION\", \"value\": $REGION_ESCAPED}, {\"key\": \"AWS_SESSION_TOKEN\", \"value\": $TOKEN_ESCAPED}]" IntegrationTests/XCTestPlans/AWSIntegrationTestsOnCI.xctestplan > testplan.tmp
mv testplan.tmp IntegrationTests/XCTestPlans/AWSIntegrationTestsOnCI.xctestplan
- name: Prepare Integration Tests
run: ./scripts/ci_steps/prepare_integration_tests.sh
- name: Run Integration Tests
run: |
cd IntegrationTests
set -o pipefail && \
NSUnbufferedIO=YES xcodebuild \
-scheme AWSIntegrationTestsOnCI \
Expand Down Expand Up @@ -192,6 +193,12 @@ jobs:
- name: Prepare Integration Tests
run: ./scripts/ci_steps/prepare_integration_tests.sh
- name: Build Integration Tests
run: swift build --build-tests
run: |
cd IntegrationTests
swift build --build-tests
cd ..
- name: Run Integration Tests
run: swift test
run: |
cd IntegrationTests
swift test
cd ..
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ struct GeneratePackageManifestCommand: ParsableCommand {
@Option(help: "The names of the services to include in the package manifest. This defaults to all services located in aws-sdk-swift/Sources/Services")
var services: [String] = []

@Flag(help: "If the package manifest should include the integration tests.")
var includeIntegrationTests: Bool = false
@Flag(help: "If the package manifest should include services with integration tests.")
var includeServicesWithIntegTests: Bool = false
jbelkins marked this conversation as resolved.
Show resolved Hide resolved

@Flag(help: "If the package manifest should include the protocol tests.")
var includeProtocolTests: Bool = false
Expand All @@ -51,7 +51,7 @@ struct GeneratePackageManifestCommand: ParsableCommand {
clientRuntimeVersion: clientRuntimeVersion,
crtVersion: crtVersion,
services: services.isEmpty ? nil : services,
includeIntegrationTests: includeIntegrationTests,
includeServicesWithIntegTests: includeServicesWithIntegTests,
includeProtocolTests: includeProtocolTests,
excludeAWSServices: excludeAWSServices,
excludeRuntimeTests: excludeRuntimeTests
Expand All @@ -77,8 +77,8 @@ struct GeneratePackageManifest {
/// The list of services to include as products
/// If `nil` then the list is populated with the names of all items within the `Sources/Services` directory
let services: [String]?
/// If the package manifest should include the integration tests.
let includeIntegrationTests: Bool
/// If the package manifest should include the services that have integration tests.
let includeServicesWithIntegTests: Bool
/// If the package manifest should include the protocol tests.
let includeProtocolTests: Bool
/// If the package manifest should exclude the AWS services.
Expand Down Expand Up @@ -113,7 +113,7 @@ struct GeneratePackageManifest {
let services = try resolveServices().map {
PackageManifestBuilder.Service(
name: $0,
includeIntegrationTests: servicesWithIntegrationTests.contains($0)
includeServicesWithIntegTests: servicesWithIntegrationTests.contains($0)
)
}
log("Creating package manifest contents...")
Expand Down Expand Up @@ -237,7 +237,7 @@ extension GeneratePackageManifest {
clientRuntimeVersion: Version? = nil,
crtVersion: Version? = nil,
services: [String]? = nil,
includeIntegrationTests: Bool = false,
includeServicesWithIntegTests: Bool = false,
includeProtocolTests: Bool = false,
excludeAWSServices: Bool = false,
excludeRuntimeTests: Bool = false
Expand All @@ -248,7 +248,7 @@ extension GeneratePackageManifest {
clientRuntimeVersion: clientRuntimeVersion,
crtVersion: crtVersion,
services: services,
includeIntegrationTests: includeIntegrationTests,
includeServicesWithIntegTests: includeServicesWithIntegTests,
includeProtocolTests: includeProtocolTests,
excludeAWSServices: excludeAWSServices,
excludeRuntimeTests: excludeRuntimeTests
Expand All @@ -258,7 +258,7 @@ extension GeneratePackageManifest {
crtVersion: _crtVersion,
services: _services,
includeProtocolTests: includeProtocolTests,
includeIntegrationTests: includeIntegrationTests,
includeServicesWithIntegTests: includeServicesWithIntegTests,
excludeAWSServices: excludeAWSServices,
excludeRuntimeTests: excludeRuntimeTests
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import PackageDescription
struct PackageManifestBuilder {
struct Service {
let name: String
let includeIntegrationTests: Bool
let includeServicesWithIntegTests: Bool
}

let clientRuntimeVersion: Version
let crtVersion: Version
let services: [Service]
let includeProtocolTests: Bool
let includeIntegrationTests: Bool
let includeServicesWithIntegTests: Bool
let excludeAWSServices: Bool
let excludeRuntimeTests: Bool
let basePackageContents: () throws -> String
Expand All @@ -29,7 +29,7 @@ struct PackageManifestBuilder {
crtVersion: Version,
services: [Service],
includeProtocolTests: Bool,
includeIntegrationTests: Bool,
includeServicesWithIntegTests: Bool,
excludeAWSServices: Bool,
excludeRuntimeTests: Bool,
basePackageContents: @escaping () throws -> String
Expand All @@ -38,7 +38,7 @@ struct PackageManifestBuilder {
self.crtVersion = crtVersion
self.services = services
self.includeProtocolTests = includeProtocolTests
self.includeIntegrationTests = includeIntegrationTests
self.includeServicesWithIntegTests = includeServicesWithIntegTests
self.excludeAWSServices = excludeAWSServices
self.basePackageContents = basePackageContents
self.excludeRuntimeTests = excludeRuntimeTests
Expand All @@ -49,11 +49,11 @@ struct PackageManifestBuilder {
crtVersion: Version,
services: [Service],
includeProtocolTests: Bool,
includeIntegrationTests: Bool,
includeServicesWithIntegTests: Bool,
excludeAWSServices: Bool,
excludeRuntimeTests: Bool
) {
self.init(clientRuntimeVersion: clientRuntimeVersion, crtVersion: crtVersion, services: services, includeProtocolTests: includeProtocolTests, includeIntegrationTests: includeIntegrationTests, excludeAWSServices: excludeAWSServices, excludeRuntimeTests: excludeRuntimeTests) {
self.init(clientRuntimeVersion: clientRuntimeVersion, crtVersion: crtVersion, services: services, includeProtocolTests: includeProtocolTests, includeServicesWithIntegTests: includeServicesWithIntegTests, excludeAWSServices: excludeAWSServices, excludeRuntimeTests: excludeRuntimeTests) {
// Returns the contents of the base package manifest stored in the bundle at `Resources/Package.Base.swift`
let basePackageName = "Package.Base"

Expand Down Expand Up @@ -158,11 +158,11 @@ struct PackageManifestBuilder {
private func buildIntegrationTestsTargets() -> String {
var lines: [String] = []
lines += ["let servicesWithIntegrationTests: [String] = ["]
lines += services.filter(\.includeIntegrationTests).map { " \($0.name.wrappedInQuotes())," }
lines += services.filter(\.includeServicesWithIntegTests).map { " \($0.name.wrappedInQuotes())," }
lines += ["]"]
lines += [""]
lines += ["// Uncomment this line to enable integration tests"]
lines += ["\(includeIntegrationTests ? "" : "// ")addIntegrationTests()"]
lines += ["// Uncomment this line to enable services that have integration tests"]
lines += ["\(includeServicesWithIntegTests ? "" : "// ")enableServicesWithIntegrationTests()"]

return lines.joined(separator: .newline)
}
Expand Down
24 changes: 3 additions & 21 deletions AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Resources/Package.Base.swift
Original file line number Diff line number Diff line change
Expand Up @@ -228,22 +228,13 @@ func addServiceUnitTestTarget(_ name: String) {
]
}

func addIntegrationTestTarget(_ name: String) {
let integrationTestName = "\(name)IntegrationTests"
func addIntegrationTestService(_ name: String) {
var additionalDependencies: [String] = []
var exclusions: [String] = []
switch name {
case "AWSEC2":
additionalDependencies = ["AWSIAM", "AWSSTS", "AWSCloudWatchLogs"]
exclusions = [
"Resources/IMDSIntegTestApp"
]
case "AWSECS":
additionalDependencies = ["AWSCloudWatchLogs", "AWSEC2", "AWSIAM", "AWSSTS"]
exclusions = [
"README.md",
"Resources/ECSIntegTestApp/"
]
case "AWSS3":
additionalDependencies = ["AWSSSOAdmin", "AWSS3Control", "AWSSTS"]
case "AWSEventBridge":
Expand All @@ -257,15 +248,6 @@ func addIntegrationTestTarget(_ name: String) {
}
integrationTestServices.insert(name)
additionalDependencies.forEach { integrationTestServices.insert($0) }
package.targets += [
.testTarget(
name: integrationTestName,
dependencies: [.crt, .clientRuntime, .awsClientRuntime, .byName(name: name), .smithyTestUtils, .awsSDKIdentity, .smithyIdentity, .awsSDKCommon] + additionalDependencies.map { Target.Dependency.target(name: $0, condition: nil) },
path: "./IntegrationTests/Services/\(integrationTestName)",
exclude: exclusions,
resources: [.process("Resources")]
)
]
}

var enabledServices = Set<String>()
Expand All @@ -278,8 +260,8 @@ func addAllServices() {

var integrationTestServices = Set<String>()

func addIntegrationTests() {
servicesWithIntegrationTests.forEach { addIntegrationTestTarget($0) }
func enableServicesWithIntegrationTests() {
servicesWithIntegrationTests.forEach { addIntegrationTestService($0) }
}

func excludeRuntimeUnitTests() {
Expand Down
168 changes: 168 additions & 0 deletions IntegrationTests/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// swift-tools-version:5.9

//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation
import PackageDescription

// MARK: - Target dependencies

extension Target.Dependency {
// AWS modules
static var awsClientRuntime: Self { .product(name: "AWSClientRuntime", package: "aws-sdk-swift") }
static var awsSDKCommon: Self { .product(name: "AWSSDKCommon", package: "aws-sdk-swift") }
static var awsSDKEventStreamsAuth: Self { .product(name: "AWSSDKEventStreamsAuth", package: "aws-sdk-swift") }
static var awsSDKHTTPAuth: Self { .product(name: "AWSSDKHTTPAuth", package: "aws-sdk-swift") }
static var awsSDKIdentity: Self { .product(name: "AWSSDKIdentity", package: "aws-sdk-swift") }

// CRT module
static var crt: Self { .product(name: "AwsCommonRuntimeKit", package: "aws-crt-swift") }

// Smithy modules
static var clientRuntime: Self { .product(name: "ClientRuntime", package: "smithy-swift") }
static var smithy: Self { .product(name: "Smithy", package: "smithy-swift") }
static var smithyChecksumsAPI: Self { .product(name: "SmithyChecksumsAPI", package: "smithy-swift") }
static var smithyEventStreams: Self { .product(name: "SmithyEventStreams", package: "smithy-swift") }
static var smithyEventStreamsAPI: Self { .product(name: "SmithyEventStreamsAPI", package: "smithy-swift") }
static var smithyEventStreamsAuthAPI: Self { .product(name: "SmithyEventStreamsAuthAPI", package: "smithy-swift") }
static var smithyHTTPAPI: Self { .product(name: "SmithyHTTPAPI", package: "smithy-swift") }
static var smithyHTTPAuth: Self { .product(name: "SmithyHTTPAuth", package: "smithy-swift") }
static var smithyIdentity: Self { .product(name: "SmithyIdentity", package: "smithy-swift") }
static var smithyIdentityAPI: Self { .product(name: "SmithyIdentityAPI", package: "smithy-swift") }
static var smithyRetries: Self { .product(name: "SmithyRetries", package: "smithy-swift") }
static var smithyRetriesAPI: Self { .product(name: "SmithyRetriesAPI", package: "smithy-swift") }
static var smithyWaitersAPI: Self { .product(name: "SmithyWaitersAPI", package: "smithy-swift") }
static var smithyTestUtils: Self { .product(name: "SmithyTestUtil", package: "smithy-swift") }
}

// MARK: - Base Package

let package = Package(
name: "aws-sdk-swift-integration-tests",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6)
]
)

// MARK: - CRT, Smithy ClientRuntime, AWS ClientRuntime Dependencies

func addDependencies() {
addClientRuntimeDependency()
addAWSClientRuntimeDependency()
addCRTDependency()
}

func addClientRuntimeDependency() {
let smithySwiftURL = "https://github.com/smithy-lang/smithy-swift"
let useLocalDeps = ProcessInfo.processInfo.environment["AWS_SWIFT_SDK_USE_LOCAL_DEPS"] != nil
let useMainDeps = ProcessInfo.processInfo.environment["AWS_SWIFT_SDK_USE_MAIN_DEPS"] != nil
switch (useLocalDeps, useMainDeps) {
case (true, true):
fatalError("Unable to determine which dependencies to use. Please only specify one of AWS_SWIFT_SDK_USE_LOCAL_DEPS or AWS_SWIFT_SDK_USE_MAIN_DEPS.")
case (true, false):
package.dependencies += [
.package(path: "../../smithy-swift")
]
case (false, true):
package.dependencies += [
.package(url: smithySwiftURL, branch: "main")
]
case (false, false):
package.dependencies += [
.package(url: smithySwiftURL, .upToNextMajor(from: "0.0.0"))
]
}
}

func addAWSClientRuntimeDependency() {
package.dependencies += [
.package(path: "../../aws-sdk-swift")
]
}

func addCRTDependency() {
package.dependencies += [
.package(url: "https://github.com/awslabs/aws-crt-swift", .upToNextMajor(from: "0.0.0"))
]
}

// MARK: - Integration test target helper functions


func addIntegrationTestTarget(_ name: String) {
let integrationTestName = "\(name)IntegrationTests"
var additionalDependencies: [String] = []
var exclusions: [String] = []
switch name {
case "AWSEC2":
additionalDependencies = ["AWSIAM", "AWSSTS", "AWSCloudWatchLogs"]
exclusions = [
"Resources/IMDSIntegTestApp"
]
case "AWSECS":
additionalDependencies = ["AWSCloudWatchLogs", "AWSEC2", "AWSIAM", "AWSSTS"]
exclusions = [
"README.md",
"Resources/ECSIntegTestApp/"
]
case "AWSS3":
additionalDependencies = ["AWSSSOAdmin", "AWSS3Control", "AWSSTS"]
case "AWSEventBridge":
additionalDependencies = ["AWSRoute53"]
case "AWSCloudFrontKeyValueStore":
additionalDependencies = ["AWSCloudFront"]
case "AWSSTS":
additionalDependencies = ["AWSIAM", "AWSCognitoIdentity"]
default:
break
}
package.targets += [
.testTarget(
name: integrationTestName,
dependencies: [
.crt,
.clientRuntime,
.awsClientRuntime,
.smithyTestUtils,
.awsSDKIdentity,
.smithyIdentity,
.awsSDKCommon,
.product(name: name, package: "aws-sdk-swift")
] + additionalDependencies.map {
Target.Dependency.product(name: $0, package: "aws-sdk-swift", condition: nil)
},
path: "./Services/\(integrationTestName)",
exclude: exclusions,
resources: [.process("Resources")]
)
]
}

let servicesWithIntegrationTests: [String] = [
"AWSCloudFrontKeyValueStore",
"AWSEC2",
"AWSECS",
"AWSEventBridge",
"AWSKinesis",
"AWSMediaConvert",
"AWSRoute53",
"AWSS3",
"AWSSQS",
"AWSSTS",
"AWSTranscribeStreaming",
]

func addIntegrationTests() {
servicesWithIntegrationTests.forEach { addIntegrationTestTarget($0) }
}

addDependencies()
addIntegrationTests()
2 changes: 1 addition & 1 deletion scripts/ci_steps/prepare_integration_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ rm -rf Tests/Services/*

# Regenerate the SDK Package.swift to run only integration tests
cd AWSSDKSwiftCLI
swift run AWSSDKSwiftCLI generate-package-manifest --include-integration-tests --exclude-aws-services --exclude-runtime-tests ..
swift run AWSSDKSwiftCLI generate-package-manifest --include-services-with-integ-tests --exclude-aws-services --exclude-runtime-tests ..
cd ..

# Dump the Package.swift contents to the logs
Expand Down
Loading