Add a clock package for better time mocking (#1136)
* Add a clock package for better time mocking * Make Clock a struct so it doesn't need initialization * Test clock package * Use atomic for live time tests * Refer to same clock.Mock throughout methods
This commit is contained in:
parent
42475c28f7
commit
d3423408c7
@ -8,6 +8,7 @@
|
||||
|
||||
## Changes since v7.1.2
|
||||
|
||||
- [#1136](https://github.com/oauth2-proxy/oauth2-proxy/pull/1136) Add clock package for better time mocking in tests (@NickMeves)
|
||||
- [#947](https://github.com/oauth2-proxy/oauth2-proxy/pull/947) Multiple provider ingestion and validation in alpha options (first stage: [#926](https://github.com/oauth2-proxy/oauth2-proxy/issues/926)) (@yanasega)
|
||||
|
||||
# V7.1.2
|
||||
|
1
go.mod
1
go.mod
@ -5,6 +5,7 @@ go 1.16
|
||||
require (
|
||||
github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb
|
||||
github.com/alicebob/miniredis/v2 v2.13.0
|
||||
github.com/benbjohnson/clock v1.1.1-0.20210213131748-c97fc7b6bee0
|
||||
github.com/bitly/go-simplejson v0.5.0
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||
|
2
go.sum
2
go.sum
@ -38,6 +38,8 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/benbjohnson/clock v1.1.1-0.20210213131748-c97fc7b6bee0 h1:ROGOOFsMU1fh3kR94itIWlWiPLtgd4TA/qWi4+lL0GM=
|
||||
github.com/benbjohnson/clock v1.1.1-0.20210213131748-c97fc7b6bee0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
|
164
pkg/clock/clock.go
Normal file
164
pkg/clock/clock.go
Normal file
@ -0,0 +1,164 @@
|
||||
package clock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
clockapi "github.com/benbjohnson/clock"
|
||||
)
|
||||
|
||||
var (
|
||||
globalClock = clockapi.New()
|
||||
mu sync.Mutex
|
||||
)
|
||||
|
||||
// Set the global clock to a clockapi.Mock with the given time.Time
|
||||
func Set(t time.Time) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
mock, ok := globalClock.(*clockapi.Mock)
|
||||
if !ok {
|
||||
mock = clockapi.NewMock()
|
||||
}
|
||||
mock.Set(t)
|
||||
globalClock = mock
|
||||
}
|
||||
|
||||
// Add moves the mocked global clock forward the given duration. It will error
|
||||
// if the global clock is not mocked.
|
||||
func Add(d time.Duration) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
mock, ok := globalClock.(*clockapi.Mock)
|
||||
if !ok {
|
||||
return errors.New("time not mocked")
|
||||
}
|
||||
mock.Add(d)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset sets the global clock to a pure time implementation. Returns any
|
||||
// existing Mock if set in case lingering time operations are attached to it.
|
||||
func Reset() *clockapi.Mock {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
existing := globalClock
|
||||
globalClock = clockapi.New()
|
||||
|
||||
mock, ok := existing.(*clockapi.Mock)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return mock
|
||||
}
|
||||
|
||||
// Clock is a non-package level wrapper around time that supports stubbing.
|
||||
// It will use its localized stubs (allowing for parallelized unit tests
|
||||
// where package level stubbing would cause issues). It falls back to any
|
||||
// package level time stubs for non-parallel, cross-package integration
|
||||
// testing scenarios.
|
||||
//
|
||||
// If nothing is stubbed, it defaults to default time behavior in the time
|
||||
// package.
|
||||
type Clock struct {
|
||||
mock *clockapi.Mock
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Set sets the Clock to a clock.Mock at the given time.Time
|
||||
func (c *Clock) Set(t time.Time) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
if c.mock == nil {
|
||||
c.mock = clockapi.NewMock()
|
||||
}
|
||||
c.mock.Set(t)
|
||||
}
|
||||
|
||||
// Add moves clock forward time.Duration if it is mocked. It will error
|
||||
// if the clock is not mocked.
|
||||
func (c *Clock) Add(d time.Duration) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
if c.mock == nil {
|
||||
return errors.New("clock not mocked")
|
||||
}
|
||||
c.mock.Add(d)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset removes local clock.Mock. Returns any existing Mock if set in case
|
||||
// lingering time operations are attached to it.
|
||||
func (c *Clock) Reset() *clockapi.Mock {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
existing := c.mock
|
||||
c.mock = nil
|
||||
return existing
|
||||
}
|
||||
|
||||
func (c *Clock) After(d time.Duration) <-chan time.Time {
|
||||
m := c.mock
|
||||
if m == nil {
|
||||
return globalClock.After(d)
|
||||
}
|
||||
return m.After(d)
|
||||
}
|
||||
|
||||
func (c *Clock) AfterFunc(d time.Duration, f func()) *clockapi.Timer {
|
||||
m := c.mock
|
||||
if m == nil {
|
||||
return globalClock.AfterFunc(d, f)
|
||||
}
|
||||
return m.AfterFunc(d, f)
|
||||
}
|
||||
|
||||
func (c *Clock) Now() time.Time {
|
||||
m := c.mock
|
||||
if m == nil {
|
||||
return globalClock.Now()
|
||||
}
|
||||
return m.Now()
|
||||
}
|
||||
|
||||
func (c *Clock) Since(t time.Time) time.Duration {
|
||||
m := c.mock
|
||||
if m == nil {
|
||||
return globalClock.Since(t)
|
||||
}
|
||||
return m.Since(t)
|
||||
}
|
||||
|
||||
func (c *Clock) Sleep(d time.Duration) {
|
||||
m := c.mock
|
||||
if m == nil {
|
||||
globalClock.Sleep(d)
|
||||
return
|
||||
}
|
||||
m.Sleep(d)
|
||||
}
|
||||
|
||||
func (c *Clock) Tick(d time.Duration) <-chan time.Time {
|
||||
m := c.mock
|
||||
if m == nil {
|
||||
return globalClock.Tick(d)
|
||||
}
|
||||
return m.Tick(d)
|
||||
}
|
||||
|
||||
func (c *Clock) Ticker(d time.Duration) *clockapi.Ticker {
|
||||
m := c.mock
|
||||
if m == nil {
|
||||
return globalClock.Ticker(d)
|
||||
}
|
||||
return m.Ticker(d)
|
||||
}
|
||||
|
||||
func (c *Clock) Timer(d time.Duration) *clockapi.Timer {
|
||||
m := c.mock
|
||||
if m == nil {
|
||||
return globalClock.Timer(d)
|
||||
}
|
||||
return m.Timer(d)
|
||||
}
|
17
pkg/clock/clock_suite_test.go
Normal file
17
pkg/clock/clock_suite_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package clock_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestClockSuite(t *testing.T) {
|
||||
logger.SetOutput(GinkgoWriter)
|
||||
logger.SetErrOutput(GinkgoWriter)
|
||||
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Clock")
|
||||
}
|
380
pkg/clock/clock_test.go
Normal file
380
pkg/clock/clock_test.go
Normal file
@ -0,0 +1,380 @@
|
||||
package clock_test
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/clock"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
const (
|
||||
testGlobalEpoch = 1000000000
|
||||
testLocalEpoch = 1234567890
|
||||
)
|
||||
|
||||
var _ = Describe("Clock suite", func() {
|
||||
var testClock = clock.Clock{}
|
||||
|
||||
AfterEach(func() {
|
||||
clock.Reset()
|
||||
testClock.Reset()
|
||||
})
|
||||
|
||||
Context("Global time not overridden", func() {
|
||||
It("errors when trying to Add", func() {
|
||||
err := clock.Add(123 * time.Hour)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
Context("Clock not mocked via Set", func() {
|
||||
const (
|
||||
outsideTolerance = int32(0)
|
||||
withinTolerance = int32(1)
|
||||
)
|
||||
|
||||
It("uses time.After for After", func() {
|
||||
var tolerance int32
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, withinTolerance)
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, outsideTolerance)
|
||||
}()
|
||||
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
|
||||
<-testClock.After(20 * time.Millisecond)
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(withinTolerance))
|
||||
|
||||
<-testClock.After(20 * time.Millisecond)
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
})
|
||||
|
||||
It("uses time.AfterFunc for AfterFunc", func() {
|
||||
var tolerance int32
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, withinTolerance)
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, outsideTolerance)
|
||||
}()
|
||||
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
testClock.AfterFunc(20*time.Millisecond, func() {
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(withinTolerance))
|
||||
|
||||
wg.Add(1)
|
||||
testClock.AfterFunc(20*time.Millisecond, func() {
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
})
|
||||
|
||||
It("uses time.Now for Now", func() {
|
||||
a := time.Now()
|
||||
b := testClock.Now()
|
||||
Expect(b.Sub(a).Round(10 * time.Millisecond)).To(Equal(0 * time.Millisecond))
|
||||
})
|
||||
|
||||
It("uses time.Since for Since", func() {
|
||||
past := time.Now().Add(-60 * time.Second)
|
||||
Expect(time.Since(past).Round(10 * time.Millisecond)).
|
||||
To(Equal(60 * time.Second))
|
||||
})
|
||||
|
||||
It("uses time.Sleep for Sleep", func() {
|
||||
var tolerance int32
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, withinTolerance)
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, outsideTolerance)
|
||||
}()
|
||||
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
|
||||
testClock.Sleep(20 * time.Millisecond)
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(withinTolerance))
|
||||
|
||||
testClock.Sleep(20 * time.Millisecond)
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
})
|
||||
|
||||
It("uses time.Tick for Tick", func() {
|
||||
var tolerance int32
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, withinTolerance)
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, outsideTolerance)
|
||||
}()
|
||||
|
||||
ch := testClock.Tick(20 * time.Millisecond)
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
<-ch
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(withinTolerance))
|
||||
<-ch
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(withinTolerance))
|
||||
<-ch
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
})
|
||||
|
||||
It("uses time.Ticker for Ticker", func() {
|
||||
var tolerance int32
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, withinTolerance)
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
atomic.StoreInt32(&tolerance, outsideTolerance)
|
||||
}()
|
||||
|
||||
ticker := testClock.Ticker(20 * time.Millisecond)
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
<-ticker.C
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(withinTolerance))
|
||||
<-ticker.C
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(withinTolerance))
|
||||
<-ticker.C
|
||||
Expect(atomic.LoadInt32(&tolerance)).To(Equal(outsideTolerance))
|
||||
})
|
||||
|
||||
It("errors if Add is used", func() {
|
||||
err := testClock.Add(100 * time.Second)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Context("Clock mocked via Set", func() {
|
||||
var now = time.Unix(testLocalEpoch, 0)
|
||||
|
||||
BeforeEach(func() {
|
||||
testClock.Set(now)
|
||||
})
|
||||
|
||||
It("mocks After", func() {
|
||||
var after int32
|
||||
ready := make(chan struct{})
|
||||
ch := testClock.After(10 * time.Second)
|
||||
go func(ch <-chan time.Time) {
|
||||
close(ready)
|
||||
<-ch
|
||||
atomic.StoreInt32(&after, 1)
|
||||
}(ch)
|
||||
<-ready
|
||||
|
||||
err := testClock.Add(9 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&after)).To(Equal(int32(0)))
|
||||
|
||||
err = testClock.Add(1 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&after)).To(Equal(int32(1)))
|
||||
})
|
||||
|
||||
It("mocks AfterFunc", func() {
|
||||
var after int32
|
||||
testClock.AfterFunc(10*time.Second, func() {
|
||||
atomic.StoreInt32(&after, 1)
|
||||
})
|
||||
|
||||
err := testClock.Add(9 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&after)).To(Equal(int32(0)))
|
||||
|
||||
err = testClock.Add(1 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&after)).To(Equal(int32(1)))
|
||||
})
|
||||
|
||||
It("mocks AfterFunc with a stopped timer", func() {
|
||||
var after int32
|
||||
timer := testClock.AfterFunc(10*time.Second, func() {
|
||||
atomic.StoreInt32(&after, 1)
|
||||
})
|
||||
timer.Stop()
|
||||
|
||||
err := testClock.Add(11 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&after)).To(Equal(int32(0)))
|
||||
})
|
||||
|
||||
It("mocks Now", func() {
|
||||
Expect(testClock.Now()).To(Equal(now))
|
||||
err := testClock.Add(123 * time.Hour)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(testClock.Now()).To(Equal(now.Add(123 * time.Hour)))
|
||||
})
|
||||
|
||||
It("mocks Since", func() {
|
||||
Expect(testClock.Since(time.Unix(testLocalEpoch-100, 0))).
|
||||
To(Equal(100 * time.Second))
|
||||
})
|
||||
|
||||
It("mocks Sleep", func() {
|
||||
var after int32
|
||||
ready := make(chan struct{})
|
||||
go func() {
|
||||
close(ready)
|
||||
testClock.Sleep(10 * time.Second)
|
||||
atomic.StoreInt32(&after, 1)
|
||||
}()
|
||||
<-ready
|
||||
|
||||
err := testClock.Add(9 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&after)).To(Equal(int32(0)))
|
||||
|
||||
err = testClock.Add(1 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&after)).To(Equal(int32(1)))
|
||||
})
|
||||
|
||||
It("mocks Tick", func() {
|
||||
var ticks int32
|
||||
ready := make(chan struct{})
|
||||
go func() {
|
||||
close(ready)
|
||||
tick := testClock.Tick(10 * time.Second)
|
||||
for ticks < 5 {
|
||||
<-tick
|
||||
atomic.AddInt32(&ticks, 1)
|
||||
}
|
||||
}()
|
||||
<-ready
|
||||
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(0)))
|
||||
|
||||
err := testClock.Add(9 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(0)))
|
||||
|
||||
err = testClock.Add(1 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(1)))
|
||||
|
||||
err = testClock.Add(30 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(4)))
|
||||
|
||||
err = testClock.Add(10 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(5)))
|
||||
})
|
||||
|
||||
It("mocks Ticker", func() {
|
||||
var ticks int32
|
||||
ready := make(chan struct{})
|
||||
go func() {
|
||||
ticker := testClock.Ticker(10 * time.Second)
|
||||
close(ready)
|
||||
for ticks < 5 {
|
||||
<-ticker.C
|
||||
atomic.AddInt32(&ticks, 1)
|
||||
}
|
||||
}()
|
||||
<-ready
|
||||
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(0)))
|
||||
|
||||
err := testClock.Add(9 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(0)))
|
||||
|
||||
err = testClock.Add(1 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(1)))
|
||||
|
||||
err = testClock.Add(30 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(4)))
|
||||
|
||||
err = testClock.Add(10 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&ticks)).To(Equal(int32(5)))
|
||||
})
|
||||
|
||||
It("mocks Timer", func() {
|
||||
var after int32
|
||||
ready := make(chan struct{})
|
||||
go func() {
|
||||
timer := testClock.Timer(10 * time.Second)
|
||||
close(ready)
|
||||
<-timer.C
|
||||
atomic.AddInt32(&after, 1)
|
||||
}()
|
||||
<-ready
|
||||
|
||||
err := testClock.Add(9 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&after)).To(Equal(int32(0)))
|
||||
|
||||
err = testClock.Add(1 * time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(atomic.LoadInt32(&after)).To(Equal(int32(1)))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("Global time overridden", func() {
|
||||
var (
|
||||
globalNow = time.Unix(testGlobalEpoch, 0)
|
||||
localNow = time.Unix(testLocalEpoch, 0)
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
clock.Set(globalNow)
|
||||
})
|
||||
|
||||
Context("Clock not mocked via Set", func() {
|
||||
It("uses globally mocked Now", func() {
|
||||
Expect(testClock.Now()).To(Equal(globalNow))
|
||||
err := clock.Add(123 * time.Hour)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(testClock.Now()).To(Equal(globalNow.Add(123 * time.Hour)))
|
||||
})
|
||||
|
||||
It("errors when Add is called on the local Clock", func() {
|
||||
err := testClock.Add(100 * time.Hour)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Context("Clock is mocked via Set", func() {
|
||||
BeforeEach(func() {
|
||||
testClock.Set(localNow)
|
||||
})
|
||||
|
||||
It("uses the local mock and ignores the global", func() {
|
||||
Expect(testClock.Now()).To(Equal(localNow))
|
||||
|
||||
err := clock.Add(456 * time.Hour)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = testClock.Add(123 * time.Hour)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(testClock.Now()).To(Equal(localNow.Add(123 * time.Hour)))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user