-
Notifications
You must be signed in to change notification settings - Fork 49
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: aws smoke tests support #1437
Changes from 46 commits
602bac1
989d8ec
9ca8f2e
b00ec1f
35708df
2399355
2d98a99
d7a4877
f390f6a
90a93ac
6b288ed
c6701cb
95b553d
5ac3db2
ca30211
08356db
e7fdeff
8f0dec1
431e63e
1706764
bb53c3d
e13e9fc
afc5168
c39f3fe
5dfd004
87fa6bb
c1e0edf
dfcffbb
25b8e8e
8aae6e4
5687f7e
1e35fc7
d465c50
73f694a
774a856
578350b
e2107d7
408b3cf
ecec7e3
ca2fa02
f7c17d6
ea40b9b
c9d266f
d427f65
dc5c114
c6ab629
93c850b
e784343
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package aws.sdk.kotlin.codegen.model.traits.testing | ||
|
||
import software.amazon.smithy.model.node.ObjectNode | ||
import software.amazon.smithy.model.shapes.ShapeId | ||
import software.amazon.smithy.model.traits.AnnotationTrait | ||
|
||
/** | ||
* Indicates the annotated service should always return a failed response. | ||
* IMPORTANT: This trait is intended for use in integration or E2E tests only, not in real-life smoke tests that run | ||
* against a service endpoint. | ||
*/ | ||
class TestFailedResponseTrait(node: ObjectNode) : AnnotationTrait(ID, node) { | ||
companion object { | ||
val ID: ShapeId = ShapeId.from("smithy.kotlin.traits#failedResponseTrait") | ||
} | ||
} | ||
|
||
/** | ||
* Indicates the annotated service should always return a success response. | ||
* IMPORTANT: This trait is intended for use in integration or E2E tests only, not in real-life smoke tests that run | ||
* against a service endpoint. | ||
*/ | ||
class TestSuccessResponseTrait(node: ObjectNode) : AnnotationTrait(ID, node) { | ||
companion object { | ||
val ID: ShapeId = ShapeId.from("smithy.kotlin.traits#successResponseTrait") | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package aws.sdk.kotlin.codegen.smoketests | ||
|
||
import aws.sdk.kotlin.codegen.AwsRuntimeTypes | ||
import software.amazon.smithy.kotlin.codegen.KotlinSettings | ||
import software.amazon.smithy.kotlin.codegen.core.RuntimeTypes | ||
import software.amazon.smithy.kotlin.codegen.core.getContextValue | ||
import software.amazon.smithy.kotlin.codegen.core.withBlock | ||
import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration | ||
import software.amazon.smithy.kotlin.codegen.integration.SectionWriterBinding | ||
import software.amazon.smithy.kotlin.codegen.model.hasTrait | ||
import software.amazon.smithy.kotlin.codegen.rendering.smoketests.* | ||
import software.amazon.smithy.kotlin.codegen.utils.topDownOperations | ||
import software.amazon.smithy.model.Model | ||
import software.amazon.smithy.smoketests.traits.SmokeTestsTrait | ||
|
||
/** | ||
* Generates AWS specific code for smoke test runners | ||
*/ | ||
class AwsSmokeTestsRunnerGeneratorIntegration : KotlinIntegration { | ||
override fun enabledForService(model: Model, settings: KotlinSettings): Boolean = | ||
model.topDownOperations(settings.service).any { it.hasTrait<SmokeTestsTrait>() } | ||
|
||
override val sectionWriters: List<SectionWriterBinding> | ||
get() = listOf( | ||
AwsSmokeTestsRunnerGenerator.regionEnvironmentVariable, | ||
AwsSmokeTestsRunnerGenerator.clientConfig, | ||
AwsSmokeTestsRunnerGenerator.defaultClientConfig, | ||
AwsSmokeTestsRunnerGenerator.skipTagsEnvironmentVariable, | ||
AwsSmokeTestsRunnerGenerator.serviceFilterEnvironmentVariable, | ||
) | ||
} | ||
|
||
/** | ||
* The section writer bindings used by [AwsSmokeTestsRunnerGeneratorIntegration] | ||
*/ | ||
private object AwsSmokeTestsRunnerGenerator { | ||
/** | ||
* Adds region environment variable support to AWS smoke test runners. | ||
* Preserves other environment variables added via section writer binding, if any. | ||
*/ | ||
val regionEnvironmentVariable = | ||
SectionWriterBinding(AdditionalEnvironmentVariables) { writer, previous -> | ||
writer.write("#L", previous) | ||
writer.write( | ||
"private val regionOverride = #T.System.getenv(#S)", | ||
RuntimeTypes.Core.Utils.PlatformProvider, | ||
AWS_REGION, | ||
) | ||
} | ||
|
||
/** | ||
* Add AWS specific client config support to AWS smoke test runners | ||
*/ | ||
val clientConfig = | ||
SectionWriterBinding(ClientConfig) { writer, _ -> | ||
val name = writer.getContextValue(ClientConfig.Name) | ||
val value = writer.getContextValue(ClientConfig.Value) | ||
|
||
// Normalize client config names | ||
val newName = when (name) { | ||
"uri" -> "endpointProvider" | ||
"useDualstack" -> "useDualStack" | ||
"sigv4aRegionSet" -> "sigV4aSigningRegionSet" | ||
"useAccountIdRouting" -> "accountIdEndpointMode" | ||
"useAccelerate" -> "enableAccelerate" | ||
"useMultiRegionAccessPoints" -> "disableMrap" | ||
"useGlobalEndpoint" -> { | ||
writer.write("throw Exception(#S)", "'useGlobalEndpoint' is not supported by the SDK") | ||
return@SectionWriterBinding | ||
} | ||
else -> name | ||
} | ||
writer.writeInline("#L = ", newName) | ||
|
||
// Normalize client values | ||
when (newName) { | ||
"endpointProvider" -> { | ||
val endpointProvider = writer.getContextValue(ClientConfig.EndpointProvider) | ||
val endpointParameters = writer.getContextValue(ClientConfig.EndpointParams) | ||
|
||
writer.withBlock("object : #T {", "}", endpointProvider) { | ||
write( | ||
"override suspend fun resolveEndpoint(params: #1T): #2T = #2T(#3L)", | ||
endpointParameters, | ||
RuntimeTypes.SmithyClient.Endpoints.Endpoint, | ||
value, | ||
) | ||
} | ||
} | ||
"sigV4aSigningRegionSet" -> { | ||
// Render new value | ||
writer.write("#L.toSet()", value) | ||
// Also configure sigV4a - TODO: Remove once sigV4a is supported for default signer. | ||
writer.write( | ||
"authSchemes = listOf(#T(#T))", | ||
RuntimeTypes.Auth.HttpAuthAws.SigV4AsymmetricAuthScheme, | ||
RuntimeTypes.Auth.AwsSigningCrt.CrtAwsSigner, | ||
) | ||
} | ||
"accountIdEndpointMode" -> { | ||
when (value) { | ||
"true" -> writer.write("#T.REQUIRED", AwsRuntimeTypes.Config.Endpoints.AccountIdEndpointMode) | ||
"false" -> writer.write("#T.DISABLED", AwsRuntimeTypes.Config.Endpoints.AccountIdEndpointMode) | ||
} | ||
} | ||
"disableMrap" -> { | ||
when (value) { | ||
"true" -> writer.write("false") | ||
"false" -> writer.write("true") | ||
} | ||
} | ||
"region" -> { | ||
writer.write("regionOverride ?: #L", value) | ||
} | ||
else -> writer.write("#L", value) | ||
} | ||
} | ||
|
||
/** | ||
* Add default client config to AWS smoke test runners. | ||
* Preserves previous default config if any. | ||
*/ | ||
val defaultClientConfig = | ||
SectionWriterBinding(DefaultClientConfig) { writer, previous -> | ||
writer.write("#L", previous) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is writing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added |
||
writer.write("region = regionOverride") | ||
} | ||
|
||
/** | ||
* Replaces environment variable with one specific to AWS smoke test runners | ||
*/ | ||
val skipTagsEnvironmentVariable = | ||
SectionWriterBinding(SkipTags) { writer, _ -> writer.writeInline("#S", AWS_SKIP_TAGS) } | ||
|
||
/** | ||
* Replaces environment variable with one specific to AWS smoke test runners | ||
*/ | ||
val serviceFilterEnvironmentVariable = | ||
SectionWriterBinding(ServiceFilter) { writer, _ -> writer.writeInline("#S", AWS_SERVICE_FILTER) } | ||
} | ||
|
||
/** | ||
* Env var for AWS smoke test runners. | ||
* Should be a string that corresponds to an AWS region. | ||
* The region to use when executing smoke tests. This value MUST override any value supplied in the smoke tests themselves. | ||
*/ | ||
private const val AWS_REGION = "AWS_SMOKE_TEST_REGION" | ||
|
||
/** | ||
* Env var for AWS smoke test runners. | ||
* Should be a comma-delimited list of strings that correspond to tags on the test cases. | ||
* If a test case is tagged with one of the tags indicated by AWS_SMOKE_TEST_SKIP_TAGS, it MUST be skipped by the smoke test runner. | ||
*/ | ||
const val AWS_SKIP_TAGS = "AWS_SMOKE_TEST_SKIP_TAGS" | ||
|
||
/** | ||
* Env var for AWS smoke test runners. | ||
* Should be a comma-separated list of service identifiers to test. | ||
*/ | ||
const val AWS_SERVICE_FILTER = "AWS_SMOKE_TEST_SERVICE_IDS" |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package aws.sdk.kotlin.codegen.smoketests.testing | ||
|
||
import aws.sdk.kotlin.codegen.model.traits.testing.TestFailedResponseTrait | ||
import aws.sdk.kotlin.codegen.model.traits.testing.TestSuccessResponseTrait | ||
import software.amazon.smithy.kotlin.codegen.KotlinSettings | ||
import software.amazon.smithy.kotlin.codegen.core.RuntimeTypes | ||
import software.amazon.smithy.kotlin.codegen.core.withBlock | ||
import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration | ||
import software.amazon.smithy.kotlin.codegen.integration.SectionWriter | ||
import software.amazon.smithy.kotlin.codegen.integration.SectionWriterBinding | ||
import software.amazon.smithy.kotlin.codegen.model.expectShape | ||
import software.amazon.smithy.kotlin.codegen.model.hasTrait | ||
import software.amazon.smithy.kotlin.codegen.rendering.smoketests.HttpEngineOverride | ||
import software.amazon.smithy.kotlin.codegen.utils.topDownOperations | ||
import software.amazon.smithy.model.Model | ||
import software.amazon.smithy.model.shapes.ServiceShape | ||
import software.amazon.smithy.smoketests.traits.SmokeTestsTrait | ||
|
||
/** | ||
* Adds [TestFailedResponseTrait] support to smoke tests | ||
* IMPORTANT: This integration is intended for use in integration or E2E tests only, not in real-life smoke tests that run | ||
* against a service endpoint. | ||
*/ | ||
class SmokeTestFailHttpEngineIntegration : KotlinIntegration { | ||
override fun enabledForService(model: Model, settings: KotlinSettings): Boolean = | ||
model.topDownOperations(settings.service).any { it.hasTrait<SmokeTestsTrait>() } && | ||
!model.expectShape<ServiceShape>(settings.service).hasTrait(TestSuccessResponseTrait.ID) && | ||
model.expectShape<ServiceShape>(settings.service).hasTrait(TestFailedResponseTrait.ID) | ||
|
||
override val sectionWriters: List<SectionWriterBinding> | ||
get() = listOf( | ||
SectionWriterBinding(HttpEngineOverride, httpClientOverride), | ||
) | ||
|
||
private val httpClientOverride = SectionWriter { writer, _ -> | ||
writer.withBlock("httpClient = #T(", ")", RuntimeTypes.HttpTest.TestEngine) { | ||
withBlock("roundTripImpl = { _, request ->", "}") { | ||
write( | ||
"val resp = #T(#T.BadRequest, #T.Empty, #T.Empty)", | ||
RuntimeTypes.Http.Response.HttpResponse, | ||
RuntimeTypes.Http.StatusCode, | ||
RuntimeTypes.Http.Headers, | ||
RuntimeTypes.Http.HttpBody, | ||
) | ||
write("val now = #T.now()", RuntimeTypes.Core.Instant) | ||
write("#T(request, resp, now, now)", RuntimeTypes.Http.HttpCall) | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception
should be#T
and can probably be a better exception type