Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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, []);
}));
Expand Down
16 changes: 16 additions & 0 deletions test/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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` [\<number>][<number>] Passed to `b.end()`. **Default:** `1`.
* `options` [\<Object>][<Object>] 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.
Expand Down
13 changes: 13 additions & 0 deletions test/common/bench.js
Original file line number Diff line number Diff line change
@@ -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 };
5 changes: 2 additions & 3 deletions test/fixtures/bench-runner/identity-child-a.cjs
Original file line number Diff line number Diff line change
@@ -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);
});
};
5 changes: 2 additions & 3 deletions test/fixtures/bench-runner/identity-child-b.cjs
Original file line number Diff line number Diff line change
@@ -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);
});
};
5 changes: 2 additions & 3 deletions test/fixtures/bench-runner/identity-preload.cjs
Original file line number Diff line number Diff line change
@@ -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);
});
5 changes: 2 additions & 3 deletions test/fixtures/bench-runner/identity-shared.cjs
Original file line number Diff line number Diff line change
@@ -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);
});
};
5 changes: 2 additions & 3 deletions test/fixtures/bench-runner/load-error-after-declaration.cjs
Original file line number Diff line number Diff line change
@@ -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');
9 changes: 2 additions & 7 deletions test/fixtures/bench-runner/tools.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

const { completeSample } = require('../../common/bench');
const { bench } = require('node:bench');

if (process.env.NODE_BENCH_PID_LOG !== undefined) {
Expand All @@ -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));
}
5 changes: 4 additions & 1 deletion test/fixtures/wasi-preview-1.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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];
Expand Down
5 changes: 2 additions & 3 deletions test/parallel/test-bench-context-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
'use strict';

const common = require('../common');
const { completeSample } = require('../common/bench');
const assert = require('assert');
const { createRunner } = require('node:bench');

Expand All @@ -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);
Expand Down
5 changes: 2 additions & 3 deletions test/parallel/test-bench-context-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
17 changes: 5 additions & 12 deletions test/parallel/test-bench-create-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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();
Expand Down Expand Up @@ -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',
Expand All @@ -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', {
Expand Down
5 changes: 2 additions & 3 deletions test/parallel/test-bench-custom-reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand Down
15 changes: 5 additions & 10 deletions test/parallel/test-bench-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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(() => {});
});
Expand Down
5 changes: 2 additions & 3 deletions test/parallel/test-bench-filtering.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand All @@ -10,9 +11,7 @@ const calls = [];
function complete(name) {
return (b) => {
calls.push(name);
b.start();
process.hrtime.bigint();
b.end(1);
completeSample(b);
};
}

Expand Down
17 changes: 6 additions & 11 deletions test/parallel/test-bench-harness-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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'));
Expand All @@ -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);
Expand All @@ -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(
Expand All @@ -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();
Expand All @@ -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(() => {
Expand Down
Loading
Loading