diff --git a/test/async-hooks/async-hooks.status b/test/async-hooks/async-hooks.status index 344ff8e7affc83..7f36d5a78a6e2b 100644 --- a/test/async-hooks/async-hooks.status +++ b/test/async-hooks/async-hooks.status @@ -5,8 +5,6 @@ prefix async-hooks # sample-test : PASS,FLAKY [true] # This section applies to all platforms -# https://github.com/nodejs/node/issues/21425 -test-statwatcher: PASS,FLAKY [$system==win32] diff --git a/test/async-hooks/test-statwatcher.js b/test/async-hooks/test-statwatcher.js index 48d7b0b22eedff..3daeb1b3fd6652 100644 --- a/test/async-hooks/test-statwatcher.js +++ b/test/async-hooks/test-statwatcher.js @@ -15,68 +15,81 @@ tmpdir.refresh({ spawn: false }); const file1 = path.join(tmpdir.path, 'file1'); const file2 = path.join(tmpdir.path, 'file2'); -fs.writeFileSync(file1, 'foo'); -fs.writeFileSync(file2, 'bar'); -const hooks = initHooks(); -hooks.enable(); - -function onchange1(curr, prev) { - console.log('Watcher: w1'); +const onchangex = (x) => (curr, prev) => { + console.log(`Watcher: ${x}`); console.log('current stat data:', curr); console.log('previous stat data:', prev); -} -// Install first file watcher -const w1 = fs.watchFile(file1, { interval: 10 }, onchange1); +}; + +const checkWatcherStart = (name, watcher) => { + assert.strictEqual(watcher.type, 'STATWATCHER'); + assert.strictEqual(typeof watcher.uid, 'number'); + assert.strictEqual(watcher.triggerAsyncId, 1); + checkInvocations(watcher, { init: 1 }, + `${name}: when started to watch file`); +}; + +const hooks = initHooks(); +hooks.enable(); +// Install first file watcher. +const w1 = fs.watchFile(file1, { interval: 10 }, onchangex('w1')); let as = hooks.activitiesOfTypes('STATWATCHER'); assert.strictEqual(as.length, 1); +// Count all change events to account for all of them in checkInvocations. +let w1HookCount = 0; +w1.on('change', () => w1HookCount++); const statwatcher1 = as[0]; -assert.strictEqual(statwatcher1.type, 'STATWATCHER'); -assert.strictEqual(typeof statwatcher1.uid, 'number'); -assert.strictEqual(statwatcher1.triggerAsyncId, 1); -checkInvocations(statwatcher1, { init: 1 }, - 'watcher1: when started to watch file'); - -function onchange2(curr, prev) { - console.log('Watcher: w2'); - console.log('current stat data:', curr); - console.log('previous stat data:', prev); -} +checkWatcherStart('watcher1', statwatcher1); // Install second file watcher -const w2 = fs.watchFile(file2, { interval: 10 }, onchange2); +const w2 = fs.watchFile(file2, { interval: 10 }, onchangex('w2')); as = hooks.activitiesOfTypes('STATWATCHER'); assert.strictEqual(as.length, 2); +// Count all change events to account for all of them in checkInvocations. +let w2HookCount = 0; +w2.on('change', () => w2HookCount++); const statwatcher2 = as[1]; -assert.strictEqual(statwatcher2.type, 'STATWATCHER'); -assert.strictEqual(typeof statwatcher2.uid, 'number'); -assert.strictEqual(statwatcher2.triggerAsyncId, 1); checkInvocations(statwatcher1, { init: 1 }, 'watcher1: when started to watch second file'); -checkInvocations(statwatcher2, { init: 1 }, - 'watcher2: when started to watch second file'); +checkWatcherStart('watcher2', statwatcher2); setTimeout(() => fs.writeFileSync(file1, 'foo++'), common.platformTimeout(100)); -w1.once('change', common.mustCall((curr, prev) => { - console.log('w1 change', curr, prev); +w1.on('change', common.mustCallAtLeast((curr, prev) => { + console.log('w1 change to', curr, 'from', prev); + // Wait until we get the write above. + if (prev.size !== 0 || curr.size !== 5) + return; + // Remove listeners to make w1HookCount final + w1.removeAllListeners('change'); + setImmediate(() => { - checkInvocations(statwatcher1, { init: 1, before: 1, after: 1 }, + checkInvocations(statwatcher1, + { init: 1, before: w1HookCount, after: w1HookCount }, 'watcher1: when unwatched first file'); checkInvocations(statwatcher2, { init: 1 }, 'watcher2: when unwatched first file'); setTimeout(() => fs.writeFileSync(file2, 'bar++'), common.platformTimeout(100)); - w2.once('change', common.mustCall((curr, prev) => { - console.log('w2 change', curr, prev); + w2.on('change', common.mustCallAtLeast((curr, prev) => { + console.log('w2 change to', curr, 'from', prev); + // Wait until we get the write above. + if (prev.size !== 0 || curr.size !== 5) + return; + // Remove listeners to make w2HookCount final + w2.removeAllListeners('change'); + setImmediate(() => { - checkInvocations(statwatcher1, { init: 1, before: 1, after: 1 }, + checkInvocations(statwatcher1, + { init: 1, before: w1HookCount, after: w1HookCount }, 'watcher1: when unwatched second file'); - checkInvocations(statwatcher2, { init: 1, before: 1, after: 1 }, + checkInvocations(statwatcher2, + { init: 1, before: w2HookCount, after: w2HookCount }, 'watcher2: when unwatched second file'); fs.unwatchFile(file1); fs.unwatchFile(file2); @@ -85,13 +98,13 @@ w1.once('change', common.mustCall((curr, prev) => { }); })); -process.on('exit', onexit); - -function onexit() { +process.once('exit', () => { hooks.disable(); hooks.sanityCheck('STATWATCHER'); - checkInvocations(statwatcher1, { init: 1, before: 1, after: 1 }, + checkInvocations(statwatcher1, + { init: 1, before: w1HookCount, after: w1HookCount }, 'watcher1: when process exits'); - checkInvocations(statwatcher2, { init: 1, before: 1, after: 1 }, + checkInvocations(statwatcher2, + { init: 1, before: w2HookCount, after: w2HookCount }, 'watcher2: when process exits'); -} +});