git.iko.soy/typeable/oauth2-proxy
on 2dd4a96 help sign in
164 lines 3.3 kB history raw
1package clock
3import (
4 "errors"
5 "sync"
6 "time"
8 clockapi "github.com/benbjohnson/clock"
9)
11var (
12 globalClock = clockapi.New()
13 mu sync.Mutex
16// Set the global clock to a clockapi.Mock with the given time.Time
17func Set(t time.Time) {
18 mu.Lock()
19 defer mu.Unlock()
20 mock, ok := globalClock.(*clockapi.Mock)
21 if !ok {
22 mock = clockapi.NewMock()
23 }
24 mock.Set(t)
25 globalClock = mock
28// Add moves the mocked global clock forward the given duration. It will error
29// if the global clock is not mocked.
30func Add(d time.Duration) error {
31 mu.Lock()
32 defer mu.Unlock()
33 mock, ok := globalClock.(*clockapi.Mock)
34 if !ok {
35 return errors.New("time not mocked")
36 }
37 mock.Add(d)
38 return nil
41// Reset sets the global clock to a pure time implementation. Returns any
42// existing Mock if set in case lingering time operations are attached to it.
43func Reset() *clockapi.Mock {
44 mu.Lock()
45 defer mu.Unlock()
46 existing := globalClock
47 globalClock = clockapi.New()
49 mock, ok := existing.(*clockapi.Mock)
50 if !ok {
51 return nil
52 }
53 return mock
56// Clock is a non-package level wrapper around time that supports stubbing.
57// It will use its localized stubs (allowing for parallelized unit tests
58// where package level stubbing would cause issues). It falls back to any
59// package level time stubs for non-parallel, cross-package integration
60// testing scenarios.
61//
62// If nothing is stubbed, it defaults to default time behavior in the time
63// package.
64type Clock struct {
65 mock *clockapi.Mock
66 sync.Mutex
69// Set sets the Clock to a clock.Mock at the given time.Time
70func (c *Clock) Set(t time.Time) {
71 c.Lock()
72 defer c.Unlock()
73 if c.mock == nil {
74 c.mock = clockapi.NewMock()
75 }
76 c.mock.Set(t)
79// Add moves clock forward time.Duration if it is mocked. It will error
80// if the clock is not mocked.
81func (c *Clock) Add(d time.Duration) error {
82 c.Lock()
83 defer c.Unlock()
84 if c.mock == nil {
85 return errors.New("clock not mocked")
86 }
87 c.mock.Add(d)
88 return nil
91// Reset removes local clock.Mock. Returns any existing Mock if set in case
92// lingering time operations are attached to it.
93func (c *Clock) Reset() *clockapi.Mock {
94 c.Lock()
95 defer c.Unlock()
96 existing := c.mock
97 c.mock = nil
98 return existing
101func (c *Clock) After(d time.Duration) <-chan time.Time {
102 m := c.mock
103 if m == nil {
104 return globalClock.After(d)
105 }
106 return m.After(d)
109func (c *Clock) AfterFunc(d time.Duration, f func()) *clockapi.Timer {
110 m := c.mock
111 if m == nil {
112 return globalClock.AfterFunc(d, f)
113 }
114 return m.AfterFunc(d, f)
117func (c *Clock) Now() time.Time {
118 m := c.mock
119 if m == nil {
120 return globalClock.Now()
121 }
122 return m.Now()
125func (c *Clock) Since(t time.Time) time.Duration {
126 m := c.mock
127 if m == nil {
128 return globalClock.Since(t)
129 }
130 return m.Since(t)
133func (c *Clock) Sleep(d time.Duration) {
134 m := c.mock
135 if m == nil {
136 globalClock.Sleep(d)
137 return
138 }
139 m.Sleep(d)
142func (c *Clock) Tick(d time.Duration) <-chan time.Time {
143 m := c.mock
144 if m == nil {
145 return globalClock.Tick(d)
146 }
147 return m.Tick(d)
150func (c *Clock) Ticker(d time.Duration) *clockapi.Ticker {
151 m := c.mock
152 if m == nil {
153 return globalClock.Ticker(d)
154 }
155 return m.Ticker(d)
158func (c *Clock) Timer(d time.Duration) *clockapi.Timer {
159 m := c.mock
160 if m == nil {
161 return globalClock.Timer(d)
162 }
163 return m.Timer(d)