mirror of https://github.com/smithy-lang/smithy-rs
Change `make_operation(..)` to be an async function (#797)
* Change `make_operation(..)` to be an async function As part of the work towards glacier customizations, calling `make_operation(..)` needs to be able to perform asyncrhonous operations like potentially reading the body. To enable this and other future requirements, we now always generate make_operation as an async function. * Add CR to changelog * Fix server tests
This commit is contained in:
parent
f77b00ce79
commit
d341c6eec7
|
@ -1,5 +1,7 @@
|
|||
vNext (Month Day, Year)
|
||||
=======================
|
||||
**Breaking Changes**
|
||||
- `<operation>.make_operation(&config)` is now an `async` function for all operations. Code should be updated to call `.await`. This will only impact users using the low-level API. (smithy-rs#797)
|
||||
|
||||
v0.27 (October 20th, 2021)
|
||||
==========================
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
vNext (Month Day, Year)
|
||||
=======================
|
||||
**Breaking Changes**
|
||||
- `<operation>.make_operation(&config)` is now an `async` function for all operations. Code should be updated to call `.await`. This will only impact users using the low-level API. (smithy-rs#797)
|
||||
|
||||
v0.0.22-alpha (October 20th, 2021)
|
||||
==================================
|
||||
|
|
|
@ -55,6 +55,7 @@ impl AssumeRoleProvider {
|
|||
.build()
|
||||
.expect("operation is valid")
|
||||
.make_operation(&config)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
let assume_role_creds = client_config
|
||||
.core_client
|
||||
|
|
|
@ -172,6 +172,7 @@ impl AssumeRoleProvider {
|
|||
.op
|
||||
.clone()
|
||||
.make_operation(&self.conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
|
||||
let assumed = self.sts.call(op).in_current_span().await;
|
||||
|
|
|
@ -247,6 +247,7 @@ async fn load_credentials(
|
|||
.build()
|
||||
.expect("valid operation")
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
let resp = client.call(operation).await.map_err(|sdk_error| {
|
||||
tracing::warn!(error = ?sdk_error, "sts returned an error assuming web identity role");
|
||||
|
|
|
@ -197,6 +197,7 @@ class AwsInputPresignedMethod(
|
|||
rustTemplate(
|
||||
"""
|
||||
let (mut request, _) = self.$makeOperationFn(config)
|
||||
.await
|
||||
.map_err(|err| #{SdkError}::ConstructionFailure(err.into()))?
|
||||
.into_request_response();
|
||||
""",
|
||||
|
|
|
@ -62,6 +62,7 @@ class IntegrationTestDependencies(
|
|||
addDependency(smithyClient)
|
||||
addDependency(SerdeJson)
|
||||
addDependency(Tokio)
|
||||
addDependency(FuturesUtil)
|
||||
}
|
||||
if (hasBenches) {
|
||||
addDependency(Criterion)
|
||||
|
@ -93,3 +94,4 @@ private val FuturesCore = CargoDependency("futures-core", CratesIo("0.3"), Depen
|
|||
private val Hound = CargoDependency("hound", CratesIo("3.4"), DependencyScope.Dev)
|
||||
private val SerdeJson = CargoDependency("serde_json", CratesIo("1"), features = emptySet(), scope = DependencyScope.Dev)
|
||||
private val Tokio = CargoDependency("tokio", CratesIo("1"), features = setOf("macros", "test-util"), scope = DependencyScope.Dev)
|
||||
private val FuturesUtil = CargoDependency("futures-util", CratesIo("0.3"), scope = DependencyScope.Dev)
|
||||
|
|
|
@ -8,7 +8,13 @@ package software.amazon.smithy.rustsdk
|
|||
import org.junit.jupiter.api.Test
|
||||
import software.amazon.smithy.model.node.ObjectNode
|
||||
import software.amazon.smithy.rust.codegen.rustlang.CargoDependency
|
||||
import software.amazon.smithy.rust.codegen.testutil.*
|
||||
import software.amazon.smithy.rust.codegen.testutil.TestWorkspace
|
||||
import software.amazon.smithy.rust.codegen.testutil.asSmithyModel
|
||||
import software.amazon.smithy.rust.codegen.testutil.compileAndTest
|
||||
import software.amazon.smithy.rust.codegen.testutil.stubConfigProject
|
||||
import software.amazon.smithy.rust.codegen.testutil.testCodegenContext
|
||||
import software.amazon.smithy.rust.codegen.testutil.unitTest
|
||||
import software.amazon.smithy.rust.codegen.testutil.validateConfigCustomizations
|
||||
import software.amazon.smithy.rust.codegen.util.lookup
|
||||
|
||||
internal class EndpointConfigCustomizationTest {
|
||||
|
|
|
@ -285,7 +285,7 @@ async fn main() -> Result<(), Error> {
|
|||
let raw_client = aws_hyper::Client::https();
|
||||
|
||||
raw_client
|
||||
.call(wait_for_ready_table(&table, client.conf()))
|
||||
.call(wait_for_ready_table(&table, client.conf()).await)
|
||||
.await
|
||||
.expect("table should become ready.");
|
||||
|
||||
|
@ -363,7 +363,7 @@ async fn main() -> Result<(), Error> {
|
|||
|
||||
/// Construct a `DescribeTable` request with a policy to retry every second until the table
|
||||
/// is ready
|
||||
fn wait_for_ready_table(
|
||||
async fn wait_for_ready_table(
|
||||
table_name: &str,
|
||||
conf: &Config,
|
||||
) -> Operation<DescribeTable, WaitForReadyTable<AwsErrorRetryPolicy>> {
|
||||
|
@ -372,6 +372,7 @@ fn wait_for_ready_table(
|
|||
.build()
|
||||
.expect("valid input")
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
let waiting_policy = WaitForReadyTable {
|
||||
inner: operation.retry_policy().clone(),
|
||||
|
|
|
@ -97,7 +97,7 @@ async fn main() -> Result<(), Error> {
|
|||
}
|
||||
|
||||
raw_client
|
||||
.call(wait_for_ready_table(&table.to_string(), client.conf()))
|
||||
.call(wait_for_ready_table(&table.to_string(), client.conf()).await)
|
||||
.await
|
||||
.expect("table should become ready");
|
||||
|
||||
|
@ -255,7 +255,7 @@ where
|
|||
|
||||
/// Construct a `DescribeTable` request with a policy to retry every second until the table
|
||||
/// is ready
|
||||
fn wait_for_ready_table(
|
||||
async fn wait_for_ready_table(
|
||||
table_name: &str,
|
||||
conf: &Config,
|
||||
) -> Operation<DescribeTable, WaitForReadyTable<AwsErrorRetryPolicy>> {
|
||||
|
@ -264,6 +264,7 @@ fn wait_for_ready_table(
|
|||
.build()
|
||||
.expect("valid input")
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
let waiting_policy = WaitForReadyTable {
|
||||
inner: operation.retry_policy().clone(),
|
||||
|
|
|
@ -7,6 +7,7 @@ use aws_sdk_dynamodb::input::PutItemInput;
|
|||
use aws_sdk_dynamodb::model::AttributeValue;
|
||||
use aws_sdk_dynamodb::Config;
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use futures_util::FutureExt;
|
||||
|
||||
macro_rules! attr_s {
|
||||
($str_val:expr) => {
|
||||
|
@ -36,6 +37,8 @@ macro_rules! attr_obj {
|
|||
fn do_bench(config: &Config, input: &PutItemInput) {
|
||||
let operation = input
|
||||
.make_operation(&config)
|
||||
.now_or_never()
|
||||
.unwrap()
|
||||
.expect("operation failed to build");
|
||||
let (http_request, _parts) = operation.into_request_response().0.into_parts();
|
||||
let body = http_request.body().bytes().unwrap();
|
||||
|
|
|
@ -148,7 +148,7 @@ where
|
|||
|
||||
/// Construct a `DescribeTable` request with a policy to retry every second until the table
|
||||
/// is ready
|
||||
fn wait_for_ready_table(
|
||||
async fn wait_for_ready_table(
|
||||
table_name: &str,
|
||||
conf: &Config,
|
||||
) -> Operation<DescribeTable, WaitForReadyTable<AwsErrorRetryPolicy>> {
|
||||
|
@ -157,6 +157,7 @@ fn wait_for_ready_table(
|
|||
.build()
|
||||
.unwrap()
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
let waiting_policy = WaitForReadyTable {
|
||||
inner: operation.retry_policy().clone(),
|
||||
|
@ -197,6 +198,7 @@ async fn movies_it() {
|
|||
.call(
|
||||
create_table(table_name)
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid request"),
|
||||
)
|
||||
.await
|
||||
|
@ -204,7 +206,7 @@ async fn movies_it() {
|
|||
|
||||
let waiter_start = tokio::time::Instant::now();
|
||||
client
|
||||
.call(wait_for_ready_table(table_name, &conf))
|
||||
.call(wait_for_ready_table(table_name, &conf).await)
|
||||
.await
|
||||
.expect("table should become ready");
|
||||
|
||||
|
@ -220,6 +222,7 @@ async fn movies_it() {
|
|||
.call(
|
||||
add_item(table_name, item.clone())
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid request"),
|
||||
)
|
||||
.await
|
||||
|
@ -229,6 +232,7 @@ async fn movies_it() {
|
|||
.call(
|
||||
movies_in_year(table_name, 2222)
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid request"),
|
||||
)
|
||||
.await
|
||||
|
@ -240,6 +244,7 @@ async fn movies_it() {
|
|||
.call(
|
||||
movies_in_year(table_name, 2013)
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid request"),
|
||||
)
|
||||
.await
|
||||
|
|
|
@ -7,13 +7,14 @@ use aws_endpoint::get_endpoint_resolver;
|
|||
use aws_sdk_iam::Region;
|
||||
use http::Uri;
|
||||
|
||||
#[test]
|
||||
fn correct_endpoint_resolver() {
|
||||
#[tokio::test]
|
||||
async fn correct_endpoint_resolver() {
|
||||
let conf = aws_sdk_iam::Config::builder().build();
|
||||
let operation = aws_sdk_iam::operation::ListRoles::builder()
|
||||
.build()
|
||||
.unwrap()
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
let props = operation.properties();
|
||||
let resolver = get_endpoint_resolver(&props).expect("operation should have endpoint resolver");
|
||||
|
|
|
@ -84,6 +84,7 @@ async fn generate_random() {
|
|||
.build()
|
||||
.unwrap()
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
op.properties_mut()
|
||||
.insert(UNIX_EPOCH + Duration::from_secs(1614952162));
|
||||
|
@ -126,6 +127,7 @@ async fn generate_random_malformed_response() {
|
|||
.build()
|
||||
.unwrap()
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
client.call(op).await.expect_err("response was malformed");
|
||||
}
|
||||
|
@ -171,6 +173,7 @@ async fn generate_random_keystore_not_found() {
|
|||
.build()
|
||||
.unwrap()
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
|
||||
op.properties_mut()
|
||||
|
|
|
@ -71,6 +71,7 @@ async fn create_alias_op() -> Parts<CreateAlias, AwsErrorRetryPolicy> {
|
|||
.build()
|
||||
.unwrap()
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid request")
|
||||
.into_request_response();
|
||||
parts
|
||||
|
|
|
@ -58,6 +58,7 @@ async fn signv4_use_correct_service_name() {
|
|||
.build()
|
||||
.unwrap()
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.expect("valid operation");
|
||||
// Fix the request time and user agent so the headers are stable
|
||||
op.properties_mut()
|
||||
|
|
|
@ -36,6 +36,7 @@ async fn test_signer() -> Result<(), aws_sdk_s3::Error> {
|
|||
.build()
|
||||
.unwrap()
|
||||
.make_operation(&conf)
|
||||
.await
|
||||
.unwrap();
|
||||
op.properties_mut()
|
||||
.insert(UNIX_EPOCH + Duration::from_secs(1624036048));
|
||||
|
|
|
@ -47,6 +47,7 @@ import software.amazon.smithy.rust.codegen.smithy.protocols.RestJson
|
|||
import software.amazon.smithy.rust.codegen.smithy.protocols.parse.JsonParserGenerator
|
||||
import software.amazon.smithy.rust.codegen.smithy.protocols.serialize.JsonSerializerGenerator
|
||||
import software.amazon.smithy.rust.codegen.smithy.transformers.errorMessageMember
|
||||
import software.amazon.smithy.rust.codegen.testutil.TokioTest
|
||||
import software.amazon.smithy.rust.codegen.util.dq
|
||||
import software.amazon.smithy.rust.codegen.util.expectTrait
|
||||
import software.amazon.smithy.rust.codegen.util.findMemberWithTrait
|
||||
|
@ -585,8 +586,8 @@ class RestJson1HttpDeserializerGenerator(
|
|||
}
|
||||
|
||||
private fun RustWriter.renderRequestDeserializerTestCase(testCase: HttpRequestTestCase, operationShape: OperationShape) {
|
||||
Attribute.Custom("test").render(this)
|
||||
rustBlock("fn ${testCase.id.toSnakeCase()}()") {
|
||||
TokioTest.render(this)
|
||||
rustBlock("async fn ${testCase.id.toSnakeCase()}()") {
|
||||
val inputShape = operationShape.inputShape(model)
|
||||
val deserFnName = "deser_${operationShape.id.name.toSnakeCase()}_request"
|
||||
val customToken =
|
||||
|
@ -599,7 +600,7 @@ class RestJson1HttpDeserializerGenerator(
|
|||
instantiator.render(this, inputShape, testCase.params)
|
||||
write(";")
|
||||
rust(
|
||||
"""let op = expected.make_operation(&config).expect("failed to build operation");"""
|
||||
"""let op = expected.make_operation(&config).await.expect("failed to build operation");"""
|
||||
)
|
||||
rust("let (request, parts) = op.into_request_response().0.into_parts();")
|
||||
rustTemplate(
|
||||
|
|
|
@ -270,13 +270,13 @@ class RustWriter private constructor(
|
|||
init {
|
||||
expressionStart = '#'
|
||||
if (filename.endsWith(".rs")) {
|
||||
require(namespace.startsWith("crate")) { "We can only write into files in the crate (got $namespace)" }
|
||||
require(namespace.startsWith("crate") || filename.startsWith("tests/")) { "We can only write into files in the crate (got $namespace)" }
|
||||
}
|
||||
putFormatter('T', formatter)
|
||||
putFormatter('D', RustDocLinker())
|
||||
}
|
||||
|
||||
fun module(): String? = if (filename.endsWith(".rs")) {
|
||||
fun module(): String? = if (filename.startsWith("src") && filename.endsWith(".rs")) {
|
||||
filename.removeSuffix(".rs").split('/').last()
|
||||
} else null
|
||||
|
||||
|
|
|
@ -84,6 +84,8 @@ open class CombinedCodegenDecorator(decorators: List<RustCodegenDecorator>) : Ru
|
|||
override val order: Byte
|
||||
get() = 0
|
||||
|
||||
fun withDecorator(decorator: RustCodegenDecorator) = CombinedCodegenDecorator(orderedDecorators + decorator)
|
||||
|
||||
override fun configCustomizations(
|
||||
codegenContext: CodegenContext,
|
||||
baseCustomizations: List<ConfigCustomization>
|
||||
|
@ -145,7 +147,7 @@ open class CombinedCodegenDecorator(decorators: List<RustCodegenDecorator>) : Ru
|
|||
|
||||
companion object {
|
||||
private val logger = Logger.getLogger("RustCodegenSPILoader")
|
||||
fun fromClasspath(context: PluginContext): RustCodegenDecorator {
|
||||
fun fromClasspath(context: PluginContext): CombinedCodegenDecorator {
|
||||
val decorators = ServiceLoader.load(
|
||||
RustCodegenDecorator::class.java,
|
||||
context.pluginClassLoader.orElse(RustCodegenDecorator::class.java.classLoader)
|
||||
|
|
|
@ -287,6 +287,7 @@ class FluentClientGenerator(
|
|||
{
|
||||
let input = self.inner.build().map_err(|err|#{sdk_err}::ConstructionFailure(err.into()))?;
|
||||
let op = input.make_operation(&self.handle.conf)
|
||||
.await
|
||||
.map_err(|err|#{sdk_err}::ConstructionFailure(err.into()))?;
|
||||
self.handle.client.call(op).await
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ open class MakeOperationGenerator(
|
|||
val mut = customizations.any { it.mutSelf() }
|
||||
val consumes = customizations.any { it.consumesSelf() } || takesOwnership
|
||||
val self = "self".letIf(mut) { "mut $it" }.letIf(!consumes) { "&$it" }
|
||||
val fnType = if (public) "pub fn" else "fn"
|
||||
val fnType = if (public) "pub async fn" else "async fn"
|
||||
|
||||
implBlockWriter.docs("Consumes the builder and constructs an Operation<#D>", outputSymbol)
|
||||
implBlockWriter.rust("##[allow(clippy::let_and_return)]") // For codegen simplicity, allow `let x = ...; x`
|
||||
|
|
|
@ -21,8 +21,6 @@ import software.amazon.smithy.protocoltests.traits.HttpResponseTestCase
|
|||
import software.amazon.smithy.protocoltests.traits.HttpResponseTestsTrait
|
||||
import software.amazon.smithy.rust.codegen.rustlang.Attribute
|
||||
import software.amazon.smithy.rust.codegen.rustlang.CargoDependency
|
||||
import software.amazon.smithy.rust.codegen.rustlang.CratesIo
|
||||
import software.amazon.smithy.rust.codegen.rustlang.DependencyScope
|
||||
import software.amazon.smithy.rust.codegen.rustlang.RustMetadata
|
||||
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
|
||||
import software.amazon.smithy.rust.codegen.rustlang.asType
|
||||
|
@ -35,6 +33,7 @@ import software.amazon.smithy.rust.codegen.smithy.CodegenContext
|
|||
import software.amazon.smithy.rust.codegen.smithy.RuntimeType
|
||||
import software.amazon.smithy.rust.codegen.smithy.generators.Instantiator
|
||||
import software.amazon.smithy.rust.codegen.smithy.generators.error.errorSymbol
|
||||
import software.amazon.smithy.rust.codegen.testutil.TokioTest
|
||||
import software.amazon.smithy.rust.codegen.util.dq
|
||||
import software.amazon.smithy.rust.codegen.util.findMemberWithTrait
|
||||
import software.amazon.smithy.rust.codegen.util.getTrait
|
||||
|
@ -144,14 +143,7 @@ class ProtocolTestGenerator(
|
|||
}
|
||||
testModuleWriter.write("Test ID: ${testCase.id}")
|
||||
testModuleWriter.setNewlinePrefix("")
|
||||
testModuleWriter.writeWithNoFormatting("#[tokio::test]")
|
||||
val Tokio = CargoDependency(
|
||||
"tokio",
|
||||
CratesIo("1"),
|
||||
features = setOf("macros", "test-util", "rt"),
|
||||
scope = DependencyScope.Dev
|
||||
)
|
||||
testModuleWriter.addDependency(Tokio)
|
||||
TokioTest.render(testModuleWriter)
|
||||
val action = when (testCase) {
|
||||
is HttpResponseTestCase -> Action.Response
|
||||
is HttpRequestTestCase -> Action.Request
|
||||
|
@ -186,7 +178,7 @@ class ProtocolTestGenerator(
|
|||
writeInline("let input =")
|
||||
instantiator.render(this, inputShape, httpRequestTestCase.params)
|
||||
|
||||
rust(""".make_operation(&config).expect("operation failed to build");""")
|
||||
rust(""".make_operation(&config).await.expect("operation failed to build");""")
|
||||
rust("let (http_request, parts) = input.into_request_response().0.into_parts();")
|
||||
with(httpRequestTestCase) {
|
||||
host.orNull()?.also { host ->
|
||||
|
|
|
@ -9,7 +9,12 @@ import software.amazon.smithy.model.Model
|
|||
import software.amazon.smithy.model.shapes.ServiceShape
|
||||
import software.amazon.smithy.model.shapes.ShapeId
|
||||
import software.amazon.smithy.model.shapes.StructureShape
|
||||
import software.amazon.smithy.rust.codegen.rustlang.Attribute
|
||||
import software.amazon.smithy.rust.codegen.rustlang.CargoDependency
|
||||
import software.amazon.smithy.rust.codegen.rustlang.CratesIo
|
||||
import software.amazon.smithy.rust.codegen.rustlang.DependencyScope
|
||||
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
|
||||
import software.amazon.smithy.rust.codegen.rustlang.asType
|
||||
import software.amazon.smithy.rust.codegen.smithy.CodegenConfig
|
||||
import software.amazon.smithy.rust.codegen.smithy.CodegenContext
|
||||
import software.amazon.smithy.rust.codegen.smithy.RuntimeConfig
|
||||
|
@ -96,3 +101,12 @@ fun StructureShape.renderWithModelBuilder(model: Model, symbolProvider: RustSymb
|
|||
modelBuilder.renderConvenienceMethod(this)
|
||||
}
|
||||
}
|
||||
|
||||
private val Tokio = CargoDependency(
|
||||
"tokio",
|
||||
CratesIo("1"),
|
||||
features = setOf("macros", "test-util", "rt"),
|
||||
scope = DependencyScope.Dev
|
||||
)
|
||||
|
||||
val TokioTest = Attribute.Custom("tokio::test", listOf(Tokio.asType()))
|
||||
|
|
|
@ -12,10 +12,14 @@ import software.amazon.smithy.model.traits.EndpointTrait
|
|||
import software.amazon.smithy.rust.codegen.rustlang.RustModule
|
||||
import software.amazon.smithy.rust.codegen.rustlang.rust
|
||||
import software.amazon.smithy.rust.codegen.rustlang.rustBlock
|
||||
import software.amazon.smithy.rust.codegen.smithy.CodegenContext
|
||||
import software.amazon.smithy.rust.codegen.smithy.CodegenVisitor
|
||||
import software.amazon.smithy.rust.codegen.smithy.RustCrate
|
||||
import software.amazon.smithy.rust.codegen.smithy.customize.CombinedCodegenDecorator
|
||||
import software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator
|
||||
import software.amazon.smithy.rust.codegen.testutil.TestRuntimeConfig
|
||||
import software.amazon.smithy.rust.codegen.testutil.TestWorkspace
|
||||
import software.amazon.smithy.rust.codegen.testutil.TokioTest
|
||||
import software.amazon.smithy.rust.codegen.testutil.asSmithyModel
|
||||
import software.amazon.smithy.rust.codegen.testutil.compileAndTest
|
||||
import software.amazon.smithy.rust.codegen.testutil.generatePluginContext
|
||||
|
@ -24,8 +28,6 @@ import software.amazon.smithy.rust.codegen.testutil.unitTest
|
|||
import software.amazon.smithy.rust.codegen.util.lookup
|
||||
import software.amazon.smithy.rust.codegen.util.runCommand
|
||||
import kotlin.io.path.ExperimentalPathApi
|
||||
import kotlin.io.path.createDirectory
|
||||
import kotlin.io.path.writeText
|
||||
|
||||
internal class EndpointTraitBindingsTest {
|
||||
@Test
|
||||
|
@ -135,30 +137,37 @@ internal class EndpointTraitBindingsTest {
|
|||
}
|
||||
""".asSmithyModel()
|
||||
val (ctx, testDir) = generatePluginContext(model)
|
||||
val visitor = CodegenVisitor(ctx, CombinedCodegenDecorator.fromClasspath(ctx))
|
||||
val moduleName = ctx.settings.expectStringMember("module").value.replace('-', '_')
|
||||
visitor.execute()
|
||||
testDir.resolve("tests").createDirectory()
|
||||
testDir.resolve("tests/validate_errors.rs").writeText(
|
||||
"""
|
||||
#[test]
|
||||
fn test_endpoint_prefix() {
|
||||
let conf = $moduleName::Config::builder().build();
|
||||
$moduleName::operation::SayHello::builder()
|
||||
.greeting("hey there!").build().expect("input is valid")
|
||||
.make_operation(&conf).expect_err("no spaces or exclamation points in ep prefixes");
|
||||
let op = $moduleName::operation::SayHello::builder()
|
||||
.greeting("hello")
|
||||
.build().expect("valid operation")
|
||||
.make_operation(&conf).expect("hello is a valid prefix");
|
||||
let properties = op.properties();
|
||||
let prefix = properties.get::<aws_smithy_http::endpoint::EndpointPrefix>()
|
||||
.expect("prefix should be in config")
|
||||
.as_str();
|
||||
assert_eq!(prefix, "test123.hello.");
|
||||
val testWriter = object : RustCodegenDecorator {
|
||||
override val name: String = "add tests"
|
||||
override val order: Byte = 0
|
||||
override fun extras(codegenContext: CodegenContext, rustCrate: RustCrate) {
|
||||
rustCrate.withFile("tests/validate_errors.rs") {
|
||||
TokioTest.render(it)
|
||||
it.rust(
|
||||
"""
|
||||
async fn test_endpoint_prefix() {
|
||||
let conf = $moduleName::Config::builder().build();
|
||||
$moduleName::operation::SayHello::builder()
|
||||
.greeting("hey there!").build().expect("input is valid")
|
||||
.make_operation(&conf).await.expect_err("no spaces or exclamation points in ep prefixes");
|
||||
let op = $moduleName::operation::SayHello::builder()
|
||||
.greeting("hello")
|
||||
.build().expect("valid operation")
|
||||
.make_operation(&conf).await.expect("hello is a valid prefix");
|
||||
let properties = op.properties();
|
||||
let prefix = properties.get::<aws_smithy_http::endpoint::EndpointPrefix>()
|
||||
.expect("prefix should be in config")
|
||||
.as_str();
|
||||
assert_eq!(prefix, "test123.hello.");
|
||||
}
|
||||
"""
|
||||
)
|
||||
}
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
val visitor = CodegenVisitor(ctx, CombinedCodegenDecorator.fromClasspath(ctx).withDecorator(testWriter))
|
||||
visitor.execute()
|
||||
"cargo test".runCommand(testDir)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue