Skip to content

Commit 46e1c36

Browse files
authored
feat: add Next() method to mock Clock (#13657)
1 parent 0d2f146 commit 46e1c36

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

clock/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,22 @@ w.MustWait(ctx)
188188
// d contains the duration we advanced
189189
```
190190

191+
`d, ok := Peek()` returns the duration until the next event, if any (`ok` is `true`). You can use
192+
this to advance a specific time, regardless of the tickers and timer events:
193+
194+
```go
195+
desired := time.Minute // time to advance
196+
for desired > 0 {
197+
p, ok := mClock.Peek()
198+
if !ok || p > desired {
199+
mClock.Advance(desired).MustWait(ctx)
200+
break
201+
}
202+
mClock.Advance(p).MustWait(ctx)
203+
desired -= p
204+
}
205+
```
206+
191207
### Traps
192208

193209
A trap allows you to match specific calls into the library while mocking, block their return,

clock/mock.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,18 @@ func (m *Mock) AdvanceNext() (time.Duration, AdvanceWaiter) {
357357
return d, w
358358
}
359359

360+
// Peek returns the duration until the next ticker or timer event and the value
361+
// true, or, if there are no running tickers or timers, it returns zero and
362+
// false.
363+
func (m *Mock) Peek() (d time.Duration, ok bool) {
364+
m.mu.Lock()
365+
defer m.mu.Unlock()
366+
if m.nextTime.IsZero() {
367+
return 0, false
368+
}
369+
return m.nextTime.Sub(m.cur), true
370+
}
371+
360372
// Trapper allows the creation of Traps
361373
type Trapper struct {
362374
// mock is the underlying Mock. This is a thin wrapper around Mock so that

clock/mock_test.go

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func TestAfterFunc_NegativeDuration(t *testing.T) {
8484
func TestNewTicker(t *testing.T) {
8585
t.Parallel()
8686
// nolint:gocritic // trying to avoid Coder-specific stuff with an eye toward spinning this out
87-
ctx, cancel := context.WithTimeout(context.Background(), 1000*time.Second)
87+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
8888
defer cancel()
8989

9090
mClock := clock.NewMock(t)
@@ -167,3 +167,50 @@ func TestNewTicker(t *testing.T) {
167167
}
168168
}
169169
}
170+
171+
func TestPeek(t *testing.T) {
172+
t.Parallel()
173+
// nolint:gocritic // trying to avoid Coder-specific stuff with an eye toward spinning this out
174+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
175+
defer cancel()
176+
177+
mClock := clock.NewMock(t)
178+
d, ok := mClock.Peek()
179+
if d != 0 {
180+
t.Fatal("expected Peek() to return 0")
181+
}
182+
if ok {
183+
t.Fatal("expected Peek() to return false")
184+
}
185+
186+
tmr := mClock.NewTimer(time.Second)
187+
d, ok = mClock.Peek()
188+
if d != time.Second {
189+
t.Fatal("expected Peek() to return 1s")
190+
}
191+
if !ok {
192+
t.Fatal("expected Peek() to return true")
193+
}
194+
195+
mClock.Advance(999 * time.Millisecond).MustWait(ctx)
196+
d, ok = mClock.Peek()
197+
if d != time.Millisecond {
198+
t.Fatal("expected Peek() to return 1ms")
199+
}
200+
if !ok {
201+
t.Fatal("expected Peek() to return true")
202+
}
203+
204+
stopped := tmr.Stop()
205+
if !stopped {
206+
t.Fatal("expected Stop() to return true")
207+
}
208+
209+
d, ok = mClock.Peek()
210+
if d != 0 {
211+
t.Fatal("expected Peek() to return 0")
212+
}
213+
if ok {
214+
t.Fatal("expected Peek() to return false")
215+
}
216+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy