async def test_proactive_refresher_keeps_scheduling_again(self):
        refresh_minutes = 10
        token_validity_minutes = 60
        expired_token = generate_token_with_custom_expiry(-5 * 60)
        skip_to_timestamp = get_current_utc_as_int() + (
            token_validity_minutes - refresh_minutes) * 60 + 1
        first_refreshed_token = create_access_token(
            generate_token_with_custom_expiry(token_validity_minutes * 60))
        last_refreshed_token = create_access_token(
            generate_token_with_custom_expiry(2 * token_validity_minutes * 60))
        refresher = MagicMock(side_effect=[
            self.get_completed_future(first_refreshed_token),
            self.get_completed_future(last_refreshed_token)
        ])

        credential = CommunicationTokenCredential(expired_token,
                                                  token_refresher=refresher,
                                                  proactive_refresh=True)
        async with credential:
            access_token = await credential.get_token()
            with patch(user_credential_async.__name__ + '.' +
                       get_current_utc_as_int.__name__,
                       return_value=skip_to_timestamp):
                access_token = await credential.get_token()

        assert refresher.call_count == 2
        assert access_token.token == last_refreshed_token.token
        # check that next refresh is always scheduled
        assert credential._timer is not None
    async def test_fractional_backoff_applied_when_token_expiring(self):
        token_validity_seconds = 5 * 60
        expiring_token = generate_token_with_custom_expiry(
            token_validity_seconds)

        refresher = MagicMock(side_effect=[
            create_access_token(expiring_token),
            create_access_token(expiring_token)
        ])

        credential = CommunicationTokenCredential(expiring_token,
                                                  token_refresher=refresher,
                                                  proactive_refresh=True)

        next_milestone = token_validity_seconds / 2
        assert credential._timer.interval == next_milestone

        async with credential:
            with patch(user_credential_async.__name__ + '.' +
                       get_current_utc_as_int.__name__,
                       return_value=(get_current_utc_as_int() +
                                     next_milestone)):
                await credential.get_token()

        assert refresher.call_count == 1
        next_milestone = next_milestone / 2
        assert credential._timer.interval == next_milestone
    async def test_proactive_refresher_should_be_called_after_specified_time(
            self):
        refresh_minutes = 10
        token_validity_minutes = 60
        start_timestamp = get_current_utc_as_int()
        skip_to_timestamp = start_timestamp + \
            (token_validity_minutes - refresh_minutes + 5) * 60

        initial_token = generate_token_with_custom_expiry(
            token_validity_minutes * 60)
        refreshed_token = generate_token_with_custom_expiry(
            2 * token_validity_minutes * 60)
        refresher = MagicMock(return_value=self.get_completed_future(
            create_access_token(refreshed_token)))

        with patch(user_credential_async.__name__ + '.' +
                   get_current_utc_as_int.__name__,
                   return_value=skip_to_timestamp):
            credential = CommunicationTokenCredential(
                initial_token,
                token_refresher=refresher,
                proactive_refresh=True)
            async with credential:
                access_token = await credential.get_token()

        assert refresher.call_count == 1
        assert access_token.token == refreshed_token
        # check that next refresh is always scheduled
        assert credential._timer is not None