Skip to content

Commit 886fe35

Browse files
committed
Mock Date in integration tests
1 parent b43045a commit 886fe35

File tree

2 files changed

+37
-9
lines changed

2 files changed

+37
-9
lines changed

extensions/ql-vscode/src/helpers.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,12 @@ export function getQueryName(info: EvaluationInfo) {
140140
* the last invocation of that function.
141141
*/
142142
export class InvocationRateLimiter<T> {
143-
constructor(extensionContext: ExtensionContext, funcIdentifier: string, func: () => Promise<T>) {
143+
constructor(
144+
extensionContext: ExtensionContext,
145+
funcIdentifier: string,
146+
func: () => Promise<T>,
147+
createDate: (dateString?: string) => Date = s => s ? new Date(s) : new Date()) {
148+
this._createDate = createDate;
144149
this._extensionContext = extensionContext;
145150
this._func = func;
146151
this._funcIdentifier = funcIdentifier;
@@ -150,7 +155,7 @@ export class InvocationRateLimiter<T> {
150155
* Invoke the function if `minSecondsSinceLastInvocation` seconds have elapsed since the last invocation.
151156
*/
152157
public async invokeFunctionIfIntervalElapsed(minSecondsSinceLastInvocation: number): Promise<InvocationRateLimiterResult<T>> {
153-
const updateCheckStartDate = new Date();
158+
const updateCheckStartDate = this._createDate();
154159
const lastInvocationDate = this.getLastInvocationDate();
155160
if (minSecondsSinceLastInvocation && lastInvocationDate && lastInvocationDate <= updateCheckStartDate &&
156161
lastInvocationDate.getTime() + minSecondsSinceLastInvocation * 1000 > updateCheckStartDate.getTime()) {
@@ -162,15 +167,16 @@ export class InvocationRateLimiter<T> {
162167
}
163168

164169
private getLastInvocationDate(): Date | undefined {
165-
const maybeDate: Date | undefined =
170+
const maybeDateString: string | undefined =
166171
this._extensionContext.globalState.get(InvocationRateLimiter._invocationRateLimiterPrefix + this._funcIdentifier);
167-
return maybeDate ? new Date(maybeDate) : undefined;
172+
return maybeDateString ? this._createDate(maybeDateString) : undefined;
168173
}
169174

170175
private async setLastInvocationDate(date: Date): Promise<void> {
171176
return await this._extensionContext.globalState.update(InvocationRateLimiter._invocationRateLimiterPrefix + this._funcIdentifier, date);
172177
}
173178

179+
private readonly _createDate: (dateString?: string) => Date;
174180
private readonly _extensionContext: ExtensionContext;
175181
private readonly _func: () => Promise<T>;
176182
private readonly _funcIdentifier: string;

extensions/ql-vscode/src/vscode-tests/no-workspace/helpers.test.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,19 @@ import { ExtensionContext, Memento } from "vscode";
44
import { InvocationRateLimiter } from "../../helpers";
55

66
describe("Invocation rate limiter", () => {
7+
// 1 January 2020
8+
let currentUnixTime = 1577836800;
9+
10+
function createDate(dateString?: string): Date {
11+
if (dateString) {
12+
return new Date(dateString);
13+
}
14+
const numMillisecondsPerSecond = 1000;
15+
return new Date(currentUnixTime * numMillisecondsPerSecond);
16+
}
17+
718
function createInvocationRateLimiter<T>(funcIdentifier: string, func: () => Promise<T>): InvocationRateLimiter<T> {
8-
return new InvocationRateLimiter(new MockExtensionContext(), funcIdentifier, func);
19+
return new InvocationRateLimiter(new MockExtensionContext(), funcIdentifier, func, s => createDate(s));
920
}
1021

1122
it("initially invokes function", async () => {
@@ -17,7 +28,7 @@ describe("Invocation rate limiter", () => {
1728
expect(numTimesFuncCalled).to.equal(1);
1829
});
1930

20-
it("doesn't invoke function within time period", async () => {
31+
it("doesn't invoke function again if no time has passed", async () => {
2132
let numTimesFuncCalled = 0;
2233
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
2334
numTimesFuncCalled++;
@@ -27,7 +38,18 @@ describe("Invocation rate limiter", () => {
2738
expect(numTimesFuncCalled).to.equal(1);
2839
});
2940

30-
it("invoke function again after 0s time period has elapsed", async () => {
41+
it("doesn't invoke function again if requested time since last invocation hasn't passed", async () => {
42+
let numTimesFuncCalled = 0;
43+
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
44+
numTimesFuncCalled++;
45+
});
46+
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(100);
47+
currentUnixTime += 1;
48+
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(2);
49+
expect(numTimesFuncCalled).to.equal(1);
50+
});
51+
52+
it("invokes function again immediately if requested time since last invocation is 0 seconds", async () => {
3153
let numTimesFuncCalled = 0;
3254
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
3355
numTimesFuncCalled++;
@@ -37,13 +59,13 @@ describe("Invocation rate limiter", () => {
3759
expect(numTimesFuncCalled).to.equal(2);
3860
});
3961

40-
it("invoke function again after 1s time period has elapsed", async () => {
62+
it("invokes function again after requested time since last invocation has elapsed", async () => {
4163
let numTimesFuncCalled = 0;
4264
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
4365
numTimesFuncCalled++;
4466
});
4567
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(1);
46-
await new Promise((resolve, _reject) => setTimeout(() => resolve(), 1000));
68+
currentUnixTime += 1;
4769
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(1);
4870
expect(numTimesFuncCalled).to.equal(2);
4971
});

0 commit comments

Comments
 (0)