public void ProactiveRefreshingEnabled_KeepsSchedulingNewTimers()
        {
            var testClock      = new TestClock();
            var twentyMinToken = GenerateTokenValidForMinutes(testClock.UtcNow, 20);

            using var tokenCredential = CreateTokenCredentialWithTestClock(
                      testClock,
                      refreshProactively: true,
                      _ => GenerateTokenValidForMinutes(testClock.UtcNow, 20),
                      _ => throw new NotImplementedException(),
                      twentyMinToken);

            Assert.AreEqual(1, testClock.ScheduledActions.Count());
            var firstTimer = testClock.ScheduledActions.First();

            // go into soon to expire window
            testClock.Tick(TimeSpan.FromMinutes(20 - ThreadSafeRefreshableAccessTokenCache.ProactiveRefreshIntervalInMinutes + 0.5));

            Assert.AreEqual(1, testClock.ScheduledActions.Count());
            var secondTimer = testClock.ScheduledActions.First();

            Assert.AreNotEqual(firstTimer, secondTimer);
        }
        public void CommunicationTokenCredential_RefreshsTokenProactively_ImmediateWhenExpired()
        {
            var refreshCallCount = 0;

            var testClock = new TestClock();

            using var tokenCredential = CreateTokenCredentialWithTestClock(
                      testClock,
                      true,
                      RefreshToken,
                      _ => throw new NotImplementedException(),
                      ExpiredToken);

            Assert.AreEqual(1, testClock.ScheduledActions.Count());
            testClock.Tick();
            Assert.AreEqual(1, refreshCallCount);

            string RefreshToken(CancellationToken _)
            {
                refreshCallCount++;
                return(SampleToken);
            }
        }
        public async Task GetTokenSeries_CallsRefreshTokenOnlyOnce(bool async)
        {
            var refreshCallCount = 0;
            var testClock        = new TestClock();
            var twentyMinToken   = GenerateTokenValidForMinutes(testClock.UtcNow, 20);

            using var tokenCredential = CreateTokenCredentialWithTestClock(
                      testClock,
                      refreshProactively: true,
                      RefreshToken,
                      _ => throw new NotImplementedException(),
                      twentyMinToken);

            // go into soon to expire window
            testClock.Tick(TimeSpan.FromMinutes(20 - ThreadSafeRefreshableAccessTokenCache.ProactiveRefreshIntervalInMinutes + 0.5));

            for (var i = 0; i < 10; i++)
            {
                if (async)
                {
                    await tokenCredential.GetTokenAsync();
                }
                else
                {
                    tokenCredential.GetToken();
                }
            }

            Assert.AreEqual(1, refreshCallCount);

            string RefreshToken(CancellationToken _)
            {
                refreshCallCount++;
                return(GenerateTokenValidForMinutes(testClock.UtcNow, 20));
            }
        }