public void Dispose() { // Clear the cache after running each test. AppAuthResultCache.Clear(); // Delete environment variable Environment.SetEnvironmentVariable(Constants.TestCertUrlEnv, null); }
public async Task GetAppAuthResultCacheTest() { // Create two instances of AzureServiceTokenProvider based on AzureCliAccessTokenProvider. MockProcessManager mockProcessManager = new MockProcessManager(MockProcessManager.MockProcessManagerRequestType.Success); AzureCliAccessTokenProvider azureCliAccessTokenProvider = new AzureCliAccessTokenProvider(mockProcessManager); AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(azureCliAccessTokenProvider); AzureServiceTokenProvider azureServiceTokenProvider1 = new AzureServiceTokenProvider(azureCliAccessTokenProvider); List <Task> tasks = new List <Task>(); // ManualResetEvent will enable testing of SemaphoreSlim used in AzureServiceTokenProvider. ManualResetEvent manualResetEvent = new ManualResetEvent(false); // Use AzureServiceTokenProviders to get tokens in parallel. for (int i = 0; i < 5; i++) { Task task = Task.Run(async delegate { // This will prevent the next line from running, until manualResetEvent.Set() is called. // This will ensure all GetAccessTokenAsync calls are made at once. manualResetEvent.WaitOne(); await azureServiceTokenProvider.GetAccessTokenAsync(Constants.KeyVaultResourceId); }); tasks.Add(task); Task task1 = Task.Run(async delegate { manualResetEvent.WaitOne(); // This is using the other instance of AzureServiceTokenProvider. await azureServiceTokenProvider1.GetAccessTokenAsync(Constants.KeyVaultResourceId); }); tasks.Add(task1); } // This will cause GetAccessTokenAsync calls to be made concurrently. manualResetEvent.Set(); await Task.WhenAll(tasks); // Even though multiple calls are made to get token concurrently, using two different instances, the process manager should only be called once. // This test tells us that the cache is working as intended. Assert.Equal(1, mockProcessManager.HitCount); // Get the token again. This will test if the cache call before semaphore use is working as intended. for (int i = 0; i < 5; i++) { tasks.Add(azureServiceTokenProvider.GetAccessTokenAsync(Constants.KeyVaultResourceId)); } await Task.WhenAll(tasks); // The hit count should still be 1, since the token should be fetched from cache. Assert.Equal(1, mockProcessManager.HitCount); // Update the cache entry, to simulate token expiration. This updated token will expire in just less than 5 minutes. // In a real scenario, the token will expire after some time. // AppAuthResultCache should not return this, since it is about to expire. var tokenResponse = TokenResponse.Parse(TokenHelper.GetUserTokenResponse(5 * 60 - 2)); var authResult = AppAuthenticationResult.Create(tokenResponse, TokenResponse.DateFormat.DateTimeString); AppAuthResultCache.AddOrUpdate("ConnectionString:;Authority:;Resource:https://vault.azure.net/", new Tuple <AppAuthenticationResult, Principal>(authResult, null)); // Get the token again. for (int i = 0; i < 5; i++) { tasks.Add(azureServiceTokenProvider.GetAccessTokenAsync(Constants.KeyVaultResourceId)); } await Task.WhenAll(tasks); // Hit count should be 2 now, since new token should have been aquired. Assert.Equal(2, mockProcessManager.HitCount); }