Skip to content

Commit b61be7e

Browse files
authored
chore: reintegrate E2E smoke tests into the top-level Gradle build; modularize smoke test runners to improve testability (#1558)
1 parent 6e8607e commit b61be7e

File tree

5 files changed

+80
-163
lines changed

5 files changed

+80
-163
lines changed

settings.gradle.kts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ include(":tests:codegen:event-stream")
5757
include(":tests:codegen:rules-engine")
5858
include(":tests:e2e-test-util")
5959
include(":tests:codegen:smoke-tests")
60-
include(":tests:codegen:smoke-tests:services")
6160
include(":tests:codegen:checksums")
6261

6362
// generated services
@@ -73,13 +72,6 @@ file("services").listFiles().forEach {
7372
}
7473
}
7574

76-
// generated services by smoke tests test suite
77-
file("tests/codegen/smoke-tests/services").listFiles().forEach {
78-
if (it.isServiceDir) {
79-
include(":tests:codegen:smoke-tests:services:${it.name}")
80-
}
81-
}
82-
8375
if ("dynamodb".isBootstrappedService) {
8476
include(":hll:dynamodb-mapper")
8577
include(":hll:dynamodb-mapper:dynamodb-mapper")

tests/codegen/build.gradle.kts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,6 @@ subprojects {
1919
}
2020
}
2121

22-
/*
23-
Don't apply the rest of the configuration to the code generated smoke test services!
24-
Those use the KMP plugin not JVM.
25-
*/
26-
if (project.path.startsWith(":tests:codegen:smoke-tests:services")) return@subprojects
27-
2822
apply(plugin = libraries.plugins.aws.kotlin.repo.tools.smithybuild.get().pluginId)
2923
apply(plugin = libraries.plugins.kotlin.jvm.get().pluginId)
3024

tests/codegen/smoke-tests/build.gradle.kts

Lines changed: 22 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,84 +3,53 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import aws.sdk.kotlin.gradle.codegen.dsl.generateSmithyProjections
76
import aws.sdk.kotlin.gradle.codegen.dsl.smithyKotlinPlugin
87
import aws.sdk.kotlin.gradle.codegen.smithyKotlinProjectionPath
8+
import aws.sdk.kotlin.gradle.codegen.smithyKotlinProjectionSrcDir
99
import aws.sdk.kotlin.tests.codegen.CodegenTest
1010
import aws.sdk.kotlin.tests.codegen.Model
1111

1212
description = "AWS SDK for Kotlin's smoke test codegen test suite"
1313

14-
dependencies {
15-
testImplementation(gradleTestKit())
16-
}
17-
1814
val tests = listOf(
1915
CodegenTest("successService", Model("smoke-tests-success.smithy"), "smithy.kotlin.traits#SuccessService"),
2016
CodegenTest("failureService", Model("smoke-tests-failure.smithy"), "smithy.kotlin.traits#FailureService"),
2117
CodegenTest("exceptionService", Model("smoke-tests-exception.smithy"), "smithy.kotlin.traits#ExceptionService"),
2218
)
2319

