AWS SDK

AWS SDK

rev. c4f9295a7b4566dca79c361e3a2aa9e63cdf82e7

Files changed:

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/external-types.toml

@@ -1,1 +29,34 @@
   16     16   
    "http::response::Response",
   17     17   
    "http::uri::Uri",
   18     18   
   19     19   
   20     20   
   21     21   
    # TODO(https://github.com/smithy-lang/smithy-rs/issues/1193): Once tooling permits it, only allow the following types in the `connector-hyper-0-14-x` feature
   22     22   
    "hyper::client::client::Builder",
   23     23   
    "hyper::client::connect::Connection",
   24     24   
    "tokio::io::async_read::AsyncRead",
   25     25   
    "tokio::io::async_write::AsyncWrite",
          26  +
    "aws_smithy_http_client::hyper_014",
          27  +
    "aws_smithy_http_client::test_util::*",
          28  +
    "aws_smithy_http_client::ev",
          29  +
    "aws_smithy_http_client::match_events",
          30  +
    "aws_smithy_http_client::matcher",
   26     31   
   27     32   
    # TODO(https://github.com/smithy-lang/smithy-rs/issues/1193): Once tooling permits it, only allow the following types in the `http-0-x` feature
   28     33   
    "http_body::Body"
   29     34   
]

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client.rs

@@ -6,6 +55,55 @@
   26     26   
   27     27   
/// Smithy code related to retry handling and token buckets.
   28     28   
///
   29     29   
/// This code defines when and how failed requests should be retried. It also defines the behavior
   30     30   
/// used to limit the rate at which requests are sent.
   31     31   
pub mod retries;
   32     32   
   33     33   
/// Utilities for testing orchestrators. An orchestrator missing required components will panic when
   34     34   
/// run. This module contains stub components that can be used when you only care about testing some
   35     35   
/// specific aspect of the orchestrator.
   36         -
#[cfg(feature = "test-util")]
          36  +
#[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
   37     37   
pub mod test_util;
   38     38   
   39     39   
mod timeout;
   40     40   
   41     41   
/// Smithy identity used by auth and signing.
   42     42   
pub mod identity;
   43     43   
   44     44   
/// Interceptors for Smithy clients.
   45     45   
pub mod interceptors;
   46     46   

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/defaults.rs

@@ -25,25 +88,127 @@
   45     45   
fn layer<LayerFn>(name: &'static str, layer_fn: LayerFn) -> FrozenLayer
   46     46   
where
   47     47   
    LayerFn: FnOnce(&mut Layer),
   48     48   
{
   49     49   
    let mut layer = Layer::new(name);
   50     50   
    (layer_fn)(&mut layer);
   51     51   
    layer.freeze()
   52     52   
}
   53     53   
   54     54   
/// Runtime plugin that provides a default connector.
          55  +
#[deprecated(
          56  +
    since = "1.8.0",
          57  +
    note = "This function wasn't intended to be public, and didn't take the behavior major version as an argument, so it couldn't be evolved over time."
          58  +
)]
   55     59   
pub fn default_http_client_plugin() -> Option<SharedRuntimePlugin> {
   56         -
    let _default: Option<SharedHttpClient> = None;
   57         -
    #[cfg(feature = "connector-hyper-0-14-x")]
   58         -
    let _default = crate::client::http::hyper_014::default_client();
          60  +
    #[allow(deprecated)]
          61  +
    default_http_client_plugin_v2(BehaviorVersion::v2024_03_28())
          62  +
}
          63  +
          64  +
/// Runtime plugin that provides a default HTTPS connector.
          65  +
pub fn default_http_client_plugin_v2(
          66  +
    behavior_version: BehaviorVersion,
          67  +
) -> Option<SharedRuntimePlugin> {
          68  +
    let mut _default: Option<SharedHttpClient> = None;
          69  +
          70  +
    if behavior_version.is_at_least(BehaviorVersion::v2025_01_17()) {
          71  +
        // the latest https stack takes precedence if the config flag
          72  +
        // is enabled otherwise try to fall back to the legacy connector
          73  +
        // if that feature flag is available.
          74  +
        #[cfg(all(
          75  +
            feature = "connector-hyper-0-14-x",
          76  +
            not(feature = "default-https-client")
          77  +
        ))]
          78  +
        #[allow(deprecated)]
          79  +
        {
          80  +
            _default = crate::client::http::hyper_014::default_client();
          81  +
        }
          82  +
          83  +
        // takes precedence over legacy connector if enabled
          84  +
        #[cfg(feature = "default-https-client")]
          85  +
        {
          86  +
            let opts = crate::client::http::DefaultClientOptions::default()
          87  +
                .with_behavior_version(behavior_version);
          88  +
            _default = crate::client::http::default_https_client(opts);
          89  +
        }
          90  +
    } else {
          91  +
        // fallback to legacy hyper client for given behavior version
          92  +
        #[cfg(feature = "connector-hyper-0-14-x")]
          93  +
        #[allow(deprecated)]
          94  +
        {
          95  +
            _default = crate::client::http::hyper_014::default_client();
          96  +
        }
          97  +
    }
   59     98   
   60     99   
    _default.map(|default| {
   61    100   
        default_plugin("default_http_client_plugin", |components| {
   62    101   
            components.with_http_client(Some(default))
   63    102   
        })
   64    103   
        .into_shared()
   65    104   
    })
   66    105   
}
   67    106   
   68    107   
/// Runtime plugin that provides a default async sleep implementation.
@@ -171,210 +230,270 @@
  191    230   
            |components| {
  192    231   
                components.with_config_validator(SharedConfigValidator::base_client_config_fn(
  193    232   
                    validate_stalled_stream_protection_config,
  194    233   
                ))
  195    234   
            },
  196    235   
        )
  197    236   
        .with_config(layer("default_stalled_stream_protection_config", |layer| {
  198    237   
            let mut config =
  199    238   
                StalledStreamProtectionConfig::enabled().grace_period(Duration::from_secs(5));
  200    239   
            // Before v2024_03_28, upload streams did not have stalled stream protection by default
         240  +
            #[allow(deprecated)]
  201    241   
            if !behavior_version.is_at_least(BehaviorVersion::v2024_03_28()) {
  202    242   
                config = config.upload_enabled(false);
  203    243   
            }
  204    244   
            layer.store_put(config.build());
  205    245   
        }))
  206    246   
        .into_shared(),
  207    247   
    )
  208    248   
}
  209    249   
  210    250   
