diff --git a/test/client-proxy/test-https-proxy-request-invalid-char-in-url.mjs b/test/client-proxy/test-https-proxy-request-invalid-char-in-url.mjs index 888137b9a5a6..6f27f0775aee 100644 --- a/test/client-proxy/test-https-proxy-request-invalid-char-in-url.mjs +++ b/test/client-proxy/test-https-proxy-request-invalid-char-in-url.mjs @@ -83,7 +83,9 @@ for (const testCase of testCases) { server.close(); assert.deepStrictEqual(requests, expectedUrls); const requestLogs = logs.filter((log) => !('error' in log)); - const errors = logs.filter((log) => 'error' in log); + // The client may reset a tunnel while the proxy is still relaying + // the upstream's TLS shutdown; that says nothing about the URLs. + const errors = logs.filter((log) => 'error' in log && log.error.code !== 'ECONNRESET'); assert.deepStrictEqual(new Set(requestLogs), expectedProxyLogs); assert.deepStrictEqual(errors, []); })); diff --git a/test/common/README.md b/test/common/README.md index 6c8fcf42847a..193250562972 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -28,6 +28,7 @@ several other tasks: ## Table of contents * [ArrayStream module](#arraystream-module) +* [Bench module](#bench-module) * [Benchmark module](#benchmark-module) * [Child process module](#child-process-module) * [Common module API](#common-module-api) @@ -49,6 +50,21 @@ several other tasks: * [UDP pair helper](#udp-pair-helper) * [WPT module](#wpt-module) +## Bench module + +The `bench` module has helpers for tests of `node:bench`. + +### `completeSample(b[, operations[, options]])` + +* `b` The `BenchContext` passed to a `node:bench` benchmark function. +* `operations` [\][] Passed to `b.end()`. **Default:** `1`. +* `options` [\][] Passed to `b.end()`. +* return the sample returned by `b.end()`. + +Calls `b.start()` and `b.end()` with at least one `process.hrtime.bigint()` +tick in between, so the sample has a non-zero duration on hosts whose +monotonic clock is coarse. + ## Benchmark module The `benchmark` module is used by tests to run benchmarks. diff --git a/test/common/bench.js b/test/common/bench.js new file mode 100644 index 000000000000..25d67e3a17b2 --- /dev/null +++ b/test/common/bench.js @@ -0,0 +1,13 @@ +'use strict'; + +// Records a sample with start()/end() and at least one hrtime tick in +// between, so its duration is non-zero even on hosts with a coarse clock. +function completeSample(b, operations = 1, options = undefined) { + b.start(); + const started = process.hrtime.bigint(); + let now = started; + while (now === started) now = process.hrtime.bigint(); + return b.end(operations, options); +} + +module.exports = { completeSample }; diff --git a/test/fixtures/bench-runner/identity-child-a.cjs b/test/fixtures/bench-runner/identity-child-a.cjs index 2b8c4b728b1c..ae7824d0ab7d 100644 --- a/test/fixtures/bench-runner/identity-child-a.cjs +++ b/test/fixtures/bench-runner/identity-child-a.cjs @@ -1,11 +1,10 @@ 'use strict'; +const { completeSample } = require('../../common/bench'); const { bench } = require('node:bench'); module.exports = function declareChildA() { bench('child a', { samples: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); }; diff --git a/test/fixtures/bench-runner/identity-child-b.cjs b/test/fixtures/bench-runner/identity-child-b.cjs index 249bcdcfc4f1..2841a98055e0 100644 --- a/test/fixtures/bench-runner/identity-child-b.cjs +++ b/test/fixtures/bench-runner/identity-child-b.cjs @@ -1,11 +1,10 @@ 'use strict'; +const { completeSample } = require('../../common/bench'); const { bench } = require('node:bench'); module.exports = function declareChildB() { bench('child b', { samples: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); }; diff --git a/test/fixtures/bench-runner/identity-preload.cjs b/test/fixtures/bench-runner/identity-preload.cjs index ed55e627527b..bcc9df72c410 100644 --- a/test/fixtures/bench-runner/identity-preload.cjs +++ b/test/fixtures/bench-runner/identity-preload.cjs @@ -1,9 +1,8 @@ 'use strict'; +const { completeSample } = require('../../common/bench'); const { bench } = require('node:bench'); bench('preload identity', { samples: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); diff --git a/test/fixtures/bench-runner/identity-shared.cjs b/test/fixtures/bench-runner/identity-shared.cjs index 40ce0f27be29..c47bcc954745 100644 --- a/test/fixtures/bench-runner/identity-shared.cjs +++ b/test/fixtures/bench-runner/identity-shared.cjs @@ -1,11 +1,10 @@ 'use strict'; +const { completeSample } = require('../../common/bench'); const { bench } = require('node:bench'); module.exports = function registerSharedIdentity() { bench('shared identity', { samples: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); }; diff --git a/test/fixtures/bench-runner/load-error-after-declaration.cjs b/test/fixtures/bench-runner/load-error-after-declaration.cjs index eca2188d41c5..6f2cf085742c 100644 --- a/test/fixtures/bench-runner/load-error-after-declaration.cjs +++ b/test/fixtures/bench-runner/load-error-after-declaration.cjs @@ -1,11 +1,10 @@ 'use strict'; +const { completeSample } = require('../../common/bench'); const { bench } = require('node:bench'); bench('declared before load error', { samples: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); throw new Error('load failed after declaration'); diff --git a/test/fixtures/bench-runner/tools.cjs b/test/fixtures/bench-runner/tools.cjs index 108a6f81dd63..073a090d8829 100644 --- a/test/fixtures/bench-runner/tools.cjs +++ b/test/fixtures/bench-runner/tools.cjs @@ -1,5 +1,6 @@ 'use strict'; +const { completeSample } = require('../../common/bench'); const { bench } = require('node:bench'); if (process.env.NODE_BENCH_PID_LOG !== undefined) { @@ -10,11 +11,5 @@ if (process.env.NODE_BENCH_PID_LOG !== undefined) { for (const size of [1, 2]) { bench('tools/simple.js', { params: { method: 'loop', size }, - }, (b) => { - let value = 0; - b.start(); - for (let i = 0; i < 1_000; i++) value += size; - b.end(1_000); - if (value === 0) throw new Error('unreachable'); - }); + }, (b) => completeSample(b, 1_000)); } diff --git a/test/fixtures/wasi-preview-1.js b/test/fixtures/wasi-preview-1.js index 535bc3e5ec18..3fde5a30b759 100644 --- a/test/fixtures/wasi-preview-1.js +++ b/test/fixtures/wasi-preview-1.js @@ -68,6 +68,9 @@ assert.strictEqual(wasiPreview1.wasiImport, const name = `pthread-${tid}`; const sab = new SharedArrayBuffer(8 + 8192); const result = new Int32Array(sab); + // The thread stores 0 once it has loaded or 1 with an error; wait on a + // value neither of them writes so an early notify cannot be missed. + Atomics.store(result, 0, -1); const workerData = { name, @@ -106,7 +109,7 @@ assert.strictEqual(wasiPreview1.wasiImport, throw new Error(e); }); - const r = Atomics.wait(result, 0, 0, 1000); + const r = Atomics.wait(result, 0, -1, common.platformTimeout(30_000)); if (r === 'timed-out') { workers[tid].terminate(); delete workers[tid]; diff --git a/test/parallel/test-bench-context-control.js b/test/parallel/test-bench-context-control.js index b847e926ffcd..6ee095f94eae 100644 --- a/test/parallel/test-bench-context-control.js +++ b/test/parallel/test-bench-context-control.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { createRunner } = require('node:bench'); @@ -16,9 +17,7 @@ const { createRunner } = require('node:bench'); }, common.mustCall((b) => { invocations.push(`${b.phase}:${b.index}`); const detail = { index: b.index, phase: b.phase }; - b.start(); - process.hrtime.bigint(); - const sample = b.end(2, { detail }); + const sample = completeSample(b, 2, { detail }); detail.index = -1; assert.strictEqual(sample.operations, 2); diff --git a/test/parallel/test-bench-context-errors.js b/test/parallel/test-bench-context-errors.js index 9ba104443ad6..995330c5faef 100644 --- a/test/parallel/test-bench-context-errors.js +++ b/test/parallel/test-bench-context-errors.js @@ -2,15 +2,14 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { createRunner } = require('node:bench'); const runner = createRunner({ yieldBetweenSamples: false }); runner.bench('done during warmup', { samples: 1, warmup: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); b.done(); }); runner.bench('invalid record', { samples: 1 }, (b) => b.record(null)); diff --git a/test/parallel/test-bench-create-runner.js b/test/parallel/test-bench-create-runner.js index 5540a189ad52..51474af3d99c 100644 --- a/test/parallel/test-bench-create-runner.js +++ b/test/parallel/test-bench-create-runner.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { createRunner } = require('node:bench'); const { setImmediate } = require('timers/promises'); @@ -18,16 +19,12 @@ const { setImmediate } = require('timers/promises'); const firstCompletion = first.bench( 'same name', { samples: 2 }, common.mustCall((b) => { firstCalls++; - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }, 2)); const secondCompletion = second.bench( 'same name', { samples: 1 }, common.mustCall((b) => { secondCalls++; - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); })); await setImmediate(); @@ -74,9 +71,7 @@ const { setImmediate } = require('timers/promises'); const retry = createRunner({ yieldBetweenSamples: false }); retry.bench('not filtered', { samples: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); assert.throws(() => retry.run({ namePattern: 'filtered', @@ -90,9 +85,7 @@ const { setImmediate } = require('timers/promises'); const reentrant = createRunner({ yieldBetweenSamples: false }); reentrant.bench('reentrant options', { samples: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); const reentrantOptions = {}; Object.defineProperty(reentrantOptions, 'samples', { diff --git a/test/parallel/test-bench-custom-reporter.js b/test/parallel/test-bench-custom-reporter.js index 9589834baf3a..1d4ec8bed191 100644 --- a/test/parallel/test-bench-custom-reporter.js +++ b/test/parallel/test-bench-custom-reporter.js @@ -2,15 +2,14 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { Writable } = require('stream'); const { finished } = require('stream/promises'); const { bench, run } = require('node:bench'); bench('completed', { samples: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); bench.skip('skipped', { samples: 1 }, common.mustNotCall()); diff --git a/test/parallel/test-bench-errors.js b/test/parallel/test-bench-errors.js index 2124720fee63..e540d5d847c5 100644 --- a/test/parallel/test-bench-errors.js +++ b/test/parallel/test-bench-errors.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { bench, run, suite } = require('node:bench'); const { setTimeout } = require('timers/promises'); @@ -40,21 +41,15 @@ bench('late timeout', { samples: 1, timeout: 5 }, async (b) => { }); bench('after late timeout', options, common.mustCall((b) => { assert.strictEqual(lateTimeoutActive, false); - complete(b); + completeSample(b); })); const signal = AbortSignal.abort(new Error('stop')); bench('aborted', { samples: 1, signal }, () => {}); -function complete(b) { - b.start(); - process.hrtime.bigint(); - b.end(1); -} - -bench('duplicate', { samples: 1, params: { value: 1 } }, complete); -bench('duplicate', { samples: 1, params: { value: 1 } }, complete); -bench('continues', options, complete); +bench('duplicate', { samples: 1, params: { value: 1 } }, completeSample); +bench('duplicate', { samples: 1, params: { value: 1 } }, completeSample); +bench('continues', options, completeSample); bench('timeout', { samples: 1, timeout: 10 }, async () => { await new Promise(() => {}); }); diff --git a/test/parallel/test-bench-filtering.js b/test/parallel/test-bench-filtering.js index 39f5368d26a0..da580dcdafc0 100644 --- a/test/parallel/test-bench-filtering.js +++ b/test/parallel/test-bench-filtering.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { bench, run, suite } = require('node:bench'); @@ -10,9 +11,7 @@ const calls = []; function complete(name) { return (b) => { calls.push(name); - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }; } diff --git a/test/parallel/test-bench-harness-errors.js b/test/parallel/test-bench-harness-errors.js index 1cb0b505689f..4fd6ec739488 100644 --- a/test/parallel/test-bench-harness-errors.js +++ b/test/parallel/test-bench-harness-errors.js @@ -2,16 +2,11 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { createRunner } = require('node:bench'); const { setImmediate } = require('timers/promises'); -function complete(b) { - b.start(); - process.hrtime.bigint(); - b.end(1); -} - async function testSynchronousSuiteFailure() { const runner = createRunner({ yieldBetweenSamples: false }); const completion = runner.suite('outer', () => { @@ -43,7 +38,7 @@ async function testRunSignal() { samples: 3, }, (b) => { invocations++; - complete(b); + completeSample(b); if (b.index === 0) { abortPromise = setImmediate().then(() => { controller.abort(new Error('run aborted')); @@ -65,7 +60,7 @@ async function testRunSignalAfterSample() { const reason = new Error('sample aborted'); const completion = runner.bench('aborted after sample', { samples: 2, - }, complete); + }, completeSample); const stream = runner.run({ signal: controller.signal }); stream.once('bench:sample', common.mustCall(() => { controller.abort(reason); @@ -80,7 +75,7 @@ async function testRunSignalAfterSample() { async function testStringNamePattern() { const runner = createRunner({ yieldBetweenSamples: false }); - runner.bench('included', { samples: 1 }, complete); + runner.bench('included', { samples: 1 }, completeSample); runner.bench('excluded', { samples: 1 }, common.mustNotCall()); const records = await runner.run({ namePattern: 'included' }).toArray(); const excluded = records.find( @@ -97,7 +92,7 @@ async function testStringNamePattern() { async function testTopLevelRecovery() { const runner = createRunner({ yieldBetweenSamples: false }); const suiteCompletion = runner.suite('nested', () => { - runner.bench('listener failure', { samples: 1 }, complete); + runner.bench('listener failure', { samples: 1 }, completeSample); }); const stream = runner.run(); const failure = new Error(); @@ -123,7 +118,7 @@ async function testRepeatedReportingFailure() { const summary = new Error('summary listener failed'); const completion = runner.bench('reporting failures', { samples: 1, - }, complete); + }, completeSample); const stream = runner.run(); stream.on('bench:start', common.mustCall(() => { throw original; })); stream.on('bench:diagnostic', common.mustCall(() => { diff --git a/test/parallel/test-bench-hook-errors.js b/test/parallel/test-bench-hook-errors.js index c4615419674a..f2977f241deb 100644 --- a/test/parallel/test-bench-hook-errors.js +++ b/test/parallel/test-bench-hook-errors.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { setImmediate } = require('timers/promises'); const { @@ -14,12 +15,6 @@ const { suite, } = require('node:bench'); -function complete(b) { - b.start(); - process.hrtime.bigint(); - b.end(1); -} - suite('before failure', () => { before(() => { throw new Error('before failure'); }); after(common.mustCall()); @@ -34,7 +29,7 @@ suite('beforeEach failure', () => { suite('after failure', () => { after(() => { throw new Error('after failure'); }); - bench('completes before after', { samples: 1 }, complete); + bench('completes before after', { samples: 1 }, completeSample); }); suite('build failure', async () => { @@ -42,7 +37,7 @@ suite('build failure', async () => { throw new Error('build failure'); }); -bench('continues after suite failures', { samples: 1 }, complete); +bench('continues after suite failures', { samples: 1 }, completeSample); const completions = []; const diagnostics = []; diff --git a/test/parallel/test-bench-reporters.js b/test/parallel/test-bench-reporters.js index 44e43bd5be78..f383e2cf5213 100644 --- a/test/parallel/test-bench-reporters.js +++ b/test/parallel/test-bench-reporters.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { Readable } = require('stream'); const { bench, run } = require('node:bench'); @@ -11,9 +12,7 @@ bench('json completed', { params: { size: 'small' }, samples: 1, }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); bench('json failed', { samples: 1 }, () => { diff --git a/test/parallel/test-bench-run-options.js b/test/parallel/test-bench-run-options.js index e04bc15ef335..bbb89f5fdc99 100644 --- a/test/parallel/test-bench-run-options.js +++ b/test/parallel/test-bench-run-options.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { bench, run } = require('node:bench'); @@ -9,9 +10,7 @@ let invocations = 0; const timeout = common.platformTimeout(1000); bench('overridden', { samples: 8, timeout, warmup: 8 }, (b) => { invocations++; - b.start(); - process.hrtime.bigint(); - b.end(invocations); + completeSample(b, invocations); }); const plans = []; diff --git a/test/parallel/test-bench-run.js b/test/parallel/test-bench-run.js index 0e152342bcaa..e79411f83e1d 100644 --- a/test/parallel/test-bench-run.js +++ b/test/parallel/test-bench-run.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { setImmediate } = require('timers/promises'); const { @@ -42,9 +43,7 @@ const suiteCompletion = suite('group', { tags: ['Group'] }, async () => { contexts.add(b); calls.push('sync sample'); assert.deepStrictEqual(b.params, { __proto__: null, a: true, z: 2 }); - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); active = false; }, 3)); @@ -54,9 +53,7 @@ const suiteCompletion = suite('group', { tags: ['Group'] }, async () => { contexts.add(b); calls.push('async sample'); await setImmediate(); - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); await setImmediate(); active = false; }, 2)); diff --git a/test/parallel/test-bench-validation.js b/test/parallel/test-bench-validation.js index fa7a579aa60c..39edc5d411cc 100644 --- a/test/parallel/test-bench-validation.js +++ b/test/parallel/test-bench-validation.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { bench, createRunner, run } = require('node:bench'); @@ -11,17 +12,13 @@ let objectOverloadCalls = 0; function functionOverload(b) { functionOverloadCalls++; - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); b.done(); } function objectOverload(b) { objectOverloadCalls++; - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); } assert.throws(() => bench('', noop), { code: 'ERR_INVALID_ARG_VALUE' }); @@ -69,9 +66,7 @@ bench(functionOverload); bench({ samples: 1 }, objectOverload); bench('valid', { samples: 1 }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); const stream = run(); diff --git a/test/parallel/test-bench-yield-between-samples.js b/test/parallel/test-bench-yield-between-samples.js index 7d08318a027a..aceb381d1a57 100644 --- a/test/parallel/test-bench-yield-between-samples.js +++ b/test/parallel/test-bench-yield-between-samples.js @@ -2,6 +2,7 @@ 'use strict'; const common = require('../common'); +const { completeSample } = require('../common/bench'); const assert = require('assert'); const { createRunner } = require('node:bench'); const { setImmediate } = require('timers/promises'); @@ -16,9 +17,7 @@ async function observe(factoryOptions, runOptions) { runner.bench('yielding', { samples: 2 }, (b) => { observed.push(turnOccurred); - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); await runner.run(runOptions).toArray(); @@ -55,9 +54,7 @@ async function observeAfterEachTimeout() { samples: 1, timeout: 5, }, (b) => { - b.start(); - process.hrtime.bigint(); - b.end(1); + completeSample(b); }); await runner.run().toArray(); const result = await completion; diff --git a/test/parallel/test-dns-resolver-max-timeout.js b/test/parallel/test-dns-resolver-max-timeout.js index 7abac39323e1..1a4aaef96c96 100644 --- a/test/parallel/test-dns-resolver-max-timeout.js +++ b/test/parallel/test-dns-resolver-max-timeout.js @@ -52,9 +52,11 @@ server.bind(0, common.mustCall(async () => { // Test that maxTimeout is effective. // Without maxTimeout, the timeout will keep increasing when retrying. - const timeout1 = await timeout(address, { timeout: 500, tries: 3 }); - // With maxTimeout, the timeout will always be 500 when retrying. - const timeout2 = await timeout(address, { timeout: 500, tries: 3, maxTimeout: 500 }); + // Expired tries are only noticed on the resolver's `timeout` ms timer tick, + // so use enough tries that the doubling run cannot overlap the capped one. + const timeout1 = await timeout(address, { timeout: 100, tries: 5 }); + // With maxTimeout, the timeout will always be 100 when retrying. + const timeout2 = await timeout(address, { timeout: 100, tries: 5, maxTimeout: 100 }); console.log(`timeout1: ${timeout1}, timeout2: ${timeout2}`); assert.strictEqual(timeout1 !== undefined && timeout2 !== undefined, true); assert.strictEqual(timeout1 > timeout2, true); diff --git a/test/parallel/test-external-memory-reasonable-size.js b/test/parallel/test-external-memory-reasonable-size.js index 14e2573328ba..f9ff1af8e5a1 100644 --- a/test/parallel/test-external-memory-reasonable-size.js +++ b/test/parallel/test-external-memory-reasonable-size.js @@ -8,7 +8,7 @@ const common = require('../common'); const assert = require('assert'); -const { spawnSync } = require('child_process'); +const { execSync } = require('child_process'); const { totalmem } = require('os'); // The smallest limit V8 accepts is 1 GB, so the child has to allocate more @@ -20,14 +20,15 @@ for (const flag of [ '--external-memory-max-reasonable-size=1', '--external_memory_max_reasonable_size=1', ]) { - const child = spawnSync(process.execPath, [ - flag, '-e', 'new Float64Array(150_000_000)', - ]); - - assert.notStrictEqual( - child.status, - 0, - `${flag} was not honored, the child exited cleanly`, + // The child aborts with over a gigabyte resident, so keep it from writing a + // core file; on some hosts that dump alone outlasts the test timeout. + const [cmd, opts] = common.escapePOSIXShell`"${process.execPath}" ${flag} -e "new Float64Array(150_000_000)"`; + assert.throws( + () => execSync(common.isWindows ? cmd : `ulimit -c 0; ${cmd}`, { ...opts, stdio: 'pipe' }), + (err) => { + assert.notStrictEqual(err.status, 0, `${flag} was not honored, the child exited cleanly`); + assert.match(err.stderr.toString(), /kMaxReasonableBytes/); + return true; + }, ); - assert.match(child.stderr.toString(), /kMaxReasonableBytes/); } diff --git a/test/test-runner/test-run-watch-emit-restarted.mjs b/test/test-runner/test-run-watch-emit-restarted.mjs index 200231c69043..fd596bd818ca 100644 --- a/test/test-runner/test-run-watch-emit-restarted.mjs +++ b/test/test-runner/test-run-watch-emit-restarted.mjs @@ -1,5 +1,5 @@ // Test run({ watch: true }) emits test:watch:restarted when file is updated -import * as common from '../common/index.mjs'; +import '../common/index.mjs'; import { run } from 'node:test'; import assert from 'node:assert'; import { writeFileSync } from 'node:fs'; @@ -11,9 +11,8 @@ import { refreshForTestRunnerWatch, skipIfNoWatch, fixtureContent } from '../com skipIfNoWatch(); refreshForTestRunnerWatch(); -let alreadyDrained = false; const events = []; -const testWatchRestarted = common.mustCall(1); +let written = false; const controller = new AbortController(); const stream = run({ @@ -21,27 +20,24 @@ const stream = run({ watch: true, signal: controller.signal, }).on('data', function({ type }) { - events.push(type); - if (type === 'test:watch:restarted') { - testWatchRestarted(); + if (type !== 'test:watch:restarted' && type !== 'test:watch:drained') { + return; } - if (type === 'test:watch:drained') { - if (alreadyDrained) { - controller.abort(); - } - alreadyDrained = true; + events.push(type); + // Watchers with latency (FSEvents) can still report the fixture setup after + // the first run has started, so only a restart after the write below counts. + if (written && type === 'test:watch:drained' && events.at(-2) === 'test:watch:restarted') { + controller.abort(); } }); await once(stream, 'test:watch:drained'); +events.length = 0; +written = true; writeFileSync(join(tmpdir.path, 'test.js'), fixtureContent['test.js']); // eslint-disable-next-line no-unused-vars for await (const _ of stream); -assert.partialDeepStrictEqual(events, [ - 'test:watch:drained', - 'test:watch:restarted', - 'test:watch:drained', -]); +assert.deepStrictEqual(events.slice(-2), ['test:watch:restarted', 'test:watch:drained']); diff --git a/test/test-runner/test-runner.status b/test/test-runner/test-runner.status index 149d6ab689cd..7d2d59d3540c 100644 --- a/test/test-runner/test-runner.status +++ b/test/test-runner/test-runner.status @@ -14,4 +14,3 @@ test-watch-create-isolation-none: SKIP # https://github.com/nodejs/node/issues/54534#issuecomment-5423551021 test-run-watch-cwd-isolation-none: PASS, FLAKY test-run-watch-cwd-isolation-none-argv: PASS, FLAKY -test-run-watch-emit-restarted: PASS, FLAKY diff --git a/test/wasi/wasi.status b/test/wasi/wasi.status index 14b671b6e3b1..a26617e01367 100644 --- a/test/wasi/wasi.status +++ b/test/wasi/wasi.status @@ -15,10 +15,3 @@ test-wasi-getrusage: SKIP # Unsupported on Windows and Android test-wasi-readdir: SKIP -[$system==win32 || $system==macos] -# https://github.com/nodejs/node/issues/64226#issuecomment-5423585588 -test-wasi-pthread: PASS, FLAKY - -[$system==linux] -# https://github.com/nodejs/node/issues/59146 -test-wasi-pthread: PASS, FLAKY