mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-18 22:02:49 +08:00
The symlink retarget/restart test flaked inside the full suite with "waitFor timed out". A traced failing run showed the edit made right after unwatch()+watch() was never reported: fs.watch() returns before macOS registers the stream (libuv serves a process's watches from one FSEvents stream, rebuilt on its own thread after each watch/close), and an edit made in that gap is dropped, not delayed — so no timeout would have helped. Poke a probe file under the link until the watcher reports it, then make the edit under test once. Applied after the restart (the observed failure) and after the retarget (the same race with a 100-300ms gap). Under a simulated 300ms registration delay the old test fails 3/3 and the new one passes 3/3; a dead post-restart stream still fails it. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1180,6 +1180,21 @@ describe('FileWatcher', () => {
|
||||
// FSEvents can coalesce writes made while a new stream is being registered.
|
||||
await new Promise(resolve => setTimeout(resolve, 700));
|
||||
};
|
||||
// fs.watch() returns before macOS registers the stream: libuv serves every
|
||||
// watch in a process from one FSEvents stream, rebuilt on its own thread
|
||||
// after each watch/close, and an edit made before that lands is never
|
||||
// reported. Under full-suite load that dropped the edit made right after a
|
||||
// restart. Poke a probe under `dir` until the watcher reports it, so the
|
||||
// edit under test is made once, against a stream known to be live.
|
||||
const untilLive = (dir: string) => {
|
||||
const probe = path.join(dir, 'watch-probe.ts');
|
||||
const rel = path.relative(testDir, probe).replace(/\\/g, '/');
|
||||
return waitFor(() => {
|
||||
if (cg!.getPendingFiles().some(p => p.path === rel)) return true;
|
||||
fs.writeFileSync(probe, `// ${Date.now()}\n`);
|
||||
return false;
|
||||
}, 8000);
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
cg = undefined;
|
||||
@@ -1234,10 +1249,12 @@ describe('FileWatcher', () => {
|
||||
fs.unlinkSync(alias);
|
||||
link(b, alias);
|
||||
await waitFor(() => has('secondTarget') && !has('firstTarget'), 8000);
|
||||
await untilLive(alias);
|
||||
fs.writeFileSync(path.join(b, 'b.ts'), 'export function retargetEdit() {}');
|
||||
await waitFor(() => has('retargetEdit'), 8000);
|
||||
cg!.unwatch();
|
||||
expect(cg!.watch({ debounceMs: 100 })).toBe(true);
|
||||
await untilLive(alias);
|
||||
fs.writeFileSync(path.join(b, 'b.ts'), 'export function restartedEdit() {}');
|
||||
await waitFor(() => has('restartedEdit'), 8000);
|
||||
fs.unlinkSync(alias);
|
||||
|
||||
Reference in New Issue
Block a user