Skip to content

Commit

Permalink
Allow integration tests to run in both runtime modes (#2709)
Browse files Browse the repository at this point in the history
## Description
This will allow integration tests under `aws/sdk/integration-tests` to
run in both smithy runtime modes. Prior to the PR, the integration tests
use `map_operation` to customize operations, which is not supported in
the orchestrator, preventing us from running them in the orchestrator
mode. Fortunately, all the usages of `map_operation` in the integration
tests involve setting a test request time and a test user agent in a
property bag.

This PR stops using `map_operation` in those tests and instead
introduces separate test helper methods in both runtime modes: one for
setting a test request and the other for setting a test user agent. They
allow the integration tests to compile and run in both modes.

Note that the integration tests in the orchestrator do not necessarily
pass at this time. We'll address the failures subsequently.

## Testing
Confirmed integration tests continue passing with the changes when run
in the middleware . Confirmed those complied (but not necessarily
passed) in the orchestrator.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._

---------

Co-authored-by: Yuki Saito <[email protected]>
  • Loading branch information
ysaito1001 and ysaito1001 authored May 19, 2023
1 parent 3a9e64e commit 61b7a77
Show file tree
Hide file tree
Showing 18 changed files with 252 additions and 119 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rustsdk

import software.amazon.smithy.rust.codegen.client.smithy.generators.client.CustomizableOperationCustomization
import software.amazon.smithy.rust.codegen.client.smithy.generators.client.CustomizableOperationSection
import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
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.RuntimeConfig
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType

class CustomizableOperationTestHelpers(runtimeConfig: RuntimeConfig) :
CustomizableOperationCustomization() {
private val codegenScope = arrayOf(
*RuntimeType.preludeScope,
"AwsUserAgent" to AwsRuntimeType.awsHttp(runtimeConfig)
.resolve("user_agent::AwsUserAgent"),
"BeforeTransmitInterceptorContextMut" to RuntimeType.smithyRuntimeApi(runtimeConfig)
.resolve("client::interceptors::BeforeTransmitInterceptorContextMut"),
"ConfigBag" to RuntimeType.smithyRuntimeApi(runtimeConfig).resolve("config_bag::ConfigBag"),
"ConfigBagAccessors" to RuntimeType.smithyRuntimeApi(runtimeConfig).resolve("client::orchestrator::ConfigBagAccessors"),
"http" to CargoDependency.Http.toType(),
"InterceptorContext" to RuntimeType.smithyRuntimeApi(runtimeConfig)
.resolve("client::interceptors::InterceptorContext"),
"RequestTime" to RuntimeType.smithyRuntimeApi(runtimeConfig).resolve("client::orchestrator::RequestTime"),
"SharedInterceptor" to RuntimeType.smithyRuntimeApi(runtimeConfig)
.resolve("client::interceptors::SharedInterceptor"),
"TestParamsSetterInterceptor" to CargoDependency.smithyRuntime(runtimeConfig).withFeature("test-util")
.toType().resolve("client::test_util::interceptor::TestParamsSetterInterceptor"),
)

override fun section(section: CustomizableOperationSection): Writable =
writable {
if (section is CustomizableOperationSection.CustomizableOperationImpl) {
if (section.operationShape == null) {
// TODO(enableNewSmithyRuntime): Delete this branch when middleware is no longer used
// This branch customizes CustomizableOperation in the middleware. section.operationShape being
// null means that this customization is rendered in a place where we don't need to figure out
// the module for an operation (which is the case for CustomizableOperation in the middleware
// that is rendered in the customize module).
rustTemplate(
"""
##[doc(hidden)]
// This is a temporary method for testing. NEVER use it in production
pub fn request_time_for_tests(mut self, request_time: ::std::time::SystemTime) -> Self {
self.operation.properties_mut().insert(request_time);
self
}
##[doc(hidden)]
// This is a temporary method for testing. NEVER use it in production
pub fn user_agent_for_tests(mut self) -> Self {
self.operation.properties_mut().insert(#{AwsUserAgent}::for_tests());
self
}
""",
*codegenScope,
)
} else {
// The else branch is for rendering customization for the orchestrator.
rustTemplate(
"""
##[doc(hidden)]
// This is a temporary method for testing. NEVER use it in production
pub fn request_time_for_tests(mut self, request_time: ::std::time::SystemTime) -> Self {
use #{ConfigBagAccessors};
let interceptor = #{TestParamsSetterInterceptor}::new(move |_: &mut #{BeforeTransmitInterceptorContextMut}<'_>, cfg: &mut #{ConfigBag}| {
cfg.set_request_time(#{RequestTime}::new(request_time));
});
self.interceptors.push(#{SharedInterceptor}::new(interceptor));
self
}
##[doc(hidden)]
// This is a temporary method for testing. NEVER use it in production
pub fn user_agent_for_tests(mut self) -> Self {
let interceptor = #{TestParamsSetterInterceptor}::new(|context: &mut #{BeforeTransmitInterceptorContextMut}<'_>, _: &mut #{ConfigBag}| {
let headers = context.request_mut().headers_mut();
let user_agent = #{AwsUserAgent}::for_tests();
headers.insert(
#{http}::header::USER_AGENT,
#{http}::HeaderValue::try_from(user_agent.ua_header()).unwrap(),
);
headers.insert(
#{http}::HeaderName::from_static("x-amz-user-agent"),
#{http}::HeaderValue::try_from(user_agent.aws_ua_header()).unwrap(),
);
});
self.interceptors.push(#{SharedInterceptor}::new(interceptor));
self
}
""",
*codegenScope,
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class AwsFluentClientDecorator : ClientCodegenDecorator {
AwsFluentClientDocs(codegenContext),
),
retryClassifier = AwsRuntimeType.awsHttp(runtimeConfig).resolve("retry::AwsResponseRetryClassifier"),
).render(rustCrate)
).render(rustCrate, listOf(CustomizableOperationTestHelpers(runtimeConfig)))
rustCrate.withModule(ClientRustModule.Client.customize) {
renderCustomizableOperationSendMethod(runtimeConfig, generics, this)
}
Expand Down
26 changes: 5 additions & 21 deletions aws/sdk/integration-tests/s3/tests/checksums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

use aws_config::SdkConfig;
use aws_credential_types::provider::SharedCredentialsProvider;
use aws_http::user_agent::AwsUserAgent;
use aws_sdk_s3::config::{Credentials, Region};
use aws_sdk_s3::types::ChecksumMode;
use aws_sdk_s3::Client;
Expand All @@ -14,10 +13,7 @@ use aws_smithy_client::test_connection::{capture_request, TestConnection};
use aws_smithy_http::body::SdkBody;
use http::header::AUTHORIZATION;
use http::{HeaderValue, Uri};
use std::{
convert::Infallible,
time::{Duration, UNIX_EPOCH},
};
use std::time::{Duration, UNIX_EPOCH};
use tracing_test::traced_test;

/// Test connection for the movies IT
Expand Down Expand Up @@ -77,14 +73,8 @@ async fn test_checksum_on_streaming_response(
.customize()
.await
.unwrap()
.map_operation(|mut op| {
op.properties_mut()
.insert(UNIX_EPOCH + Duration::from_secs(1624036048));
op.properties_mut().insert(AwsUserAgent::for_tests());

Result::Ok::<_, Infallible>(op)
})
.unwrap()
.request_time_for_tests(UNIX_EPOCH + Duration::from_secs(1624036048))
.user_agent_for_tests()
.send()
.await
.unwrap();
Expand Down Expand Up @@ -191,14 +181,8 @@ async fn test_checksum_on_streaming_request<'a>(
.customize()
.await
.unwrap()
.map_operation(|mut op| {
op.properties_mut()
.insert(UNIX_EPOCH + Duration::from_secs(1624036048));
op.properties_mut().insert(AwsUserAgent::for_tests());

Result::Ok::<_, Infallible>(op)
})
.unwrap()
.request_time_for_tests(UNIX_EPOCH + Duration::from_secs(1624036048))
.user_agent_for_tests()
.send()
.await
.unwrap();
Expand Down
12 changes: 2 additions & 10 deletions aws/sdk/integration-tests/s3/tests/customizable-operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@

use aws_config::SdkConfig;
use aws_credential_types::provider::SharedCredentialsProvider;
use aws_http::user_agent::AwsUserAgent;
use aws_sdk_s3::config::{Credentials, Region};
use aws_sdk_s3::Client;
use aws_smithy_client::test_connection::capture_request;

use std::convert::Infallible;
use std::time::{Duration, UNIX_EPOCH};

#[tokio::test]
Expand All @@ -29,14 +27,8 @@ async fn test_s3_ops_are_customizable() {
.customize()
.await
.expect("list_buckets is customizable")
.map_operation(|mut op| {
op.properties_mut()
.insert(UNIX_EPOCH + Duration::from_secs(1624036048));
op.properties_mut().insert(AwsUserAgent::for_tests());

Result::<_, Infallible>::Ok(op)
})
.expect("inserting into the property bag is infallible");
.request_time_for_tests(UNIX_EPOCH + Duration::from_secs(1624036048))
.user_agent_for_tests();

// The response from the fake connection won't return the expected XML but we don't care about
// that error in this test
Expand Down
8 changes: 1 addition & 7 deletions aws/sdk/integration-tests/s3/tests/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use aws_sdk_s3::config::Builder;
use aws_sdk_s3::config::{Credentials, Region};
use aws_sdk_s3::Client;
use aws_smithy_client::test_connection::{capture_request, CaptureRequestReceiver};
use std::convert::Infallible;
use std::time::{Duration, UNIX_EPOCH};

fn test_client(update_builder: fn(Builder) -> Builder) -> (CaptureRequestReceiver, Client) {
Expand Down Expand Up @@ -90,12 +89,7 @@ async fn s3_object_lambda() {
.customize()
.await
.unwrap()
.map_operation(|mut op| {
op.properties_mut()
.insert(UNIX_EPOCH + Duration::from_secs(1234567890));
Result::<_, Infallible>::Ok(op)
})
.unwrap()
.request_time_for_tests(UNIX_EPOCH + Duration::from_secs(1234567890))
.send()
.await
.unwrap();
Expand Down
16 changes: 3 additions & 13 deletions aws/sdk/integration-tests/s3/tests/ignore-invalid-xml-body-root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@
*/

use aws_credential_types::provider::SharedCredentialsProvider;
use aws_http::user_agent::AwsUserAgent;
use aws_sdk_s3::{config::Credentials, config::Region, types::ObjectAttributes, Client};
use aws_smithy_client::test_connection::TestConnection;
use aws_smithy_http::body::SdkBody;
use aws_types::SdkConfig;
use http::header::AUTHORIZATION;
use std::{
convert::Infallible,
time::{Duration, UNIX_EPOCH},
};
use std::time::{Duration, UNIX_EPOCH};

const RESPONSE_BODY_XML: &[u8] = b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<GetObjectAttributesResponse xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Checksum><ChecksumSHA1>e1AsOh9IyGCa4hLN+2Od7jlnP14=</ChecksumSHA1></Checksum></GetObjectAttributesResponse>";

Expand Down Expand Up @@ -60,14 +56,8 @@ async fn ignore_invalid_xml_body_root() {
.customize()
.await
.unwrap()
.map_operation(|mut op| {
op.properties_mut()
.insert(UNIX_EPOCH + Duration::from_secs(1624036048));
op.properties_mut().insert(AwsUserAgent::for_tests());

Result::Ok::<_, Infallible>(op)
})
.unwrap()
.request_time_for_tests(UNIX_EPOCH + Duration::from_secs(1624036048))
.user_agent_for_tests()
.send()
.await
.unwrap();
Expand Down
16 changes: 3 additions & 13 deletions aws/sdk/integration-tests/s3/tests/naughty-string-metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@
*/

use aws_credential_types::provider::SharedCredentialsProvider;
use aws_http::user_agent::AwsUserAgent;
use aws_sdk_s3::{config::Credentials, config::Region, primitives::ByteStream, Client};
use aws_smithy_client::test_connection::capture_request;
use aws_types::SdkConfig;
use http::HeaderValue;
use std::{
convert::Infallible,
time::{Duration, UNIX_EPOCH},
};
use std::time::{Duration, UNIX_EPOCH};

const NAUGHTY_STRINGS: &str = include_str!("blns/blns.txt");

Expand Down Expand Up @@ -83,14 +79,8 @@ async fn test_s3_signer_with_naughty_string_metadata() {
.customize()
.await
.unwrap()
.map_operation(|mut op| {
op.properties_mut()
.insert(UNIX_EPOCH + Duration::from_secs(1624036048));
op.properties_mut().insert(AwsUserAgent::for_tests());

Result::Ok::<_, Infallible>(op)
})
.unwrap()
.request_time_for_tests(UNIX_EPOCH + Duration::from_secs(1624036048))
.user_agent_for_tests()
.send()
.await
.unwrap();
Expand Down
12 changes: 2 additions & 10 deletions aws/sdk/integration-tests/s3/tests/normalize-uri-path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@

use aws_config::SdkConfig;
use aws_credential_types::provider::SharedCredentialsProvider;
use aws_http::user_agent::AwsUserAgent;
use aws_sdk_s3::primitives::ByteStream;
use aws_sdk_s3::{config::Credentials, config::Region, Client};
use aws_smithy_client::test_connection::capture_request;
use std::convert::Infallible;
use std::time::{Duration, UNIX_EPOCH};

#[tokio::test]
Expand All @@ -33,14 +31,8 @@ async fn test_operation_should_not_normalize_uri_path() {
.customize()
.await
.unwrap()
.map_operation(|mut op| {
op.properties_mut()
.insert(UNIX_EPOCH + Duration::from_secs(1669257290));
op.properties_mut().insert(AwsUserAgent::for_tests());

Ok::<_, Infallible>(op)
})
.unwrap()
.request_time_for_tests(UNIX_EPOCH + Duration::from_secs(1669257290))
.user_agent_for_tests()
.send()
.await
.unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@

use aws_config::SdkConfig;
use aws_credential_types::provider::SharedCredentialsProvider;
use aws_http::user_agent::AwsUserAgent;
use aws_sdk_s3::config::{Credentials, Region};
use aws_sdk_s3::Client;
use aws_smithy_client::test_connection::capture_request;
use std::convert::Infallible;
use std::time::{Duration, UNIX_EPOCH};

#[tokio::test]
Expand All @@ -35,14 +33,8 @@ async fn test_s3_signer_query_string_with_all_valid_chars() {
.customize()
.await
.unwrap()
.map_operation(|mut op| {
op.properties_mut()
.insert(UNIX_EPOCH + Duration::from_secs(1624036048));
op.properties_mut().insert(AwsUserAgent::for_tests());

Result::Ok::<_, Infallible>(op)
})
.unwrap()
.request_time_for_tests(UNIX_EPOCH + Duration::from_secs(1624036048))
.user_agent_for_tests()
.send()
.await;

Expand Down
12 changes: 2 additions & 10 deletions aws/sdk/integration-tests/s3/tests/signing-it.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@

use aws_config::SdkConfig;
use aws_credential_types::provider::SharedCredentialsProvider;
use aws_http::user_agent::AwsUserAgent;
use aws_sdk_s3::config::{Credentials, Region};
use aws_sdk_s3::Client;
use aws_smithy_client::test_connection::TestConnection;
use aws_smithy_http::body::SdkBody;
use std::convert::Infallible;
use std::time::{Duration, UNIX_EPOCH};

#[tokio::test]
Expand All @@ -36,14 +34,8 @@ async fn test_signer() {
.customize()
.await
.unwrap()
.map_operation(|mut op| {
op.properties_mut()
.insert(UNIX_EPOCH + Duration::from_secs(1624036048));
op.properties_mut().insert(AwsUserAgent::for_tests());

Result::Ok::<_, Infallible>(op)
})
.unwrap()
.request_time_for_tests(UNIX_EPOCH + Duration::from_secs(1624036048))
.user_agent_for_tests()
.send()
.await;

Expand Down
Loading

0 comments on commit 61b7a77

Please sign in to comment.