Golang 1.24 provides synctest, which can create isolated environments with synctest.Run(f) called bubbles that have their own synthetic clock. This is really useful for testing my production code, which depends on UTC timestamps. However, it contains some goroutines that are triggered asynchronously in the background, and I need to actually wait for their result inside the synctest bubble before I can continue test execution.
How can I write a polling function that waits properly inside a synctest bubble? My current polling function uses time.NewTicker, but that doesn't seeom to integrate with synctest's synthetic clock. It does not seem to wait between polling cycles.
Simplified test code:
func TestTimingWithSynctest(t *testing.T) {
synctest.Run(func() {
// run other test code..
// now I need to actually wait between polling cycles inside the bubble
polling.Run(...)
// run other test code again..
})
}
My current polling function:
// Package polling provides utility functions for polling.
package polling
import (
"context"
"time"
)
// Run repeatedly calls action() until it returns true or an error,
// or until ctx is canceled or timeout is reached.
func Run(ctx context.Context, interval, timeout time.Duration,
action func() (bool, error)) error {
if timeout > 0 {
var cancel context.CancelFunc
// create child context that combines passed ctx with timeout
// then either an cancellation from outside or the timeout cancels polling
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
done, err := action()
if err != nil {
return err
}
if done {
return nil
}
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.C:
// continue looping
}
}
}
timeoutin this test). Can you please add more detail (ideally a fully working example with an explanation of what you expect vs the current result). "to actually wait" this should happen if your routines are not "durably blocked" (but as you don't include this detail it's difficult to comment) - example with external ticker.