fn enforce_content_length_runtime_plugin() -> Option<SharedRuntimePlugin> {
@@ -250,290 +310,350 @@
  270    310   
  271    311   
/// All default plugins.
  272    312   
pub fn default_plugins(
  273    313   
    params: DefaultPluginParams,
  274    314   
) -> impl IntoIterator<Item = SharedRuntimePlugin> {
  275    315   
    let behavior_version = params
  276    316   
        .behavior_version
  277    317   
        .unwrap_or_else(BehaviorVersion::latest);
  278    318   
  279    319   
    [
  280         -
        default_http_client_plugin(),
         320  +
        default_http_client_plugin_v2(behavior_version),
  281    321   
        default_identity_cache_plugin(),
  282    322   
        default_retry_config_plugin(
  283    323   
            params
  284    324   
                .retry_partition_name
  285    325   
                .expect("retry_partition_name is required"),
  286    326   
        ),
  287    327   
        default_sleep_impl_plugin(),
  288    328   
        default_time_source_plugin(),
  289    329   
        default_timeout_config_plugin(),
  290    330   
        enforce_content_length_runtime_plugin(),

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/endpoint.rs

@@ -1,1 +45,49 @@
    6      6   
//! Code for applying endpoints to a request.
    7      7   
    8      8   
use aws_smithy_runtime_api::client::endpoint::{error::InvalidEndpointError, EndpointPrefix};
    9      9   
use std::borrow::Cow;
   10     10   
use std::result::Result as StdResult;
   11     11   
use std::str::FromStr;
   12     12   
   13     13   
/// Apply `endpoint` to `uri`
   14     14   
///
   15     15   
/// This method mutates `uri` by setting the `endpoint` on it
          16  +
#[deprecated(
          17  +
    since = "1.8.0",
          18  +
    note = "Depends on pre 1.x http types. May be removed or feature gated in a future minor version."
          19  +
)]
   16     20   
pub fn apply_endpoint(
   17     21   
    uri: &mut http_02x::Uri,
   18     22   
    endpoint: &http_02x::Uri,
   19     23   
    prefix: Option<&EndpointPrefix>,
   20     24   
) -> StdResult<(), InvalidEndpointError> {
   21     25   
    let prefix = prefix.map(EndpointPrefix::as_str).unwrap_or("");
   22     26   
    let authority = endpoint
   23     27   
        .authority()
   24     28   
        .as_ref()
   25     29   
        .map(|auth| auth.as_str())

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/http.rs

@@ -1,1 +0,95 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
           5  +
use aws_smithy_runtime_api::client::behavior_version::BehaviorVersion;
           6  +
#[cfg(feature = "default-https-client")]
           7  +
use aws_smithy_runtime_api::client::http::SharedHttpClient;
    5      8   
    6      9   
/// Interceptor for connection poisoning.
    7     10   
pub mod connection_poisoning;
    8     11   
          12  +
#[deprecated = "Direct HTTP test utility support from `aws-smithy-runtime` crate is deprecated. Please use the `test-util` feature from `aws-smithy-http-client` instead"]
    9     13   
#[cfg(feature = "test-util")]
   10         -
pub mod test_util;
          14  +
pub mod test_util {
          15  +
    #![allow(missing_docs)]
          16  +
          17  +
    pub use aws_smithy_http_client::test_util::{
          18  +
        legacy_capture_request as capture_request, CaptureRequestHandler, CaptureRequestReceiver,
          19  +
    };
          20  +
          21  +
    #[cfg(feature = "connector-hyper-0-14-x")]
          22  +
    pub mod dvr {
          23  +
        pub use aws_smithy_http_client::test_util::dvr::*;
          24  +
    }
          25  +
          26  +
    pub use aws_smithy_http_client::test_util::{ReplayEvent, StaticReplayClient};
          27  +
          28  +
    pub use aws_smithy_http_client::test_util::legacy_infallible::infallible_client_fn;
          29  +
          30  +
    pub use aws_smithy_http_client::test_util::NeverClient;
          31  +
          32  +
    #[cfg(feature = "connector-hyper-0-14-x")]
          33  +
    pub use aws_smithy_http_client::test_util::NeverTcpConnector;
          34  +
          35  +
    #[cfg(all(feature = "connector-hyper-0-14-x", feature = "wire-mock"))]
          36  +
    #[macro_use]
          37  +
    pub mod wire {
          38  +
        pub use aws_smithy_http_client::test_util::wire::ev;
          39  +
        pub use aws_smithy_http_client::test_util::wire::match_events;
          40  +
        pub use aws_smithy_http_client::test_util::wire::matcher;
          41  +
        pub use aws_smithy_http_client::test_util::wire::*;
          42  +
    }
          43  +
}
   11     44   
   12     45   
/// Default HTTP and TLS connectors that use hyper 0.14.x and rustls.
   13     46   
///
   14     47   
/// This module is named after the hyper version number since we anticipate
   15     48   
/// needing to provide equivalent functionality for hyper 1.x in the future.
   16     49   
#[cfg(feature = "connector-hyper-0-14-x")]
   17         -
pub mod hyper_014;
          50  +
#[deprecated = "hyper 0.14.x connector is deprecated, please use the `aws-smithy-http-client` crate directly instead."]
          51  +
pub mod hyper_014 {
          52  +
    #[allow(deprecated)]
          53  +
    pub use aws_smithy_http_client::hyper_014::*;
          54  +
}
   18     55   
   19     56   
/// HTTP body and body-wrapper types
   20     57   
pub mod body;
          58  +
          59  +
// NOTE: We created default client options to evolve defaults over time (e.g. allow passing a different DNS resolver)
          60  +
/// Configuration options for the default HTTPS client
          61  +
#[derive(Debug, Clone)]
          62  +
pub(crate) struct DefaultClientOptions {
          63  +
    _behavior_version: BehaviorVersion,
          64  +
}
          65  +
          66  +
impl Default for DefaultClientOptions {
          67  +
    fn default() -> Self {
          68  +
        DefaultClientOptions {
          69  +
            _behavior_version: BehaviorVersion::latest(),
          70  +
        }
          71  +
    }
          72  +
}
          73  +
          74  +
impl DefaultClientOptions {
          75  +
    /// Set the behavior version to use
          76  +
    #[allow(unused)]
          77  +
    pub(crate) fn with_behavior_version(mut self, behavior_version: BehaviorVersion) -> Self {
          78  +
        self._behavior_version = behavior_version;
          79  +
        self
          80  +
    }
          81  +
}
          82  +
          83  +
/// Creates an HTTPS client using the default TLS provider
          84  +
#[cfg(feature = "default-https-client")]
          85  +
pub(crate) fn default_https_client(_options: DefaultClientOptions) -> Option<SharedHttpClient> {
          86  +
    use aws_smithy_http_client::{tls, Builder};
          87  +
    tracing::trace!("creating a new default hyper 1.x client using rustls<aws-lc>");
          88  +
    Some(
          89  +
        Builder::new()
          90  +
            .tls_provider(tls::Provider::Rustls(
          91  +
                tls::rustls_provider::CryptoMode::AwsLc,
          92  +
            ))
          93  +
            .build_https(),
          94  +
    )
          95  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/http/body/content_length_enforcement.rs

@@ -179,179 +239,239 @@
  199    199   
        &self,
  200    200   
        _current_components: &RuntimeComponentsBuilder,
  201    201   
    ) -> Cow<'_, RuntimeComponentsBuilder> {
  202    202   
        Cow::Owned(
  203    203   
            RuntimeComponentsBuilder::new("EnforceContentLength")
  204    204   
                .with_interceptor(EnforceContentLengthInterceptor {}),
  205    205   
        )
  206    206   
    }
  207    207   
}
  208    208   
  209         -
#[cfg(all(feature = "test-util", test))]
         209  +
#[cfg(all(test, any(feature = "test-util", feature = "legacy-test-util")))]
  210    210   
mod test {
  211    211   
    use crate::assert_str_contains;
  212    212   
    use crate::client::http::body::content_length_enforcement::{
  213    213   
        extract_content_length, ContentLengthEnforcingBody,
  214    214   
    };
  215    215   
    use aws_smithy_runtime_api::http::Response;
  216    216   
    use aws_smithy_types::body::SdkBody;
  217    217   
    use aws_smithy_types::byte_stream::ByteStream;
  218    218   
    use aws_smithy_types::error::display::DisplayErrorContext;
  219    219   
    use bytes::Bytes;

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/http/connection_poisoning.rs

@@ -1,1 +50,50 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
use crate::client::retries::classifiers::run_classifiers_on_ctx;
    7      7   
use aws_smithy_runtime_api::box_error::BoxError;
    8         -
use aws_smithy_runtime_api::client::connection::ConnectionMetadata;
    9      8   
use aws_smithy_runtime_api::client::interceptors::context::{
   10      9   
    AfterDeserializationInterceptorContextRef, BeforeTransmitInterceptorContextMut,
   11     10   
};
   12     11   
use aws_smithy_runtime_api::client::interceptors::Intercept;
   13     12   
use aws_smithy_runtime_api::client::retries::classifiers::RetryAction;
   14     13   
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
   15         -
use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreReplace};
          14  +
use aws_smithy_types::config_bag::ConfigBag;
   16     15   
use aws_smithy_types::retry::{ReconnectMode, RetryConfig};
   17         -
use std::fmt;
   18         -
use std::sync::{Arc, Mutex};
   19     16   
use tracing::{debug, error};
   20     17   
          18  +
// re-export relocated struct that used to live here
          19  +
pub use aws_smithy_runtime_api::client::connection::CaptureSmithyConnection;
          20  +
   21     21   
/// An interceptor for poisoning connections in response to certain events.
   22     22   
///
   23     23   
/// This interceptor, when paired with a compatible connection, allows the connection to be
   24     24   
/// poisoned in reaction to certain events *(like receiving a transient error.)* This allows users
   25     25   
/// to avoid sending requests to a server that isn't responding. This can increase the load on a
   26     26   
/// server, because more connections will be made overall.
   27     27   
///
   28     28   
/// **In order for this interceptor to work,** the configured connection must interact with the
   29     29   
/// "connection retriever" stored in an HTTP request's `extensions` map. For an example of this,
   30     30   
/// see [`HyperConnector`]. When a connection is made available to the retriever, this interceptor
@@ -69,69 +168,0 @@
   89     89   
            } else {
   90     90   
                error!(
   91     91   
                    "unable to mark the connection for closure because no connection was found! The underlying HTTP connector never set a connection."
   92     92   
                );
   93     93   
            }
   94     94   
        }
   95     95   
   96     96   
        Ok(())
   97     97   
    }
   98     98   
}
   99         -
  100         -
type LoaderFn = dyn Fn() -> Option<ConnectionMetadata> + Send + Sync;
  101         -
  102         -
/// State for a middleware that will monitor and manage connections.
  103         -
#[derive(Clone, Default)]
  104         -
pub struct CaptureSmithyConnection {
  105         -
    loader: Arc<Mutex<Option<Box<LoaderFn>>>>,
  106         -
}
  107         -
  108         -
impl CaptureSmithyConnection {
  109         -
    /// Create a new connection monitor.
  110         -
    pub fn new() -> Self {
  111         -
        Self {
  112         -
            loader: Default::default(),
  113         -
        }
  114         -
    }
  115         -
  116         -
    /// Set the retriever that will capture the `hyper` connection.
  117         -
    pub fn set_connection_retriever<F>(&self, f: F)
  118         -
    where
  119         -
        F: Fn() -> Option<ConnectionMetadata> + Send + Sync + 'static,
  120         -
    {
  121         -
        *self.loader.lock().unwrap() = Some(Box::new(f));
  122         -
    }
  123         -
  124         -
    /// Get the associated connection metadata.
  125         -
    pub fn get(&self) -> Option<ConnectionMetadata> {
  126         -
        match self.loader.lock().unwrap().as_ref() {
  127         -
            Some(loader) => loader(),
  128         -
            None => {
  129         -
                tracing::debug!("no loader was set on the CaptureSmithyConnection");
  130         -
                None
  131         -
            }
  132         -
        }
  133         -
    }
  134         -
}
  135         -
  136         -
impl fmt::Debug for CaptureSmithyConnection {
  137         -
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  138         -
        write!(f, "CaptureSmithyConnection")
  139         -
    }
  140         -
}
  141         -
  142         -
impl Storable for CaptureSmithyConnection {
  143         -
    type Storer = StoreReplace<Self>;
  144         -
}
  145         -
  146         -
#[cfg(test)]
  147         -
