Skip to content
Prev Previous commit
Next Next commit
test_runner: refactor TestPlan
  • Loading branch information
pmarchini committed Feb 14, 2025
commit 927ffdb2a606381e8d59bb1f675f005626b0ce2f
57 changes: 32 additions & 25 deletions lib/internal/test_runner/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,23 +179,27 @@ class TestPlan {
#waitIndefinitely = false;
Comment thread
pmarchini marked this conversation as resolved.

constructor(count, options = kEmptyObject) {
validateUint32(count, 'count');
validateObject(options, 'options');

this.#validateConstructorArgs(count, options);
this.expected = count;
this.actual = 0;
this.#setWaitOption(options);
}

#validateConstructorArgs(count, options) {
validateUint32(count, 'count');
validateObject(options, 'options');
}

#setWaitOption(options) {
Comment thread
pmarchini marked this conversation as resolved.
Outdated
switch (typeof options.wait) {
case 'boolean':
this.wait = options.wait;
this.#waitIndefinitely = true;
break;

case 'number':
validateNumber(options.wait, 'options.wait', 0, TIMEOUT_MAX);
this.wait = options.wait;
break;

default:
if (options.wait !== undefined) {
throw new ERR_INVALID_ARG_TYPE('options.wait', ['boolean', 'number'], options.wait);
Expand All @@ -211,12 +215,12 @@ class TestPlan {
const { promise, resolve, reject } = PromiseWithResolvers();
const noError = Symbol();
let pollerId;
let timeoutId;
let maxWaitingTimeId;
const interval = 50;

const done = (err, result) => {
clearTimeout(pollerId);
timeoutId ?? clearTimeout(timeoutId);
maxWaitingTimeId ?? clearTimeout(maxWaitingTimeId);

if (err === noError) {
resolve(result);
Expand All @@ -225,17 +229,10 @@ class TestPlan {
}
};

// If the plan has a maximum wait time, then we need to set a timeout
// Otherwise, the plan will wait indefinitely
// If the plan has a maximum wait time, set a timeout.
// Otherwise, the plan will wait indefinitely.
if (!this.#waitIndefinitely) {
timeoutId = setTimeout(() => {
const err = new ERR_TEST_FAILURE(
`plan timed out after ${this.wait}ms with ${this.actual} assertions when expecting ${this.expected}`,
kTestTimeoutFailure,
);
// The pooler has timed out, the test should fail
done(err);
}, this.wait);
maxWaitingTimeId = this.#setMaxWaitingTime(done);
}

const poller = async () => {
Expand All @@ -250,33 +247,43 @@ class TestPlan {
return promise;
}

#setMaxWaitingTime(done) {
return setTimeout(() => {
const err = new ERR_TEST_FAILURE(
`Plan timed out after ${this.wait}ms with ${this.actual} assertions when expecting ${this.expected}`,
kTestTimeoutFailure,
);
// The poller has timed out; the test should fail.
done(err);
}, this.wait);
}

check() {
if (this.#planMet()) {
// If the plan has been met, then there is no need to check for a timeout.
// If the plan has been met, there is no need to check for a timeout.
return;
}
// The plan has not been met
if (!this.hasTimeout()) {
// If the plan doesn't have a timeout, then the test should fail immediately.
// The plan has not been met.
if (!this.#isWaitDefined()) {
// If the plan doesn't have a wait time defined, the test should fail immediately.
throw new ERR_TEST_FAILURE(
`plan expected ${this.expected} assertions but received ${this.actual}`,
`Plan expected ${this.expected} assertions but received ${this.actual}`,
kTestCodeFailure,
);
}
// If the plan has a timeout, then the test is still running
// we need to pool until the timeout is reached or the plan is met
return this.#startPoller();
}

count() {
this.actual++;
}

hasTimeout() {
#isWaitDefined() {
return this.wait !== undefined;
}
}


Comment thread
pmarchini marked this conversation as resolved.
class TestContext {
#assert;
#test;
Expand Down