mirror of https://github.com/smithy-lang/smithy-rs
Remove vestiges of the old TimeSource implementation & refactor (#2877)
## Motivation and Context When `TimeSource` was created, we didn't carefully track down all the places and left a bit of existing implementation to limit the scope of the change. ## Description This removes the public (doc hidden) Testing code from aws-credential-types and our other test time sources instead. ## Testing - IT/UT ## Checklist <!--- If a checkbox below is not applicable, then please DELETE it rather than leaving it unchecked --> - [x] I have updated `CHANGELOG.next.toml` if I made changes to the smithy-rs codegen or runtime crates - [x] I have updated `CHANGELOG.next.toml` if I made changes to the AWS SDK, generated SDK code, or SDK runtime crates ---- _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: John DiSanti <jdisanti@amazon.com>
This commit is contained in:
parent
5d0887034e
commit
9a4156de04
|
@ -686,3 +686,15 @@ x-amzn-errortype: InvalidRequestException
|
|||
references = ["smithy-rs#2866"]
|
||||
meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "server" }
|
||||
author = "david-perez"
|
||||
|
||||
[[aws-sdk-rust]]
|
||||
message = """The `doc(hidden)` `time_source` in `aws-credential-types` was removed. Use `aws_smithy_async::time` instead."""
|
||||
meta = { "breaking" = true, "tada" = false, "bug" = false }
|
||||
author = "rcoh"
|
||||
references = ["smithy-rs#2877"]
|
||||
|
||||
[[aws-sdk-rust]]
|
||||
message = """The `doc(hidden)` `with_env` in `ProviderConfig` was removed."""
|
||||
meta = { "breaking" = true, "tada" = false, "bug" = false }
|
||||
author = "rcoh"
|
||||
references = ["smithy-rs#2877"]
|
||||
|
|
|
@ -66,6 +66,7 @@ aws-smithy-client = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-client", fe
|
|||
|
||||
# used for a usage example
|
||||
hyper-rustls = { version = "0.24", features = ["webpki-tokio", "http2", "http1"] }
|
||||
aws-smithy-async = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-async", features = ["test-util"] }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
|
|
@ -199,6 +199,8 @@ impl Builder {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use aws_credential_types::provider::ProvideCredentials;
|
||||
use aws_smithy_async::time::StaticTimeSource;
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
||||
use crate::default_provider::credentials::DefaultCredentialsChain;
|
||||
|
||||
|
@ -279,21 +281,15 @@ mod test {
|
|||
make_test!(imds_no_iam_role);
|
||||
make_test!(imds_default_chain_error);
|
||||
make_test!(imds_default_chain_success, builder: |config| {
|
||||
config.with_time_source(aws_credential_types::time_source::TimeSource::testing(
|
||||
&aws_credential_types::time_source::TestingTimeSource::new(std::time::UNIX_EPOCH),
|
||||
))
|
||||
config.with_time_source(StaticTimeSource::new(UNIX_EPOCH))
|
||||
});
|
||||
make_test!(imds_assume_role);
|
||||
make_test!(imds_config_with_no_creds, builder: |config| {
|
||||
config.with_time_source(aws_credential_types::time_source::TimeSource::testing(
|
||||
&aws_credential_types::time_source::TestingTimeSource::new(std::time::UNIX_EPOCH),
|
||||
))
|
||||
config.with_time_source(StaticTimeSource::new(UNIX_EPOCH))
|
||||
});
|
||||
make_test!(imds_disabled);
|
||||
make_test!(imds_default_chain_retries, builder: |config| {
|
||||
config.with_time_source(aws_credential_types::time_source::TimeSource::testing(
|
||||
&aws_credential_types::time_source::TestingTimeSource::new(std::time::UNIX_EPOCH),
|
||||
))
|
||||
config.with_time_source(StaticTimeSource::new(UNIX_EPOCH))
|
||||
});
|
||||
make_test!(ecs_assume_role);
|
||||
make_test!(ecs_credentials);
|
||||
|
@ -335,7 +331,6 @@ mod test {
|
|||
async fn no_providers_configured_err() {
|
||||
use crate::provider_config::ProviderConfig;
|
||||
use aws_credential_types::provider::error::CredentialsError;
|
||||
use aws_credential_types::time_source::TimeSource;
|
||||
use aws_smithy_async::rt::sleep::TokioSleep;
|
||||
use aws_smithy_client::erase::boxclone::BoxCloneService;
|
||||
use aws_smithy_client::never::NeverConnected;
|
||||
|
@ -343,7 +338,7 @@ mod test {
|
|||
tokio::time::pause();
|
||||
let conf = ProviderConfig::no_configuration()
|
||||
.with_tcp_connector(BoxCloneService::new(NeverConnected::new()))
|
||||
.with_time_source(TimeSource::default())
|
||||
.with_time_source(StaticTimeSource::new(UNIX_EPOCH))
|
||||
.with_sleep(TokioSleep::new());
|
||||
let provider = DefaultCredentialsChain::builder()
|
||||
.configure(conf)
|
||||
|
|
|
@ -571,8 +571,8 @@ impl<T, E> ClassifyRetry<SdkSuccess<T>, SdkError<E>> for ImdsResponseRetryClassi
|
|||
pub(crate) mod test {
|
||||
use crate::imds::client::{Client, EndpointMode, ImdsResponseRetryClassifier};
|
||||
use crate::provider_config::ProviderConfig;
|
||||
use aws_credential_types::time_source::{TestingTimeSource, TimeSource};
|
||||
use aws_smithy_async::rt::sleep::TokioSleep;
|
||||
use aws_smithy_async::test_util::instant_time_and_sleep;
|
||||
use aws_smithy_client::erase::DynConnector;
|
||||
use aws_smithy_client::test_connection::{capture_request, TestConnection};
|
||||
use aws_smithy_client::{SdkError, SdkSuccess};
|
||||
|
@ -700,14 +700,13 @@ pub(crate) mod test {
|
|||
imds_response(r#"test-imds-output2"#),
|
||||
),
|
||||
]);
|
||||
let mut time_source = TestingTimeSource::new(UNIX_EPOCH);
|
||||
tokio::time::pause();
|
||||
let (time_source, sleep) = instant_time_and_sleep(UNIX_EPOCH);
|
||||
let client = super::Client::builder()
|
||||
.configure(
|
||||
&ProviderConfig::no_configuration()
|
||||
.with_http_connector(DynConnector::new(connection.clone()))
|
||||
.with_time_source(TimeSource::testing(&time_source))
|
||||
.with_sleep(TokioSleep::new()),
|
||||
.with_time_source(time_source.clone())
|
||||
.with_sleep(sleep),
|
||||
)
|
||||
.endpoint_mode(EndpointMode::IpV6)
|
||||
.token_ttl(Duration::from_secs(600))
|
||||
|
@ -752,14 +751,13 @@ pub(crate) mod test {
|
|||
imds_response(r#"test-imds-output3"#),
|
||||
),
|
||||
]);
|
||||
tokio::time::pause();
|
||||
let mut time_source = TestingTimeSource::new(UNIX_EPOCH);
|
||||
let (time_source, sleep) = instant_time_and_sleep(UNIX_EPOCH);
|
||||
let client = super::Client::builder()
|
||||
.configure(
|
||||
&ProviderConfig::no_configuration()
|
||||
.with_sleep(TokioSleep::new())
|
||||
.with_sleep(sleep)
|
||||
.with_http_connector(DynConnector::new(connection.clone()))
|
||||
.with_time_source(TimeSource::testing(&time_source)),
|
||||
.with_time_source(time_source.clone()),
|
||||
)
|
||||
.endpoint_mode(EndpointMode::IpV6)
|
||||
.token_ttl(Duration::from_secs(600))
|
||||
|
|
|
@ -306,8 +306,7 @@ mod test {
|
|||
};
|
||||
use crate::provider_config::ProviderConfig;
|
||||
use aws_credential_types::provider::ProvideCredentials;
|
||||
use aws_credential_types::time_source::{TestingTimeSource, TimeSource};
|
||||
use aws_smithy_async::rt::sleep::TokioSleep;
|
||||
use aws_smithy_async::test_util::instant_time_and_sleep;
|
||||
use aws_smithy_client::erase::DynConnector;
|
||||
use aws_smithy_client::test_connection::TestConnection;
|
||||
use tracing_test::traced_test;
|
||||
|
@ -369,16 +368,12 @@ mod test {
|
|||
// set to 2021-09-21T04:16:50Z that makes returned credentials' expiry (2021-09-21T04:16:53Z)
|
||||
// not stale
|
||||
let time_of_request_to_fetch_credentials = UNIX_EPOCH + Duration::from_secs(1632197810);
|
||||
let time_source = TimeSource::testing(&TestingTimeSource::new(
|
||||
time_of_request_to_fetch_credentials,
|
||||
));
|
||||
|
||||
tokio::time::pause();
|
||||
let (time_source, sleep) = instant_time_and_sleep(time_of_request_to_fetch_credentials);
|
||||
|
||||
let provider_config = ProviderConfig::no_configuration()
|
||||
.with_http_connector(DynConnector::new(connection.clone()))
|
||||
.with_time_source(time_source)
|
||||
.with_sleep(TokioSleep::new());
|
||||
.with_sleep(sleep)
|
||||
.with_time_source(time_source);
|
||||
let client = crate::imds::Client::builder()
|
||||
.configure(&provider_config)
|
||||
.build()
|
||||
|
@ -419,16 +414,12 @@ mod test {
|
|||
|
||||
// set to 2021-09-21T17:41:25Z that renders fetched credentials already expired (2021-09-21T04:16:53Z)
|
||||
let time_of_request_to_fetch_credentials = UNIX_EPOCH + Duration::from_secs(1632246085);
|
||||
let time_source = TimeSource::testing(&TestingTimeSource::new(
|
||||
time_of_request_to_fetch_credentials,
|
||||
));
|
||||
|
||||
tokio::time::pause();
|
||||
let (time_source, sleep) = instant_time_and_sleep(time_of_request_to_fetch_credentials);
|
||||
|
||||
let provider_config = ProviderConfig::no_configuration()
|
||||
.with_http_connector(DynConnector::new(connection.clone()))
|
||||
.with_time_source(time_source)
|
||||
.with_sleep(TokioSleep::new());
|
||||
.with_sleep(sleep)
|
||||
.with_time_source(time_source);
|
||||
let client = crate::imds::Client::builder()
|
||||
.configure(&provider_config)
|
||||
.build()
|
||||
|
|
|
@ -620,9 +620,8 @@ mod loader {
|
|||
|
||||
let credentials_cache = if credentials_provider.is_some() {
|
||||
Some(self.credentials_cache.unwrap_or_else(|| {
|
||||
let mut builder = CredentialsCache::lazy_builder().time_source(
|
||||
aws_credential_types::time_source::TimeSource::shared(conf.time_source()),
|
||||
);
|
||||
let mut builder =
|
||||
CredentialsCache::lazy_builder().time_source(conf.time_source());
|
||||
builder.set_sleep(conf.sleep());
|
||||
builder.into_credentials_cache()
|
||||
}))
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
//! Configuration Options for Credential Providers
|
||||
|
||||
use aws_credential_types::time_source::TimeSource;
|
||||
use aws_smithy_async::rt::sleep::{default_async_sleep, AsyncSleep, SharedAsyncSleep};
|
||||
use aws_smithy_async::time::SharedTimeSource;
|
||||
use aws_smithy_client::erase::DynConnector;
|
||||
|
@ -282,7 +281,7 @@ impl ProviderConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(test)]
|
||||
pub fn with_env(self, env: Env) -> Self {
|
||||
ProviderConfig {
|
||||
parsed_profile: Default::default(),
|
||||
|
@ -291,8 +290,11 @@ impl ProviderConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn with_time_source(self, time_source: TimeSource) -> Self {
|
||||
/// Override the time source for this configuration
|
||||
pub fn with_time_source(
|
||||
self,
|
||||
time_source: impl aws_smithy_async::time::TimeSource + 'static,
|
||||
) -> Self {
|
||||
ProviderConfig {
|
||||
time_source: SharedTimeSource::new(time_source),
|
||||
..self
|
||||
|
|
|
@ -291,9 +291,10 @@ mod test {
|
|||
use crate::sts::AssumeRoleProvider;
|
||||
use aws_credential_types::credential_fn::provide_credentials_fn;
|
||||
use aws_credential_types::provider::ProvideCredentials;
|
||||
use aws_credential_types::time_source::{TestingTimeSource, TimeSource};
|
||||
use aws_credential_types::Credentials;
|
||||
use aws_smithy_async::rt::sleep::TokioSleep;
|
||||
use aws_smithy_async::test_util::instant_time_and_sleep;
|
||||
use aws_smithy_async::time::StaticTimeSource;
|
||||
use aws_smithy_client::erase::DynConnector;
|
||||
use aws_smithy_client::test_connection::{capture_request, TestConnection};
|
||||
use aws_smithy_http::body::SdkBody;
|
||||
|
@ -305,9 +306,9 @@ mod test {
|
|||
let (server, request) = capture_request(None);
|
||||
let provider_conf = ProviderConfig::empty()
|
||||
.with_sleep(TokioSleep::new())
|
||||
.with_time_source(TimeSource::testing(&TestingTimeSource::new(
|
||||
.with_time_source(StaticTimeSource::new(
|
||||
UNIX_EPOCH + Duration::from_secs(1234567890 - 120),
|
||||
)))
|
||||
))
|
||||
.with_http_connector(DynConnector::new(server));
|
||||
let provider = AssumeRoleProvider::builder("myrole")
|
||||
.configure(&provider_conf)
|
||||
|
@ -335,13 +336,13 @@ mod test {
|
|||
)).unwrap()),
|
||||
]);
|
||||
|
||||
let mut testing_time_source = TestingTimeSource::new(
|
||||
let (testing_time_source, sleep) = instant_time_and_sleep(
|
||||
UNIX_EPOCH + Duration::from_secs(1234567890 - 120), // 1234567890 since UNIX_EPOCH is 2009-02-13T23:31:30Z
|
||||
);
|
||||
|
||||
let provider_conf = ProviderConfig::empty()
|
||||
.with_sleep(TokioSleep::new())
|
||||
.with_time_source(TimeSource::testing(&testing_time_source))
|
||||
.with_sleep(sleep)
|
||||
.with_time_source(testing_time_source.clone())
|
||||
.with_http_connector(DynConnector::new(conn));
|
||||
let credentials_list = std::sync::Arc::new(std::sync::Mutex::new(vec![
|
||||
Credentials::new(
|
||||
|
@ -371,8 +372,6 @@ mod test {
|
|||
}
|
||||
}));
|
||||
|
||||
tokio::time::pause();
|
||||
|
||||
let creds_first = provider
|
||||
.provide_credentials()
|
||||
.await
|
||||
|
|
|
@ -20,7 +20,7 @@ tracing = "0.1"
|
|||
zeroize = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async", features = ["rt-tokio"] }
|
||||
aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async", features = ["rt-tokio", "test-util"] }
|
||||
|
||||
# used to test compatibility
|
||||
async-trait = "0.1.51"
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
|
||||
//! Lazy, credentials cache implementation
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
use std::time::Duration;
|
||||
|
||||
use aws_smithy_async::future::timeout::Timeout;
|
||||
use aws_smithy_async::rt::sleep::{AsyncSleep, SharedAsyncSleep};
|
||||
use aws_smithy_async::time::SharedTimeSource;
|
||||
use tracing::{debug, info, info_span, Instrument};
|
||||
|
||||
use crate::cache::{ExpiringCache, ProvideCachedCredentials};
|
||||
use crate::provider::SharedCredentialsProvider;
|
||||
use crate::provider::{error::CredentialsError, future, ProvideCredentials};
|
||||
use crate::time_source::TimeSource;
|
||||
|
||||
const DEFAULT_LOAD_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
const DEFAULT_CREDENTIAL_EXPIRATION: Duration = Duration::from_secs(15 * 60);
|
||||
|
@ -23,7 +23,7 @@ const DEFAULT_BUFFER_TIME_JITTER_FRACTION: fn() -> f64 = fastrand::f64;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct LazyCredentialsCache {
|
||||
time: TimeSource,
|
||||
time: SharedTimeSource,
|
||||
sleeper: SharedAsyncSleep,
|
||||
cache: ExpiringCache<Credentials, CredentialsError>,
|
||||
provider: SharedCredentialsProvider,
|
||||
|
@ -35,7 +35,7 @@ pub(crate) struct LazyCredentialsCache {
|
|||
|
||||
impl LazyCredentialsCache {
|
||||
fn new(
|
||||
time: TimeSource,
|
||||
time: SharedTimeSource,
|
||||
sleeper: SharedAsyncSleep,
|
||||
provider: SharedCredentialsProvider,
|
||||
load_timeout: Duration,
|
||||
|
@ -79,7 +79,7 @@ impl ProvideCachedCredentials for LazyCredentialsCache {
|
|||
// since the futures are not eagerly executed, and the cache will only run one
|
||||
// of them.
|
||||
let future = Timeout::new(provider.provide_credentials(), timeout_future);
|
||||
let start_time = Instant::now();
|
||||
let start_time = self.time.now();
|
||||
let result = cache
|
||||
.get_or_load(|| {
|
||||
let span = info_span!("lazy_load_credentials");
|
||||
|
@ -111,14 +111,14 @@ impl ProvideCachedCredentials for LazyCredentialsCache {
|
|||
// only once for the first thread that succeeds in populating a cache value.
|
||||
info!(
|
||||
"credentials cache miss occurred; added new AWS credentials (took {:?})",
|
||||
start_time.elapsed()
|
||||
self.time.now().duration_since(start_time)
|
||||
);
|
||||
|
||||
Ok((credentials, expiry + jitter))
|
||||
}
|
||||
// Only instrument the the actual load future so that no span
|
||||
// is opened if the cache decides not to execute it.
|
||||
.instrument(span)
|
||||
// Only instrument the the actual load future so that no span
|
||||
// is opened if the cache decides not to execute it.
|
||||
.instrument(span)
|
||||
})
|
||||
.await;
|
||||
debug!("loaded credentials");
|
||||
|
@ -137,8 +137,8 @@ mod builder {
|
|||
use crate::cache::{CredentialsCache, Inner};
|
||||
use crate::provider::SharedCredentialsProvider;
|
||||
use aws_smithy_async::rt::sleep::{default_async_sleep, SharedAsyncSleep};
|
||||
use aws_smithy_async::time::SharedTimeSource;
|
||||
|
||||
use super::TimeSource;
|
||||
use super::{
|
||||
LazyCredentialsCache, DEFAULT_BUFFER_TIME, DEFAULT_BUFFER_TIME_JITTER_FRACTION,
|
||||
DEFAULT_CREDENTIAL_EXPIRATION, DEFAULT_LOAD_TIMEOUT,
|
||||
|
@ -159,7 +159,7 @@ mod builder {
|
|||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Builder {
|
||||
sleep: Option<SharedAsyncSleep>,
|
||||
time_source: Option<TimeSource>,
|
||||
time_source: Option<SharedTimeSource>,
|
||||
load_timeout: Option<Duration>,
|
||||
buffer_time: Option<Duration>,
|
||||
buffer_time_jitter_fraction: Option<fn() -> f64>,
|
||||
|
@ -193,13 +193,13 @@ mod builder {
|
|||
}
|
||||
|
||||
#[doc(hidden)] // because they only exist for tests
|
||||
pub fn time_source(mut self, time_source: TimeSource) -> Self {
|
||||
pub fn time_source(mut self, time_source: SharedTimeSource) -> Self {
|
||||
self.set_time_source(Some(time_source));
|
||||
self
|
||||
}
|
||||
|
||||
#[doc(hidden)] // because they only exist for tests
|
||||
pub fn set_time_source(&mut self, time_source: Option<TimeSource>) -> &mut Self {
|
||||
pub fn set_time_source(&mut self, time_source: Option<SharedTimeSource>) -> &mut Self {
|
||||
self.time_source = time_source;
|
||||
self
|
||||
}
|
||||
|
@ -346,37 +346,45 @@ mod tests {
|
|||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use aws_smithy_async::rt::sleep::{SharedAsyncSleep, TokioSleep};
|
||||
use aws_smithy_async::test_util::{instant_time_and_sleep, ManualTimeSource};
|
||||
use aws_smithy_async::time::{SharedTimeSource, TimeSource};
|
||||
use tracing::info;
|
||||
use tracing_test::traced_test;
|
||||
|
||||
use crate::provider::SharedCredentialsProvider;
|
||||
use crate::{
|
||||
cache::ProvideCachedCredentials, credential_fn::provide_credentials_fn,
|
||||
provider::error::CredentialsError, time_source::TestingTimeSource, Credentials,
|
||||
provider::error::CredentialsError, Credentials,
|
||||
};
|
||||
|
||||
use super::{
|
||||
LazyCredentialsCache, TimeSource, DEFAULT_BUFFER_TIME, DEFAULT_CREDENTIAL_EXPIRATION,
|
||||
LazyCredentialsCache, DEFAULT_BUFFER_TIME, DEFAULT_CREDENTIAL_EXPIRATION,
|
||||
DEFAULT_LOAD_TIMEOUT,
|
||||
};
|
||||
|
||||
const BUFFER_TIME_NO_JITTER: fn() -> f64 = || 0_f64;
|
||||
|
||||
fn test_provider(
|
||||
time: TimeSource,
|
||||
time: impl TimeSource + 'static,
|
||||
buffer_time_jitter_fraction: fn() -> f64,
|
||||
load_list: Vec<crate::provider::Result>,
|
||||
) -> LazyCredentialsCache {
|
||||
let load_list = Arc::new(Mutex::new(load_list));
|
||||
LazyCredentialsCache::new(
|
||||
time,
|
||||
SharedTimeSource::new(time),
|
||||
SharedAsyncSleep::new(TokioSleep::new()),
|
||||
SharedCredentialsProvider::new(provide_credentials_fn(move || {
|
||||
let list = load_list.clone();
|
||||
async move {
|
||||
let next = list.lock().unwrap().remove(0);
|
||||
info!("refreshing the credentials to {:?}", next);
|
||||
next
|
||||
let mut list = list.lock().unwrap();
|
||||
if list.len() > 0 {
|
||||
let next = list.remove(0);
|
||||
info!("refreshing the credentials to {:?}", next);
|
||||
next
|
||||
} else {
|
||||
drop(list);
|
||||
panic!("no more credentials")
|
||||
}
|
||||
}
|
||||
})),
|
||||
DEFAULT_LOAD_TIMEOUT,
|
||||
|
@ -405,13 +413,13 @@ mod tests {
|
|||
#[traced_test]
|
||||
#[tokio::test]
|
||||
async fn initial_populate_credentials() {
|
||||
let time = TestingTimeSource::new(UNIX_EPOCH);
|
||||
let time = ManualTimeSource::new(UNIX_EPOCH);
|
||||
let provider = SharedCredentialsProvider::new(provide_credentials_fn(|| async {
|
||||
info!("refreshing the credentials");
|
||||
Ok(credentials(1000))
|
||||
}));
|
||||
let credentials_cache = LazyCredentialsCache::new(
|
||||
TimeSource::testing(&time),
|
||||
SharedTimeSource::new(time),
|
||||
SharedAsyncSleep::new(TokioSleep::new()),
|
||||
provider,
|
||||
DEFAULT_LOAD_TIMEOUT,
|
||||
|
@ -433,9 +441,9 @@ mod tests {
|
|||
#[traced_test]
|
||||
#[tokio::test]
|
||||
async fn reload_expired_credentials() {
|
||||
let mut time = TestingTimeSource::new(epoch_secs(100));
|
||||
let time = ManualTimeSource::new(epoch_secs(100));
|
||||
let credentials_cache = test_provider(
|
||||
TimeSource::testing(&time),
|
||||
time.clone(),
|
||||
BUFFER_TIME_NO_JITTER,
|
||||
vec![
|
||||
Ok(credentials(1000)),
|
||||
|
@ -457,9 +465,9 @@ mod tests {
|
|||
#[traced_test]
|
||||
#[tokio::test]
|
||||
async fn load_failed_error() {
|
||||
let mut time = TestingTimeSource::new(epoch_secs(100));
|
||||
let time = ManualTimeSource::new(epoch_secs(100));
|
||||
let credentials_cache = test_provider(
|
||||
TimeSource::testing(&time),
|
||||
time.clone(),
|
||||
BUFFER_TIME_NO_JITTER,
|
||||
vec![
|
||||
Ok(credentials(1000)),
|
||||
|
@ -484,9 +492,9 @@ mod tests {
|
|||
.build()
|
||||
.unwrap();
|
||||
|
||||
let time = TestingTimeSource::new(epoch_secs(0));
|
||||
let time = ManualTimeSource::new(epoch_secs(0));
|
||||
let credentials_cache = Arc::new(test_provider(
|
||||
TimeSource::testing(&time),
|
||||
time.clone(),
|
||||
BUFFER_TIME_NO_JITTER,
|
||||
vec![
|
||||
Ok(credentials(500)),
|
||||
|
@ -497,16 +505,15 @@ mod tests {
|
|||
],
|
||||
));
|
||||
|
||||
let locked_time = Arc::new(Mutex::new(time));
|
||||
|
||||
for i in 0..4 {
|
||||
// credentials are available up until 4500 seconds after the unix epoch
|
||||
// 4*50 = 200 tasks are launched => we can advance time 4500/20 => 225 seconds per advance
|
||||
for _ in 0..4 {
|
||||
let mut tasks = Vec::new();
|
||||
for j in 0..50 {
|
||||
for _ in 0..50 {
|
||||
let credentials_cache = credentials_cache.clone();
|
||||
let time = locked_time.clone();
|
||||
let time = time.clone();
|
||||
tasks.push(rt.spawn(async move {
|
||||
let now = epoch_secs(i * 1000 + (4 * j));
|
||||
time.lock().unwrap().set_time(now);
|
||||
let now = time.advance(Duration::from_secs(22));
|
||||
|
||||
let creds = credentials_cache
|
||||
.provide_cached_credentials()
|
||||
|
@ -529,15 +536,15 @@ mod tests {
|
|||
#[tokio::test]
|
||||
#[traced_test]
|
||||
async fn load_timeout() {
|
||||
let time = TestingTimeSource::new(epoch_secs(100));
|
||||
let (time, sleep) = instant_time_and_sleep(epoch_secs(100));
|
||||
let credentials_cache = LazyCredentialsCache::new(
|
||||
TimeSource::testing(&time),
|
||||
SharedAsyncSleep::new(TokioSleep::new()),
|
||||
SharedTimeSource::new(time.clone()),
|
||||
SharedAsyncSleep::new(sleep),
|
||||
SharedCredentialsProvider::new(provide_credentials_fn(|| async {
|
||||
aws_smithy_async::future::never::Never::new().await;
|
||||
Ok(credentials(1000))
|
||||
})),
|
||||
Duration::from_millis(5),
|
||||
Duration::from_secs(5),
|
||||
DEFAULT_BUFFER_TIME,
|
||||
BUFFER_TIME_NO_JITTER,
|
||||
DEFAULT_CREDENTIAL_EXPIRATION,
|
||||
|
@ -547,14 +554,15 @@ mod tests {
|
|||
credentials_cache.provide_cached_credentials().await,
|
||||
Err(CredentialsError::ProviderTimedOut { .. })
|
||||
));
|
||||
assert_eq!(time.now(), epoch_secs(105));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn buffer_time_jitter() {
|
||||
let mut time = TestingTimeSource::new(epoch_secs(100));
|
||||
let time = ManualTimeSource::new(epoch_secs(100));
|
||||
let buffer_time_jitter_fraction = || 0.5_f64;
|
||||
let credentials_cache = test_provider(
|
||||
TimeSource::testing(&time),
|
||||
time.clone(),
|
||||
buffer_time_jitter_fraction,
|
||||
vec![Ok(credentials(1000)), Ok(credentials(2000))],
|
||||
);
|
||||
|
|
|
@ -21,7 +21,5 @@ pub mod cache;
|
|||
pub mod credential_fn;
|
||||
mod credentials_impl;
|
||||
pub mod provider;
|
||||
#[doc(hidden)]
|
||||
pub mod time_source;
|
||||
|
||||
pub use credentials_impl::Credentials;
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
use aws_smithy_async::time::{SharedTimeSource, TimeSource as TimeSourceTrait};
|
||||
use std::ops::Deref;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
impl TimeSourceTrait for TimeSource {
|
||||
fn now(&self) -> SystemTime {
|
||||
self.now()
|
||||
}
|
||||
}
|
||||
|
||||
/// Time source abstraction
|
||||
///
|
||||
/// Simple abstraction representing time either real-time or manually-specified for testing
|
||||
#[derive(Debug, Clone)]
|
||||
// TODO(breakingChangeWindow): Delete this struct
|
||||
pub struct TimeSource(Inner);
|
||||
|
||||
impl TimeSource {
|
||||
/// Creates `TimeSource` from the manually specified `time_source`.
|
||||
pub fn testing(time_source: &TestingTimeSource) -> Self {
|
||||
TimeSource(Inner::Testing(time_source.clone()))
|
||||
}
|
||||
|
||||
/// Creates `TimeSource` from a shared time source
|
||||
pub fn shared(time_source: SharedTimeSource) -> Self {
|
||||
TimeSource(Inner::Shared(time_source))
|
||||
}
|
||||
|
||||
/// Returns the current system time based on the mode.
|
||||
pub fn now(&self) -> SystemTime {
|
||||
match &self.0 {
|
||||
Inner::Default => SystemTime::now(),
|
||||
Inner::Testing(testing) => testing.now(),
|
||||
Inner::Shared(ts) => ts.now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TimeSource {
|
||||
/// Creates `TimeSource` from the current system time.
|
||||
fn default() -> Self {
|
||||
TimeSource(Inner::Default)
|
||||
}
|
||||
}
|
||||
|
||||
/// Time Source that can be manually moved for tests
|
||||
/// > This has been superseded by [`aws_smithy_async::time::TimeSource`] and will be removed in a
|
||||
/// > future release.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # struct Client {
|
||||
/// # // stub
|
||||
/// # }
|
||||
/// #
|
||||
/// # impl Client {
|
||||
/// # fn with_timesource(ts: TimeSource) -> Self {
|
||||
/// # Client { }
|
||||
/// # }
|
||||
/// # }
|
||||
/// use aws_credential_types::time_source::{TestingTimeSource, TimeSource};
|
||||
/// use std::time::{UNIX_EPOCH, Duration};
|
||||
/// let mut time = TestingTimeSource::new(UNIX_EPOCH);
|
||||
/// let client = Client::with_timesource(TimeSource::testing(&time));
|
||||
/// time.advance(Duration::from_secs(100));
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TestingTimeSource {
|
||||
queries: Arc<Mutex<Vec<SystemTime>>>,
|
||||
now: Arc<Mutex<SystemTime>>,
|
||||
}
|
||||
|
||||
impl TestingTimeSource {
|
||||
/// Creates `TestingTimeSource` with `start_time`.
|
||||
pub fn new(start_time: SystemTime) -> Self {
|
||||
Self {
|
||||
queries: Default::default(),
|
||||
now: Arc::new(Mutex::new(start_time)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets time to the specified `time`.
|
||||
pub fn set_time(&mut self, time: SystemTime) {
|
||||
let mut now = self.now.lock().unwrap();
|
||||
*now = time;
|
||||
}
|
||||
|
||||
/// Advances time by `delta`.
|
||||
pub fn advance(&mut self, delta: Duration) {
|
||||
let mut now = self.now.lock().unwrap();
|
||||
*now += delta;
|
||||
}
|
||||
|
||||
/// Returns a `Vec` of queried times so far.
|
||||
pub fn queries(&self) -> impl Deref<Target = Vec<SystemTime>> + '_ {
|
||||
self.queries.lock().unwrap()
|
||||
}
|
||||
|
||||
/// Returns the current time understood by `TestingTimeSource`.
|
||||
pub fn now(&self) -> SystemTime {
|
||||
let ts = *self.now.lock().unwrap();
|
||||
self.queries.lock().unwrap().push(ts);
|
||||
ts
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Inner {
|
||||
Default,
|
||||
Testing(TestingTimeSource),
|
||||
Shared(SharedTimeSource),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{TestingTimeSource, TimeSource};
|
||||
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
#[test]
|
||||
fn default_time_source_should_not_panic_on_calling_now() {
|
||||
let time_source = TimeSource::default();
|
||||
// no panics
|
||||
let _ = time_source.now();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testing_time_source_should_behave_as_expected() {
|
||||
let mut testing = TestingTimeSource::new(UNIX_EPOCH);
|
||||
let time_source = TimeSource::testing(&testing);
|
||||
assert_eq!(time_source.now(), UNIX_EPOCH);
|
||||
testing.advance(Duration::from_secs(10));
|
||||
assert_eq!(time_source.now(), UNIX_EPOCH + Duration::from_secs(10));
|
||||
}
|
||||
}
|
|
@ -35,11 +35,43 @@ impl ManualTimeSource {
|
|||
.unwrap()
|
||||
.as_secs_f64()
|
||||
}
|
||||
|
||||
/// Creates a new [`ManualTimeSource`]
|
||||
pub fn new(start_time: SystemTime) -> ManualTimeSource {
|
||||
Self {
|
||||
start_time,
|
||||
log: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Advances the time of this time source by `duration`.
|
||||
pub fn advance(&self, duration: Duration) -> SystemTime {
|
||||
let mut log = self.log.lock().unwrap();
|
||||
log.push(duration);
|
||||
self._now(&log)
|
||||
}
|
||||
|
||||
fn _now(&self, log: &[Duration]) -> SystemTime {
|
||||
self.start_time + log.iter().sum::<Duration>()
|
||||
}
|
||||
|
||||
/// Sets the `time` of this manual time source.
|
||||
///
|
||||
/// # Panics
|
||||
/// This function panics if `time` < `now()`
|
||||
pub fn set_time(&self, time: SystemTime) {
|
||||
let mut log = self.log.lock().unwrap();
|
||||
let now = self._now(&log);
|
||||
if time < now {
|
||||
panic!("Cannot move time backwards!");
|
||||
}
|
||||
log.push(time.duration_since(now).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
impl TimeSource for ManualTimeSource {
|
||||
fn now(&self) -> SystemTime {
|
||||
self.start_time + self.log.lock().unwrap().iter().sum::<Duration>()
|
||||
self._now(&self.log.lock().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue