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

Conversation

mdouglass
Copy link
Contributor

fixes #3373

@@ -218,7 +218,7 @@ export default class Api extends Emittery {
}

runStatus.on('stateChange', record => {
if (record.testFile && !timedOutWorkerFiles.has(record.testFile)) {
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".

Copy link
Member

@novemberborn novemberborn left a comment

Choose a reason for hiding this comment

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

This fix is correct, but for a different reason than you might expect. The timeout in the api.js file is best thought of as an "idle guard". I agree that stdout/stderr shouldn't count as non-idle activity.

In #3373 the test worker isn't exiting because it's still waiting on a timer. And the idle guard doesn't force it to exit. With this change it will, though only 10 seconds after the test itself has timed out.

@@ -218,7 +218,7 @@ export default class Api extends Emittery {
}

runStatus.on('stateChange', record => {
if (record.testFile && !timedOutWorkerFiles.has(record.testFile)) {
if (record.testFile && !timedOutWorkerFiles.has(record.testFile) && record.type !== 'worker-stderr' && record.type !== 'worker-stdout') {
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".

Comment on lines 18 to 22
test('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.snapshot(error.message, 'timeout despite console output');
});
Copy link
Member

Choose a reason for hiding this comment

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

This test is in the wrong place. test-timeouts refers to t.timeout() but this is modifying the overall timeout behavior. A new idle-timeout/ folder would be more appropriate.

(Can't recall whether there's existing tests under the old test-tap but I'm happy not to add there.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Went ahead and moved the test, thanks.

@mdouglass
Copy link
Contributor Author

This fix is correct, but for a different reason than you might expect. The timeout in the api.js file is best thought of as an "idle guard". I agree that stdout/stderr shouldn't count as non-idle activity.

In #3373 the test worker isn't exiting because it's still waiting on a timer. And the idle guard doesn't force it to exit. With this change it will, though only 10 seconds after the test itself has timed out.

Thanks for explaining that, some of the behavior I saw while fixing this makes more sense now that I see the test timeout in Test#timeout vs. the worker timeout here.

@mdouglass mdouglass requested a review from novemberborn April 6, 2025 19:30
* Set a short timeout so it finishes more quickly
* Remove the snapshot; the assertion message was the same as the error message being snapshotted
* Tweak delays within test to be clearer that it can run for a second, but then we keep writing to stdout/stderr
* Use timers/promises rather than new Promise()
* Alternate writing to stdout and stderr
@novemberborn novemberborn changed the title Fix timeouts so that stdout/stderr activity does not keep a test running Do not count writes to stdout/stderr as non-idling activity for timeouts Apr 15, 2025
@novemberborn
Copy link
Member

Thanks @mdouglass, this looks good. I've made some smaller tweaks, mostly in the test itself. Your version took 10.8 seconds to execute in CI which is a little unnecessary 😄

@mdouglass
Copy link
Contributor Author

Thanks @mdouglass, this looks good. I've made some smaller tweaks, mostly in the test itself. Your version took 10.8 seconds to execute in CI which is a little unnecessary 😄

🤣 most definitely too long. Thanks 👍

@novemberborn novemberborn merged commit f243cab into avajs:main Apr 15, 2025
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Timeout does not function if test is writing to the console
2 participants