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

test typescriptification - timeline-window, scheduler, etc #2539

Merged
merged 9 commits into from
Jul 27, 2022
Merged
157 changes: 79 additions & 78 deletions spec/unit/scheduler.spec.js → spec/unit/scheduler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ describe("MatrixScheduler", function() {
queueFn = function() {
return "one_big_queue";
};
const deferA = defer();
const deferB = defer();
const deferA = defer<Record<string, boolean>>();
const deferB = defer<Record<string, boolean>>();
let yieldedA = false;
scheduler.setProcessFunction(function(event) {
if (yieldedA) {
Expand All @@ -70,84 +70,84 @@ describe("MatrixScheduler", function() {
});

it("should invoke the retryFn on failure and wait the amount of time specified",
async function() {
const waitTimeMs = 1500;
const retryDefer = defer();
retryFn = function() {
retryDefer.resolve();
return waitTimeMs;
};
queueFn = function() {
return "yep";
};
async function() {
const waitTimeMs = 1500;
const retryDefer = defer();
retryFn = function() {
retryDefer.resolve();
return waitTimeMs;
};
queueFn = function() {
return "yep";
};

let procCount = 0;
scheduler.setProcessFunction(function(ev) {
procCount += 1;
if (procCount === 1) {
expect(ev).toEqual(eventA);
return deferred.promise;
} else if (procCount === 2) {
let procCount = 0;
scheduler.setProcessFunction(function(ev) {
procCount += 1;
if (procCount === 1) {
expect(ev).toEqual(eventA);
return deferred.promise;
} else if (procCount === 2) {
// don't care about this deferred
return new Promise();
}
expect(procCount).toBeLessThan(3);
});
return new Promise(() => {});
}
expect(procCount).toBeLessThan(3);
});

scheduler.queueEvent(eventA);
// as queueing doesn't start processing synchronously anymore (see commit bbdb5ac)
// wait just long enough before it does
await Promise.resolve();
expect(procCount).toEqual(1);
deferred.reject({});
await retryDefer.promise;
expect(procCount).toEqual(1);
jest.advanceTimersByTime(waitTimeMs);
await Promise.resolve();
expect(procCount).toEqual(2);
});
scheduler.queueEvent(eventA);
// as queueing doesn't start processing synchronously anymore (see commit bbdb5ac)
// wait just long enough before it does
await Promise.resolve();
expect(procCount).toEqual(1);
deferred.reject({});
await retryDefer.promise;
expect(procCount).toEqual(1);
jest.advanceTimersByTime(waitTimeMs);
await Promise.resolve();
expect(procCount).toEqual(2);
});

it("should give up if the retryFn on failure returns -1 and try the next event",
async function() {
async function() {
// Queue A & B.
// Reject A and return -1 on retry.
// Expect B to be tried next and the promise for A to be rejected.
retryFn = function() {
return -1;
};
queueFn = function() {
return "yep";
};
retryFn = function() {
return -1;
};
queueFn = function() {
return "yep";
};

const deferA = defer();
const deferB = defer();
let procCount = 0;
scheduler.setProcessFunction(function(ev) {
procCount += 1;
if (procCount === 1) {
expect(ev).toEqual(eventA);
return deferA.promise;
} else if (procCount === 2) {
expect(ev).toEqual(eventB);
return deferB.promise;
}
expect(procCount).toBeLessThan(3);
});
const deferA = defer();
const deferB = defer();
let procCount = 0;
scheduler.setProcessFunction(function(ev) {
procCount += 1;
if (procCount === 1) {
expect(ev).toEqual(eventA);
return deferA.promise;
} else if (procCount === 2) {
expect(ev).toEqual(eventB);
return deferB.promise;
}
expect(procCount).toBeLessThan(3);
});

const globalA = scheduler.queueEvent(eventA);
scheduler.queueEvent(eventB);
// as queueing doesn't start processing synchronously anymore (see commit bbdb5ac)
// wait just long enough before it does
await Promise.resolve();
expect(procCount).toEqual(1);
deferA.reject({});
try {
await globalA;
} catch (err) {
const globalA = scheduler.queueEvent(eventA);
scheduler.queueEvent(eventB);
// as queueing doesn't start processing synchronously anymore (see commit bbdb5ac)
// wait just long enough before it does
await Promise.resolve();
expect(procCount).toEqual(2);
}
});
expect(procCount).toEqual(1);
deferA.reject({});
try {
await globalA;
} catch (err) {
await Promise.resolve();
expect(procCount).toEqual(2);
}
});

it("should treat each queue separately", function(done) {
// Queue messages A B C D.
Expand Down Expand Up @@ -175,7 +175,7 @@ describe("MatrixScheduler", function() {
const expectOrder = [
eventA.getId(), eventB.getId(), eventD.getId(),
];
const deferA = defer();
const deferA = defer<void>();
scheduler.setProcessFunction(function(event) {
const id = expectOrder.shift();
expect(id).toEqual(event.getId());
Expand All @@ -191,7 +191,7 @@ describe("MatrixScheduler", function() {

// wait a bit then resolve A and we should get D (not C) next.
setTimeout(function() {
deferA.resolve({});
deferA.resolve();
}, 1000);
jest.advanceTimersByTime(1000);
});
Expand Down Expand Up @@ -336,28 +336,29 @@ describe("MatrixScheduler", function() {
errcode: "M_LIMIT_EXCEEDED", retry_after_ms: 5000,
}),
);
expect(res >= 500).toBe(true, "Didn't wait long enough.");
expect(res >= 500).toBe(true);
});

it("should give up after 5 attempts", function() {
const res = MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 5, {},
eventA, 5, new MatrixError({}),
);
expect(res).toBe(-1, "Didn't give up.");
expect(res).toBe(-1);
});

it("should do exponential backoff", function() {
const error = new MatrixError({});
expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 1, {},
eventA, 1, error,
)).toEqual(2000);
expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 2, {},
eventA, 2, error,
)).toEqual(4000);
expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 3, {},
eventA, 3, error,
)).toEqual(8000);
expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 4, {},
eventA, 4, error,
)).toEqual(16000);
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2019, 2022 The Matrix.org Foundation C.I.C.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -384,6 +384,10 @@ describe("SyncAccumulator", function() {
};
}

