forked from NoeFabris/opencode-antigravity-auth
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcache.test.ts
More file actions
295 lines (231 loc) · 9.45 KB
/
Copy pathcache.test.ts
File metadata and controls
295 lines (231 loc) · 9.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
resolveCachedAuth,
storeCachedAuth,
clearCachedAuth,
cacheSignature,
getCachedSignature,
clearSignatureCache,
} from "./cache";
import type { OAuthAuthDetails } from "./types";
function createAuth(overrides: Partial<OAuthAuthDetails> = {}): OAuthAuthDetails {
return {
type: "oauth",
refresh: "refresh-token|project-id",
access: "access-token",
expires: Date.now() + 3600000,
...overrides,
};
}
describe("Auth Cache", () => {
beforeEach(() => {
vi.useRealTimers();
clearCachedAuth();
});
afterEach(() => {
clearCachedAuth();
});
describe("resolveCachedAuth", () => {
it("returns input auth when no cache exists and caches it", () => {
const auth = createAuth();
const result = resolveCachedAuth(auth);
expect(result).toEqual(auth);
});
it("returns input auth when refresh key is empty", () => {
const auth = createAuth({ refresh: "" });
const result = resolveCachedAuth(auth);
expect(result).toEqual(auth);
});
it("returns input auth when it has valid (unexpired) access token", () => {
const oldAuth = createAuth({ access: "old-access", expires: Date.now() + 3600000 });
resolveCachedAuth(oldAuth); // cache it
const newAuth = createAuth({ access: "new-access", expires: Date.now() + 7200000 });
const result = resolveCachedAuth(newAuth);
expect(result.access).toBe("new-access");
});
it("returns cached auth when input auth is expired but cached is valid", () => {
vi.useFakeTimers();
vi.setSystemTime(new Date(0));
const validAuth = createAuth({
access: "valid-access",
expires: 3600000, // expires at t=3600000
});
resolveCachedAuth(validAuth); // cache it
// Now create an expired auth with the same refresh token
const expiredAuth = createAuth({
access: "expired-access",
expires: 30000, // expires within buffer (60s)
});
const result = resolveCachedAuth(expiredAuth);
expect(result.access).toBe("valid-access");
});
it("returns input auth when both are expired (updates cache)", () => {
vi.useFakeTimers();
vi.setSystemTime(new Date(0));
const expiredCached = createAuth({
access: "cached-expired",
expires: 30000, // expired within buffer
});
resolveCachedAuth(expiredCached);
const expiredNew = createAuth({
access: "new-expired",
expires: 20000, // also expired within buffer
});
const result = resolveCachedAuth(expiredNew);
expect(result.access).toBe("new-expired");
});
});
describe("storeCachedAuth", () => {
it("stores auth in cache", () => {
const auth = createAuth({ access: "stored-access" });
storeCachedAuth(auth);
const expiredAuth = createAuth({ access: "expired", expires: Date.now() - 1000 });
const result = resolveCachedAuth(expiredAuth);
expect(result.access).toBe("stored-access");
});
it("does nothing when refresh key is empty", () => {
const auth = createAuth({ refresh: "", access: "no-key-access" });
storeCachedAuth(auth);
// Should not be retrievable since key was empty
const testAuth = createAuth({ refresh: "", access: "test" });
const result = resolveCachedAuth(testAuth);
expect(result.access).toBe("test"); // returns the input, not cached
});
it("does nothing when refresh key is whitespace only", () => {
const auth = createAuth({ refresh: " ", access: "whitespace-access" });
storeCachedAuth(auth);
const testAuth = createAuth({ refresh: " ", access: "test" });
const result = resolveCachedAuth(testAuth);
expect(result.access).toBe("test");
});
});
describe("clearCachedAuth", () => {
it("clears all cache when no argument provided", () => {
storeCachedAuth(createAuth({ refresh: "token1|p", access: "access1" }));
storeCachedAuth(createAuth({ refresh: "token2|p", access: "access2" }));
clearCachedAuth();
const auth1 = createAuth({ refresh: "token1|p", access: "new1" });
const auth2 = createAuth({ refresh: "token2|p", access: "new2" });
expect(resolveCachedAuth(auth1).access).toBe("new1");
expect(resolveCachedAuth(auth2).access).toBe("new2");
});
it("clears specific refresh token from cache", () => {
storeCachedAuth(createAuth({ refresh: "token1|p", access: "access1" }));
storeCachedAuth(createAuth({ refresh: "token2|p", access: "access2" }));
clearCachedAuth("token1|p");
// token1 should be cleared
const expiredAuth1 = createAuth({ refresh: "token1|p", access: "new1", expires: Date.now() - 1000 });
expect(resolveCachedAuth(expiredAuth1).access).toBe("new1");
// token2 should still be cached
const expiredAuth2 = createAuth({ refresh: "token2|p", access: "new2", expires: Date.now() - 1000 });
expect(resolveCachedAuth(expiredAuth2).access).toBe("access2");
});
});
});
describe("Signature Cache", () => {
beforeEach(() => {
vi.useRealTimers();
clearSignatureCache();
});
afterEach(() => {
clearSignatureCache();
});
describe("cacheSignature", () => {
it("caches a signature for session and text", () => {
cacheSignature("session1", "thinking text", "sig123");
const result = getCachedSignature("session1", "thinking text");
expect(result).toBe("sig123");
});
it("does nothing when sessionId is empty", () => {
cacheSignature("", "text", "sig");
expect(getCachedSignature("", "text")).toBeUndefined();
});
it("does nothing when text is empty", () => {
cacheSignature("session", "", "sig");
expect(getCachedSignature("session", "")).toBeUndefined();
});
it("does nothing when signature is empty", () => {
cacheSignature("session", "text", "");
expect(getCachedSignature("session", "text")).toBeUndefined();
});
it("stores multiple signatures per session", () => {
cacheSignature("session1", "text1", "sig1");
cacheSignature("session1", "text2", "sig2");
expect(getCachedSignature("session1", "text1")).toBe("sig1");
expect(getCachedSignature("session1", "text2")).toBe("sig2");
});
it("stores signatures for different sessions independently", () => {
cacheSignature("session1", "text", "sig1");
cacheSignature("session2", "text", "sig2");
expect(getCachedSignature("session1", "text")).toBe("sig1");
expect(getCachedSignature("session2", "text")).toBe("sig2");
});
});
describe("getCachedSignature", () => {
it("returns undefined when session not found", () => {
expect(getCachedSignature("unknown", "text")).toBeUndefined();
});
it("returns undefined when text not found in session", () => {
cacheSignature("session", "known-text", "sig");
expect(getCachedSignature("session", "unknown-text")).toBeUndefined();
});
it("returns undefined when sessionId is empty", () => {
expect(getCachedSignature("", "text")).toBeUndefined();
});
it("returns undefined when text is empty", () => {
expect(getCachedSignature("session", "")).toBeUndefined();
});
it("returns undefined when signature is expired", () => {
vi.useFakeTimers();
vi.setSystemTime(new Date(0));
cacheSignature("session", "text", "sig");
// Advance time past TTL (1 hour = 3600000ms)
vi.setSystemTime(new Date(3600001));
expect(getCachedSignature("session", "text")).toBeUndefined();
});
it("returns signature when not expired", () => {
vi.useFakeTimers();
vi.setSystemTime(new Date(0));
cacheSignature("session", "text", "sig");
// Advance time but stay within TTL
vi.setSystemTime(new Date(3599999));
expect(getCachedSignature("session", "text")).toBe("sig");
});
});
describe("clearSignatureCache", () => {
it("clears all signature cache when no argument provided", () => {
cacheSignature("session1", "text", "sig1");
cacheSignature("session2", "text", "sig2");
clearSignatureCache();
expect(getCachedSignature("session1", "text")).toBeUndefined();
expect(getCachedSignature("session2", "text")).toBeUndefined();
});
it("clears specific session from cache", () => {
cacheSignature("session1", "text", "sig1");
cacheSignature("session2", "text", "sig2");
clearSignatureCache("session1");
expect(getCachedSignature("session1", "text")).toBeUndefined();
expect(getCachedSignature("session2", "text")).toBe("sig2");
});
});
describe("cache eviction", () => {
it("evicts entries when at capacity", () => {
vi.useFakeTimers();
vi.setSystemTime(new Date(0));
// Fill cache with 100 entries (MAX_ENTRIES_PER_SESSION)
for (let i = 0; i < 100; i++) {
vi.setSystemTime(new Date(i * 1000)); // stagger timestamps
cacheSignature("session", `text-${i}`, `sig-${i}`);
}
// Reset time to check entries
vi.setSystemTime(new Date(100 * 1000));
// Adding one more should trigger eviction
cacheSignature("session", "new-text", "new-sig");
// New entry should exist
expect(getCachedSignature("session", "new-text")).toBe("new-sig");
// Some old entries should have been evicted (oldest 25%)
// Entry at index 0 (timestamp 0) should be evicted
expect(getCachedSignature("session", "text-0")).toBeUndefined();
});
});
});