From 366054ba0347df52799d6083ce2f600a1c162510 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 4 Feb 2021 11:54:09 -0800 Subject: [PATCH] test: re-implement promises.setInterval() test robustly By using events, we can make sure the call to `controller.abort()` doesn't happen before the next iteration starts. Fixes: https://github.com/nodejs/node/issues/37226 --- test/parallel/test-timers-promisified.js | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/parallel/test-timers-promisified.js b/test/parallel/test-timers-promisified.js index 348f6c2ae0476d..b9d971b3f2ab52 100644 --- a/test/parallel/test-timers-promisified.js +++ b/test/parallel/test-timers-promisified.js @@ -10,6 +10,7 @@ const child_process = require('child_process'); const { NodeEventTarget } = require('internal/event_target'); const timerPromises = require('timers/promises'); +const EventEmitter = require('events'); /* eslint-disable no-restricted-syntax */ @@ -348,6 +349,33 @@ process.on('multipleResolves', common.mustNotCall()); assert.strictEqual(loopCount, 5); })); } + + { + // Check that if we abort when we have some unresolved callbacks, + // we actually call them. + const controller = new AbortController(); + const myEvent = new EventEmitter(); + const { signal } = controller; + const delay = 10; + let totalIterations = 0; + const timeoutLoop = runInterval(async (iterationNumber) => { + myEvent.emit('myevent'); + // The call to abort() will typically happen while we're awaiting here. + await setTimeout(delay); + if (iterationNumber === 2) { + myEvent.once('myevent', () => { + controller.abort(); + }); + } + if (iterationNumber > totalIterations) { + totalIterations = iterationNumber; + } + }, delay, signal); + + timeoutLoop.catch(common.mustCall(() => { + assert.ok(totalIterations >= 3, `iterations was ${totalIterations} < 3`); + })); + } } {