fix(tests): fix flaky time-based tests (#699)

* fix(tests): fix flaky time-based tests

* test: replace time package with a mock
Using a dedicated dependency would have been awesome, but i try to keep this repo with minimal dependencies
This commit is contained in:
Samuel Berthe
2025-10-05 00:34:07 +02:00
committed by GitHub
parent dedd62f639
commit 380e1a0ae2
15 changed files with 353 additions and 238 deletions
+6
View File
@@ -0,0 +1,6 @@
# xtime
Lightweight mock for time package.
A dedicated package such as [jonboulle/clockwork](https://github.com/jonboulle/clockwork/) would be better, but I would rather limit dependencies for this package. `clockwork` does not support Go 1.18 anymore.
+40
View File
@@ -0,0 +1,40 @@
//nolint:revive
package xtime
import (
"time"
)
func NewFakeClock() *FakeClock {
return NewFakeClockAt(time.Now())
}
func NewFakeClockAt(t time.Time) *FakeClock {
return &FakeClock{
time: t,
}
}
type FakeClock struct {
_ noCopy
// Not protected by a mutex. If a warning is thrown in your tests,
// just disable parallel tests.
time time.Time
}
func (c *FakeClock) Now() time.Time {
return c.time
}
func (c *FakeClock) Since(t time.Time) time.Duration {
return c.time.Sub(t)
}
func (c *FakeClock) Until(t time.Time) time.Duration {
return t.Sub(c.time)
}
func (c *FakeClock) Sleep(d time.Duration) {
c.time = c.time.Add(d)
}
+14
View File
@@ -0,0 +1,14 @@
package xtime
// noCopy may be added to structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
//
// Note that it must not be embedded, due to the Lock and Unlock methods.
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}
+30
View File
@@ -0,0 +1,30 @@
//nolint:revive
package xtime
import (
"time"
)
func NewRealClock() *RealClock {
return &RealClock{}
}
type RealClock struct {
_ noCopy
}
func (c *RealClock) Now() time.Time {
return time.Now()
}
func (c *RealClock) Since(t time.Time) time.Duration {
return time.Since(t)
}
func (c *RealClock) Until(t time.Time) time.Duration {
return time.Until(t)
}
func (c *RealClock) Sleep(d time.Duration) {
time.Sleep(d)
}
+33
View File
@@ -0,0 +1,33 @@
//nolint:revive
package xtime
import "time"
var clock Clock = &RealClock{}
func SetClock(c Clock) {
clock = c
}
func Now() time.Time {
return clock.Now()
}
func Since(t time.Time) time.Duration {
return clock.Since(t)
}
func Until(t time.Time) time.Duration {
return clock.Until(t)
}
func Sleep(d time.Duration) {
clock.Sleep(d)
}
type Clock interface {
Now() time.Time
Since(t time.Time) time.Duration
Until(t time.Time) time.Duration
Sleep(d time.Duration)
}