diff --git a/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs b/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs index 1b2584d78c29..7e437c68ea56 100644 --- a/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs +++ b/sdk/identity/Azure.Identity/tests/DefaultAzureCredentialTests.cs @@ -38,7 +38,7 @@ public void ValidateCtorNoOptions() } [Test] - public void ValidateCtorIncludedInteractiveParam([Values(true, false)]bool includeInteractive) + public void ValidateCtorIncludedInteractiveParam([Values(true, false)] bool includeInteractive) { var cred = new DefaultAzureCredential(includeInteractive); @@ -110,7 +110,7 @@ public void ValidateCtorOptionsPassedToCredentials() [Test] [NonParallelizable] - public void ValidateEnvironmentBasedOptionsPassedToCredentials([Values]bool clientIdSpecified, [Values]bool usernameSpecified, [Values]bool tenantIdSpecified) + public void ValidateEnvironmentBasedOptionsPassedToCredentials([Values] bool clientIdSpecified, [Values] bool usernameSpecified, [Values] bool tenantIdSpecified) { var expClientId = clientIdSpecified ? Guid.NewGuid().ToString() : null; var expUsername = usernameSpecified ? Guid.NewGuid().ToString() : null; @@ -121,9 +121,11 @@ public void ValidateEnvironmentBasedOptionsPassedToCredentials([Values]bool clie bool onCreateVsCalled = false; bool onCreateVsCodeCalled = false; - using (new TestEnvVar("AZURE_CLIENT_ID", expClientId)) - using (new TestEnvVar("AZURE_USERNAME", expUsername)) - using (new TestEnvVar("AZURE_TENANT_ID", expTenantId)) + using (new TestEnvVar(new () + { + { "AZURE_CLIENT_ID", expClientId }, + { "AZURE_USERNAME", expUsername }, + { "AZURE_TENANT_ID", expTenantId } })) { var credFactory = new MockDefaultAzureCredentialFactory(CredentialPipeline.GetInstance(null)); @@ -191,9 +193,11 @@ public void ValidateEmptyEnvironmentBasedOptionsNotPassedToCredentials([Values] bool onCreateVsCalled = false; bool onCreateVsCodeCalled = false; - using (new TestEnvVar("AZURE_CLIENT_ID", expClientId)) - using (new TestEnvVar("AZURE_USERNAME", expUsername)) - using (new TestEnvVar("AZURE_TENANT_ID", expTenantId)) + using (new TestEnvVar(new () + { + { "AZURE_CLIENT_ID", expClientId }, + { "AZURE_USERNAME", expUsername }, + { "AZURE_TENANT_ID", expTenantId } })) { var credFactory = new MockDefaultAzureCredentialFactory(CredentialPipeline.GetInstance(null)); @@ -249,13 +253,13 @@ public void ValidateEmptyEnvironmentBasedOptionsNotPassedToCredentials([Values] } [Test] - public void ValidateCtorWithExcludeOptions([Values(true, false)]bool excludeEnvironmentCredential, - [Values(true, false)]bool excludeManagedIdentityCredential, - [Values(true, false)]bool excludeSharedTokenCacheCredential, - [Values(true, false)]bool excludeVisualStudioCredential, - [Values(true, false)]bool excludeVisualStudioCodeCredential, - [Values(true, false)]bool excludeCliCredential, - [Values(true, false)]bool excludeInteractiveBrowserCredential) + public void ValidateCtorWithExcludeOptions([Values(true, false)] bool excludeEnvironmentCredential, + [Values(true, false)] bool excludeManagedIdentityCredential, + [Values(true, false)] bool excludeSharedTokenCacheCredential, + [Values(true, false)] bool excludeVisualStudioCredential, + [Values(true, false)] bool excludeVisualStudioCodeCredential, + [Values(true, false)] bool excludeCliCredential, + [Values(true, false)] bool excludeInteractiveBrowserCredential) { var credFactory = new MockDefaultAzureCredentialFactory(CredentialPipeline.GetInstance(null)); @@ -311,13 +315,13 @@ public void ValidateCtorWithExcludeOptions([Values(true, false)]bool excludeEnvi } [Test] - public void ValidateAllUnavailable([Values(true, false)]bool excludeEnvironmentCredential, - [Values(true, false)]bool excludeManagedIdentityCredential, - [Values(true, false)]bool excludeSharedTokenCacheCredential, - [Values(true, false)]bool excludeVisualStudioCredential, - [Values(true, false)]bool excludeVisualStudioCodeCredential, - [Values(true, false)]bool excludeCliCredential, - [Values(true, false)]bool excludeInteractiveBrowserCredential) + public void ValidateAllUnavailable([Values(true, false)] bool excludeEnvironmentCredential, + [Values(true, false)] bool excludeManagedIdentityCredential, + [Values(true, false)] bool excludeSharedTokenCacheCredential, + [Values(true, false)] bool excludeVisualStudioCredential, + [Values(true, false)] bool excludeVisualStudioCodeCredential, + [Values(true, false)] bool excludeCliCredential, + [Values(true, false)] bool excludeInteractiveBrowserCredential) { if (excludeEnvironmentCredential && excludeManagedIdentityCredential && excludeSharedTokenCacheCredential && excludeVisualStudioCredential && excludeVisualStudioCodeCredential && excludeCliCredential && excludeInteractiveBrowserCredential) { @@ -401,7 +405,7 @@ public void ValidateAllUnavailable([Values(true, false)]bool excludeEnvironmentC } [Test] - public void ValidateUnhandledException([Values(0, 1, 2, 3, 4, 5, 6)]int exPossition) + public void ValidateUnhandledException([Values(0, 1, 2, 3, 4, 5, 6)] int exPossition) { var credFactory = new MockDefaultAzureCredentialFactory(CredentialPipeline.GetInstance(null)); @@ -541,7 +545,7 @@ public void ValidateUnhandledException([Values(0, 1, 2, 3, 4, 5, 6)]int exPossit } [Test] - public async Task ValidateSelectedCredentialCaching([Values(typeof(EnvironmentCredential), typeof(ManagedIdentityCredential), typeof(SharedTokenCacheCredential), typeof(VisualStudioCredential), typeof(VisualStudioCodeCredential), typeof(AzureCliCredential), typeof(InteractiveBrowserCredential))]Type availableCredential) + public async Task ValidateSelectedCredentialCaching([Values(typeof(EnvironmentCredential), typeof(ManagedIdentityCredential), typeof(SharedTokenCacheCredential), typeof(VisualStudioCredential), typeof(VisualStudioCodeCredential), typeof(AzureCliCredential), typeof(InteractiveBrowserCredential))] Type availableCredential) { var expToken = new AccessToken(Guid.NewGuid().ToString(), DateTimeOffset.MaxValue); diff --git a/sdk/identity/Azure.Identity/tests/DeviceCodeCredentialTests.cs b/sdk/identity/Azure.Identity/tests/DeviceCodeCredentialTests.cs index 3a85d9b1707d..fe4f4c4ce4c1 100644 --- a/sdk/identity/Azure.Identity/tests/DeviceCodeCredentialTests.cs +++ b/sdk/identity/Azure.Identity/tests/DeviceCodeCredentialTests.cs @@ -162,7 +162,7 @@ public async Task AuthenticateWithDeviceCodeMockVerifyCallbackCancellationAsync( var options = new TokenCredentialOptions() { Transport = mockTransport }; - var cancelSource = new CancellationTokenSource(1000); + var cancelSource = new CancellationTokenSource(100); var cred = InstrumentClient(new DeviceCodeCredential(VerifyDeviceCodeCallbackCancellationToken, ClientId, options: options)); diff --git a/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs b/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs index d331cc74d998..d156426acf82 100644 --- a/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs +++ b/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs @@ -8,6 +8,7 @@ using Azure.Core.TestFramework; using Azure.Identity.Tests.Mock; using System.Threading.Tasks; +using System.Collections.Generic; namespace Azure.Identity.Tests { @@ -57,16 +58,13 @@ public void CredentialConstructionClientSecret() [Test] public void CredentialConstructionClientCertificate() { - string clientIdBackup = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); - string tenantIdBackup = Environment.GetEnvironmentVariable("AZURE_TENANT_ID"); - string clientCertificateLocationBackup = Environment.GetEnvironmentVariable("AZURE_CLIENT_CERTIFICATE_PATH"); - - try + using (new TestEnvVar(new () + { + { "AZURE_CLIENT_ID", "mockclientid" }, + { "AZURE_TENANT_ID", "mocktenantid" }, + { "AZURE_CLIENT_CERTIFICATE_PATH", "mockcertificatepath" } + })) { - Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", "mockclientid"); - Environment.SetEnvironmentVariable("AZURE_TENANT_ID", "mocktenantid"); - Environment.SetEnvironmentVariable("AZURE_CLIENT_CERTIFICATE_PATH", "mockcertificatepath"); - var provider = new EnvironmentCredential(); var cred = provider.Credential as ClientCertificateCredential; Assert.NotNull(cred); @@ -78,12 +76,6 @@ public void CredentialConstructionClientCertificate() Assert.NotNull(certProvider); Assert.AreEqual("mockcertificatepath", certProvider.CertificatePath); } - finally - { - Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", clientIdBackup); - Environment.SetEnvironmentVariable("AZURE_TENANT_ID", tenantIdBackup); - Environment.SetEnvironmentVariable("AZURE_CLIENT_CERTIFICATE_PATH", clientCertificateLocationBackup); - } } [Test] @@ -113,52 +105,26 @@ public async Task EnvironmentCredentialAuthenticationFailedException() await Task.CompletedTask; } - [NonParallelizable] - [Test] - public void AssertCredentialUnavailableWhenEmptyString() + public static IEnumerable AssertCredentialUnavailableWhenEmptyStringEnvironmentSettings() { - // ensure no env vars are set before starting the test - using (new TestEnvVar("AZURE_CLIENT_ID", null)) - using (new TestEnvVar("AZURE_TENANT_ID", null)) - using (new TestEnvVar("AZURE_CLIENT_SECRET", null)) - using (new TestEnvVar("AZURE_CLIENT_CERTIFICATE_PATH", null)) - using (new TestEnvVar("AZURE_USERNAME", null)) - using (new TestEnvVar("AZURE_PASSWORD", null)) - { - using (new TestEnvVar("AZURE_CLIENT_ID", "mockclientid")) - using (new TestEnvVar("AZURE_CLIENT_SECRET", "mockclientsecret")) - using (new TestEnvVar("AZURE_TENANT_ID", "mocktenantid")) - { - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_ID"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_SECRET"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_TENANT_ID"); - } - - using (new TestEnvVar("AZURE_CLIENT_ID", "mockclientid")) - using (new TestEnvVar("AZURE_CLIENT_CERTIFICATE_PATH", "mockcertpath")) - using (new TestEnvVar("AZURE_TENANT_ID", "mocktenantid")) - { - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_ID"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_CERTIFICATE_PATH"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_TENANT_ID"); - } - - using (new TestEnvVar("AZURE_USERNAME", "mockusername")) - using (new TestEnvVar("AZURE_PASSWORD", "mockpassword")) - using (new TestEnvVar("AZURE_TENANT_ID", "mocktenantid")) - using (new TestEnvVar("AZURE_CLIENT_ID", "mockclientid")) - { - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_CLIENT_ID"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_TENANT_ID"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_USERNAME"); - SetEnvVarToEmptyStringAndAssertCredentialUnavailable("AZURE_PASSWORD"); - } - } + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", string.Empty }, { "AZURE_CLIENT_SECRET", "mockclientsecret" }, { "AZURE_TENANT_ID", "mocktenantid" } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", "mockclientid" }, { "AZURE_CLIENT_SECRET", string.Empty }, { "AZURE_TENANT_ID", "mocktenantid" } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", "mockclientid" }, { "AZURE_CLIENT_SECRET", "mockclientsecret" }, { "AZURE_TENANT_ID", string.Empty } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", string.Empty }, { "AZURE_CLIENT_CERTIFICATE_PATH", "mockcertpath" }, { "AZURE_TENANT_ID", "mocktenantid" } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", "mockclientid" }, { "AZURE_CLIENT_CERTIFICATE_PATH", string.Empty }, { "AZURE_TENANT_ID", "mocktenantid" } } }; + yield return new object[] { new Dictionary { { "AZURE_CLIENT_ID", "mockclientid" }, { "AZURE_CLIENT_CERTIFICATE_PATH", "mockcertpath" }, { "AZURE_TENANT_ID", string.Empty } } }; + yield return new object[] { new Dictionary { { "AZURE_USERNAME", string.Empty }, { "AZURE_PASSWORD", "mockpassword" }, { "AZURE_TENANT_ID", "mocktenantid" }, { "AZURE_CLIENT_ID", "mockclientid" } } }; + yield return new object[] { new Dictionary { { "AZURE_USERNAME", "mockusername" }, { "AZURE_PASSWORD", string.Empty }, { "AZURE_TENANT_ID", "mocktenantid" }, { "AZURE_CLIENT_ID", "mockclientid" } } }; + yield return new object[] { new Dictionary { { "AZURE_USERNAME", "mockusername" }, { "AZURE_PASSWORD", "mockpassword" }, { "AZURE_TENANT_ID", string.Empty }, { "AZURE_CLIENT_ID", "mockclientid" } } }; + yield return new object[] { new Dictionary { { "AZURE_USERNAME", "mockusername" }, { "AZURE_PASSWORD", "mockpassword" }, { "AZURE_TENANT_ID", "mocktenantid" }, { "AZURE_CLIENT_ID", string.Empty } } }; } - private void SetEnvVarToEmptyStringAndAssertCredentialUnavailable(string envVar) + [NonParallelizable] + [Test] + [TestCaseSource(nameof(AssertCredentialUnavailableWhenEmptyStringEnvironmentSettings))] + public void AssertCredentialUnavailableWhenEmptyString(Dictionary environmentVars) { - using (new TestEnvVar(envVar, string.Empty)) + using (new TestEnvVar(environmentVars)) { var credential = InstrumentClient(new EnvironmentCredential()); diff --git a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialLiveTestBase.cs b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialLiveTestBase.cs index a181ca02065f..a8febc374389 100644 --- a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialLiveTestBase.cs +++ b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialLiveTestBase.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.Reflection; using Azure.Core.TestFramework; using Azure.Security.KeyVault.Secrets; @@ -38,27 +39,24 @@ public void ClearChallengeCacheforRecord() private class ManagedIdenityEnvironment : IDisposable { - private readonly TestEnvVar[] _envVars; + private readonly TestEnvVar _envVar; public ManagedIdenityEnvironment(IdentityTestEnvironment env) { - _envVars = new TestEnvVar[] - { - new TestEnvVar("IDENTITY_ENDPOINT", env.IdentityEndpoint), - new TestEnvVar("IMDS_ENDPOINT", env.ImdsEndpoint), - new TestEnvVar("MSI_ENDPOINT", env.MsiEndpoint), - new TestEnvVar("MSI_SECRET", env.MsiSecret), - new TestEnvVar("IDENTITY_HEADER", env.IdentityHeader), - new TestEnvVar("IDENTITY_SERVER_THUMBPRINT", env.IdentityServerThumbprint) - }; + _envVar = + new TestEnvVar( + new Dictionary + { + { "IDENTITY_ENDPOINT", env.IdentityEndpoint }, + { "IMDS_ENDPOINT", env.ImdsEndpoint }, + { "MSI_ENDPOINT", env.MsiEndpoint }, + { "MSI_SECRET", env.MsiSecret },{ "IDENTITY_HEADER", env.IdentityHeader }, + { "IDENTITY_SERVER_THUMBPRINT", env.IdentityServerThumbprint } }); } public void Dispose() { - foreach (TestEnvVar envVar in _envVars) - { - envVar.Dispose(); - } + _envVar.Dispose(); } } } diff --git a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs index 7c7ea52232fd..c7301c5840ba 100644 --- a/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs +++ b/sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; @@ -24,8 +25,7 @@ public ManagedIdentityCredentialTests(bool isAsync) : base(isAsync) [Test] public async Task VerifyImdsRequestMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", null)) - using (new TestEnvVar("MSI_SECRET", null)) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", null }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); @@ -65,8 +65,7 @@ public async Task VerifyImdsRequestMockAsync() [Test] public async Task VerifyImdsRequestWithClientIdMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", null)) - using (new TestEnvVar("MSI_SECRET", null)) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", null }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); @@ -108,8 +107,7 @@ public async Task VerifyImdsRequestWithClientIdMockAsync() [Test] public async Task VerifyAppService2017RequestMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", "mock-msi-secret")) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) { var response = new MockResponse(200); @@ -147,8 +145,7 @@ public async Task VerifyAppService2017RequestMockAsync() [Test] public async Task VerifyAppService2017RequestWithClientIdMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", "mock-msi-secret")) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) { var response = new MockResponse(200); @@ -189,8 +186,7 @@ public async Task VerifyAppService2017RequestWithClientIdMockAsync() [Test] public async Task VerifyAppService2019RequestMockAsync() { - using (new TestEnvVar("IDENTITY_ENDPOINT", "https://identity.endpoint/")) - using (new TestEnvVar("IDENTITY_HEADER", "mock-identity-header")) + using (new TestEnvVar(new () { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" } })) { var expectedToken = "mock-access-token"; var response = new MockResponse(200); @@ -222,10 +218,7 @@ public async Task VerifyAppService2019RequestMockAsync() // The test should be removed if and when support for this api version is added back public async Task VerifyAppService2017RequestWith2019EnvVarsMockAsync() { - using (new TestEnvVar("IDENTITY_ENDPOINT", "https://identity.endpoint/")) - using (new TestEnvVar("IDENTITY_HEADER", "mock-identity-header")) - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", "mock-msi-secret")) + using (new TestEnvVar(new () { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" }, { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", "mock-msi-secret" } })) { var response = new MockResponse(200); @@ -264,8 +257,7 @@ public async Task VerifyAppService2017RequestWith2019EnvVarsMockAsync() [Test] public async Task VerifyAppService2019RequestWithClientIdMockAsync() { - using (new TestEnvVar("IDENTITY_ENDPOINT", "https://identity.endpoint/")) - using (new TestEnvVar("IDENTITY_HEADER", "mock-identity-header")) + using (new TestEnvVar(new () { { "IDENTITY_ENDPOINT", "https://identity.endpoint/" }, { "IDENTITY_HEADER", "mock-identity-header" } })) { var expectedToken = "mock-access-token"; var response = new MockResponse(200); @@ -296,8 +288,7 @@ public async Task VerifyAppService2019RequestWithClientIdMockAsync() [Test] public async Task VerifyCloudShellMsiRequestMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", null)) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); @@ -341,8 +332,7 @@ public async Task VerifyCloudShellMsiRequestMockAsync() [Test] public async Task VerifyCloudShellMsiRequestWithClientIdMockAsync() { - using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) - using (new TestEnvVar("MSI_SECRET", null)) + using (new TestEnvVar(new () { { "MSI_ENDPOINT", "https://mock.msi.endpoint/" }, { "MSI_SECRET", null } })) { var response = new MockResponse(200); diff --git a/sdk/identity/Azure.Identity/tests/TestEnvVar.cs b/sdk/identity/Azure.Identity/tests/TestEnvVar.cs index fdf94b32ac2a..4a60f49c315b 100644 --- a/sdk/identity/Azure.Identity/tests/TestEnvVar.cs +++ b/sdk/identity/Azure.Identity/tests/TestEnvVar.cs @@ -2,29 +2,82 @@ // Licensed under the MIT License. using System; -using System.Collections; using System.Collections.Generic; -using System.Text; +using System.Threading; namespace Azure.Identity.Tests { internal class TestEnvVar : IDisposable { - private readonly string _origValue = null; - private readonly string _name; + private static SemaphoreSlim _lock = new SemaphoreSlim(1, 1); + private readonly Dictionary _originalValues = new Dictionary() + { + { "AZURE_USERNAME", EnvironmentVariables.Username}, + { "AZURE_PASSWORD", EnvironmentVariables.Password}, + { "AZURE_TENANT_ID", EnvironmentVariables.TenantId}, + { "AZURE_CLIENT_ID", EnvironmentVariables.ClientId}, + { "AZURE_CLIENT_SECRET", EnvironmentVariables.ClientSecret}, + { "AZURE_CLIENT_CERTIFICATE_PATH", EnvironmentVariables.ClientCertificatePath}, + { "IDENTITY_ENDPOINT", EnvironmentVariables.IdentityEndpoint}, + { "IDENTITY_HEADER", EnvironmentVariables.IdentityHeader}, + { "MSI_ENDPOINT", EnvironmentVariables.MsiEndpoint}, + { "MSI_SECRET", EnvironmentVariables.MsiSecret}, + { "IMDS_ENDPOINT", EnvironmentVariables.ImdsEndpoint}, + { "IDENTITY_SERVER_THUMBPRINT", EnvironmentVariables.IdentityServerThumbprint}, + }; public TestEnvVar(string name, string value) { - _name = name; + var acquired = _lock.Wait(TimeSpan.Zero); + if (!acquired) + { + throw new Exception($"Concurrent use of {nameof(TestEnvVar)}. Consider marking these tests as NonParallelizable."); + } + + _originalValues[name] = Environment.GetEnvironmentVariable(name); - _origValue = Environment.GetEnvironmentVariable(name); + CleanExistingEnvironmentVariables(); Environment.SetEnvironmentVariable(name, value); } + public TestEnvVar(Dictionary environmentVariables) + { + var acquired = _lock.Wait(TimeSpan.Zero); + if (!acquired) + { + throw new Exception($"Concurrent use of {nameof(TestEnvVar)}. Consider marking these tests as NonParallelizable."); + } + + foreach (var kvp in environmentVariables) + { + _originalValues[kvp.Key] = kvp.Value; + } + + CleanExistingEnvironmentVariables(); + + foreach (var kvp in environmentVariables) + { + Environment.SetEnvironmentVariable(kvp.Key, kvp.Value); + } + } + public void Dispose() { - Environment.SetEnvironmentVariable(_name, _origValue); + foreach (var kvp in _originalValues) + { + Environment.SetEnvironmentVariable(kvp.Key, kvp.Value); + } + _lock.Release(); + } + + // clear the existing values so that the test needs only set up the values relevant to it. + private void CleanExistingEnvironmentVariables() + { + foreach (var kvp in _originalValues) + { + Environment.SetEnvironmentVariable(kvp.Key, null); + } } } }