Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@azure/communication-common] Test improvements #20250

Merged
merged 1 commit into from
Feb 8, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,6 @@ const exposeInternalTimeout = (
return ((tokenCredential as any).tokenCredential as any).activeTimeout;
};

const getDivisionWithoutFractionCount = (dividend: number, divisor: number): number => {
let i = dividend;
let result = 0;
while (i >= divisor) {
i = Math.round(i / divisor);
result++;
}
return result;
};

const exposeInternalUpdatePromise = async (
tokenCredential: AzureCommunicationTokenCredential
): Promise<void> => {
Expand Down Expand Up @@ -111,6 +101,18 @@ describe("CommunicationTokenCredential", () => {
sinon.assert.notCalled(tokenRefresher);
});

it("with proactive refresh, passing an expired token to constructor triggers immediate refresh", async () => {
const tokenRefresher = sinon.stub().resolves(generateToken(30));
new AzureCommunicationTokenCredential({
tokenRefresher,
refreshProactively: true,
token: generateToken(-1),
});
clock.tick(5 * 60 * 1000);

sinon.assert.calledOnce(tokenRefresher);
});

it("throws if tokenRefresher returns an expired token", async () => {
const tokenRefresher = sinon.stub().resolves(generateToken(-1));
const credential = new AzureCommunicationTokenCredential({
Expand Down Expand Up @@ -262,17 +264,12 @@ describe("CommunicationTokenCredential", () => {

it("applies fractional backoff when the token is about to expire", async () => {
const defaultRefreshAfterLifetimePercentage = 0.5;
const tokenExpiration = 20;
const tokenExpirationMinutes = 20;
const expectedPreBackOffCallCount = 1;
const lastMsCall = 1;
const expectedTotalCallCount =
expectedPreBackOffCallCount +
getDivisionWithoutFractionCount(
tokenExpiration * 60 * 1000,
1 / defaultRefreshAfterLifetimePercentage
) -
lastMsCall;
const staticToken = generateToken(tokenExpiration);
const expectedTotalCallCount = Math.floor(
Math.log(tokenExpirationMinutes * 60) / Math.log(1 / defaultRefreshAfterLifetimePercentage)
);
const staticToken = generateToken(tokenExpirationMinutes);
const tokenRefresher = sinon.stub().resolves(((): string => staticToken)()); // keep returning the same token for the duration of the test
const tokenCredential = new AzureCommunicationTokenCredential({
tokenRefresher,
Expand All @@ -283,24 +280,24 @@ describe("CommunicationTokenCredential", () => {
const newToken = await tokenCredential.getToken();

// go into the soon-to-expire window
for (let i = 0; i < 10 * 60 * 1000; i++) {
for (let i = 0; i < 10 * 60; i++) {
// perform token refreshing & scheduling
await exposeInternalUpdatePromise(tokenCredential);
clock.tick(1);
clock.tick(1000);
}

// expect the token to be refreshed only once within the first 10 minutes
sinon.assert.callCount(tokenRefresher, expectedPreBackOffCallCount);

// iterate until the penultimate millisecond of the token expiration
// iterate until the penultimate second of the token expiration
// to prevent an exception being thrown due to the token being expired
while (newToken.expiresOnTimestamp - Date.now() > lastMsCall) {
while (Math.floor((newToken.expiresOnTimestamp - Date.now()) / 1000) > 1) {
// perform token refreshing & scheduling
await exposeInternalUpdatePromise(tokenCredential);
clock.tick(1);
clock.tick(1000);
}

// expect the token to be refreshed approx. Math.floor(Math.log(tokenExpirationInMs) / Math.log(2)) times
// expect the token to be refreshed with an increasing frequency in the remaining 10 minutes
sinon.assert.callCount(tokenRefresher, expectedTotalCallCount);
});
});