24-
configureProjections()
25-
configureTasks()
20+
smithyBuild {
21+
val basePackage = "aws.sdk.kotlin.test.codegen.smoketest"
22+
23+
projections {
24+
tests.forEach { test ->
25+
create(test.name) {
26+
val modelPath = layout.projectDirectory.file(test.model.path + test.model.fileName).asFile.absolutePath
27+
imports = listOf(modelPath)
2628

27-
fun configureProjections() {
28-
smithyBuild {
29-
this@Build_gradle.tests.forEach { test ->
30-
projections.register(test.name) {
31-
imports = listOf(layout.projectDirectory.file(test.model.path + test.model.fileName).asFile.absolutePath)
3229
smithyKotlinPlugin {
3330
serviceShapeId = test.serviceShapeId
34-
packageName = "aws.sdk.kotlin.test.${test.name.lowercase()}"
35-
packageVersion = "1.0"
31+
packageName = "$basePackage.${test.name}"
32+
packageVersion = project.version.toString()
33+
sdkId = test.name.replaceFirstChar { it.uppercaseChar() }
3634
buildSettings {
37-
generateFullProject = false
3835
generateDefaultBuildFiles = false
39-
optInAnnotations = listOf(
40-
"aws.smithy.kotlin.runtime.InternalApi",
41-
"aws.sdk.kotlin.runtime.InternalSdkApi",
42-
)
36+
generateFullProject = false
37+
}
38+
apiSettings {
39+
visibility = "internal"
4340
}
4441
}
4542
}
4643
}
4744
}
4845
}
4946

50-
fun configureTasks() {
51-
tasks.register("stageServices") {
52-
dependsOn(tasks.generateSmithyProjections)
53-
doLast {
54-
this@Build_gradle.tests.forEach { test ->
55-
val projectionPath = smithyBuild.smithyKotlinProjectionPath(test.name).get()
56-
val destinationPath = layout.projectDirectory.asFile.absolutePath + "/services/${test.name}"
57-
58-
copy {
59-
from("$projectionPath/src")
60-
into("$destinationPath/generated-src")
61-
}
62-
63-
copy {
64-
from("$projectionPath/build.gradle.kts")
65-
into(destinationPath)
66-
}
67-
}
68-
}
69-
}
47+
kotlin.sourceSets.getByName("test") {
48+
smithyBuild.projections.forEach { projection ->
49+
// Add generated model to source set
50+
kotlin.srcDir(smithyBuild.smithyKotlinProjectionSrcDir(projection.name))
7051

71-
tasks.withType<Test> {
72-
dependsOn(tasks.getByName("stageServices"))
73-
mustRunAfter(tasks.getByName("stageServices"))
74-
}
75-
76-
tasks.build {
77-
dependsOn(tasks.getByName("stageServices"))
78-
mustRunAfter(tasks.getByName("stageServices"))
79-
}
80-
81-
tasks.clean {
82-
this@Build_gradle.tests.forEach { test ->
83-
delete("services/${test.name}")
84-
}
52+
// Add generated smoke tests to source set
53+
kotlin.srcDir(smithyBuild.smithyKotlinProjectionPath(projection.name).map { it.resolve("src/test/kotlin") })
8554
}
8655
}

tests/codegen/smoke-tests/services/build.gradle.kts

Lines changed: 0 additions & 32 deletions
This file was deleted.

tests/codegen/smoke-tests/src/test/kotlin/aws/sdk/kotlin/test/codegen/smoketest/SmokeTestE2ETest.kt

Lines changed: 58 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,93 +7,87 @@ package aws.sdk.kotlin.test.codegen.smoketest
77

88
import aws.sdk.kotlin.codegen.smoketests.AWS_SERVICE_FILTER
99
import aws.sdk.kotlin.codegen.smoketests.AWS_SKIP_TAGS
10-
import aws.smithy.kotlin.runtime.util.OsFamily
11-
import aws.smithy.kotlin.runtime.util.PlatformProvider
12-
import java.io.File
10+
import aws.smithy.kotlin.runtime.util.TestPlatformProvider
11+
import kotlinx.coroutines.test.runTest
1312
import kotlin.test.Test
1413
import kotlin.test.assertContains
14+
import kotlin.test.assertFalse
1515
import kotlin.test.assertTrue
1616

1717
class SmokeTestE2ETest {
1818
@Test
19-
fun successService() {
20-
val smokeTestRunnerOutput = runSmokeTests("successService")
19+
fun successService() = runTest {
20+
val output = StringBuilder()
21+
val runner = aws.sdk.kotlin.test.codegen.smoketest.successService.smoketests.SmokeTestRunner(
22+
TestPlatformProvider(),
23+
output,
24+
)
25+
val success = runner.runAllTests()
26+
assertTrue(success, "Unexpected failures running successService E2E smoke test. Full output: $output")
2127

22-
assertContains(smokeTestRunnerOutput, "ok SuccessService SuccessTest - no error expected from service")
23-
assertContains(smokeTestRunnerOutput, "ok SuccessService SuccessTestWithTags - no error expected from service")
28+
assertContains(output, "ok SuccessService SuccessTest - no error expected from service")
29+
assertContains(output, "ok SuccessService SuccessTestWithTags - no error expected from service")
2430
}
2531

2632
@Test
27-
fun failureService() {
28-
val smokeTestRunnerOutput = runSmokeTests("failureService")
33+
fun failureService() = runTest {
34+
val output = StringBuilder()
35+
val runner = aws.sdk.kotlin.test.codegen.smoketest.failureService.smoketests.SmokeTestRunner(
36+
TestPlatformProvider(),
37+
output,
38+
)
39+
val success = runner.runAllTests()
40+
assertTrue(success, "Unexpected failures running failureService E2E smoke test. Full output: $output")
2941

30-
assertContains(smokeTestRunnerOutput, "ok FailureService FailuresTest - error expected from service")
42+
assertContains(output, "ok FailureService FailuresTest - error expected from service")
3143
}
3244

3345
@Test
34-
fun exceptionService() {
35-
val smokeTestRunnerOutput = runSmokeTests("exceptionService", expectingFailure = true)
46+
fun exceptionService() = runTest {
47+
val output = StringBuilder()
48+
val runner = aws.sdk.kotlin.test.codegen.smoketest.exceptionService.smoketests.SmokeTestRunner(
49+
TestPlatformProvider(),
50+
output,
51+
)
52+
val success = runner.runAllTests()
53+
assertFalse(success, "Unexpected success running exceptionService E2E smoke test. Full output: $output")
3654

37-
assertContains(smokeTestRunnerOutput, "not ok ExceptionService ExceptionTest - no error expected from service")
38-
assertContains(smokeTestRunnerOutput, "#aws.smithy.kotlin.runtime.http.interceptors.SmokeTestsFailureException: Smoke test failed with HTTP status code: 400")
55+
assertContains(output, "not ok ExceptionService ExceptionTest - no error expected from service")
56+
assertContains(
57+
output,
58+
"# aws.smithy.kotlin.runtime.http.interceptors.SmokeTestsFailureException: Smoke test failed with HTTP status code: 400",
59+
)
3960
}
4061

4162
@Test
42-
fun successServiceSkipTags() {
43-
val envVars = mapOf(AWS_SKIP_TAGS to "success")
44-
val smokeTestRunnerOutput = runSmokeTests("successService", envVars)
63+
fun successServiceSkipTags() = runTest {
64+
val output = StringBuilder()
65+
val runner = aws.sdk.kotlin.test.codegen.smoketest.successService.smoketests.SmokeTestRunner(
66+
TestPlatformProvider(
67+
env = mapOf(AWS_SKIP_TAGS to "success"),
68+
),
69+
output,
70+
)
71+
val success = runner.runAllTests()
72+
assertTrue(success, "Unexpected failures running successService E2E smoke test. Full output: $output")
4573

46-
assertContains(smokeTestRunnerOutput, "ok SuccessService SuccessTest - no error expected from service")
47-
assertContains(smokeTestRunnerOutput, "ok SuccessService SuccessTestWithTags - no error expected from service # skip")
74+
assertContains(output, "ok SuccessService SuccessTest - no error expected from service")
75+
assertContains(output, "ok SuccessService SuccessTestWithTags - no error expected from service # skip")
4876
}
4977

5078
@Test
51-
fun successServiceServiceFilter() {
52-
val envVars = mapOf(AWS_SERVICE_FILTER to "Failure") // Only run tests for services with this SDK ID
53-
val smokeTestRunnerOutput = runSmokeTests("successService", envVars)
54-
55-
assertContains(smokeTestRunnerOutput, "ok SuccessService SuccessTest - no error expected from service # skip")
56-
assertContains(smokeTestRunnerOutput, "ok SuccessService SuccessTestWithTags - no error expected from service # skip")
57-
}
58-
}
59-
60-
private fun runSmokeTests(
61-
service: String,
62-
envVars: Map<String, String> = emptyMap(),
63-
expectingFailure: Boolean = false,
64-
): String {
65-
val sdkRootDir = System.getProperty("user.dir") + "/../../../"
66-
val processBuilder =
67-
ProcessBuilder(
68-
*gradleWrapperCommand(),
69-
":tests:codegen:smoke-tests:services:$service:smokeTest",
70-
// Make sure unexpected errors are debuggable
71-
"--stacktrace",
72-
// FIXME: Remove `-Paws.kotlin.native=false` when Kotlin Native is ready
73-
"-Paws.kotlin.native=false",
79+
fun successServiceServiceFilter() = runTest {
80+
val output = StringBuilder()
81+
val runner = aws.sdk.kotlin.test.codegen.smoketest.successService.smoketests.SmokeTestRunner(
82+
TestPlatformProvider(
83+
env = mapOf(AWS_SERVICE_FILTER to "Failure"), // Only run tests for services with this SDK ID
84+
),
85+
output,
7486
)
75-
.directory(File(sdkRootDir))
76-
.redirectErrorStream(true)
77-
78-
processBuilder.environment().putAll(envVars)
87+
val success = runner.runAllTests()
88+
assertTrue(success, "Unexpected failures running successService E2E smoke test. Full output: $output")
7989

80-
val process = processBuilder.start()
81-
val output = process.inputStream.bufferedReader().use { it.readText() }
82-
val exitCode = process.waitFor()
83-
84-
if (expectingFailure) {
85-
assertTrue(exitCode != 0)
90+
assertContains(output, "ok SuccessService SuccessTest - no error expected from service # skip")
91+
assertContains(output, "ok SuccessService SuccessTestWithTags - no error expected from service # skip")
8692
}
87-
88-
return output
8993
}
90-
91-
/**
92-
* Determines the appropriate Gradle wrapper command based on the operating system.
93-
*/
94-
private fun gradleWrapperCommand() =
95-
if (PlatformProvider.System.osInfo().family == OsFamily.Windows) {
96-
arrayOf("cmd.exe", "/c", "gradlew.bat")
97-
} else {
98-
arrayOf("./gradlew")
99-
}

0 commit comments

Comments
 (0)