@itwin/core-backend
Version:
iTwin.js backend components
111 lines • 5.14 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { assert } from "chai";
import { BeDuration } from "@itwin/core-bentley";
import { PromiseMemoizer } from "../../PromiseMemoizer";
import * as sinon from "sinon";
describe("PromiseMemoizer", () => {
let clock;
const generateTestFunctionKey = (param, waitTime) => {
return `key ${param}:${waitTime}`;
};
const testFunction = async (param, waitTime) => {
await BeDuration.wait(waitTime);
if (param === "TestError")
throw new Error("TestError");
return testFunctionResult(param, waitTime);
};
const testFunctionResult = (param, waitTime) => {
return `value ${param}:${waitTime}`;
};
const maxCacheSize = 25;
const cacheTimeout = 1500;
const testMemoizer = new PromiseMemoizer(testFunction, generateTestFunctionKey, maxCacheSize, cacheTimeout);
afterEach(() => {
if (clock !== undefined) {
clock.restore();
clock = undefined;
}
testMemoizer.clearCache();
});
it("should be able to await memoized promise", async () => {
const startTime = Date.now();
const qp = testMemoizer.memoize("test", 500);
await qp.promise;
const elapsedTime = Date.now() - startTime;
assert.isAbove(elapsedTime, 400);
});
it("should be able to memoize and deleteMemoized function calls", async () => {
clock = sinon.useFakeTimers();
const qps = new Array(4);
const expectedResults = new Array(4);
qps[0] = testMemoizer.memoize("test1", 500);
expectedResults[0] = testFunctionResult("test1", 500);
qps[1] = testMemoizer.memoize("test1", 500);
expectedResults[1] = testFunctionResult("test1", 500);
assert.strictEqual(qps[1], qps[0], "qps[1] === qps[0] fails");
qps[2] = testMemoizer.memoize("test2", 500);
expectedResults[2] = testFunctionResult("test2", 500);
assert.notStrictEqual(qps[2], qps[0], "qps[2] !== qps[0] fails");
qps[3] = testMemoizer.memoize("test1", 501);
expectedResults[3] = testFunctionResult("test1", 501);
assert.notStrictEqual(qps[3], qps[0], "qps[3] !== qps[0] fails");
const qpRej = testMemoizer.memoize("TestError", 500);
for (const qp of qps) {
assert.isTrue(qp.isPending, "qp.isPending check fails");
}
assert.isTrue(qpRej.isPending, "qpRej.isPending check fails");
await clock.tickAsync(501);
for (let ii = 0; ii < 4; ii++) {
assert.isTrue(qps[ii].isFulfilled, "qp.isFulfilled check fails");
assert.strictEqual(qps[ii].result, expectedResults[ii]);
}
assert.isTrue(qpRej.isRejected);
assert.strictEqual(qpRej.error.message, "TestError");
testMemoizer.deleteMemoized("test1", 500);
const qp0 = testMemoizer.memoize("test1", 500);
assert.isTrue(qp0.isPending);
});
it("should not increase the cache size when repeating the same call", () => {
for (let ii = 0; ii < 5; ii++) {
const qp = testMemoizer.memoize("test", 1000); // same call every time
assert.isTrue(qp.isPending); // Ensure the testFn doesn't resolve
}
const actualCacheSize = testMemoizer._cachedPromises.size;
assert.equal(actualCacheSize, 1);
});
it("should increase the cache size as expected", () => {
for (let ii = 0; ii < 5; ii++) {
const qp = testMemoizer.memoize(ii.toString(), 1000); // different call every time
assert.isTrue(qp.isPending);
}
const actualCacheSize = testMemoizer._cachedPromises.size;
assert.equal(actualCacheSize, 5);
});
it("should clear the cache if there is an overflow", () => {
for (let ii = 0; ii < maxCacheSize; ii++) {
testMemoizer.memoize(ii.toString(), 1000);
}
let actualCacheSize = testMemoizer._cachedPromises.size;
assert.equal(actualCacheSize, maxCacheSize);
testMemoizer.memoize(maxCacheSize.toString(), 1000);
actualCacheSize = testMemoizer._cachedPromises.size;
assert.equal(actualCacheSize, 1);
});
it("should clear old promises", async () => {
clock = sinon.useFakeTimers();
testMemoizer.memoize("test", 1000);
testMemoizer.memoize("test", 100);
let actualCacheSize = testMemoizer._cachedPromises.size;
assert.equal(actualCacheSize, 2);
await clock.tickAsync(cacheTimeout + 100);
actualCacheSize = testMemoizer._cachedPromises.size;
assert.equal(actualCacheSize, 1);
await clock.tickAsync(900);
actualCacheSize = testMemoizer._cachedPromises.size;
assert.equal(actualCacheSize, 0);
});
});
//# sourceMappingURL=PromiseMemoizer.test.js.map