Repository: rusoto/rusoto (language: rust)

Issue:
Flickering profile provider test
I'm seeing this a few times in CI.  A recent example from TravisCI:

```
test profile::tests::profile_provider_profile_name ... FAILED
failures:
---- profile::tests::profile_provider_profile_name stdout ----
	thread 'profile::tests::profile_provider_profile_name' panicked at 'assertion failed: `(left == right)`
  left: `"default"`,
 right: `"bar"`', rusoto/credential/src/profile.rs:411:9
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:380
   3: std::panicking::default_hook
             at libstd/panicking.rs:390
   4: std::panicking::rust_panic_with_hook
             at libstd/panicking.rs:576
   5: std::panicking::begin_panic
             at libstd/panicking.rs:537
   6: std::panicking::begin_panic_fmt
             at libstd/panicking.rs:521
   7: rusoto_credential::profile::tests::profile_provider_profile_name
             at rusoto/credential/src/profile.rs:411
   8: <F as alloc::boxed::FnBox<A>>::call_box
             at libtest/lib.rs:1453
             at /checkout/src/libcore/ops/function.rs:223
             at /checkout/src/liballoc/boxed.rs:788
   9: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:102
failures:
    profile::tests::profile_provider_profile_name
test result: FAILED. 22 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--lib'
```

Another example:

```
test profile::tests::profile_provider_profile_name ... FAILED
failures:
---- profile::tests::profile_provider_profile_name stdout ----
    thread 'profile::tests::profile_provider_profile_name' panicked at 'assertion failed: `(left == right)`
  left: `"default"`,
 right: `"bar"`', rusoto/credential/src/profile.rs:391:8
```

Line numbers differ because the second example is pre-async-PR merging. 😄 
Flickering profile provider test
I'm seeing this a few times in CI.  A recent example from TravisCI:

```
test profile::tests::profile_provider_profile_name ... FAILED
failures:
---- profile::tests::profile_provider_profile_name stdout ----
	thread 'profile::tests::profile_provider_profile_name' panicked at 'assertion failed: `(left == right)`
  left: `"default"`,
 right: `"bar"`', rusoto/credential/src/profile.rs:411:9
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:380
   3: std::panicking::default_hook
             at libstd/panicking.rs:390
   4: std::panicking::rust_panic_with_hook
             at libstd/panicking.rs:576
   5: std::panicking::begin_panic
             at libstd/panicking.rs:537
   6: std::panicking::begin_panic_fmt
             at libstd/panicking.rs:521
   7: rusoto_credential::profile::tests::profile_provider_profile_name
             at rusoto/credential/src/profile.rs:411
   8: <F as alloc::boxed::FnBox<A>>::call_box
             at libtest/lib.rs:1453
             at /checkout/src/libcore/ops/function.rs:223
             at /checkout/src/liballoc/boxed.rs:788
   9: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:102
failures:
    profile::tests::profile_provider_profile_name
test result: FAILED. 22 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--lib'
```

Another example:

```
test profile::tests::profile_provider_profile_name ... FAILED
failures:
---- profile::tests::profile_provider_profile_name stdout ----
    thread 'profile::tests::profile_provider_profile_name' panicked at 'assertion failed: `(left == right)`
  left: `"default"`,
 right: `"bar"`', rusoto/credential/src/profile.rs:391:8
```

Line numbers differ because the second example is pre-async-PR merging. 😄 


Discussion / hints:
This are race conditions from environment variable changes in other tests. We need to add locking on  ENV_MUTEX to more tests. I will fix that.
This are race conditions from environment variable changes in other tests. We need to add locking on  ENV_MUTEX to more tests. I will fix that.

Fix patch:
diff --git a/rusoto/credential/src/profile.rs b/rusoto/credential/src/profile.rs
index 7794f0cf18a..f2058bd82a4 100644
--- a/rusoto/credential/src/profile.rs
+++ b/rusoto/credential/src/profile.rs
@@ -13,6 +13,10 @@ use regex::Regex;
 
 use {AwsCredentials, CredentialsError, ProvideAwsCredentials, in_ten_minutes};
 