mod test {
  148         -
    use super::*;
  149         -
  150         -
    #[test]
  151         -
    #[allow(clippy::redundant_clone)]
  152         -
    fn retrieve_connection_metadata() {
  153         -
        let retriever = CaptureSmithyConnection::new();
  154         -
        let retriever_clone = retriever.clone();
  155         -
        assert!(retriever.get().is_none());
  156         -
        retriever.set_connection_retriever(|| {
  157         -
            Some(
  158         -
                ConnectionMetadata::builder()
  159         -
                    .proxied(true)
  160         -
                    .poison_fn(|| {})
  161         -
                    .build(),
  162         -
            )
  163         -
        });
  164         -
  165         -
        assert!(retriever.get().is_some());
  166         -
        assert!(retriever_clone.get().is_some());
  167         -
    }
  168         -
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/orchestrator.rs

@@ -352,352 +412,412 @@
  372    372   
    }
  373    373   
  374    374   
    // The connection consumes the request but we need to keep a copy of it
  375    375   
    // within the interceptor context, so we clone it here.
  376    376   
    ctx.enter_transmit_phase();
  377    377   
    let response = halt_on_err!([ctx] => {
  378    378   
        let request = ctx.take_request().expect("set during serialization");
  379    379   
        trace!(request = ?request, "transmitting request");
  380    380   
        let http_client = halt_on_err!([ctx] => runtime_components.http_client().ok_or_else(||
  381    381   
            OrchestratorError::other("No HTTP client was available to send this request. \
  382         -
                Enable the `rustls` crate feature or configure a HTTP client to fix this.")
         382  +
                Enable the `default-https-client` crate feature or configure an HTTP client to fix this.")
  383    383   
        ));
  384    384   
        let timeout_config = cfg.load::<TimeoutConfig>().expect("timeout config must be set");
  385    385   
        let settings = {
  386    386   
            let mut builder = HttpConnectorSettings::builder();
  387    387   
            builder.set_connect_timeout(timeout_config.connect_timeout());
  388    388   
            builder.set_read_timeout(timeout_config.read_timeout());
  389    389   
            builder.build()
  390    390   
        };
  391    391   
        let connector = http_client.http_connector(&settings, runtime_components);
  392    392   
        let response_future = MaybeUploadThroughputCheckFuture::new(
@@ -435,435 +504,504 @@
  455    455   
    ctx: &mut InterceptorContext,
  456    456   
    cfg: &mut ConfigBag,
  457    457   
    runtime_components: &RuntimeComponents,
  458    458   
) {
  459    459   
    run_interceptors!(continue_on_err: {
  460    460   
        modify_before_completion(ctx, runtime_components, cfg);
  461    461   
        read_after_execution(ctx, runtime_components, cfg);
  462    462   
    });
  463    463   
}
  464    464   
  465         -
#[cfg(all(test, feature = "test-util"))]
         465  +
#[cfg(all(test, any(feature = "test-util", feature = "legacy-test-util")))]
  466    466   
mod tests {
  467    467   
    use crate::client::auth::no_auth::{NoAuthRuntimePlugin, NO_AUTH_SCHEME_ID};
  468         -
    use crate::client::http::test_util::NeverClient;
  469    468   
    use crate::client::orchestrator::endpoints::StaticUriEndpointResolver;
  470    469   
    use crate::client::orchestrator::{invoke, invoke_with_stop_point, StopPoint};
  471    470   
    use crate::client::retries::strategy::NeverRetryStrategy;
  472    471   
    use crate::client::test_util::{
  473    472   
        deserializer::CannedResponseDeserializer, serializer::CannedRequestSerializer,
  474    473   
    };
         474  +
    use aws_smithy_http_client::test_util::NeverClient;
  475    475   
    use aws_smithy_runtime_api::box_error::BoxError;
  476    476   
    use aws_smithy_runtime_api::client::auth::static_resolver::StaticAuthSchemeOptionResolver;
  477    477   
    use aws_smithy_runtime_api::client::auth::{
  478    478   
        AuthSchemeOptionResolverParams, SharedAuthSchemeOptionResolver,
  479    479   
    };
  480    480   
    use aws_smithy_runtime_api::client::endpoint::{
  481    481   
        EndpointResolverParams, SharedEndpointResolver,
  482    482   
    };
  483    483   
    use aws_smithy_runtime_api::client::http::{
  484    484   
        http_client_fn, HttpConnector, HttpConnectorFuture,

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/orchestrator/auth.rs

@@ -251,251 +311,311 @@
  271    271   
}
  272    272   
impl fmt::Debug for ExploredList {
  273    273   
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  274    274   
        f.debug_struct("ExploredList")
  275    275   
            .field("items", &&self.items[0..self.len])
  276    276   
            .field("truncated", &self.truncated)
  277    277   
            .finish()
  278    278   
    }
  279    279   
}
  280    280   
  281         -
#[cfg(all(test, feature = "test-util"))]
         281  +
#[cfg(all(test, any(feature = "test-util", feature = "legacy-test-util")))]
  282    282   
mod tests {
  283    283   
    use super::*;
  284    284   
    use aws_smithy_runtime_api::client::auth::static_resolver::StaticAuthSchemeOptionResolver;
  285    285   
    use aws_smithy_runtime_api::client::auth::{
  286    286   
        AuthScheme, AuthSchemeId, AuthSchemeOptionResolverParams, SharedAuthScheme,
  287    287   
        SharedAuthSchemeOptionResolver, Sign,
  288    288   
    };
  289    289   
    use aws_smithy_runtime_api::client::identity::{
  290    290   
        Identity, IdentityFuture, ResolveIdentity, SharedIdentityResolver,
  291    291   
    };

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/orchestrator/operation.rs

@@ -373,373 +534,534 @@
  393    393   
  394    394   
        #[cfg(debug_assertions)]
  395    395   
        {
  396    396   
            let mut config = ConfigBag::base();
  397    397   
            let components = runtime_plugins
  398    398   
                .apply_client_configuration(&mut config)
  399    399   
                .expect("the runtime plugins should succeed");
  400    400   
  401    401   
            assert!(
  402    402   
                components.http_client().is_some(),
  403         -
                "a http_client is required. Enable the `rustls` crate feature or configure a HTTP client to fix this."
         403  +
                "a http_client is required. Enable the `default-https-client` crate feature or configure an HTTP client to fix this."
  404    404   
            );
  405    405   
            assert!(
  406    406   
                components.endpoint_resolver().is_some(),
  407    407   
                "a endpoint_resolver is required"
  408    408   
            );
  409    409   
            assert!(
  410    410   
                components.retry_strategy().is_some(),
  411    411   
                "a retry_strategy is required"
  412    412   
            );
  413    413   
            assert!(
  414    414   
                config.load::<SharedRequestSerializer>().is_some(),
  415    415   
                "a serializer is required"
  416    416   
            );
  417    417   
            assert!(
  418    418   
                config.load::<SharedResponseDeserializer>().is_some(),
  419    419   
                "a deserializer is required"
  420    420   
            );
  421    421   
            assert!(
  422    422   
                config.load::<EndpointResolverParams>().is_some(),
  423    423   
                "endpoint resolver params are required"
  424    424   
            );
  425    425   
            assert!(
  426    426   
                config.load::<TimeoutConfig>().is_some(),
  427    427   
                "timeout config is required"
  428    428   
            );
  429    429   
        }
  430    430   
  431    431   
        Operation {
  432    432   
            service_name,
  433    433   
            operation_name,
  434    434   
            runtime_plugins,
  435    435   
            _phantom: Default::default(),
  436    436   
        }
  437    437   
    }
  438    438   
}
  439    439   
  440         -
#[cfg(all(test, feature = "test-util"))]
         440  +
#[cfg(all(test, any(feature = "test-util", feature = "legacy-test-util")))]
  441    441   
mod tests {
  442    442   
    use super::*;
  443         -
    use crate::client::http::test_util::{capture_request, ReplayEvent, StaticReplayClient};
  444    443   
    use crate::client::retries::classifiers::HttpStatusCodeClassifier;
  445    444   
    use aws_smithy_async::rt::sleep::{SharedAsyncSleep, TokioSleep};
         445  +
    use aws_smithy_http_client::test_util::{capture_request, ReplayEvent, StaticReplayClient};
  446    446   
    use aws_smithy_runtime_api::client::result::ConnectorError;
  447    447   
    use aws_smithy_types::body::SdkBody;
  448    448   
    use std::convert::Infallible;
  449    449   
  450    450   
    #[tokio::test]
  451    451   
    async fn operation() {
  452    452   
        let (connector, request_rx) = capture_request(Some(
  453         -
            http_02x::Response::builder()
         453  +
            http_1x::Response::builder()
  454    454   
                .status(418)
  455    455   
                .body(SdkBody::from(&b"I'm a teapot!"[..]))
  456    456   
                .unwrap(),
  457    457   
        ));
  458    458   
        let operation = Operation::builder()
  459    459   
            .service_name("test")
  460    460   
            .operation_name("test")
  461    461   
            .http_client(connector)
  462    462   
            .endpoint_url("http://localhost:1234")
  463    463   
            .no_auth()
  464    464   
            .no_retry()
  465    465   
            .timeout_config(TimeoutConfig::disabled())
  466    466   
            .serializer(|input: String| Ok(HttpRequest::new(SdkBody::from(input.as_bytes()))))
  467    467   
            .deserializer::<_, Infallible>(|response| {
  468    468   
                assert_eq!(418, u16::from(response.status()));
  469    469   
                Ok(std::str::from_utf8(response.body().bytes().unwrap())
  470    470   
                    .unwrap()
  471    471   
                    .to_string())
  472    472   
            })
  473    473   
            .build();
  474    474   
  475    475   
        let output = operation
  476    476   
            .invoke("what are you?".to_string())
  477    477   
            .await
  478    478   
            .expect("success");
  479    479   
        assert_eq!("I'm a teapot!", output);
  480    480   
  481    481   
        let request = request_rx.expect_request();
  482    482   
        assert_eq!("http://localhost:1234/", request.uri());
  483    483   
        assert_eq!(b"what are you?", request.body().bytes().unwrap());
  484    484   
    }
  485    485   
  486    486   
    #[tokio::test]
  487    487   
    async fn operation_retries() {
  488    488   
        let connector = StaticReplayClient::new(vec![
  489    489   
            ReplayEvent::new(
  490         -
                http_02x::Request::builder()
         490  +
                http_1x::Request::builder()
  491    491   
                    .uri("http://localhost:1234/")
  492    492   
                    .body(SdkBody::from(&b"what are you?"[..]))
  493    493   
                    .unwrap(),
  494         -
                http_02x::Response::builder()
         494  +
                http_1x::Response::builder()
  495    495   
                    .status(503)
  496    496   
                    .body(SdkBody::from(&b""[..]))
  497    497   
                    .unwrap(),
  498    498   
            ),
  499    499   
            ReplayEvent::new(
  500         -
                http_02x::Request::builder()
         500  +
                http_1x::Request::builder()
  501    501   
                    .uri("http://localhost:1234/")
  502    502   
                    .body(SdkBody::from(&b"what are you?"[..]))
  503    503   
                    .unwrap(),
  504         -
                http_02x::Response::builder()
         504  +
                http_1x::Response::builder()
  505    505   
                    .status(418)
  506    506   
                    .body(SdkBody::from(&b"I'm a teapot!"[..]))
  507    507   
                    .unwrap(),
  508    508   
            ),
  509    509   
        ]);
  510    510   
        let operation = Operation::builder()
  511    511   
            .service_name("test")
  512    512   
            .operation_name("test")
  513    513   
            .http_client(connector.clone())
  514    514   
            .endpoint_url("http://localhost:1234")

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/retries/strategy/standard.rs

@@ -513,513 +692,692 @@
  533    533   
            .expect("method is infallible for this use");
  534    534   
        assert_eq!(ShouldAttempt::YesAfterDelay(MAX_BACKOFF), actual);
  535    535   
    }
  536    536   
  537    537   
    #[allow(dead_code)] // will be unused with `--no-default-features --features client`
  538    538   
    #[derive(Debug)]
  539    539   
    struct PresetReasonRetryClassifier {
  540    540   
        retry_actions: Mutex<Vec<RetryAction>>,
  541    541   
    }
  542    542   
  543         -
    #[cfg(feature = "test-util")]
         543  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  544    544   
    impl PresetReasonRetryClassifier {
  545    545   
        fn new(mut retry_reasons: Vec<RetryAction>) -> Self {
  546    546   
            // We'll pop the retry_reasons in reverse order, so we reverse the list to fix that.
  547    547   
            retry_reasons.reverse();
  548    548   
            Self {
  549    549   
                retry_actions: Mutex::new(retry_reasons),
  550    550   
            }
  551    551   
        }
  552    552   
    }
  553    553   
  554    554   
    impl ClassifyRetry for PresetReasonRetryClassifier {
  555    555   
        fn classify_retry(&self, ctx: &InterceptorContext) -> RetryAction {
  556    556   
            // Check for a result
  557    557   
            let output_or_error = ctx.output_or_error();
  558    558   
            // Check for an error
  559    559   
            match output_or_error {
  560    560   
                Some(Ok(_)) | None => return RetryAction::NoActionIndicated,
  561    561   
                _ => (),
  562    562   
            };
  563    563   
  564    564   
            let mut retry_actions = self.retry_actions.lock().unwrap();
  565    565   
            if retry_actions.len() == 1 {
  566    566   
                retry_actions.first().unwrap().clone()
  567    567   
            } else {
  568    568   
                retry_actions.pop().unwrap()
  569    569   
            }
  570    570   
        }
  571    571   
  572    572   
        fn name(&self) -> &'static str {
  573    573   
            "Always returns a preset retry reason"
  574    574   
        }
  575    575   
    }
  576    576   
  577         -
    #[cfg(feature = "test-util")]
         577  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  578    578   
    fn setup_test(
  579    579   
        retry_reasons: Vec<RetryAction>,
  580    580   
        retry_config: RetryConfig,
  581    581   
    ) -> (ConfigBag, RuntimeComponents, InterceptorContext) {
  582    582   
        let rc = RuntimeComponentsBuilder::for_tests()
  583    583   
            .with_retry_classifier(SharedRetryClassifier::new(
  584    584   
                PresetReasonRetryClassifier::new(retry_reasons),
  585    585   
            ))
  586    586   
            .build()
  587    587   
            .unwrap();
  588    588   
        let mut layer = Layer::new("test");
  589    589   
        layer.store_put(retry_config);
  590    590   
        let cfg = ConfigBag::of_layers(vec![layer]);
  591    591   
        let mut ctx = InterceptorContext::new(Input::doesnt_matter());
  592    592   
        // This type doesn't matter b/c the classifier will just return whatever we tell it to.
  593    593   
        ctx.set_output_or_error(Err(OrchestratorError::other("doesn't matter")));
  594    594   
  595    595   
        (cfg, rc, ctx)
  596    596   
    }
  597    597   
  598         -
    #[cfg(feature = "test-util")]
         598  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  599    599   
    #[test]
  600    600   
    fn eventual_success() {
  601    601   
        let (mut cfg, rc, mut ctx) = setup_test(
  602    602   
            vec![RetryAction::server_error()],
  603    603   
            RetryConfig::standard()
  604    604   
                .with_use_static_exponential_base(true)
  605    605   
                .with_max_attempts(5),
  606    606   
        );
  607    607   
        let strategy = StandardRetryStrategy::new();
  608    608   
        cfg.interceptor_state().store_put(TokenBucket::default());
  609    609   
        let token_bucket = cfg.load::<TokenBucket>().unwrap().clone();
  610    610   
  611    611   
        cfg.interceptor_state().store_put(RequestAttempts::new(1));
  612    612   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  613    613   
        let dur = should_retry.expect_delay();
  614    614   
        assert_eq!(dur, Duration::from_secs(1));
  615    615   
        assert_eq!(token_bucket.available_permits(), 495);
  616    616   
  617    617   
        cfg.interceptor_state().store_put(RequestAttempts::new(2));
  618    618   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  619    619   
        let dur = should_retry.expect_delay();
  620    620   
        assert_eq!(dur, Duration::from_secs(2));
  621    621   
        assert_eq!(token_bucket.available_permits(), 490);
  622    622   
  623    623   
        ctx.set_output_or_error(Ok(Output::doesnt_matter()));
  624    624   
  625    625   
        cfg.interceptor_state().store_put(RequestAttempts::new(3));
  626    626   
        let no_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  627    627   
        assert_eq!(no_retry, ShouldAttempt::No);
  628    628   
        assert_eq!(token_bucket.available_permits(), 495);
  629    629   
    }
  630    630   
  631         -
    #[cfg(feature = "test-util")]
         631  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  632    632   
    #[test]
  633    633   
    fn no_more_attempts() {
  634    634   
        let (mut cfg, rc, ctx) = setup_test(
  635    635   
            vec![RetryAction::server_error()],
  636    636   
            RetryConfig::standard()
  637    637   
                .with_use_static_exponential_base(true)
  638    638   
                .with_max_attempts(3),
  639    639   
        );
  640    640   
        let strategy = StandardRetryStrategy::new();
  641    641   
        cfg.interceptor_state().store_put(TokenBucket::default());
  642    642   
        let token_bucket = cfg.load::<TokenBucket>().unwrap().clone();
  643    643   
  644    644   
        cfg.interceptor_state().store_put(RequestAttempts::new(1));
  645    645   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  646    646   
        let dur = should_retry.expect_delay();
  647    647   
        assert_eq!(dur, Duration::from_secs(1));
  648    648   
        assert_eq!(token_bucket.available_permits(), 495);
  649    649   
  650    650   
        cfg.interceptor_state().store_put(RequestAttempts::new(2));
  651    651   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  652    652   
        let dur = should_retry.expect_delay();
  653    653   
        assert_eq!(dur, Duration::from_secs(2));
  654    654   
        assert_eq!(token_bucket.available_permits(), 490);
  655    655   
  656    656   
        cfg.interceptor_state().store_put(RequestAttempts::new(3));
  657    657   
        let no_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  658    658   
        assert_eq!(no_retry, ShouldAttempt::No);
  659    659   
        assert_eq!(token_bucket.available_permits(), 490);
  660    660   
    }
  661    661   
  662         -
    #[cfg(feature = "test-util")]
         662  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  663    663   
    #[test]
  664    664   
    fn successful_request_and_deser_should_be_retryable() {
  665    665   
        #[derive(Clone, Copy, Debug)]
  666    666   
        enum LongRunningOperationStatus {
  667    667   
            Running,
  668    668   
            Complete,
  669    669   
        }
  670    670   
  671    671   
        #[derive(Debug)]
  672    672   
        struct LongRunningOperationOutput {
@@ -724,724 +946,946 @@
  744    744   
  745    745   
        ctx.set_output_or_error(Ok(Output::erase(LongRunningOperationOutput {
  746    746   
            status: Some(LongRunningOperationStatus::Complete),
  747    747   
        })));
  748    748   
        cfg.interceptor_state().store_put(RequestAttempts::new(2));
  749    749   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  750    750   
        should_retry.expect_no();
  751    751   
        assert_eq!(token_bucket.available_permits(), 5);
  752    752   
    }
  753    753   
  754         -
    #[cfg(feature = "test-util")]
         754  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  755    755   
    #[test]
  756    756   
    fn no_quota() {
  757    757   
        let (mut cfg, rc, ctx) = setup_test(
  758    758   
            vec![RetryAction::server_error()],
  759    759   
            RetryConfig::standard()
  760    760   
                .with_use_static_exponential_base(true)
  761    761   
                .with_max_attempts(5),
  762    762   
        );
  763    763   
        let strategy = StandardRetryStrategy::new();
  764    764   
        cfg.interceptor_state().store_put(TokenBucket::new(5));
  765    765   
        let token_bucket = cfg.load::<TokenBucket>().unwrap().clone();
  766    766   
  767    767   
        cfg.interceptor_state().store_put(RequestAttempts::new(1));
  768    768   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  769    769   
        let dur = should_retry.expect_delay();
  770    770   
        assert_eq!(dur, Duration::from_secs(1));
  771    771   
        assert_eq!(token_bucket.available_permits(), 0);
  772    772   
  773    773   
        cfg.interceptor_state().store_put(RequestAttempts::new(2));
  774    774   
        let no_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  775    775   
        assert_eq!(no_retry, ShouldAttempt::No);
  776    776   
        assert_eq!(token_bucket.available_permits(), 0);
  777    777   
    }
  778    778   
  779         -
    #[cfg(feature = "test-util")]
         779  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  780    780   
    #[test]
  781    781   
    fn quota_replenishes_on_success() {
  782    782   
        let (mut cfg, rc, mut ctx) = setup_test(
  783    783   
            vec![
  784    784   
                RetryAction::transient_error(),
  785    785   
                RetryAction::retryable_error_with_explicit_delay(
  786    786   
                    ErrorKind::TransientError,
  787    787   
                    Duration::from_secs(1),
  788    788   
                ),
  789    789   
            ],
  790    790   
            RetryConfig::standard()
  791    791   
                .with_use_static_exponential_base(true)
  792    792   
                .with_max_attempts(5),
  793    793   
        );
  794    794   
        let strategy = StandardRetryStrategy::new();
  795    795   
        cfg.interceptor_state().store_put(TokenBucket::new(100));
  796    796   
        let token_bucket = cfg.load::<TokenBucket>().unwrap().clone();
  797    797   
  798    798   
        cfg.interceptor_state().store_put(RequestAttempts::new(1));
  799    799   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  800    800   
        let dur = should_retry.expect_delay();
  801    801   
        assert_eq!(dur, Duration::from_secs(1));
  802    802   
        assert_eq!(token_bucket.available_permits(), 90);
  803    803   
  804    804   
        cfg.interceptor_state().store_put(RequestAttempts::new(2));
  805    805   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  806    806   
        let dur = should_retry.expect_delay();
  807    807   
        assert_eq!(dur, Duration::from_secs(1));
  808    808   
        assert_eq!(token_bucket.available_permits(), 80);
  809    809   
  810    810   
        ctx.set_output_or_error(Ok(Output::doesnt_matter()));
  811    811   
  812    812   
        cfg.interceptor_state().store_put(RequestAttempts::new(3));
  813    813   
        let no_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  814    814   
        assert_eq!(no_retry, ShouldAttempt::No);
  815    815   
  816    816   
        assert_eq!(token_bucket.available_permits(), 90);
  817    817   
    }
  818    818   
  819         -
    #[cfg(feature = "test-util")]
         819  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  820    820   
    #[test]
  821    821   
    fn quota_replenishes_on_first_try_success() {
  822    822   
        const PERMIT_COUNT: usize = 20;
  823    823   
        let (mut cfg, rc, mut ctx) = setup_test(
  824    824   
            vec![RetryAction::transient_error()],
  825    825   
            RetryConfig::standard()
  826    826   
                .with_use_static_exponential_base(true)
  827    827   
                .with_max_attempts(u32::MAX),
  828    828   
        );
  829    829   
        let strategy = StandardRetryStrategy::new();
  830    830   
        cfg.interceptor_state()
  831    831   
            .store_put(TokenBucket::new(PERMIT_COUNT));
  832    832   
        let token_bucket = cfg.load::<TokenBucket>().unwrap().clone();
  833    833   
  834    834   
        let mut attempt = 1;
  835    835   
  836    836   
        // Drain all available permits with failed attempts
  837    837   
        while token_bucket.available_permits() > 0 {
  838    838   
            // Draining should complete in 2 attempts
  839    839   
            if attempt > 2 {
  840    840   
                panic!("This test should have completed by now (drain)");
  841    841   
            }
  842    842   
  843    843   
            cfg.interceptor_state()
  844    844   
                .store_put(RequestAttempts::new(attempt));
  845    845   
            let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  846    846   
            assert!(matches!(should_retry, ShouldAttempt::YesAfterDelay(_)));
  847    847   
            attempt += 1;
  848    848   
        }
  849    849   
  850    850   
        // Forget the permit so that we can only refill by "success on first try".
  851    851   
        let permit = strategy.retry_permit.lock().unwrap().take().unwrap();
  852    852   
        permit.forget();
  853    853   
  854    854   
        ctx.set_output_or_error(Ok(Output::doesnt_matter()));
  855    855   
  856    856   
        // Replenish permits until we get back to `PERMIT_COUNT`
  857    857   
        while token_bucket.available_permits() < PERMIT_COUNT {
  858    858   
            if attempt > 23 {
  859    859   
                panic!("This test should have completed by now (fill-up)");
  860    860   
            }
  861    861   
  862    862   
            cfg.interceptor_state()
  863    863   
                .store_put(RequestAttempts::new(attempt));
  864    864   
            let no_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  865    865   
            assert_eq!(no_retry, ShouldAttempt::No);
  866    866   
            attempt += 1;
  867    867   
        }
  868    868   
  869    869   
        assert_eq!(attempt, 23);
  870    870   
        assert_eq!(token_bucket.available_permits(), PERMIT_COUNT);
  871    871   
    }
  872    872   
  873         -
    #[cfg(feature = "test-util")]
         873  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  874    874   
    #[test]
  875    875   
    fn backoff_timing() {
  876    876   
        let (mut cfg, rc, ctx) = setup_test(
  877    877   
            vec![RetryAction::server_error()],
  878    878   
            RetryConfig::standard()
  879    879   
                .with_use_static_exponential_base(true)
  880    880   
                .with_max_attempts(5),
  881    881   
        );
  882    882   
        let strategy = StandardRetryStrategy::new();
  883    883   
        cfg.interceptor_state().store_put(TokenBucket::default());
  884    884   
        let token_bucket = cfg.load::<TokenBucket>().unwrap().clone();
  885    885   
  886    886   
        cfg.interceptor_state().store_put(RequestAttempts::new(1));
  887    887   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  888    888   
        let dur = should_retry.expect_delay();
  889    889   
        assert_eq!(dur, Duration::from_secs(1));
  890    890   
        assert_eq!(token_bucket.available_permits(), 495);
  891    891   
  892    892   
        cfg.interceptor_state().store_put(RequestAttempts::new(2));
  893    893   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  894    894   
        let dur = should_retry.expect_delay();
  895    895   
        assert_eq!(dur, Duration::from_secs(2));
  896    896   
        assert_eq!(token_bucket.available_permits(), 490);
  897    897   
  898    898   
        cfg.interceptor_state().store_put(RequestAttempts::new(3));
  899    899   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  900    900   
        let dur = should_retry.expect_delay();
  901    901   
        assert_eq!(dur, Duration::from_secs(4));
  902    902   
        assert_eq!(token_bucket.available_permits(), 485);
  903    903   
  904    904   
        cfg.interceptor_state().store_put(RequestAttempts::new(4));
  905    905   
        let should_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  906    906   
        let dur = should_retry.expect_delay();
  907    907   
        assert_eq!(dur, Duration::from_secs(8));
  908    908   
        assert_eq!(token_bucket.available_permits(), 480);
  909    909   
  910    910   
        cfg.interceptor_state().store_put(RequestAttempts::new(5));
  911    911   
        let no_retry = strategy.should_attempt_retry(&ctx, &rc, &cfg).unwrap();
  912    912   
        assert_eq!(no_retry, ShouldAttempt::No);
  913    913   
        assert_eq!(token_bucket.available_permits(), 480);
  914    914   
    }
  915    915   
  916         -
    #[cfg(feature = "test-util")]
         916  +
    #[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
  917    917   
    #[test]
  918    918   
    fn max_backoff_time() {
  919    919   
        let (mut cfg, rc, ctx) = setup_test(
  920    920   
            vec![RetryAction::server_error()],
  921    921   
            RetryConfig::standard()
  922    922   
                .with_use_static_exponential_base(true)
  923    923   
                .with_max_attempts(5)
  924    924   
                .with_initial_backoff(Duration::from_secs(1))
  925    925   
                .with_max_backoff(Duration::from_secs(3)),
  926    926   
        );

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/retries/token_bucket.rs

@@ -42,42 +76,76 @@
   62     62   
            .ok()
   63     63   
    }
   64     64   
   65     65   
    pub(crate) fn regenerate_a_token(&self) {
   66     66   
        if self.semaphore.available_permits() < (self.max_permits) {
   67     67   
            trace!("adding {PERMIT_REGENERATION_AMOUNT} back into the bucket");
   68     68   
            self.semaphore.add_permits(PERMIT_REGENERATION_AMOUNT)
   69     69   
        }
   70     70   
    }
   71     71   
   72         -
    #[cfg(all(test, feature = "test-util"))]
          72  +
    #[cfg(all(test, any(feature = "test-util", feature = "legacy-test-util")))]
   73     73   
    pub(crate) fn available_permits(&self) -> usize {
   74     74   
        self.semaphore.available_permits()
   75     75   
    }
   76     76   
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/waiters.rs

@@ -169,169 +229,229 @@
  189    189   
        self.max_delay = Some(max_delay);
  190    190   
        self
  191    191   
    }
  192    192   
  193    193   
    /// Set the maximum total wait time for the waiter.
  194    194   
    pub fn max_wait(mut self, max_wait: Duration) -> Self {
  195    195   
        self.max_wait = Some(max_wait);
  196    196   
        self
  197    197   
    }
  198    198   
  199         -
    #[cfg(all(test, feature = "test-util"))]
         199  +
    #[cfg(all(test, any(feature = "test-util", feature = "legacy-test-util")))]
  200    200   
    fn random(mut self, random_fn: impl Fn(u64, u64) -> u64 + Send + Sync + 'static) -> Self {
  201    201   
        self.random_fn = RandomImpl::Override(Box::new(random_fn));
  202    202   
        self
  203    203   
    }
  204    204   
  205    205   
    /// Set the time source the waiter will use.
  206    206   
    pub fn time_source(mut self, time_source: SharedTimeSource) -> Self {
  207    207   
        self.time_source = Some(time_source);
  208    208   
        self
  209    209   
    }
@@ -254,254 +314,314 @@
  274    274   
pub fn attach_waiter_tracing_span<O, E>(
  275    275   
    future: impl Future<Output = Result<FinalPoll<O, SdkError<E, HttpResponse>>, WaiterError<O, E>>>,
  276    276   
) -> impl Future<Output = Result<FinalPoll<O, SdkError<E, HttpResponse>>, WaiterError<O, E>>> {
  277    277   
    use tracing::Instrument;
  278    278   
  279    279   
    // Create a random seven-digit ID for the waiter so that it can be correlated in the logs.
  280    280   
    let span = tracing::debug_span!("waiter", waiter_id = fastrand::u32(1_000_000..10_000_000));
  281    281   
    future.instrument(span)
  282    282   
}
  283    283   
  284         -
#[cfg(all(test, feature = "test-util"))]
         284  +
#[cfg(all(test, any(feature = "test-util", feature = "legacy-test-util")))]
  285    285   
mod tests {
  286    286   
    use super::*;
  287    287   
    use crate::test_util::capture_test_logs::show_test_logs;
  288    288   
    use aws_smithy_async::{
  289    289   
        test_util::tick_advance_sleep::tick_advance_time_and_sleep, time::TimeSource,
  290    290   
    };
  291    291   
    use aws_smithy_runtime_api::{http::StatusCode, shared::IntoShared};
  292    292   
    use aws_smithy_types::body::SdkBody;
  293    293   
    use std::{
  294    294   
        fmt,

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/lib.rs

@@ -5,5 +0,44 @@
   25     25   
#[cfg(feature = "client")]
   26     26   
pub mod client;
   27     27   
   28     28   
/// Cache for entries that have an expiration time.
   29     29   
pub mod expiring_cache;
   30     30   
   31     31   
/// A data structure for persisting and sharing state between multiple clients.
   32     32   
pub mod static_partition_map;
   33     33   
   34     34   
/// General testing utilities.
   35         -
#[cfg(feature = "test-util")]
          35  +
#[cfg(any(feature = "test-util", feature = "legacy-test-util"))]
   36     36   
pub mod test_util;
          37  +
          38  +
// legacy test-util, re-export of macros
          39  +
#[cfg(feature = "wire-mock")]
          40  +
pub use aws_smithy_http_client::test_util::wire::ev;
          41  +
#[cfg(feature = "wire-mock")]
          42  +
pub use aws_smithy_http_client::test_util::wire::match_events;
          43  +
#[cfg(feature = "wire-mock")]
          44  +
pub use aws_smithy_http_client::test_util::wire::matcher;

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/tests/reconnect_on_transient_error.rs

@@ -1,1 +40,36 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6         -
#![cfg(all(
    7         -
    feature = "client",
    8         -
    feature = "wire-mock",
    9         -
    feature = "connector-hyper-0-14-x",
   10         -
))]
           6  +
#![cfg(all(feature = "client", feature = "wire-mock",))]
   11      7   
   12      8   
use ::aws_smithy_runtime::client::retries::classifiers::{
   13      9   
    HttpStatusCodeClassifier, TransientErrorClassifier,
   14     10   
};
   15     11   
use aws_smithy_async::rt::sleep::TokioSleep;
   16     12   
use aws_smithy_runtime::client::http::hyper_014::HyperClientBuilder;
   17     13   
use aws_smithy_runtime::client::http::test_util::wire::{
   18     14   
    RecordedEvent, ReplayedEvent, WireMockServer,
   19     15   
};
   20     16   
use aws_smithy_runtime::client::orchestrator::operation::Operation;

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/tests/stalled_stream_common.rs

@@ -1,1 +36,39 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6         -
#![cfg(all(feature = "client", feature = "test-util"))]
           6  +
#![cfg(all(
           7  +
    feature = "client",
           8  +
    any(feature = "test-util", feature = "legacy-test-util")
           9  +
))]
    7     10   
// Extra imports are used by stalled_stream_download and stalled_stream_upload as conveniences
    8     11   
#![allow(unused_imports)]
    9     12   
   10     13   
pub use aws_smithy_async::{
   11     14   
    test_util::tick_advance_sleep::{
   12     15   
        tick_advance_time_and_sleep, TickAdvanceSleep, TickAdvanceTime,
   13     16   
    },
   14     17   
    time::TimeSource,
   15     18   
};
   16     19   
pub use aws_smithy_runtime::{