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: Smoke Tests V2 #1791

Merged
merged 16 commits into from
Oct 29, 2024
Merged

feat: Smoke Tests V2 #1791

merged 16 commits into from
Oct 29, 2024

Conversation

sichanyoo
Copy link
Contributor

@sichanyoo sichanyoo commented Oct 16, 2024

Companion smithy-swift PR: smithy-lang/smithy-swift#841

Issue #

1779

Description of changes

  • Adds smoke test code generator that extends smithy-swift's generic smoke test code generator
  • Adds Package.swift codegen for the new smoke tests module

New/existing dependencies impact assessment, if applicable

Conventional Commits

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Copy link
Contributor Author

@sichanyoo sichanyoo left a comment

Choose a reason for hiding this comment

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

Comments for reviewers.

@@ -26,6 +26,7 @@ let package = Package(
resources: [
.process("Resources/Package.Prefix.txt"),
.process("Resources/Package.Base.txt"),
.process("Resources/SmokeTestsPackage.Base.txt"),
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 package manifest for SmokeTests module will also be generated along with the Package.swift for aws-sdk-swift project. The static file SmokeTestsPackage.Base.txt is appended after generated content during manifest generation, similar to how it's done for root project. Both manifests will use same file for prefix (Package.Prefix.txt).

Comment on lines +39 to +51
/// Returns the list of services that have smoke tests and test runner generated for them.
/// Service names are extracted from service name prefix of directory names under `SmokeTests/`.
/// E.g., extract `AWSS3` from `SmokeTests/AWSS3SmokeTestRunner/`.
///
/// - Returns: The list of services with generated smoke tests.
func servicesWithSmokeTests() throws -> [String] {
try FileManager.default
.contentsOfDirectory(atPath: "SmokeTests")
.sorted()
.filter { !$0.hasPrefix(".") && $0.hasSuffix("SmokeTestRunner") }
.map { $0.replacingOccurrences(of: "SmokeTestRunner", with: "") }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similar logic to getting enabled services - by looking at generated directories.

Comment on lines 130 to 137
/// - Parameter contents: The contents of the package manifest.
func savePackageManifest(_ contents: String) throws {
log("Saving package manifest to \(packageFileName)...")
func savePackageManifest(_ contents: String, _ packageFilePath: String) throws {
log("Saving package manifest to \(packageFilePath)...")
try contents.write(
toFile: packageFileName,
toFile: packageFilePath,
atomically: true,
encoding: .utf8
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

A small refactor to make this function reusable for different manifest filepaths.

Comment on lines 87 to 89
// Generate package manifest for smoke tests and save it as aws-sdk-swift/SmokeTests/Package.swift
let smokeTestsContents = try generateSmokeTestsPackageManifestContents()
try savePackageManifest(smokeTestsContents, "SmokeTests/\(packageFileName)")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Generate manifest for smoke tests module at SmokeTests/Package.manifest.

@@ -0,0 +1,39 @@
// MARK: - Static Content
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 static content of package manifest. The only generated content, which comes right before this, is serviceNames array which will contain names of all services that have smoke tests. Then, that array is used in this static content for adding all the executable targets and executable products needed to build & run our test runners.

@@ -203,13 +203,23 @@ val AwsService.modelExtrasDir: String

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changes in this file adds staging logic for moving generated smoke tests for each service to corresponding directory under SmokeTests/.

Comment on lines +39 to +40
open val protocolTestsToIgnore: Set<String> = setOf()
open val protocolTestTagsToIgnore: Set<String> = setOf()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Small rename for specifying type of tests these apply to, just for additional clarity.

@@ -0,0 +1,77 @@
package software.amazon.smithy.aws.swift.codegen
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 generic smoke test generator in smithy-swift. Overrides methods to provide AWS specific logic.

Comment on lines +45 to +76
// Converts trait definition vendor param key:value pairs to Swift SDK config field:value pairs.
private fun getFormattedVendorParams(vendorParams: ObjectNode): Map<String, String> {
val formattedMapping = mutableMapOf<String, String>()
vendorParams.members.forEach { originalMapping ->
when (originalMapping.key.value) {
/* BaseAwsVendorParams members */
"region" -> {
// Take region value retrieved from environment variable if present; otherwise, take from trait definition.
val regionValue = "regionFromEnv ?? \"${originalMapping.value.expectStringNode().value}\""
formattedMapping.put("region", regionValue)
formattedMapping.put("signingRegion", regionValue)
}
"sigv4aRegionSet" -> { /* no-op; setting multiple signing regions in config is unsupported atm. */ }
"uri" -> { formattedMapping.put("endpoint", "\"${originalMapping.value.expectStringNode().value}\"") }
"useFips" -> { formattedMapping.put("useFIPS", originalMapping.value.expectBooleanNode().value.toString()) }
"useDualstack" -> { formattedMapping.put("useDualStack", originalMapping.value.expectBooleanNode().value.toString()) }
"useAccountIdRouting" -> { /* no-op; setting account ID routing in config is unsupported atm. */ }

/* S3VendorParams members */
"useAccelerate" -> { formattedMapping.put("accelerate", originalMapping.value.expectBooleanNode().value.toString()) }
"useMultiRegionAccessPoints" -> {
// Name for corresponding config in Swift SDK is: `disableMultiRegionAccessPoints`; value needs to be flipped.
formattedMapping.put("disableMultiRegionAccessPoints", (!(originalMapping.value.expectBooleanNode().value)).toString())
}
"useGlobalEndpoint", "forcePathStyle", "useArnRegion" -> {
// No change needed for these
formattedMapping.put(originalMapping.key.value, originalMapping.value.expectBooleanNode().value.toString())
}
}
}
return formattedMapping
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This "translates" vendor params officially defined in Smithy vendor param shapes that service teams can use to specify client config values in their smoke tests. There're a couple that we don't have config bindings for yet.

Copy link
Contributor

Choose a reason for hiding this comment

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

What is the behavior if they use a param we haven't supported yet? Fail codegen or generate without it & presumably fail the test later?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If they use a param we haven't supported yet, the test will be generated without it and test will most likely fail later. If that happens we'll need to disable smoke test temporarily.

@@ -0,0 +1,83 @@
#!/bin/bash
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Convenience script for running multiple test runner executables based on the comma separated string value of the AWS_SMOKE_TEST_SERVICE_IDS environment variable. This will be used in internal build system down the line as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a place holder file just to add SmokeTests/ directory to the repo. In Catapult, with each new release, contents of this directory will be cleared out and filled with most up-to-date package manifest and test runners.

… bug. Add convenience script for running every smoke test.
@@ -0,0 +1,46 @@
#!/bin/bash
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Convenience script for developers to run every smoke test generated under SmokeTests/ with overall test summary printed at the end.

Copy link
Contributor

@jbelkins jbelkins left a comment

Choose a reason for hiding this comment

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

As discussed:

  • move smoke test manifest generation to its own CLI command
  • .gitignore the generated smoke tests, and we will generate them when we need to run them.

Comment on lines +45 to +76
// Converts trait definition vendor param key:value pairs to Swift SDK config field:value pairs.
private fun getFormattedVendorParams(vendorParams: ObjectNode): Map<String, String> {
val formattedMapping = mutableMapOf<String, String>()
vendorParams.members.forEach { originalMapping ->
when (originalMapping.key.value) {
/* BaseAwsVendorParams members */
"region" -> {
// Take region value retrieved from environment variable if present; otherwise, take from trait definition.
val regionValue = "regionFromEnv ?? \"${originalMapping.value.expectStringNode().value}\""
formattedMapping.put("region", regionValue)
formattedMapping.put("signingRegion", regionValue)
}
"sigv4aRegionSet" -> { /* no-op; setting multiple signing regions in config is unsupported atm. */ }
"uri" -> { formattedMapping.put("endpoint", "\"${originalMapping.value.expectStringNode().value}\"") }
"useFips" -> { formattedMapping.put("useFIPS", originalMapping.value.expectBooleanNode().value.toString()) }
"useDualstack" -> { formattedMapping.put("useDualStack", originalMapping.value.expectBooleanNode().value.toString()) }
"useAccountIdRouting" -> { /* no-op; setting account ID routing in config is unsupported atm. */ }

/* S3VendorParams members */
"useAccelerate" -> { formattedMapping.put("accelerate", originalMapping.value.expectBooleanNode().value.toString()) }
"useMultiRegionAccessPoints" -> {
// Name for corresponding config in Swift SDK is: `disableMultiRegionAccessPoints`; value needs to be flipped.
formattedMapping.put("disableMultiRegionAccessPoints", (!(originalMapping.value.expectBooleanNode().value)).toString())
}
"useGlobalEndpoint", "forcePathStyle", "useArnRegion" -> {
// No change needed for these
formattedMapping.put(originalMapping.key.value, originalMapping.value.expectBooleanNode().value.toString())
}
}
}
return formattedMapping
}
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the behavior if they use a param we haven't supported yet? Fail codegen or generate without it & presumably fail the test later?

@@ -13,7 +13,7 @@ import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator
class RestXMLProtocolGenerator : AWSHTTPBindingProtocolGenerator(RestXMLCustomizations()) {
override val defaultContentType: String = "application/xml"
override val protocol: ShapeId = RestXmlTrait.ID
override val testsToIgnore: Set<String> = setOf(
override val protocolTestsToIgnore: Set<String> = setOf(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there also a list of smokeTestsToIgnore or are you just renaming this for clarity?

Copy link
Contributor Author

@sichanyoo sichanyoo Oct 28, 2024

Choose a reason for hiding this comment

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

The latter, just renaming this to clarify.

Sichan Yoo added 2 commits October 28, 2024 11:42
…ests package manifest generation to its independent subcommand GenerateSmokeTestsPackageManifest.swift.
@@ -0,0 +1,72 @@
//
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Separate subcommand for generating package manifest for SmokeTests module.

@sichanyoo sichanyoo merged commit 8e9b698 into main Oct 29, 2024
29 checks passed
@sichanyoo sichanyoo deleted the feat/smoke-tests-v2 branch October 29, 2024 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants