From e37e332ac6a6577f841f34d25b1214fedf296e66 Mon Sep 17 00:00:00 2001 From: JUN Date: Mon, 9 Nov 2026 16:49:26 +0900 Subject: [PATCH 1/2] test(usage): state the filter index availability contract Windows can reach --- tests/usage/usage-filter-index.test.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/usage/usage-filter-index.test.ts b/tests/usage/usage-filter-index.test.ts index 3272cbd3d51..119e9befa04 100644 --- a/tests/usage/usage-filter-index.test.ts +++ b/tests/usage/usage-filter-index.test.ts @@ -1075,7 +1075,10 @@ describe("filtered usage index availability", () => { expect(existsSync(`${indexPath}-wal`)).toBe(false); }); - test("an unwritable home degrades to the streaming read", async () => { + // chmod cannot make a Windows directory unwritable, so there this would build the index and + // assert nothing about permissions. The degrade itself is the platform-neutral catch-all in + // readUsageFilterCandidates, which the contention and foreign-file cases cover everywhere. + test.skipIf(process.platform === "win32")("an unwritable home degrades to the streaming read", async () => { const rows = Array.from({ length: 5 }, (_, index) => syntheticRow(index)); writeRows(rows); const expected = rows.filter(row => row.provider === "openai").length; @@ -1130,13 +1133,13 @@ describe("filtered usage index availability", () => { } }); - test("a projection that vanishes before the read is not recreated", async () => { + /** Delete the projection at one point of a filtered query and expect a streaming answer. */ + async function expectVanishedProjectionNotRecreated(hooks: (remove: (dbPath: string) => void) => + Parameters[0]): Promise { const rows = Array.from({ length: 5 }, (_, index) => syntheticRow(index)); writeRows(rows); const indexPath = usageFilterIndexPath(testDir); - setUsageFilterIndexTestHooksForTests({ - afterPublish: ({ dbPath }) => { rmSync(dbPath, { force: true }); }, - }); + setUsageFilterIndexTestHooksForTests(hooks(dbPath => { rmSync(dbPath, { force: true }); })); try { const result = await getFilteredUsageAggregate({ provider: "openai" }); expect(summary(result).summary.requests) @@ -1146,6 +1149,16 @@ describe("filtered usage index availability", () => { setUsageFilterIndexTestHooksForTests(null); } expect(existsSync(indexPath)).toBe(false); + } + + // Windows refuses to delete a file SQLite holds open: there the projection can only vanish once + // the refresh has closed it, which the next case covers on every platform. + test.skipIf(process.platform === "win32")("a projection that vanishes before the read is not recreated", async () => { + await expectVanishedProjectionNotRecreated(remove => ({ afterPublish: ({ dbPath }) => remove(dbPath) })); + }); + + test("a projection that vanishes after the refresh closed it is not recreated by the read", async () => { + await expectVanishedProjectionNotRecreated(remove => ({ afterRefresh: ({ dbPath }) => remove(dbPath) })); }); test("a home change during a refresh never mixes installations", async () => { From a0b87e68aef17570b1979cc4676eba90996e41ed Mon Sep 17 00:00:00 2001 From: JUN Date: Mon, 9 Nov 2026 17:29:07 +0900 Subject: [PATCH 2/2] test(usage): prove the vanish hook removed the projection and correct the coverage note --- tests/usage/usage-filter-index.test.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tests/usage/usage-filter-index.test.ts b/tests/usage/usage-filter-index.test.ts index 119e9befa04..e79ba16a10c 100644 --- a/tests/usage/usage-filter-index.test.ts +++ b/tests/usage/usage-filter-index.test.ts @@ -1077,7 +1077,8 @@ describe("filtered usage index availability", () => { // chmod cannot make a Windows directory unwritable, so there this would build the index and // assert nothing about permissions. The degrade itself is the platform-neutral catch-all in - // readUsageFilterCandidates, which the contention and foreign-file cases cover everywhere. + // readUsageFilterCandidates, which the vanishing-after-refresh case below reaches on every + // platform; contention and the foreign file cover the busy and explicit fallbacks. test.skipIf(process.platform === "win32")("an unwritable home degrades to the streaming read", async () => { const rows = Array.from({ length: 5 }, (_, index) => syntheticRow(index)); writeRows(rows); @@ -1139,7 +1140,19 @@ describe("filtered usage index availability", () => { const rows = Array.from({ length: 5 }, (_, index) => syntheticRow(index)); writeRows(rows); const indexPath = usageFilterIndexPath(testDir); - setUsageFilterIndexTestHooksForTests(hooks(dbPath => { rmSync(dbPath, { force: true }); })); + let removed = false; + setUsageFilterIndexTestHooksForTests(hooks(dbPath => { + const existed = existsSync(dbPath); + // A scanner can hold a just-closed file on Windows for a moment; that is not the subject. + for (let attempt = 0; ; attempt += 1) { + try { rmSync(dbPath, { force: true }); break; } catch (error) { + const code = (error as NodeJS.ErrnoException).code; + if (attempt >= 4 || (code !== "EBUSY" && code !== "EPERM")) throw error; + Bun.sleepSync(25); + } + } + removed = existed && !existsSync(dbPath); + })); try { const result = await getFilteredUsageAggregate({ provider: "openai" }); expect(summary(result).summary.requests) @@ -1148,6 +1161,8 @@ describe("filtered usage index availability", () => { } finally { setUsageFilterIndexTestHooksForTests(null); } + // Without this the streaming fallback would satisfy every assertion even if the hook never ran. + expect(removed).toBe(true); expect(existsSync(indexPath)).toBe(false); }