Skip to content

Do not count writes to stdout/stderr as non-idling activity for timeouts #3374

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 15, 2025
Merged
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
5 changes: 2 additions & 3 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,8 @@ export default class Api extends Emittery {
}

runStatus.on('stateChange', record => {
if (record.testFile && !timedOutWorkerFiles.has(record.testFile)) {
// Debounce the timer whenever there is activity from workers that
// haven't already timed out.
if (record.testFile && !timedOutWorkerFiles.has(record.testFile) && record.type !== 'worker-stderr' && record.type !== 'worker-stdout') {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd personally prefer to make this opt-in so only assertions/test state changes reset the timeout (so we hew closer to the documentation).
But:
a) I don't know the complete list of record type's here that would apply
b) it's a bigger change from current behavior than I'm comfortable making without feedback

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change is correct. The timeout here is a guard against test workers that are no longer making progress. It's different from t.timeout() which limits how long an individual test can take.

Essentially with this change, we no longer count stdout/stderr as "making progress".

// Debounce the timer whenever there is test-related activity from workers that haven't already timed out.
timeoutTrigger.debounce();
}

Expand Down
13 changes: 13 additions & 0 deletions test/idle-timeouts/fixtures/console-output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {setTimeout as delay} from 'node:timers/promises';
import test from 'ava';

test('timeout with console output', async t => {
t.timeout(1000, 'timeout despite console output');
for (let i = 0; await delay(100, true); i++) {
if (i % 2 === 0) {
console.log('stdout');
} else {
console.error('stderr');
}
}
});
9 changes: 9 additions & 0 deletions test/idle-timeouts/fixtures/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "module",
"ava": {
"files": [
"*.js"
],
"timeout": "500ms"
}
}
9 changes: 9 additions & 0 deletions test/idle-timeouts/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import test from '@ava/test';

import {fixture} from '../helpers/exec.js';

test('idle timeouts are not blocked by console output', async t => {
const result = await t.throwsAsync(fixture(['console-output.js']));
const error = result.stats.getError(result.stats.failed[0]);
t.is(error.message, 'timeout despite console output');
});