mirror of https://github.com/smithy-lang/smithy-rs
Allow for specified Cargo commands to be run on a subset of the integration tests (#1165)
This commit allows for the `modules` and `cargoCommands` properties to be specified when running the `codegen-test` and `codegen-server-test` Gradle modules. The `modules` property allows one to only generate a subset of the integration test services, while the `cargoCommands` property allows one to specify the Cargo commands to be run on the generated Rust crates. This functionality can be useful to reduce development iteration cycles. For instance, to only run `cargo test` on the integration test `simple.smithy`: ```sh ./gradlew codegen-test:build -P cargoCommands='test' -P modules='simple' ``` This commit also refactors the buildscripts of the `codegen-test` and the `codegen-server-test` modules, extracting shared functionality to `buildSrc/src/main/kotlin/CodegenTestCommon.kt`.
This commit is contained in:
parent
329c036e6d
commit
c3ef017d41
|
@ -0,0 +1,104 @@
|
|||
import java.lang.IllegalArgumentException
|
||||
|
||||
/*
|
||||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains common functionality shared across the buildscripts for the `codegen-test` and `codegen-server-test`
|
||||
* modules.
|
||||
*/
|
||||
|
||||
data class CodegenTest(val service: String, val module: String, val extraConfig: String? = null)
|
||||
|
||||
fun generateSmithyBuild(projectDir: String, pluginName: String, tests: List<CodegenTest>): String {
|
||||
val projections = tests.joinToString(",\n") {
|
||||
"""
|
||||
"${it.module}": {
|
||||
"plugins": {
|
||||
"$pluginName": {
|
||||
"runtimeConfig": {
|
||||
"relativePath": "$projectDir/rust-runtime"
|
||||
},
|
||||
"service": "${it.service}",
|
||||
"module": "${it.module}",
|
||||
"moduleVersion": "0.0.1",
|
||||
"moduleDescription": "test",
|
||||
"moduleAuthors": ["protocoltest@example.com"]
|
||||
${it.extraConfig ?: ""}
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
return """
|
||||
{
|
||||
"version": "1.0",
|
||||
"projections": {
|
||||
$projections
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
enum class Cargo(val toString: String) {
|
||||
CHECK("cargoCheck"),
|
||||
TEST("cargoTest"),
|
||||
DOCS("cargoDocs"),
|
||||
CLIPPY("cargoClippy");
|
||||
}
|
||||
|
||||
fun generateCargoWorkspace(pluginName: String, tests: List<CodegenTest>) =
|
||||
"""
|
||||
[workspace]
|
||||
members = [
|
||||
${tests.joinToString(",") { "\"${it.module}/$pluginName\"" }}
|
||||
]
|
||||
""".trimIndent()
|
||||
|
||||
/**
|
||||
* Filter the service integration tests for which to generate Rust crates in [allTests] using the given [properties].
|
||||
*/
|
||||
fun codegenTests(properties: PropertyRetriever, allTests: List<CodegenTest>): List<CodegenTest> {
|
||||
val modulesOverride = properties.get("modules")?.split(",")?.map { it.trim() }
|
||||
|
||||
val ret = if (modulesOverride != null) {
|
||||
println("modulesOverride: $modulesOverride")
|
||||
allTests.filter { modulesOverride.contains(it.module) }
|
||||
} else {
|
||||
allTests
|
||||
}
|
||||
require(ret.isNotEmpty()) {
|
||||
"None of the provided module overrides (`$modulesOverride`) are valid test services (`${allTests.map { it.module }}`)"
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
val AllCargoCommands = listOf(Cargo.CHECK, Cargo.TEST, Cargo.CLIPPY, Cargo.DOCS)
|
||||
/**
|
||||
* Filter the Cargo commands to be run on the generated Rust crates using the given [properties].
|
||||
* The list of Cargo commands that is run by default is defined in [AllCargoCommands].
|
||||
*/
|
||||
fun cargoCommands(properties: PropertyRetriever): List<Cargo> {
|
||||
val cargoCommandsOverride = properties.get("cargoCommands")?.split(",")?.map { it.trim() }?.map {
|
||||
when(it) {
|
||||
"check" -> Cargo.CHECK
|
||||
"test" -> Cargo.TEST
|
||||
"docs" -> Cargo.DOCS
|
||||
"clippy" -> Cargo.CLIPPY
|
||||
else -> throw IllegalArgumentException("Unexpected Cargo command `$it` (valid commands are `check`, `test`, `docs`, `clippy`)")
|
||||
}
|
||||
}
|
||||
|
||||
val ret = if (cargoCommandsOverride != null) {
|
||||
println("cargoCommandsOverride: $cargoCommandsOverride")
|
||||
AllCargoCommands.filter { cargoCommandsOverride.contains(it) }
|
||||
} else {
|
||||
AllCargoCommands
|
||||
}
|
||||
require(ret.isNotEmpty()) {
|
||||
"None of the provided cargo commands (`$cargoCommandsOverride`) are valid cargo commands (`${AllCargoCommands.map { it.toString }}`)"
|
||||
}
|
||||
return ret
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
# Codegen Integration Test
|
||||
This module defines an integration test of the code generation machinery. `.build.gradle.kts` will generate a `smithy-build.json` file as part of the build. The Smithy build plugin then invokes our codegen machinery and generates Rust crates.
|
||||
# Server Codegen Integration Tests
|
||||
|
||||
The `test` task will run `cargo check` and `cargo clippy` to validate that the generated Rust compiles and is idiomatic.
|
||||
## Usage
|
||||
```
|
||||
../gradlew test
|
||||
```
|
||||
Refer to `../codegen-test/README.md` for documentation on how to use this
|
||||
module. This module is analogous to the `codegen-test` one, but it's named
|
||||
`codegen-server-test` and it runs the `rust-server-codegen` Smithy build
|
||||
plugin instead.
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
extra["displayName"] = "Smithy :: Rust :: Codegen :: Server :: Test"
|
||||
|
||||
extra["moduleName"] = "software.amazon.smithy.rust.kotlin.codegen.server.test"
|
||||
|
||||
tasks["jar"].enabled = false
|
||||
|
@ -14,6 +13,10 @@ plugins { id("software.amazon.smithy").version("0.5.3") }
|
|||
val smithyVersion: String by project
|
||||
val defaultRustFlags: String by project
|
||||
val defaultRustDocFlags: String by project
|
||||
val properties = PropertyRetriever(rootProject, project)
|
||||
|
||||
val pluginName = "rust-server-codegen"
|
||||
val workingDirUnderBuildDir = "smithyprojections/codegen-server-test/"
|
||||
|
||||
buildscript {
|
||||
val smithyVersion: String by project
|
||||
|
@ -29,104 +32,64 @@ dependencies {
|
|||
implementation("software.amazon.smithy:smithy-aws-traits:$smithyVersion")
|
||||
}
|
||||
|
||||
data class CodegenTest(val service: String, val module: String, val extraConfig: String? = null)
|
||||
|
||||
val CodegenTests = listOf(
|
||||
val allCodegenTests = listOf(
|
||||
CodegenTest("com.amazonaws.simple#SimpleService", "simple"),
|
||||
CodegenTest("aws.protocoltests.restjson#RestJson", "rest_json"),
|
||||
CodegenTest("com.amazonaws.ebs#Ebs", "ebs"),
|
||||
CodegenTest("com.amazonaws.s3#AmazonS3", "s3")
|
||||
)
|
||||
|
||||
/**
|
||||
* `includeFluentClient` must be set to `false` as we are not generating all the supporting
|
||||
* code for it.
|
||||
* TODO: Review how can we make this a default in the server so that customers don't
|
||||
* have to specify it.
|
||||
*/
|
||||
fun generateSmithyBuild(tests: List<CodegenTest>): String {
|
||||
val projections =
|
||||
tests.joinToString(",\n") {
|
||||
"""
|
||||
"${it.module}": {
|
||||
"plugins": {
|
||||
"rust-server-codegen": {
|
||||
"runtimeConfig": {
|
||||
"relativePath": "${rootProject.projectDir.absolutePath}/rust-runtime"
|
||||
},
|
||||
"service": "${it.service}",
|
||||
"module": "${it.module}",
|
||||
"moduleVersion": "0.0.1",
|
||||
"moduleDescription": "test",
|
||||
"moduleAuthors": ["protocoltest@example.com"]
|
||||
${it.extraConfig ?: ""}
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
return """
|
||||
{
|
||||
"version": "1.0",
|
||||
"projections": { $projections }
|
||||
}
|
||||
"""
|
||||
}
|
||||
|
||||
task("generateSmithyBuild") {
|
||||
description = "generate smithy-build.json"
|
||||
doFirst { projectDir.resolve("smithy-build.json").writeText(generateSmithyBuild(CodegenTests)) }
|
||||
}
|
||||
|
||||
fun generateCargoWorkspace(tests: List<CodegenTest>): String {
|
||||
return """
|
||||
[workspace]
|
||||
members = [
|
||||
${tests.joinToString(",") { "\"${it.module}/rust-server-codegen\"" }}
|
||||
]
|
||||
""".trimIndent()
|
||||
doFirst {
|
||||
projectDir.resolve("smithy-build.json")
|
||||
.writeText(generateSmithyBuild(
|
||||
rootProject.projectDir.absolutePath,
|
||||
pluginName,
|
||||
codegenTests(properties, allCodegenTests))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
task("generateCargoWorkspace") {
|
||||
description = "generate Cargo.toml workspace file"
|
||||
doFirst {
|
||||
buildDir.resolve("smithyprojections/codegen-server-test/Cargo.toml")
|
||||
.writeText(generateCargoWorkspace(CodegenTests))
|
||||
buildDir.resolve("$workingDirUnderBuildDir/Cargo.toml")
|
||||
.writeText(generateCargoWorkspace(pluginName, codegenTests(properties, allCodegenTests)))
|
||||
}
|
||||
}
|
||||
|
||||
tasks["smithyBuildJar"].dependsOn("generateSmithyBuild")
|
||||
tasks["assemble"].dependsOn("smithyBuildJar")
|
||||
tasks["assemble"].finalizedBy("generateCargoWorkspace")
|
||||
|
||||
tasks.register<Exec>("cargoCheck") {
|
||||
workingDir("build/smithyprojections/codegen-server-test/")
|
||||
tasks.register<Exec>(Cargo.CHECK.toString) {
|
||||
workingDir("$buildDir/$workingDirUnderBuildDir")
|
||||
environment("RUSTFLAGS", defaultRustFlags)
|
||||
commandLine("cargo", "check")
|
||||
dependsOn("assemble")
|
||||
}
|
||||
|
||||
tasks.register<Exec>("cargoTest") {
|
||||
workingDir("build/smithyprojections/codegen-server-test/")
|
||||
tasks.register<Exec>(Cargo.TEST.toString) {
|
||||
workingDir("$buildDir/$workingDirUnderBuildDir")
|
||||
environment("RUSTFLAGS", defaultRustFlags)
|
||||
commandLine("cargo", "test")
|
||||
dependsOn("assemble")
|
||||
}
|
||||
|
||||
tasks.register<Exec>("cargoDocs") {
|
||||
workingDir("build/smithyprojections/codegen-server-test/")
|
||||
tasks.register<Exec>(Cargo.DOCS.toString) {
|
||||
workingDir("$buildDir/$workingDirUnderBuildDir")
|
||||
environment("RUSTDOCFLAGS", defaultRustDocFlags)
|
||||
commandLine("cargo", "doc", "--no-deps")
|
||||
dependsOn("assemble")
|
||||
}
|
||||
|
||||
tasks.register<Exec>("cargoClippy") {
|
||||
workingDir("build/smithyprojections/codegen-server-test/")
|
||||
tasks.register<Exec>(Cargo.CLIPPY.toString) {
|
||||
workingDir("$buildDir/$workingDirUnderBuildDir")
|
||||
environment("RUSTFLAGS", defaultRustFlags)
|
||||
commandLine("cargo", "clippy")
|
||||
dependsOn("assemble")
|
||||
}
|
||||
|
||||
tasks["test"].finalizedBy("cargoCheck", "cargoClippy", "cargoTest", "cargoDocs")
|
||||
tasks["test"].finalizedBy(cargoCommands(properties).map { it.toString })
|
||||
|
||||
tasks["clean"].doFirst { delete("smithy-build.json") }
|
||||
|
|
|
@ -1,8 +1,42 @@
|
|||
# Codegen Integration Test
|
||||
This module defines an integration test of the code generation machinery. `.build.gradle.kts` will generate a `smithy-build.json` file as part of the build. The Smithy build plugin then invokes our codegen machinery and generates Rust crates.
|
||||
# Codegen Integration Tests
|
||||
|
||||
This module defines integration tests of the code generation machinery.
|
||||
`./build.gradle.kts` will generate a `smithy-build.json` file as part of the
|
||||
build. The `rust-codegen` Smithy build plugin then invokes our codegen
|
||||
machinery and generates Rust crates, one for each of the integration test
|
||||
services defined under `model/`.
|
||||
|
||||
The `test` task will run `cargo check` and `cargo clippy` to validate that the generated Rust compiles and is idiomatic.
|
||||
## Usage
|
||||
|
||||
These commands are all meant to be run from the repository root.
|
||||
|
||||
To run all protocol tests of all the integration test services:
|
||||
|
||||
```sh
|
||||
./gradlew codegen-test:build
|
||||
```
|
||||
../gradlew test
|
||||
|
||||
To run only a _subset_ of the integration test services (refer to
|
||||
`./build.gradle.kts` for a full list):
|
||||
|
||||
```sh
|
||||
./gradlew codegen-test:build -P modules='simple,rest_json'
|
||||
```
|
||||
|
||||
The Gradle task will run `cargo check`, `cargo test`, `cargo docs` and `cargo
|
||||
clippy` by default on all the generated Rust crates. You can also specify a
|
||||
subset of these commands. For instance, if you're working on documentation and
|
||||
want to check that the crates also compile, you can run:
|
||||
|
||||
```sh
|
||||
./gradlew codegen-test:build -P cargoCommands='check,docs'
|
||||
```
|
||||
|
||||
For fast development iteration cycles on protocol tests, we recommend you write
|
||||
a codegen _unit_ test with a minimal service definition and only run that unit
|
||||
test. Alternatively, you can write a minimal integration test service
|
||||
definition in `model/simple.smithy` and run:
|
||||
|
||||
```sh
|
||||
./gradlew codegen-test:build -P cargoCommands='test' -P modules='simple'
|
||||
```
|
||||
|
|
|
@ -15,6 +15,10 @@ plugins {
|
|||
val smithyVersion: String by project
|
||||
val defaultRustFlags: String by project
|
||||
val defaultRustDocFlags: String by project
|
||||
val properties = PropertyRetriever(rootProject, project)
|
||||
|
||||
val pluginName = "rust-codegen"
|
||||
val workingDirUnderBuildDir = "smithyprojections/codegen-test/"
|
||||
|
||||
buildscript {
|
||||
val smithyVersion: String by project
|
||||
|
@ -30,9 +34,7 @@ dependencies {
|
|||
implementation("software.amazon.smithy:smithy-aws-traits:$smithyVersion")
|
||||
}
|
||||
|
||||
data class CodegenTest(val service: String, val module: String, val extraConfig: String? = null)
|
||||
|
||||
val CodegenTests = listOf(
|
||||
val allCodegenTests = listOf(
|
||||
CodegenTest("com.amazonaws.simple#SimpleService", "simple"),
|
||||
CodegenTest("com.amazonaws.dynamodb#DynamoDB_20120810", "dynamo"),
|
||||
CodegenTest("com.amazonaws.ebs#Ebs", "ebs"),
|
||||
|
@ -84,88 +86,58 @@ val CodegenTests = listOf(
|
|||
)
|
||||
)
|
||||
|
||||
fun generateSmithyBuild(tests: List<CodegenTest>): String {
|
||||
val projections = tests.joinToString(",\n") {
|
||||
"""
|
||||
"${it.module}": {
|
||||
"plugins": {
|
||||
"rust-codegen": {
|
||||
"runtimeConfig": {
|
||||
"relativePath": "${rootProject.projectDir.absolutePath}/rust-runtime"
|
||||
},
|
||||
"service": "${it.service}",
|
||||
"module": "${it.module}",
|
||||
"moduleVersion": "0.0.1",
|
||||
"moduleDescription": "test",
|
||||
"moduleAuthors": ["protocoltest@example.com"]
|
||||
${it.extraConfig ?: ""}
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
return """
|
||||
{
|
||||
"version": "1.0",
|
||||
"projections": { $projections }
|
||||
}
|
||||
"""
|
||||
}
|
||||
|
||||
task("generateSmithyBuild") {
|
||||
description = "generate smithy-build.json"
|
||||
doFirst {
|
||||
projectDir.resolve("smithy-build.json").writeText(generateSmithyBuild(CodegenTests))
|
||||
projectDir.resolve("smithy-build.json")
|
||||
.writeText(generateSmithyBuild(
|
||||
rootProject.projectDir.absolutePath,
|
||||
pluginName,
|
||||
codegenTests(properties, allCodegenTests))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun generateCargoWorkspace(tests: List<CodegenTest>): String {
|
||||
return """
|
||||
[workspace]
|
||||
members = [
|
||||
${tests.joinToString(",") { "\"${it.module}/rust-codegen\"" }}
|
||||
]
|
||||
""".trimIndent()
|
||||
}
|
||||
task("generateCargoWorkspace") {
|
||||
description = "generate Cargo.toml workspace file"
|
||||
doFirst {
|
||||
buildDir.resolve("smithyprojections/codegen-test/Cargo.toml").writeText(generateCargoWorkspace(CodegenTests))
|
||||
buildDir.resolve("$workingDirUnderBuildDir/Cargo.toml")
|
||||
.writeText(generateCargoWorkspace(pluginName, codegenTests(properties, allCodegenTests)))
|
||||
}
|
||||
}
|
||||
|
||||
tasks["smithyBuildJar"].dependsOn("generateSmithyBuild")
|
||||
tasks["assemble"].finalizedBy("generateCargoWorkspace")
|
||||
|
||||
tasks.register<Exec>("cargoCheck") {
|
||||
workingDir("build/smithyprojections/codegen-test/")
|
||||
tasks.register<Exec>(Cargo.CHECK.toString) {
|
||||
workingDir("$buildDir/$workingDirUnderBuildDir")
|
||||
environment("RUSTFLAGS", defaultRustFlags)
|
||||
commandLine("cargo", "check")
|
||||
dependsOn("assemble")
|
||||
}
|
||||
|
||||
tasks.register<Exec>("cargoTest") {
|
||||
workingDir("build/smithyprojections/codegen-test/")
|
||||
tasks.register<Exec>(Cargo.TEST.toString) {
|
||||
workingDir("$buildDir/$workingDirUnderBuildDir")
|
||||
environment("RUSTFLAGS", defaultRustFlags)
|
||||
commandLine("cargo", "test")
|
||||
dependsOn("assemble")
|
||||
}
|
||||
|
||||
tasks.register<Exec>("cargoDocs") {
|
||||
workingDir("build/smithyprojections/codegen-test/")
|
||||
tasks.register<Exec>(Cargo.DOCS.toString) {
|
||||
workingDir("$buildDir/$workingDirUnderBuildDir")
|
||||
environment("RUSTDOCFLAGS", defaultRustDocFlags)
|
||||
commandLine("cargo", "doc", "--no-deps")
|
||||
dependsOn("assemble")
|
||||
}
|
||||
|
||||
tasks.register<Exec>("cargoClippy") {
|
||||
workingDir("build/smithyprojections/codegen-test/")
|
||||
tasks.register<Exec>(Cargo.CLIPPY.toString) {
|
||||
workingDir("$buildDir/$workingDirUnderBuildDir")
|
||||
environment("RUSTFLAGS", defaultRustFlags)
|
||||
commandLine("cargo", "clippy")
|
||||
dependsOn("assemble")
|
||||
}
|
||||
|
||||
tasks["test"].finalizedBy("cargoCheck", "cargoClippy", "cargoTest", "cargoDocs")
|
||||
tasks["test"].finalizedBy(cargoCommands(properties).map { it.toString })
|
||||
|
||||
tasks["clean"].doFirst {
|
||||
delete("smithy-build.json")
|
||||
|
|
Loading…
Reference in New Issue