Skip to content

Commit 3954943

Browse files
committed
Harden clear entry wrapper tests
(cherry picked from commit fa4a6aa)
1 parent 6f3916e commit 3954943

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

test/account-clear-entry.test.ts

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@ import { clearAccountsEntry } from "../lib/storage/account-clear-entry.js";
44
describe("account clear entry", () => {
55
it("delegates clear through the storage lock and backup resolver", async () => {
66
const clearAccountStorageArtifacts = vi.fn(async () => undefined);
7+
const withStorageLock = vi.fn(async (fn: () => Promise<void>) => fn());
78
await clearAccountsEntry({
89
path: "/tmp/accounts.json",
9-
withStorageLock: async (fn) => fn(),
10+
withStorageLock,
1011
resetMarkerPath: "/tmp/accounts.reset-intent",
1112
walPath: "/tmp/accounts.wal",
1213
getBackupPaths: async () => ["/tmp/accounts.json.bak"],
1314
clearAccountStorageArtifacts,
1415
logError: vi.fn(),
1516
});
1617

18+
expect(withStorageLock).toHaveBeenCalledOnce();
19+
expect(clearAccountStorageArtifacts).toHaveBeenCalledTimes(1);
1720
expect(clearAccountStorageArtifacts).toHaveBeenCalledWith({
1821
path: "/tmp/accounts.json",
1922
resetMarkerPath: "/tmp/accounts.reset-intent",
@@ -22,4 +25,92 @@ describe("account clear entry", () => {
2225
logError: expect.any(Function),
2326
});
2427
});
28+
29+
it("serializes concurrent clears through the shared storage lock", async () => {
30+
const events: string[] = [];
31+
let releaseFirst: (() => void) | undefined;
32+
const firstGate = new Promise<void>((resolve) => {
33+
releaseFirst = resolve;
34+
});
35+
let queue = Promise.resolve();
36+
const withStorageLock = vi.fn(async <T>(fn: () => Promise<T>) => {
37+
const run = queue.then(fn);
38+
queue = run.then(
39+
() => undefined,
40+
() => undefined,
41+
);
42+
return run;
43+
});
44+
const clearAccountStorageArtifacts = vi.fn(
45+
async ({ path }: { path: string }) => {
46+
events.push(`start:${path}`);
47+
if (path === "/tmp/first.json") {
48+
await firstGate;
49+
}
50+
events.push(`end:${path}`);
51+
},
52+
);
53+
54+
const firstCall = clearAccountsEntry({
55+
path: "/tmp/first.json",
56+
withStorageLock,
57+
resetMarkerPath: "/tmp/first.reset-intent",
58+
walPath: "/tmp/first.wal",
59+
getBackupPaths: async () => ["/tmp/first.json.bak"],
60+
clearAccountStorageArtifacts,
61+
logError: vi.fn(),
62+
});
63+
const secondCall = clearAccountsEntry({
64+
path: "/tmp/second.json",
65+
withStorageLock,
66+
resetMarkerPath: "/tmp/second.reset-intent",
67+
walPath: "/tmp/second.wal",
68+
getBackupPaths: async () => ["/tmp/second.json.bak"],
69+
clearAccountStorageArtifacts,
70+
logError: vi.fn(),
71+
});
72+
73+
await Promise.resolve();
74+
await Promise.resolve();
75+
76+
expect(events).toEqual(["start:/tmp/first.json"]);
77+
releaseFirst?.();
78+
await Promise.all([firstCall, secondCall]);
79+
80+
expect(withStorageLock).toHaveBeenCalledTimes(2);
81+
expect(events).toEqual([
82+
"start:/tmp/first.json",
83+
"end:/tmp/first.json",
84+
"start:/tmp/second.json",
85+
"end:/tmp/second.json",
86+
]);
87+
});
88+
89+
it("preserves windows-style paths when clearing storage artifacts", async () => {
90+
const windowsPath = "C:\\codex\\accounts.json";
91+
const resetMarkerPath = "C:\\codex\\accounts.reset-intent";
92+
const walPath = "C:\\codex\\accounts.wal";
93+
const backupPath = "C:\\codex\\accounts.json.bak";
94+
const withStorageLock = vi.fn(async (fn: () => Promise<void>) => fn());
95+
const clearAccountStorageArtifacts = vi.fn(async () => undefined);
96+
97+
await clearAccountsEntry({
98+
path: windowsPath,
99+
withStorageLock,
100+
resetMarkerPath,
101+
walPath,
102+
getBackupPaths: async () => [backupPath],
103+
clearAccountStorageArtifacts,
104+
logError: vi.fn(),
105+
});
106+
107+
expect(withStorageLock).toHaveBeenCalledOnce();
108+
expect(clearAccountStorageArtifacts).toHaveBeenCalledWith({
109+
path: windowsPath,
110+
resetMarkerPath,
111+
walPath,
112+
backupPaths: [backupPath],
113+
logError: expect.any(Function),
114+
});
115+
});
25116
});

0 commit comments

Comments
 (0)