diff --git a/__tests__/resolution.test.ts b/__tests__/resolution.test.ts index 7c697a315..df8a0e092 100644 --- a/__tests__/resolution.test.ts +++ b/__tests__/resolution.test.ts @@ -28,12 +28,15 @@ describe('Resolution Module', () => { }); afterEach(() => { - // Clean up + // destroy() is an alias for close(): it releases the database but leaves + // the project directory on disk, so removing tempDir cannot be the + // alternative to it. Both must run, on every test. maxRetries covers + // Windows releasing the SQLite handles slightly after close() returns. if (cg) { cg.destroy(); - } else if (fs.existsSync(tempDir)) { - fs.rmSync(tempDir, { recursive: true }); + cg = undefined as unknown as CodeGraph; } + fs.rmSync(tempDir, { recursive: true, force: true, maxRetries: 5 }); }); describe('Name Matcher', () => { @@ -3741,6 +3744,7 @@ int run() { and src.kind = 'file' and src.file_path = 'src/main.cpp' `).all() as Array<{ dstKind: string; dstPath: string }>; + db.close(); const resolvedToHeader = rows.find( (r) => r.dstKind === 'file' && r.dstPath === 'include/utils.h' ); @@ -3751,6 +3755,13 @@ int run() { ); expect(stdlibFile).toBeUndefined(); } finally { + // The graph opened on tempProject has to be closed here: the outer + // afterEach runs after this finally, so on Windows the still-open + // database makes the removal fail with EPERM. + if (cg) { + cg.close(); + cg = undefined as unknown as CodeGraph; + } fs.rmSync(tempProject, { recursive: true, force: true }); } }); @@ -3788,6 +3799,7 @@ class Both : public Base, public Plain {}; // templated + plain in one cla where e.kind = 'extends'` ) .all() as Array<{ fromName: string; toName: string }>; + db.close(); const has = (from: string, to: string) => edges.some((r) => r.fromName === from && r.toName === to); @@ -3850,11 +3862,19 @@ class Both : public Base, public Plain {}; // templated + plain in one cla and src.kind = 'file' and src.file_path = 'src/page.php' `).all() as Array<{ dstKind: string; dstPath: string }>; + db.close(); const resolved = rows.find( (r) => r.dstKind === 'file' && r.dstPath === 'src/lib.php' ); expect(resolved, 'page.php → src/lib.php imports edge missing').toBeDefined(); } finally { + // The graph opened on tempProject has to be closed here: the outer + // afterEach runs after this finally, so on Windows the still-open + // database makes the removal fail with EPERM. + if (cg) { + cg.close(); + cg = undefined as unknown as CodeGraph; + } fs.rmSync(tempProject, { recursive: true, force: true }); } }); @@ -3884,11 +3904,19 @@ class Both : public Base, public Plain {}; // templated + plain in one cla and src.kind = 'file' and src.file_path = 'index.php' `).all() as Array<{ dstKind: string; dstPath: string }>; + db.close(); expect( rows.find((r) => r.dstKind === 'file' && r.dstPath === 'inc/db.php'), 'index.php → inc/db.php imports edge missing' ).toBeDefined(); } finally { + // The graph opened on tempProject has to be closed here: the outer + // afterEach runs after this finally, so on Windows the still-open + // database makes the removal fail with EPERM. + if (cg) { + cg.close(); + cg = undefined as unknown as CodeGraph; + } fs.rmSync(tempProject, { recursive: true, force: true }); } }); @@ -3923,11 +3951,19 @@ class Both : public Base, public Plain {}; // templated + plain in one cla and src.kind = 'file' and src.file_path = 'app/page.php' `).all() as Array<{ dstKind: string; dstPath: string }>; + db.close(); expect( rows.find((r) => r.dstKind === 'file' && r.dstPath === 'lib/inc/db.php'), 'app/page.php must NOT mis-connect to unrelated lib/inc/db.php' ).toBeUndefined(); } finally { + // The graph opened on tempProject has to be closed here: the outer + // afterEach runs after this finally, so on Windows the still-open + // database makes the removal fail with EPERM. + if (cg) { + cg.close(); + cg = undefined as unknown as CodeGraph; + } fs.rmSync(tempProject, { recursive: true, force: true }); } });