afterEach(() => {
jest.spyOn(global.Date, 'now').mockRestore();
});

it("should copy summary properties", function() {
sa.accumulate(createSyncResponseWithSummary({
"m.heroes": ["@alice:bar"],
Expand Down Expand Up @@ -413,25 +417,19 @@ describe("SyncAccumulator", function() {
const delta = 1000;
const startingTs = 1000;

const oldDateNow = Date.now;
try {
Date.now = jest.fn();
Date.now.mockReturnValue(startingTs);

sa.accumulate(RES_WITH_AGE);

Date.now.mockReturnValue(startingTs + delta);

const output = sa.getJSON();
expect(output.roomsData.join["!foo:bar"].timeline.events[0].unsigned.age).toEqual(
RES_WITH_AGE.rooms.join["!foo:bar"].timeline.events[0].unsigned.age + delta,
);
expect(Object.keys(output.roomsData.join["!foo:bar"].timeline.events[0])).toEqual(
Object.keys(RES_WITH_AGE.rooms.join["!foo:bar"].timeline.events[0]),
);
} finally {
Date.now = oldDateNow;
}
jest.spyOn(global.Date, 'now').mockReturnValue(startingTs);

sa.accumulate(RES_WITH_AGE);

jest.spyOn(global.Date, 'now').mockReturnValue(startingTs + delta);

const output = sa.getJSON();
expect(output.roomsData.join["!foo:bar"].timeline.events[0].unsigned.age).toEqual(
RES_WITH_AGE.rooms.join["!foo:bar"].timeline.events[0].unsigned.age + delta,
);
expect(Object.keys(output.roomsData.join["!foo:bar"].timeline.events[0])).toEqual(
Object.keys(RES_WITH_AGE.rooms.join["!foo:bar"].timeline.events[0]),
);
});

it("should mangle age without adding extra keys", () => {
Expand Down
Loading