+const AWS_PROFILE: &str = "AWS_PROFILE";
+const AWS_SHARED_CREDENTIALS_FILE: &str = "AWS_SHARED_CREDENTIALS_FILE";
+const DEFAULT: &str = "default";
+
 /// Provides AWS credentials from a profile in a credentials file.
 #[derive(Clone, Debug)]
 pub struct ProfileProvider {
@@ -65,7 +69,7 @@ impl ProfileProvider {
     /// 1. if set and not empty, use value from environment variable ```AWS_SHARED_CREDENTIALS_FILE```
     /// 2. otherwise return `~/.aws/credentials` (Linux/Mac) resp. `%USERPROFILE%\.aws\credentials` (Windows)
     fn default_profile_location() -> Result<PathBuf, CredentialsError> {
-        let env = ProfileProvider::non_empty_env_var("AWS_SHARED_CREDENTIALS_FILE");
+        let env = ProfileProvider::non_empty_env_var(AWS_SHARED_CREDENTIALS_FILE);
         match env {
             Some(path) => Ok(PathBuf::from(path)),
             None => ProfileProvider::hardcoded_profile_location(),
@@ -90,7 +94,7 @@ impl ProfileProvider {
     /// 2. otherwise return ```"default"```
     /// see https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html.
     fn default_profile_name() -> String {
-         ProfileProvider::non_empty_env_var("AWS_PROFILE").unwrap_or("default".to_owned())
+         ProfileProvider::non_empty_env_var(AWS_PROFILE).unwrap_or(DEFAULT.to_owned())
     }
 
     /// Get a reference to the credentials file path.
@@ -300,7 +304,7 @@ mod tests {
         let profiles = result.ok().unwrap();
         assert_eq!(profiles.len(), 1);
 
-        let default_profile = profiles.get("default").expect(
+        let default_profile = profiles.get(DEFAULT).expect(
             "No Default profile in default_profile_credentials",
         );
         assert_eq!(default_profile.aws_access_key_id(), "foo");
@@ -328,7 +332,6 @@ mod tests {
         );
         assert_eq!(bar_profile.aws_access_key_id(), "bar_access_key");
         assert_eq!(bar_profile.aws_secret_access_key(), "bar_secret_key");
-
     }
 
     #[test]
@@ -340,7 +343,7 @@ mod tests {
         let profiles = result.ok().unwrap();
         assert_eq!(profiles.len(), 1);
 
-        let default_profile = profiles.get("default").expect(
+        let default_profile = profiles.get(DEFAULT).expect(
             "No default profile in full_profile_credentials",
         );
         assert_eq!(default_profile.aws_access_key_id(), "foo");
@@ -366,28 +369,28 @@ mod tests {
     fn profile_provider_via_environment_variable() {
         let _guard = lock(&ENV_MUTEX);
         let credentials_path = "tests/sample-data/default_profile_credentials";
-        env::set_var("AWS_SHARED_CREDENTIALS_FILE", credentials_path);
+        env::set_var(AWS_SHARED_CREDENTIALS_FILE, credentials_path);
         let result = ProfileProvider::new();
         assert!(result.is_ok());
         let provider = result.unwrap();
         assert_eq!(provider.file_path().to_str().unwrap(), credentials_path);
-        env::remove_var("AWS_SHARED_CREDENTIALS_FILE");
+        env::remove_var(AWS_SHARED_CREDENTIALS_FILE);
     }
 
     #[test]
     fn profile_provider_profile_name_via_environment_variable() {
         let _guard = lock(&ENV_MUTEX);
         let credentials_path = "tests/sample-data/multiple_profile_credentials";
-        env::set_var("AWS_SHARED_CREDENTIALS_FILE", credentials_path);
-        env::set_var("AWS_PROFILE", "bar");
+        env::set_var(AWS_SHARED_CREDENTIALS_FILE, credentials_path);
+        env::set_var(AWS_PROFILE, "bar");
         let result = ProfileProvider::new();
         assert!(result.is_ok());
         let provider = result.unwrap();
         assert_eq!(provider.file_path().to_str().unwrap(), credentials_path);
         let creds = provider.credentials().wait();
         assert_eq!(creds.unwrap().aws_access_key_id(), "bar_access_key");
-        env::remove_var("AWS_SHARED_CREDENTIALS_FILE");
-        env::remove_var("AWS_PROFILE");
+        env::remove_var(AWS_SHARED_CREDENTIALS_FILE);
+        env::remove_var(AWS_PROFILE);
     } 
 
     #[test]
@@ -407,8 +410,9 @@ mod tests {
 
     #[test]
     fn profile_provider_profile_name() {
+        let _guard = lock(&ENV_MUTEX);
         let mut provider = ProfileProvider::new().unwrap();
-        assert_eq!("default", provider.profile());
+        assert_eq!(DEFAULT, provider.profile());
         provider.set_profile("foo");
         assert_eq!("foo", provider.profile());
     }
@@ -454,7 +458,7 @@ mod tests {
         let profiles = result.ok().unwrap();
         assert_eq!(profiles.len(), 1);
 
-        let default_profile = profiles.get("default").expect(
+        let default_profile = profiles.get(DEFAULT).expect(
             "No default profile in full_profile_credentials",
         );
         assert_eq!(default_profile.aws_access_key_id(), "foo");
@@ -464,46 +468,46 @@ mod tests {
     #[test]
     fn default_profile_name_from_env_var(){
         let _guard = lock(&ENV_MUTEX);
-        env::set_var("AWS_PROFILE", "bar");
+        env::set_var(AWS_PROFILE, "bar");
         assert_eq!("bar", ProfileProvider::default_profile_name());
-        env::remove_var("AWS_PROFILE");
+        env::remove_var(AWS_PROFILE);
     }
 
     #[test]
     fn default_profile_name_from_empty_env_var(){
         let _guard = lock(&ENV_MUTEX);
-        env::set_var("AWS_PROFILE", "");
-        assert_eq!("default", ProfileProvider::default_profile_name());
-        env::remove_var("AWS_PROFILE");
+        env::set_var(AWS_PROFILE, "");
+        assert_eq!(DEFAULT, ProfileProvider::default_profile_name());
+        env::remove_var(AWS_PROFILE);
     }
 
     #[test]
     fn default_profile_name(){
         let _guard = lock(&ENV_MUTEX);
-        env::remove_var("AWS_PROFILE");
-        assert_eq!("default", ProfileProvider::default_profile_name());
+        env::remove_var(AWS_PROFILE);
+        assert_eq!(DEFAULT, ProfileProvider::default_profile_name());
     }
 
     #[test]
     fn default_profile_location_from_env_var(){
         let _guard = lock(&ENV_MUTEX);
-        env::set_var("AWS_SHARED_CREDENTIALS_FILE", "bar");
+        env::set_var(AWS_SHARED_CREDENTIALS_FILE, "bar");
         assert_eq!(Ok(PathBuf::from("bar")), ProfileProvider::default_profile_location());
-        env::remove_var("AWS_SHARED_CREDENTIALS_FILE");
+        env::remove_var(AWS_SHARED_CREDENTIALS_FILE);
     }
 
     #[test]
     fn default_profile_location_from_empty_env_var(){
         let _guard = lock(&ENV_MUTEX);
-        env::set_var("AWS_SHARED_CREDENTIALS_FILE", "");
+        env::set_var(AWS_SHARED_CREDENTIALS_FILE, "");
         assert_eq!(ProfileProvider::hardcoded_profile_location(), ProfileProvider::default_profile_location());
-        env::remove_var("AWS_SHARED_CREDENTIALS_FILE");
+        env::remove_var(AWS_SHARED_CREDENTIALS_FILE);
     }
 
     #[test]
     fn default_profile_location(){
         let _guard = lock(&ENV_MUTEX);
-        env::remove_var("AWS_SHARED_CREDENTIALS_FILE");
+        env::remove_var(AWS_SHARED_CREDENTIALS_FILE);
         assert_eq!(ProfileProvider::hardcoded_profile_location(), ProfileProvider::default_profile_location());
     }
 


Test patch: