diff --git a/test/parallel/test-aborted-util.js b/test/parallel/test-aborted-util.js index 7991d72cb6c..4bc45b9f552 100644 --- a/test/parallel/test-aborted-util.js +++ b/test/parallel/test-aborted-util.js @@ -1,59 +1,94 @@ // Flags: --expose-gc 'use strict'; -const common = require('../common'); +require('../common'); const { aborted } = require('util'); -const assert = require('assert'); +const { + match, + rejects, + strictEqual, +} = require('assert'); const { getEventListeners } = require('events'); -const { spawn } = require('child_process'); +const { inspect } = require('util'); -{ - // Test aborted works when provided a resource +const { + test, +} = require('node:test'); + +test('Aborted works when provided a resource', async () => { const ac = new AbortController(); - aborted(ac.signal, {}).then(common.mustCall()); + const promise = aborted(ac.signal, {}); ac.abort(); - assert.strictEqual(ac.signal.aborted, true); - assert.strictEqual(getEventListeners(ac.signal, 'abort').length, 0); -} + await promise; + strictEqual(ac.signal.aborted, true); + strictEqual(getEventListeners(ac.signal, 'abort').length, 0); +}); -{ +test('Aborted with gc cleanup', async () => { // Test aborted with gc cleanup const ac = new AbortController(); - aborted(ac.signal, {}).then(common.mustNotCall()); + + const abortedPromise = aborted(ac.signal, {}); + const { promise, resolve } = Promise.withResolvers(); + setImmediate(() => { global.gc(); ac.abort(); - assert.strictEqual(ac.signal.aborted, true); - assert.strictEqual(getEventListeners(ac.signal, 'abort').length, 0); + strictEqual(ac.signal.aborted, true); + strictEqual(getEventListeners(ac.signal, 'abort').length, 0); + resolve(); }); -} -{ - // Fails with error if not provided abort signal - Promise.all([{}, null, undefined, Symbol(), [], 1, 0, 1n, true, false, 'a', () => {}].map((sig) => - assert.rejects(aborted(sig, {}), { + await promise; + + // Ensure that the promise is still pending + match(inspect(abortedPromise), //); +}); + +test('Fails with error if not provided AbortSignal', async () => { + await Promise.all([{}, null, undefined, Symbol(), [], 1, 0, 1n, true, false, 'a', () => {}].map((sig) => + rejects(aborted(sig, {}), { code: 'ERR_INVALID_ARG_TYPE', }) - )).then(common.mustCall()); -} + )); +}); -{ +test('Fails if not provided a resource', async () => { // Fails if not provided a resource const ac = new AbortController(); - Promise.all([null, undefined, 0, 1, 0n, 1n, Symbol(), '', 'a'].map((resource) => - assert.rejects(aborted(ac.signal, resource), { + await Promise.all([null, undefined, 0, 1, 0n, 1n, Symbol(), '', 'a'].map((resource) => + rejects(aborted(ac.signal, resource), { code: 'ERR_INVALID_ARG_TYPE', }) - )).then(common.mustCall()); + )); +}); + +// To allow this case to be more flexibly tested on runtimes that do not have +// child_process.spawn, we lazily require it and skip the test if it is not +// present. + +let spawn; +function lazySpawn() { + if (spawn === undefined) { + try { + spawn = require('child_process').spawn; + } catch { + // Ignore if spawn does not exist. + } + } + return spawn; } -{ +test('Does not hang forever', { skip: !lazySpawn() }, async () => { + const { promise, resolve } = Promise.withResolvers(); const childProcess = spawn(process.execPath, ['--input-type=module']); - childProcess.on('exit', common.mustCall((code) => { - assert.strictEqual(code, 13); - })); + childProcess.on('exit', (code) => { + strictEqual(code, 13); + resolve(); + }); childProcess.stdin.end(` import { aborted } from 'node:util'; await aborted(new AbortController().signal, {}); `); -} + await promise; +});