Skip to content

Handle unexpected exits in condition polling#1819

Open
ubunatic wants to merge 8 commits intostretchr:masterfrom
ubunatic:condition-polling-capture-unexpected-exit
Open

Handle unexpected exits in condition polling#1819
ubunatic wants to merge 8 commits intostretchr:masterfrom
ubunatic:condition-polling-capture-unexpected-exit

Conversation

@ubunatic
Copy link
Contributor

@ubunatic ubunatic commented Oct 26, 2025

Summary

Fail Eventually, Never, and EventuallyWithT with "Condition exited unexpectedly"
when the condition goroutine exits unexpectedly through runtime.Goexit.

Changes

  • Do not hang Eventually when condition does not return normally and fail fast instead.
  • Do not hang Never when condition does not return normally to fail fast and prevent false positives.
  • Fail EventuallyWithT when runtime.Goexit was not called through collect.FailNow.

Motivation

  • Never currently stops polling, when the condition exits. This can lead to false positives.
  • Eventually currently stop polling, when the condition exits. This prevents fast failures.
  • EventuallyWithT does not fail when the outer t fails.

Related issues

This PR is a concise rewrite of #1809 and should fix Issue #1810.

Changed Behavior

Eventually

condition := func() bool {
   require.Fail(t, "fail fast on outer 't'")
}
// before: assert.Eventually would hang until timeout
// after:  assert.Eventually fails early
assert.Eventually(t, condition, time.Second, time.Millisecond*10))
// 't' would still fail in both cases

EventuallyWithT

condition := func(collect *assert.CollectT) {
   require.Fail(t, "fail fast on outer 't'")
}
// before: assert.EventuallyWithT would return true
// after:  assert.EventuallyWithT returns false
ok := assert.EventuallyWithT(t, condition, time.Second, time.Millisecond*10))
// 't' would still fail in both cases

Never

getValue := func() (int, error) {
	return 1, errors.New("some error")
}

condition := func() bool {
	v, err := getValue()
	require.NoError(t, err)
	return v == 1
}

// before: assert.Never would hang and then report success
// after:  assert.Never fails early
ok := assert.Never(t, condition, time.Second, time.Millisecond*10)
// 't' would still fail in both cases

@ubunatic ubunatic force-pushed the condition-polling-capture-unexpected-exit branch from 3888c76 to a55e775 Compare October 26, 2025 17:00
@ubunatic ubunatic force-pushed the condition-polling-capture-unexpected-exit branch from a55e775 to 5e8ff6e Compare October 26, 2025 17:15
@ubunatic ubunatic marked this pull request as ready for review October 26, 2025 17:31
@dolmen dolmen added pkg-assert Change related to package testify/assert assert.Eventually About assert.Eventually/EventuallyWithT labels Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

assert.Eventually About assert.Eventually/EventuallyWithT pkg-assert Change related to package testify/assert

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants