Unverified Commit 0e90d650 authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

Fix KMS tests by fixing `Send` bound on fluent send method (#2695)

## Motivation and Context
This PR fixes the KMS tests when the generating code in orchestrator
mode by ensuring the `Future` returned by `send()` implements `Send`,
and also adds a codegen unit test for this so that it's checked at the
generic client level.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
parent 9b340fb8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ async fn sra_test() {
    conn.full_validate(MediaType::Xml).await.expect("failed")
}

#[derive(Debug)]
struct FixupPlugin {
    timestamp: SystemTime,
}
+1 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ class ServiceRuntimePluginGenerator(
    fun render(writer: RustWriter, customizations: List<ServiceRuntimePluginCustomization>) {
        writer.rustTemplate(
            """
            ##[derive(Debug)]
            pub(crate) struct ServiceRuntimePlugin {
                handle: std::sync::Arc<crate::client::Handle>,
            }
+2 −2
Original line number Diff line number Diff line
@@ -366,13 +366,13 @@ class FluentClientGenerator(
                    """
                    ##[doc(hidden)]
                    pub async fn send_orchestrator(self) -> std::result::Result<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> {
                        self.send_orchestrator_with_plugin(Option::<Box<dyn #{RuntimePlugin}>>::None).await
                        self.send_orchestrator_with_plugin(Option::<Box<dyn #{RuntimePlugin} + Send + Sync>>::None).await
                    }

                    ##[doc(hidden)]
                    // TODO(enableNewSmithyRuntime): Delete when unused
                    /// Equivalent to [`Self::send_orchestrator`] but adds a final runtime plugin to shim missing behavior
                    pub async fn send_orchestrator_with_plugin(self, final_plugin: Option<impl #{RuntimePlugin} + 'static>) -> std::result::Result<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> {
                    pub async fn send_orchestrator_with_plugin(self, final_plugin: Option<impl #{RuntimePlugin} + Send + Sync + 'static>) -> std::result::Result<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> {
                        let mut runtime_plugins = #{RuntimePlugins}::new()
                            .with_client_plugin(crate::config::ServiceRuntimePlugin::new(self.handle.clone()));
                        if let Some(config_override) = self.config_override {
+6 −16
Original line number Diff line number Diff line
@@ -6,26 +6,16 @@
package software.amazon.smithy.rust.codegen.client.smithy.customizations

import org.junit.jupiter.api.Test
import software.amazon.smithy.model.node.ObjectNode
import software.amazon.smithy.model.node.StringNode
import software.amazon.smithy.rust.codegen.client.testutil.TestCodegenSettings
import software.amazon.smithy.rust.codegen.client.testutil.clientIntegrationTest
import software.amazon.smithy.rust.codegen.core.rustlang.Attribute
import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.core.testutil.IntegrationTestParams
import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel
import software.amazon.smithy.rust.codegen.core.testutil.integrationTest

private fun additionalSettings(): ObjectNode = ObjectNode.objectNodeBuilder()
    .withMember(
        "codegen",
        ObjectNode.objectNodeBuilder()
            .withMember("enableNewSmithyRuntime", StringNode.from("orchestrator")).build(),
    )
    .build()

class HttpAuthDecoratorTest {
    private fun codegenScope(runtimeConfig: RuntimeConfig): Array<Pair<String, Any>> = arrayOf(
        "TestConnection" to CargoDependency.smithyClient(runtimeConfig)
@@ -38,7 +28,7 @@ class HttpAuthDecoratorTest {
    fun multipleAuthSchemesSchemeSelection() {
        clientIntegrationTest(
            TestModels.allSchemes,
            IntegrationTestParams(additionalSettings = additionalSettings()),
            TestCodegenSettings.orchestratorModeTestParams,
        ) { codegenContext, rustCrate ->
            rustCrate.integrationTest("tests") {
                val moduleName = codegenContext.moduleUseName()
@@ -117,7 +107,7 @@ class HttpAuthDecoratorTest {
    fun apiKeyInQueryString() {
        clientIntegrationTest(
            TestModels.apiKeyInQueryString,
            IntegrationTestParams(additionalSettings = additionalSettings()),
            TestCodegenSettings.orchestratorModeTestParams,
        ) { codegenContext, rustCrate ->
            rustCrate.integrationTest("api_key_applied_to_query_string") {
                val moduleName = codegenContext.moduleUseName()
@@ -162,7 +152,7 @@ class HttpAuthDecoratorTest {
    fun apiKeyInHeaders() {
        clientIntegrationTest(
            TestModels.apiKeyInHeaders,
            IntegrationTestParams(additionalSettings = additionalSettings()),
            TestCodegenSettings.orchestratorModeTestParams,
        ) { codegenContext, rustCrate ->
            rustCrate.integrationTest("api_key_applied_to_headers") {
                val moduleName = codegenContext.moduleUseName()
@@ -208,7 +198,7 @@ class HttpAuthDecoratorTest {
    fun basicAuth() {
        clientIntegrationTest(
            TestModels.basicAuth,
            IntegrationTestParams(additionalSettings = additionalSettings()),
            TestCodegenSettings.orchestratorModeTestParams,
        ) { codegenContext, rustCrate ->
            rustCrate.integrationTest("basic_auth") {
                val moduleName = codegenContext.moduleUseName()
@@ -254,7 +244,7 @@ class HttpAuthDecoratorTest {
    fun bearerAuth() {
        clientIntegrationTest(
            TestModels.bearerAuth,
            IntegrationTestParams(additionalSettings = additionalSettings()),
            TestCodegenSettings.orchestratorModeTestParams,
        ) { codegenContext, rustCrate ->
            rustCrate.integrationTest("bearer_auth") {
                val moduleName = codegenContext.moduleUseName()
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

package software.amazon.smithy.rust.codegen.client.smithy.generators.client

import org.junit.jupiter.api.Test
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
import software.amazon.smithy.rust.codegen.client.testutil.TestCodegenSettings
import software.amazon.smithy.rust.codegen.client.testutil.clientIntegrationTest
import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.core.rustlang.rust
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
import software.amazon.smithy.rust.codegen.core.rustlang.writable
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.core.smithy.RustCrate
import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel
import software.amazon.smithy.rust.codegen.core.testutil.integrationTest

class FluentClientGeneratorTest {
    val model = """
        namespace com.example
        use aws.protocols#awsJson1_0

        @awsJson1_0
        service HelloService {
            operations: [SayHello],
            version: "1"
        }

        operation SayHello { input: TestInput }
        structure TestInput {}
    """.asSmithyModel()

    @Test
    fun `send() future implements Send`() {
        val test: (ClientCodegenContext, RustCrate) -> Unit = { codegenContext, rustCrate ->
            rustCrate.integrationTest("send_future_is_send") {
                val moduleName = codegenContext.moduleUseName()
                rustTemplate(
                    """
                    fn check_send<T: Send>(_: T) {}

                    ##[test]
                    fn test() {
                        let connector = #{TestConnection}::<#{SdkBody}>::new(Vec::new());
                        let config = $moduleName::Config::builder()
                            .endpoint_resolver("http://localhost:1234")
                            #{set_http_connector}
                            .build();
                        let smithy_client = aws_smithy_client::Builder::new()
                            .connector(connector.clone())
                            .middleware_fn(|r| r)
                            .build_dyn();
                        let client = $moduleName::Client::with_config(smithy_client, config);
                        check_send(client.say_hello().send());
                    }
                    """,
                    "TestConnection" to CargoDependency.smithyClient(codegenContext.runtimeConfig)
                        .withFeature("test-util").toType()
                        .resolve("test_connection::TestConnection"),
                    "SdkBody" to RuntimeType.sdkBody(codegenContext.runtimeConfig),
                    "set_http_connector" to writable {
                        if (codegenContext.smithyRuntimeMode.generateOrchestrator) {
                            rust(".http_connector(connector.clone())")
                        }
                    },
                )
            }
        }
        clientIntegrationTest(model, TestCodegenSettings.middlewareModeTestParams, test = test)
        clientIntegrationTest(
            model,
            TestCodegenSettings.orchestratorModeTestParams,
            test = test,
        )
    }
}
Loading