// Flags: --experimental-bench --no-warnings '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'); const options = { samples: 1 }; bench('missing start', options, () => {}); bench('missing end', options, (b) => b.start()); bench('end before start', options, (b) => b.end(1)); bench('duplicate start', options, (b) => { b.start(); b.start(); }); bench('duplicate end', options, (b) => { b.start(); b.end(1); b.end(1); }); bench('invalid operations', options, (b) => { b.start(); b.end(0); }); bench('throws', options, () => { throw new Error('benchmark failure'); }); let lateTimeoutActive = false; bench('late timeout', { samples: 1, timeout: 5 }, async (b) => { lateTimeoutActive = true; try { b.start(); await setTimeout(30); b.end(1); } finally { lateTimeoutActive = false; } }); bench('after late timeout', options, common.mustCall((b) => { assert.strictEqual(lateTimeoutActive, false); completeSample(b); })); const signal = AbortSignal.abort(new Error('stop')); bench('aborted', { samples: 1, signal }, () => {}); bench('duplicate', { samples: 1, params: { value: 1 } }, completeSample); bench('duplicate', { samples: 1, params: { value: 1 } }, completeSample); bench('timeout', { samples: 1, timeout: 0 }, common.mustNotCall()); bench('continues', options, completeSample); // Aborting from the callback guarantees that there is unsettled work. const controller = new AbortController(); bench('unsettled abort', { samples: 1, signal: controller.signal }, common.mustCall(async () => { controller.abort(new Error('stop unsettled work')); await new Promise(() => {}); })); const suiteCompletion = suite('after unsettled abort suite', () => { bench('after unsettled abort', options, common.mustNotCall()); bench.skip('skipped after unsettled abort', options, common.mustNotCall()); }); suiteCompletion.then(common.mustCall()); const completions = []; const sampleNames = []; let summary; const stream = run({ warmup: 0 }); stream.on('bench:complete', (result) => completions.push(result)); stream.on('bench:sample', (sample) => sampleNames.push(sample.name)); stream.on('bench:summary', (result) => { summary = result; }); stream.on('end', common.mustCall(() => { assert.strictEqual(completions.length, 17); assert.deepStrictEqual(summary.counts, { __proto__: null, completed: 3, failed: 13, skipped: 1, total: 17, }); assert.strictEqual(summary.success, false); // The failed run sets the exit code; reset it so the test itself passes. assert.strictEqual(process.exitCode, 1); process.exitCode = 0; const byName = new Map(); for (const result of completions) { const values = byName.get(result.name) ?? []; values.push(result); byName.set(result.name, values); } assert.match(byName.get('missing start')[0].error.message, /did not call start/); assert.match(byName.get('missing end')[0].error.message, /did not call end/); assert.match(byName.get('end before start')[0].error.message, /before start/); assert.strictEqual(byName.get('duplicate start')[0].error.code, 'ERR_INVALID_STATE'); assert.strictEqual(byName.get('duplicate end')[0].error.code, 'ERR_INVALID_STATE'); assert.strictEqual(byName.get('invalid operations')[0].error.code, 'ERR_OUT_OF_RANGE'); assert.strictEqual(byName.get('throws')[0].error.message, 'benchmark failure'); assert.strictEqual(byName.get('timeout')[0].error.code, 'ERR_OPERATION_FAILED'); assert.strictEqual(byName.get('late timeout')[0].error.code, 'ERR_OPERATION_FAILED'); assert.strictEqual(byName.get('after late timeout')[0].error, undefined); assert.strictEqual(byName.get('aborted')[0].error.code, 'ABORT_ERR'); const duplicates = byName.get('duplicate'); assert.strictEqual(duplicates[0].error, undefined); assert.match(duplicates[1].error.message, /duplicate benchmark identity/); assert.strictEqual(byName.get('continues')[0].error, undefined); const aborted = byName.get('unsettled abort')[0].error; assert.strictEqual(aborted.code, 'ABORT_ERR'); assert.deepStrictEqual(aborted.cause, controller.signal.reason); const unsettled = byName.get('after unsettled abort')[0].error; assert.strictEqual(unsettled.code, 'ABORT_ERR'); assert.deepStrictEqual(unsettled.cause, aborted); assert.strictEqual( byName.get('skipped after unsettled abort')[0].skip, true); setTimeout(40).then(common.mustCall(() => { assert.strictEqual(sampleNames.includes('late timeout'), false); })); })); stream.resume();