public async Task TestTokenCredentialErrorAsync() { Exception exception = new Exception(); TestTokenCredential testTokenCredential = new TestTokenCredential(() => throw exception); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential)) { try { await tokenCredentialCache.GetTokenAsync(new CosmosDiagnosticsContextCore()); Assert.Fail("TokenCredentialCache.GetTokenAsync() is expected to fail but succeeded"); } catch (CosmosException cosmosException) { Assert.AreEqual(HttpStatusCode.Unauthorized, cosmosException.StatusCode); Assert.AreEqual((int)Azure.Documents.SubStatusCodes.FailedToGetAadToken, cosmosException.SubStatusCode); Assert.IsTrue(object.ReferenceEquals( exception, cosmosException.InnerException)); } // TokenCredential.GetTokenAsync() is retried for 3 times, so it should have been invoked for 4 times. Assert.AreEqual(3, testTokenCredential.NumTimesInvoked); } }
public async Task TestTokenCredentialBackgroundRefreshAsync_OnDispose() { string token1 = "Token1"; bool firstTimeGetToken = true; TestTokenCredential testTokenCredential = new TestTokenCredential(() => { if (firstTimeGetToken) { firstTimeGetToken = false; return(new ValueTask <AccessToken>(new AccessToken(token1, DateTimeOffset.UtcNow + TimeSpan.FromSeconds(10)))); } else { throw new Exception("Should not call twice"); } }); TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential, TimeSpan.FromMilliseconds(100)); string t1 = await tokenCredentialCache.GetTokenAsync(NoOpTrace.Singleton); this.ValidateSemaphoreIsReleased(tokenCredentialCache); tokenCredentialCache.Dispose(); Assert.AreEqual(token1, t1); await Task.Delay(1000); }
public async Task TestTokenCredentialMultiThreadAsync() { // When multiple thread calls TokenCredentialCache.GetTokenAsync and a valid cached token // is not available, TokenCredentialCache will only create one task to get token. int numTasks = 100; TestTokenCredential testTokenCredential = new TestTokenCredential(() => { Task.Delay(TimeSpan.FromSeconds(3)).Wait(); return(new ValueTask <AccessToken>(this.AccessToken)); }); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential)) { Task[] tasks = new Task[numTasks]; for (int i = 0; i < numTasks; i++) { tasks[i] = this.GetAndVerifyTokenAsync(tokenCredentialCache); } await Task.WhenAll(tasks); Assert.AreEqual(1, testTokenCredential.NumTimesInvoked); } }
public async Task TestTokenCredentialTimeoutAsync() { TestTokenCredential testTokenCredential = new TestTokenCredential(async() => { await Task.Delay(-1); return(new AccessToken("AccessToken", DateTimeOffset.MaxValue)); }); TimeSpan timeout = TimeSpan.FromSeconds(1); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache( tokenCredential: testTokenCredential, requestTimeout: timeout)) { try { await tokenCredentialCache.GetTokenAsync(new CosmosDiagnosticsContextCore()); Assert.Fail("TokenCredentialCache.GetTokenAsync() is expected to fail but succeeded"); } catch (CosmosException cosmosException) { Assert.AreEqual(HttpStatusCode.RequestTimeout, cosmosException.StatusCode); Assert.AreEqual((int)Azure.Documents.SubStatusCodes.FailedToGetAadToken, cosmosException.SubStatusCode); Assert.AreEqual($"TokenCredential.GetTokenAsync request timed out after {timeout}", cosmosException.InnerException.Message); } } }
public async Task TestTokenCredentialErrorAsync() { Exception exceptionToBeThrown = new Exception("Test Error Message"); TestTokenCredential testTokenCredential = new TestTokenCredential(() => throw exceptionToBeThrown); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential)) { try { await tokenCredentialCache.GetTokenAsync(NoOpTrace.Singleton); Assert.Fail("TokenCredentialCache.GetTokenAsync() is expected to fail but succeeded"); } catch (Exception exception) { // It should just throw the original exception and not be wrapped in a CosmosException. // This avoids any confusion on where the error was thrown from. Assert.IsTrue(object.ReferenceEquals( exception, exceptionToBeThrown)); } // TokenCredential.GetTokenAsync() is retried for 3 times, so it should have been invoked for 4 times. Assert.AreEqual(2, testTokenCredential.NumTimesInvoked); this.ValidateSemaphoreIsReleased(tokenCredentialCache); } }
private bool IsTokenRefreshInProgress(TokenCredentialCache tokenCredentialCache) { Type type = typeof(TokenCredentialCache); FieldInfo sempahoreFieldInfo = type.GetField("currentRefreshOperation", BindingFlags.NonPublic | BindingFlags.Instance); Task refreshToken = (Task)sempahoreFieldInfo.GetValue(tokenCredentialCache); return(refreshToken != null); }
private int GetSemaphoreCurrentCount(TokenCredentialCache tokenCredentialCache) { Type type = typeof(TokenCredentialCache); FieldInfo sempahoreFieldInfo = type.GetField("isTokenRefreshingLock", BindingFlags.NonPublic | BindingFlags.Instance); SemaphoreSlim semaphoreSlim = (SemaphoreSlim)sempahoreFieldInfo.GetValue(tokenCredentialCache); return(semaphoreSlim.CurrentCount); }
private async Task GetAndVerifyTokenAsync(TokenCredentialCache tokenCredentialCache) { string result = await tokenCredentialCache.GetTokenAsync(NoOpTrace.Singleton); Assert.AreEqual( this.AccessToken.Token, result); }
public async Task AadMockTest() { string databaseId = Guid.NewGuid().ToString(); string containerId = Guid.NewGuid().ToString(); using (CosmosClient cosmosClient = TestCommon.CreateCosmosClient()) { Database database = await cosmosClient.CreateDatabaseAsync(databaseId); Container container = await database.CreateContainerAsync( containerId, "/id"); } (string endpoint, string authKey) = TestCommon.GetAccountInfo(); LocalEmulatorTokenCredential simpleEmulatorTokenCredential = new LocalEmulatorTokenCredential(authKey); CosmosClientOptions clientOptions = new CosmosClientOptions() { ConnectionMode = ConnectionMode.Gateway, ConnectionProtocol = Protocol.Https }; using CosmosClient aadClient = new CosmosClient( endpoint, simpleEmulatorTokenCredential, clientOptions); TokenCredentialCache tokenCredentialCache = ((AuthorizationTokenProviderTokenCredential)aadClient.AuthorizationTokenProvider).tokenCredentialCache; // The refresh interval changes slightly based on how fast machine calculate the interval based on the expire time. Assert.IsTrue(15 <= tokenCredentialCache.BackgroundTokenCredentialRefreshInterval.Value.TotalMinutes, "Default background refresh should be 25% of the token life which is defaulted to 1hr"); Assert.IsTrue(tokenCredentialCache.BackgroundTokenCredentialRefreshInterval.Value.TotalMinutes > 14.7, "Default background refresh should be 25% of the token life which is defaulted to 1hr"); Database aadDatabase = await aadClient.GetDatabase(databaseId).ReadAsync(); Container aadContainer = await aadDatabase.GetContainer(containerId).ReadContainerAsync(); ToDoActivity toDoActivity = ToDoActivity.CreateRandomToDoActivity(); ItemResponse <ToDoActivity> itemResponse = await aadContainer.CreateItemAsync( toDoActivity, new PartitionKey(toDoActivity.id)); toDoActivity.cost = 42.42; await aadContainer.ReplaceItemAsync( toDoActivity, toDoActivity.id, new PartitionKey(toDoActivity.id)); await aadContainer.ReadItemAsync <ToDoActivity>( toDoActivity.id, new PartitionKey(toDoActivity.id)); await aadContainer.UpsertItemAsync(toDoActivity); await aadContainer.DeleteItemAsync <ToDoActivity>( toDoActivity.id, new PartitionKey(toDoActivity.id)); }
public async Task TestTokenCredentialCacheHappyPathAsync() { TestTokenCredential testTokenCredential = new TestTokenCredential(() => new ValueTask <AccessToken>(this.AccessToken)); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential)) { await this.GetAndVerifyTokenAsync(tokenCredentialCache); } }
public async Task TestTokenCredentialFailedToRefreshAsync() { string token = "Token"; bool firstTimeGetToken = true; Exception exception = new Exception(); TestTokenCredential testTokenCredential = new TestTokenCredential(() => { if (firstTimeGetToken) { firstTimeGetToken = false; return(new ValueTask <AccessToken>(new AccessToken(token, DateTimeOffset.UtcNow + TimeSpan.FromSeconds(6)))); } else { throw exception; } }); using ITrace trace = Trace.GetRootTrace("test"); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential)) { Assert.AreEqual(token, await tokenCredentialCache.GetTokenAsync(trace)); // Token is valid for 6 seconds. Client TokenCredentialRefreshBuffer is set to 5 seconds. // After waiting for 2 seconds, the cache token is still valid, but it will be refreshed in the background. await Task.Delay(TimeSpan.FromSeconds(2)); Assert.AreEqual(token, await tokenCredentialCache.GetTokenAsync(trace)); // Token refreshes fails except for the first time, but the cached token will be served as long as it is valid. await Task.Delay(TimeSpan.FromSeconds(3)); Assert.AreEqual(token, await tokenCredentialCache.GetTokenAsync(trace)); // Cache token has expired, and it fails to refresh. await Task.Delay(TimeSpan.FromSeconds(2)); try { await tokenCredentialCache.GetTokenAsync(trace); Assert.Fail("TokenCredentialCache.GetTokenAsync() is expected to fail but succeeded"); } catch (CosmosException cosmosException) { Assert.AreEqual(HttpStatusCode.Unauthorized, cosmosException.StatusCode); Assert.AreEqual((int)Azure.Documents.SubStatusCodes.FailedToGetAadToken, cosmosException.SubStatusCode); Assert.IsTrue(object.ReferenceEquals( exception, cosmosException.InnerException)); } } }
public async Task TestTokenCredentialBackgroundRefreshAsync() { // When token is within tokenCredentialRefreshBuffer of expiry, start background task to refresh token, // but return the cached token. string token1 = "Token1"; string token2 = "Token2"; bool firstTimeGetToken = true; TestTokenCredential testTokenCredential = new TestTokenCredential(() => { if (firstTimeGetToken) { firstTimeGetToken = false; return(new ValueTask <AccessToken>(new AccessToken(token1, DateTimeOffset.UtcNow + TimeSpan.FromSeconds(10)))); } else { return(new ValueTask <AccessToken>(new AccessToken(token2, DateTimeOffset.MaxValue))); } }); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential)) { string t1 = await tokenCredentialCache.GetTokenAsync(NoOpTrace.Singleton); Assert.AreEqual(token1, t1); // Token is valid for 6 seconds. Client TokenCredentialRefreshBuffer is set to 5 seconds. // After waiting for 2 seconds, the cache token is still valid, but it will be refreshed in the background. await Task.Delay(TimeSpan.FromSeconds(2)); string t2 = await tokenCredentialCache.GetTokenAsync(NoOpTrace.Singleton); Assert.AreEqual(token1, t2); // Wait until the background refresh occurs. while (testTokenCredential.NumTimesInvoked == 1) { await Task.Delay(500); } string t3 = await tokenCredentialCache.GetTokenAsync(NoOpTrace.Singleton); Assert.AreEqual(token2, t3); Assert.AreEqual(2, testTokenCredential.NumTimesInvoked); this.ValidateSemaphoreIsReleased(tokenCredentialCache); } }
public async Task TestTokenCredentialBackgroundRefreshAsync() { // When token is within tokenCredentialRefreshBuffer of expiry, start background task to refresh token, // but return the cached token. string token1 = "Token1"; string token2 = "Token2"; bool firstTimeGetToken = true; TestTokenCredential testTokenCredential = new TestTokenCredential(() => { if (firstTimeGetToken) { firstTimeGetToken = false; return(new ValueTask <AccessToken>(new AccessToken(token1, DateTimeOffset.UtcNow + TimeSpan.FromSeconds(10)))); } else { Task.Delay(TimeSpan.FromSeconds(.5)).Wait(); return(new ValueTask <AccessToken>(new AccessToken(token2, DateTimeOffset.MaxValue))); } }); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential)) { string t1 = await tokenCredentialCache.GetTokenAsync(new CosmosDiagnosticsContextCore()); Assert.AreEqual(token1, t1); // Token is valid for 6 seconds. Client TokenCredentialRefreshBuffer is set to 5 seconds. // After waiting for 2 seconds, the cache token is still valid, but it will be refreshed in the background. await Task.Delay(TimeSpan.FromSeconds(2)); string t2 = await tokenCredentialCache.GetTokenAsync(new CosmosDiagnosticsContextCore()); Assert.AreEqual(token1, t2); // After waiting for another 4 seconds (5 seconds for background refresh with .5 second delay), token1 is still valid, // but cached token has been refreshed to token2 by the background task started before. await Task.Delay(TimeSpan.FromSeconds(4)); string t3 = await tokenCredentialCache.GetTokenAsync(new CosmosDiagnosticsContextCore()); Assert.AreEqual(token2, t3); Assert.AreEqual(2, testTokenCredential.NumTimesInvoked); } }
public async Task TestTokenCredentialMultiThreadAsync() { // When multiple thread calls TokenCredentialCache.GetTokenAsync and a valid cached token // is not available, TokenCredentialCache will only create one task to get token. int numTasks = 100; bool delayTokenRefresh = true; TestTokenCredential testTokenCredential = new TestTokenCredential(async() => { while (delayTokenRefresh) { await Task.Delay(TimeSpan.FromMilliseconds(10)); } return(this.AccessToken); }); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential)) { Task[] tasks = new Task[numTasks]; for (int i = 0; i < numTasks; i++) { tasks[i] = Task.Run(() => this.GetAndVerifyTokenAsync(tokenCredentialCache)); } bool waitForTasksToStart = false; do { waitForTasksToStart = tasks.Where(x => x.Status == TaskStatus.Created).Any(); await Task.Delay(TimeSpan.FromMilliseconds(10)); } while (waitForTasksToStart); // Verify a task took the semaphore lock bool isRefreshing = false; do { isRefreshing = this.IsTokenRefreshInProgress(tokenCredentialCache); await Task.Delay(TimeSpan.FromMilliseconds(10)); } while (!isRefreshing); delayTokenRefresh = false; await Task.WhenAll(tasks); this.ValidateSemaphoreIsReleased(tokenCredentialCache); Assert.AreEqual(1, testTokenCredential.NumTimesInvoked); } }
public async Task AadMockRefreshTest() { int getAadTokenCount = 0; void GetAadTokenCallBack( TokenRequestContext context, CancellationToken token) { getAadTokenCount++; } (string endpoint, string authKey) = TestCommon.GetAccountInfo(); LocalEmulatorTokenCredential simpleEmulatorTokenCredential = new LocalEmulatorTokenCredential( authKey, GetAadTokenCallBack); CosmosClientOptions clientOptions = new CosmosClientOptions() { TokenCredentialBackgroundRefreshInterval = TimeSpan.FromSeconds(1) }; Assert.AreEqual(0, getAadTokenCount); using CosmosClient aadClient = new CosmosClient( endpoint, simpleEmulatorTokenCredential, clientOptions); DocumentClient documentClient = aadClient.ClientContext.DocumentClient; TokenCredentialCache tokenCredentialCache = ((AuthorizationTokenProviderTokenCredential)aadClient.AuthorizationTokenProvider).tokenCredentialCache; Assert.AreEqual(TimeSpan.FromSeconds(1), tokenCredentialCache.BackgroundTokenCredentialRefreshInterval); Assert.AreEqual(1, getAadTokenCount); await aadClient.ReadAccountAsync(); await aadClient.ReadAccountAsync(); await aadClient.ReadAccountAsync(); // Should use cached token Assert.AreEqual(1, getAadTokenCount); // Token should be refreshed after 1 second await Task.Delay(TimeSpan.FromSeconds(1.2)); Assert.AreEqual(2, getAadTokenCount); }
public void TestTokenCredentialCacheMaxAndMinValues() { try { TimeSpan toLarge = TimeSpan.MaxValue - TimeSpan.FromMilliseconds(1); new TokenCredentialCache( new Mock <TokenCredential>().Object, CosmosAuthorizationTests.AccountEndpoint, backgroundTokenCredentialRefreshInterval: toLarge); Assert.Fail("Should throw ArgumentException"); } catch (ArgumentException ae) { Assert.IsTrue(ae.ToString().Contains("backgroundTokenCredentialRefreshInterval")); } try { new TokenCredentialCache( new Mock <TokenCredential>().Object, CosmosAuthorizationTests.AccountEndpoint, backgroundTokenCredentialRefreshInterval: TimeSpan.MinValue); Assert.Fail("Should throw ArgumentException"); } catch (ArgumentException ae) { Assert.IsTrue(ae.ToString().Contains("backgroundTokenCredentialRefreshInterval")); } try { new TokenCredentialCache( new Mock <TokenCredential>().Object, CosmosAuthorizationTests.AccountEndpoint, backgroundTokenCredentialRefreshInterval: TimeSpan.Zero); Assert.Fail("Should throw ArgumentException"); } catch (ArgumentException ae) { Assert.IsTrue(ae.ToString().Contains("backgroundTokenCredentialRefreshInterval")); } try { new TokenCredentialCache( new Mock <TokenCredential>().Object, CosmosAuthorizationTests.AccountEndpoint, backgroundTokenCredentialRefreshInterval: TimeSpan.FromMilliseconds(-1)); Assert.Fail("Should throw ArgumentException"); } catch (ArgumentException ae) { Assert.IsTrue(ae.ToString().Contains("backgroundTokenCredentialRefreshInterval")); } // Which is roughly 24 days using TokenCredentialCache token = new TokenCredentialCache( new Mock <TokenCredential>().Object, CosmosAuthorizationTests.AccountEndpoint, backgroundTokenCredentialRefreshInterval: TimeSpan.FromMilliseconds(Int32.MaxValue)); using TokenCredentialCache disableBackgroundTask = new TokenCredentialCache( new Mock <TokenCredential>().Object, CosmosAuthorizationTests.AccountEndpoint, backgroundTokenCredentialRefreshInterval: TimeSpan.MaxValue); }
private void ValidateSemaphoreIsReleased(TokenCredentialCache tokenCredentialCache) { int currentCount = this.GetSemaphoreCurrentCount(tokenCredentialCache); Assert.AreEqual(1, currentCount); }
private async Task GetAndVerifyTokenAsync(TokenCredentialCache tokenCredentialCache) { Assert.AreEqual( this.AccessToken.Token, await tokenCredentialCache.GetTokenAsync(new CosmosDiagnosticsContextCore())); }
public async Task TestTokenCredentialFailedToRefreshAsync() { string token = "Token"; bool throwExceptionOnGetToken = false; Exception exception = new Exception(); const int semaphoreCount = 10; using SemaphoreSlim semaphoreSlim = new SemaphoreSlim(semaphoreCount); TestTokenCredential testTokenCredential = new TestTokenCredential(async() => { try { await semaphoreSlim.WaitAsync(); Assert.AreEqual(semaphoreCount - 1, semaphoreSlim.CurrentCount, "Only a single refresh should occur at a time."); if (throwExceptionOnGetToken) { throw exception; } else { return(new AccessToken(token, DateTimeOffset.UtcNow + TimeSpan.FromSeconds(8))); } } finally { semaphoreSlim.Release(); } }); using ITrace trace = Cosmos.Tracing.Trace.GetRootTrace("test"); using (TokenCredentialCache tokenCredentialCache = this.CreateTokenCredentialCache(testTokenCredential)) { Assert.AreEqual(token, await tokenCredentialCache.GetTokenAsync(trace)); Assert.AreEqual(1, testTokenCredential.NumTimesInvoked); throwExceptionOnGetToken = true; // Token is valid for 10 seconds. Client TokenCredentialRefreshBuffer is set to 5 seconds. // After waiting for 2 seconds, the cache token is still valid, but it will be refreshed in the background. await Task.Delay(TimeSpan.FromSeconds(2)); Assert.AreEqual(token, await tokenCredentialCache.GetTokenAsync(trace)); Assert.AreEqual(1, testTokenCredential.NumTimesInvoked); // Token refreshes fails except for the first time, but the cached token will be served as long as it is valid. // Wait for the background refresh to occur. It should fail but the cached token should still be valid Stopwatch stopwatch = Stopwatch.StartNew(); while (testTokenCredential.NumTimesInvoked != 3) { Assert.IsTrue(stopwatch.Elapsed.TotalSeconds < 10, "The background task did not start in 10 seconds"); await Task.Delay(200); } Assert.AreEqual(token, await tokenCredentialCache.GetTokenAsync(trace)); Assert.AreEqual(3, testTokenCredential.NumTimesInvoked, $"The cached token was not used. Waited time for background refresh: {stopwatch.Elapsed.TotalSeconds} seconds"); // Cache token has expired, and it fails to refresh. await Task.Delay(TimeSpan.FromSeconds(5)); throwExceptionOnGetToken = true; // Simulate multiple concurrent request on the failed token List <Task> tasks = new List <Task>(); for (int i = 0; i < 40; i++) { Task task = Task.Run(async() => { try { await tokenCredentialCache.GetTokenAsync(trace); Assert.Fail("TokenCredentialCache.GetTokenAsync() is expected to fail but succeeded"); } catch (Exception thrownException) { // It should just throw the original exception and not be wrapped in a CosmosException // This avoids any confusion on where the error was thrown from. Assert.IsTrue(object.ReferenceEquals( exception, thrownException), $"Incorrect exception thrown: Expected: {exception}; Actual: {thrownException}"); } }); tasks.Add(task); } await Task.WhenAll(tasks); this.ValidateSemaphoreIsReleased(tokenCredentialCache); // Simulate multiple concurrent request that should succeed after a failure throwExceptionOnGetToken = false; int numGetTokenCallsAfterFailures = testTokenCredential.NumTimesInvoked; tasks = new List <Task>(); for (int i = 0; i < 40; i++) { Task task = Task.Run(async() => await tokenCredentialCache.GetTokenAsync(trace)); tasks.Add(task); } await Task.WhenAll(tasks); this.ValidateSemaphoreIsReleased(tokenCredentialCache); } }
public async Task AadMockTest(ConnectionMode connectionMode) { int requestCount = 0; string databaseId = Guid.NewGuid().ToString(); string containerId = Guid.NewGuid().ToString(); using (CosmosClient cosmosClient = TestCommon.CreateCosmosClient()) { Database database = await cosmosClient.CreateDatabaseAsync(databaseId); Container container = await database.CreateContainerAsync( containerId, "/id"); } (string endpoint, string authKey) = TestCommon.GetAccountInfo(); LocalEmulatorTokenCredential simpleEmulatorTokenCredential = new LocalEmulatorTokenCredential(authKey); CosmosClientOptions clientOptions = new CosmosClientOptions() { ConnectionMode = connectionMode, ConnectionProtocol = connectionMode == ConnectionMode.Direct ? Protocol.Tcp : Protocol.Https, }; if (connectionMode == ConnectionMode.Direct) { long lsn = 2; clientOptions.TransportClientHandlerFactory = (transport) => new TransportClientWrapper(transport, interceptorAfterResult: (request, storeResponse) => { // Force a barrier request on create item. // There needs to be 2 regions and the GlobalCommittedLSN must be behind the LSN. if (storeResponse.StatusCode == HttpStatusCode.Created) { if (requestCount == 0) { requestCount++; lsn = storeResponse.LSN; storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.NumberOfReadRegions, "2"); storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.GlobalCommittedLSN, "0"); } } // Head request is the barrier request // The GlobalCommittedLSN is set to -1 because the local emulator doesn't have geo-dr so it has to be // overridden for the validation to succeed. if (request.OperationType == Documents.OperationType.Head) { if (requestCount == 1) { requestCount++; storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.NumberOfReadRegions, "2"); storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.GlobalCommittedLSN, lsn.ToString(CultureInfo.InvariantCulture)); } } return(storeResponse); }); } using CosmosClient aadClient = new CosmosClient( endpoint, simpleEmulatorTokenCredential, clientOptions); TokenCredentialCache tokenCredentialCache = ((AuthorizationTokenProviderTokenCredential)aadClient.AuthorizationTokenProvider).tokenCredentialCache; // The refresh interval changes slightly based on how fast machine calculate the interval based on the expire time. Assert.IsTrue(15 <= tokenCredentialCache.BackgroundTokenCredentialRefreshInterval.Value.TotalMinutes, "Default background refresh should be 25% of the token life which is defaulted to 1hr"); Assert.IsTrue(tokenCredentialCache.BackgroundTokenCredentialRefreshInterval.Value.TotalMinutes > 14.7, "Default background refresh should be 25% of the token life which is defaulted to 1hr"); Database aadDatabase = await aadClient.GetDatabase(databaseId).ReadAsync(); Container aadContainer = await aadDatabase.GetContainer(containerId).ReadContainerAsync(); ToDoActivity toDoActivity = ToDoActivity.CreateRandomToDoActivity(); ItemResponse <ToDoActivity> itemResponse = await aadContainer.CreateItemAsync( toDoActivity, new PartitionKey(toDoActivity.id)); // Gateway does the barrier requests so only direct mode needs to be validated. if (connectionMode == ConnectionMode.Direct) { Assert.AreEqual(2, requestCount, "The barrier request was never called."); } toDoActivity.cost = 42.42; await aadContainer.ReplaceItemAsync( toDoActivity, toDoActivity.id, new PartitionKey(toDoActivity.id)); await aadContainer.ReadItemAsync <ToDoActivity>( toDoActivity.id, new PartitionKey(toDoActivity.id)); await aadContainer.UpsertItemAsync(toDoActivity); await aadContainer.DeleteItemAsync <ToDoActivity>( toDoActivity.id, new PartitionKey(toDoActivity.id)); }