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 #1388

Merged
merged 31 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
602bac1
feat: smoke tests
0marperez Aug 23, 2024
989d8ec
Merge branch 'main' of https://github.com/awslabs/aws-sdk-kotlin into…
0marperez Aug 23, 2024
9ca8f2e
Sending verified commit to trigger CI
0marperez Aug 23, 2024
b00ec1f
Actually sign commit message[B
0marperez Aug 23, 2024
35708df
PR feedback
0marperez Aug 28, 2024
2399355
Remove error log commited by accident
0marperez Aug 28, 2024
2d98a99
Add TODO
0marperez Aug 28, 2024
d7a4877
Added E2E tests
0marperez Sep 13, 2024
f390f6a
Remove dangerous gradle task, move sdk denylist check to codegen inst…
0marperez Sep 17, 2024
90a93ac
Fix kotlin native builds failing
0marperez Sep 18, 2024
6b288ed
Temp print statement to debug
0marperez Sep 18, 2024
c6701cb
Change debugging print to exception
0marperez Sep 18, 2024
95b553d
chmod gradlew before tests
0marperez Sep 18, 2024
5ac3db2
Use gradlew.bat
0marperez Sep 19, 2024
ca30211
ls sdk root dir
0marperez Sep 19, 2024
08356db
Use gradle connector instead of process builder
0marperez Sep 20, 2024
e7fdeff
build before testing
0marperez Sep 20, 2024
8f0dec1
increase gradle connection timeout
0marperez Sep 20, 2024
431e63e
run from sdk root dir, better logging, use explicit gradle distributi…
0marperez Sep 20, 2024
1706764
Enable gradle daemon with an idle timeout, increment internal timeout
0marperez Sep 21, 2024
bb53c3d
use gradle runner instead of connector
0marperez Sep 22, 2024
e13e9fc
Specify smokeTests to run & better test failure logging
0marperez Sep 22, 2024
afc5168
fix parallel task execution issues
0marperez Sep 22, 2024
c39f3fe
move task dependency from ci tests to code
0marperez Sep 23, 2024
5dfd004
easy to fix PR feedback and decoupling SmokeTestRunnerGenerator from SDK
0marperez Sep 23, 2024
87fa6bb
Merge branch 'main' of https://github.com/awslabs/aws-sdk-kotlin into…
0marperez Sep 23, 2024
c1e0edf
Remove accidental changes to AWS model
0marperez Sep 24, 2024
dfcffbb
Run smoke tests in common
0marperez Sep 24, 2024
25b8e8e
Self nits
0marperez Sep 24, 2024
8aae6e4
Use new runtime function for env vars
0marperez Sep 24, 2024
5687f7e
Cleanup, Clarity changes to test code in src
0marperez Sep 25, 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
1 change: 1 addition & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ jobs:
./gradlew :build-support:test
./gradlew publishToMavenLocal
./gradlew apiCheck
./gradlew build
./gradlew test jvmTest
./gradlew testAllProtocols
- name: Save Test Reports
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import software.amazon.smithy.kotlin.codegen.model.hasTrait
import software.amazon.smithy.kotlin.codegen.model.traits.FailedResponseTrait
import software.amazon.smithy.kotlin.codegen.model.traits.SuccessResponseTrait
import software.amazon.smithy.kotlin.codegen.rendering.GradleWriter
import software.amazon.smithy.kotlin.codegen.utils.dq
import software.amazon.smithy.kotlin.codegen.utils.operations
import software.amazon.smithy.model.shapes.ServiceShape
import software.amazon.smithy.smoketests.traits.SmokeTestsTrait
Expand Down Expand Up @@ -83,10 +82,9 @@ class GradleGenerator : KotlinIntegration {
}

private fun generateSmokeTestConfig(writer: GradleWriter, sdkId: String, ctx: CodegenContext) {
val formattedDenyList = smokeTestDenyList.joinToString(",", "setOf(", ")") { it.dq() }
writer.withBlock("if (#S !in #L) {", "}", sdkId, formattedDenyList) {
if (sdkId !in smokeTestDenyList) {
generateSmokeTestJarTask(writer, ctx)
emptyLine()
writer.emptyLine()
generateSmokeTestTask(writer, ctx)
}
}
Expand All @@ -97,17 +95,18 @@ class GradleGenerator : KotlinIntegration {
private fun generateSmokeTestJarTask(writer: GradleWriter, ctx: CodegenContext) {
writer.withBlock("jvm {", "}") {
withBlock("compilations {", "}") {
write("val runtimePath = configurations.getByName(#S).map { if (it.isDirectory) it else zipTree(it) }", "jvmRuntimeClasspath")
write("val mainPath = getByName(#S).output.classesDirs", "main")
write("val testPath = getByName(#S).output.classesDirs", "test")
withBlock("tasks {", "}") {
withBlock("register<Jar>(#S) {", "}", "smokeTestJar") {
write("description = #S", "Creates smoke tests jar")
write("group = #S", "application")
write("dependsOn(build)")
write("mustRunAfter(build)")
Copy link
Member

Choose a reason for hiding this comment

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

dependsOn and mustRunAfter seem redundant, why do we need both?

Copy link
Contributor Author

@0marperez 0marperez Sep 23, 2024

Choose a reason for hiding this comment

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

mustRunAfter only tells gradle that if both tasks are being run then one must run after the other. But it doesn't force both tasks to run. That's what dependsOn is for. Not very intuitive imo.

For each supplied task, this action adds a task 'ordering', and does not specify a 'dependency' between the tasks.

https://docs.gradle.org/8.5/kotlin-dsl/gradle/org.gradle.api/-task/must-run-after.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And when running a task with the parallel flag , dependsOn only guarantees that the task that is depended on starts first but not that it ends first. So mustRunAfter fixes that

Copy link
Contributor

Choose a reason for hiding this comment

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

And when running a task with the parallel flag , dependsOn only guarantees that the task that is depended on starts first but not that it ends first.

That's kind of surprising. Is that documented somewhere? Or were you seeing errors in the build without this ordering constraint?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think it's documented anywhere but I was seeing errors in the build without the ordering constraint.

withBlock("manifest {", "}") {
write("attributes[#S] = #S", "Main-Class", "${ctx.settings.pkg.name}.smoketests.SmokeTestsKt")
}
write("val runtimePath = configurations.getByName(#S).map { if (it.isDirectory) it else zipTree(it) }", "jvmRuntimeClasspath")
write("duplicatesStrategy = DuplicatesStrategy.EXCLUDE")
write("from(runtimePath, mainPath, testPath)")
write("archiveBaseName.set(#S)", "\${project.name}-smoketests")
Expand All @@ -123,15 +122,19 @@ class GradleGenerator : KotlinIntegration {
private fun generateSmokeTestTask(writer: GradleWriter, ctx: CodegenContext) {
val hasSuccessResponseTrait = ctx.model.expectShape<ServiceShape>(ctx.settings.service).hasTrait(SuccessResponseTrait.ID)
val hasFailedResponseTrait = ctx.model.expectShape<ServiceShape>(ctx.settings.service).hasTrait(FailedResponseTrait.ID)

// E2E tests don't have sdkVersion in jar names
val inTestingEnvironment = hasFailedResponseTrait || hasSuccessResponseTrait

/**
* E2E tests don't have sdkVersion in jar names. They're added later for publishing.
* @see SmokeTestE2ETest
*/
val jarName = if (inTestingEnvironment) "\${project.name}-smoketests.jar" else "\${project.name}-smoketests-\$sdkVersion.jar"

writer.withBlock("tasks.register<JavaExec>(#S) {", "}", "smokeTest") {
write("description = #S", "Runs smoke tests jar")
write("group = #S", "verification")
write("dependsOn(tasks.getByName(#S))", "smokeTestJar")
write("mustRunAfter(tasks.getByName(#S))", "smokeTestJar")
emptyLine()
write("val sdkVersion: String by project")
write("val jarFile = file(#S)", "build/libs/$jarName")
Expand Down
34 changes: 23 additions & 11 deletions tests/codegen/smoke-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,38 @@ import aws.sdk.kotlin.gradle.codegen.dsl.generateSmithyProjections
import aws.sdk.kotlin.gradle.codegen.dsl.smithyKotlinPlugin
import aws.sdk.kotlin.gradle.codegen.smithyKotlinProjectionPath

description = "Tests for smoke tests runner"
description = "Tests for smoke tests runners"

plugins {
alias(libs.plugins.aws.kotlin.repo.tools.smithybuild)
alias(libs.plugins.kotlin.jvm)
}

val projections = listOf(
ProjectionMetadata("successService", "smoke-tests-success.smithy", "com.test#SuccessService"),
ProjectionMetadata("failureService", "smoke-tests-failure.smithy", "com.test#FailureService"),
Projection("successService", "smoke-tests-success.smithy", "smithy.kotlin.traits#SuccessService"),
Projection("failureService", "smoke-tests-failure.smithy", "smithy.kotlin.traits#FailureService"),
)

configureProject()
configureSmithyProjections()
configureProjections()
configureTasks()

fun configureProject() {
val codegen by configurations.getting

dependencies {
codegen(project(":codegen:aws-sdk-codegen"))
implementation(libs.smithy.kotlin.codegen)
codegen(libs.smithy.cli)
codegen(libs.smithy.model)

implementation(libs.smithy.kotlin.codegen)

testImplementation(libs.kotlin.test)
testImplementation(gradleTestKit())
}
}

fun configureSmithyProjections() {
fun configureProjections() {
smithyBuild {
val pathToSmithyModels = "src/test/resources/"

Expand Down Expand Up @@ -94,19 +97,28 @@ fun configureTasks() {
dependsOn(tasks.getByName("stageServices"))
}

tasks.register<Exec>("unstageServices") {
commandLine("git", "clean", "-fdx", "services")
tasks.clean {
this@Build_gradle.projections.forEach { projection ->
delete("services/${projection.name}")
}
}

tasks.clean {
dependsOn(tasks.getByName("unstageServices"))
tasks.withType<Test> {
testLogging {
events("passed", "skipped", "failed")
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
showExceptions = true
showCauses = true
showStackTraces = true
}
mustRunAfter(tasks.getByName("stageServices"))
}
}

/**
* Holds metadata about a smithy projection
*/
data class ProjectionMetadata(
data class Projection(
val name: String,
val modelFile: String,
val serviceShapeId: String,
Expand Down
26 changes: 7 additions & 19 deletions tests/codegen/smoke-tests/src/test/kotlin/SmokeTestE2ETest.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import org.gradle.testkit.runner.GradleRunner
import software.amazon.smithy.kotlin.codegen.rendering.smoketests.SERVICE_FILTER
import software.amazon.smithy.kotlin.codegen.rendering.smoketests.SKIP_TAGS
import java.io.File
Expand Down Expand Up @@ -40,24 +41,11 @@ class SmokeTestE2ETest {

private fun runSmokeTests(service: String, envVars: Map<String, String> = emptyMap()): String {
val sdkRootDir = System.getProperty("user.dir") + "/../../../"
val runner = GradleRunner.create()
.withProjectDir(File(sdkRootDir))
.withArguments(":tests:codegen:smoke-tests:services:$service:smokeTest")
.withEnvironment(envVars)
.build()

val output = StringBuilder()
val smokeTests = ProcessBuilder()
.command("./gradlew", ":tests:codegen:smoke-tests:services:$service:smokeTest")
.directory(File(sdkRootDir))
.redirectErrorStream(true)

envVars.forEach { (key, value) ->
smokeTests
.environment()
.put(key, value)
}

smokeTests
.start()
.inputStream
.bufferedReader()
.forEachLine { output.append("$it\n") }

return output.toString()
return runner.output
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
$version: "2"
namespace com.test
namespace smithy.kotlin.traits

use aws.protocols#awsJson1_0
use aws.api#service
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
$version: "2"
namespace com.test
namespace smithy.kotlin.traits

use aws.protocols#awsJson1_0
use aws.api#service
Expand Down
Loading