codegen-core/- Shared codegencodegen-server/- Server codegencodegen-client/- Client codegenrust-runtime/- Runtime librariescodegen-server-test/- Server integration tests
Protocol files: codegen-{core,server}/.../protocols/
Protocol tests validate that generated code correctly implements Smithy protocols (like restJson1, awsJson1_1, etc.).
Protocol tests are defined in Smithy model files using @httpRequestTests and @httpResponseTests traits:
@http(uri: "/my-operation", method: "GET")
@httpRequestTests([
{
id: "MyOperationRequest",
documentation: "Test description",
protocol: "aws.protocols#restJson1",
method: "GET",
uri: "/my-operation",
queryParams: ["param1=value1", "param2=value2"],
params: {
queryMap: {
"param1": "value1",
"param2": "value2"
}
},
appliesTo: "client",
}
])
operation MyOperation {
input: MyOperationInput,
}codegen-core/common-test-models/rest-json-extras.smithy- restJson1 protocol testscodegen-core/common-test-models/constraints.smithy- Constraint validation tests with restJson1codegen-client-test/model/main.smithy- awsJson1_1 protocol tests
When investigating the @httpQueryParams bug (where query parameters weren't appearing in requests), the issue was in RequestBindingGenerator.kt line 173. The bug occurred when:
- An operation had ONLY
@httpQueryParams(no regular@httpQueryparameters) - The condition
if (dynamicParams.isEmpty() && literalParams.isEmpty() && mapParams.isEmpty())would skip generating theuri_queryfunction
The fix was to ensure mapParams.isEmpty() was included in the condition check. The current implementation correctly generates query parameters for @httpQueryParams even when no other query parameters exist.
Testing httpQueryParams: Create operations with only @httpQueryParams to ensure they generate proper query strings in requests.
Always use preludeScope for Rust prelude types:
rustTemplate(
"let result: #{Result}<#{String}, #{Error}> = #{Ok}(value);",
*preludeScope, // Provides Result, String, Ok
"Error" to myErrorType
)❌ Wrong: "let result: Result<String, Error> = Ok(value);"
✅ Correct: Use *preludeScope in templates
RuntimeType objects contain:
path: Rust path (e.g.,"::mime::Mime")dependency:CargoDependencyorInlineDependency
Using a RuntimeType automatically adds its dependency to Cargo.toml.
// Pre-defined dependencies
val Mime = CargoDependency.Mime.toType()
val Bytes = CargoDependency.Bytes.toType().resolve("Bytes")
// Runtime crates
val smithyTypes = RuntimeType.smithyTypes(runtimeConfig)❌ Wrong: rust("const MIME: ::mime::Mime = ::mime::APPLICATION_JSON;")
✅ Correct: rustTemplate("const MIME: #{Mime}::Mime = #{Mime}::APPLICATION_JSON;", "Mime" to RuntimeType.Mime)
Code is only generated if used. forInlineFun enables lazy generation:
val mimeType = RuntimeType.forInlineFun("APPLICATION_JSON", module) {
rustTemplate(
"pub const APPLICATION_JSON: #{Mime}::Mime = #{Mime}::APPLICATION_JSON;",
"Mime" to RuntimeType.Mime
)
}Test actual generated code, not just codegen logic:
serverIntegrationTest(model) { codegenContext, rustCrate ->
rustCrate.testModule {
tokioTest("test_accept_header") {
rustTemplate("""
let request = ::http::Request::builder()
.header("Accept", "application/cbor")
.body(Body::empty()).unwrap();
let result = MyInput::from_request(request).await;
result.expect("should accept valid header");
""")
}
}
}Codegen tests:
./gradlew test --tests "*MyTest*"
./gradlew codegen-server-test:assemble --quietDebug failing tests:
# Remove --quiet to see failure details
./gradlew :codegen-core:test --tests "*InlineDependencyTest*"
# Extract just the error from HTML report (avoid HTML markup pollution)
grep -A 5 "AssertionError\|Exception" codegen-core/build/reports/tests/test/classes/software.amazon.smithy.rust.codegen.core.rustlang.InlineDependencyTest.htmlRuntime tests:
cd rust-runtime && cargo test --quiet -p aws-smithy-typesProtocol tests:
./gradlew codegen-client-test:assemble --quiet
cd codegen-client-test/build/smithyprojections/codegen-client-test/rest_xml_extras/rust-client-codegen
cargo test --quietGenerated code appears in:
codegen-server-test/build/smithyprojections/codegen-server-test/SERVICE_NAME/rust-server-codegen/
Enable debug comments:
serverIntegrationTest(model, IntegrationTestParams(
additionalSettings = ServerAdditionalSettings.builder()
.generateCodegenComments() // Adds Kotlin source line comments
.toObjectNode()
)) { /* test code */ }