git.iko.soy/typeable/oauth2-proxy
on 2bb7ea5 help sign in
157 lines 3.2 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
68// Set sets the Clock to a clock.Mock at the given time.Time
69func (c *Clock) Set(t time.Time) {
70 if c.mock == nil {
71 c.mock = clockapi.NewMock()
72 }
73 c.mock.Set(t)
76// Add moves clock forward time.Duration if it is mocked. It will error
77// if the clock is not mocked.
78func (c *Clock) Add(d time.Duration) error {
79 if c.mock == nil {
80 return errors.New("clock not mocked")
81 }
82 c.mock.Add(d)
83 return nil
86// Reset removes local clock.Mock. Returns any existing Mock if set in case
87// lingering time operations are attached to it.
88func (c *Clock) Reset() *clockapi.Mock {
89 existing := c.mock
90 c.mock = nil
91 return existing
94func (c *Clock) After(d time.Duration) <-chan time.Time {
95 m := c.mock
96 if m == nil {
97 return globalClock.After(d)
98 }
99 return m.After(d)
102func (c *Clock) AfterFunc(d time.Duration, f func()) *clockapi.Timer {
103 m := c.mock
104 if m == nil {
105 return globalClock.AfterFunc(d, f)
106 }
107 return m.AfterFunc(d, f)
110func (c *Clock) Now() time.Time {
111 m := c.mock
112 if m == nil {
113 return globalClock.Now()
114 }
115 return m.Now()
118func (c *Clock) Since(t time.Time) time.Duration {
119 m := c.mock
120 if m == nil {
121 return globalClock.Since(t)
122 }
123 return m.Since(t)
126func (c *Clock) Sleep(d time.Duration) {
127 m := c.mock
128 if m == nil {
129 globalClock.Sleep(d)
130 return
131 }
132 m.Sleep(d)
135func (c *Clock) Tick(d time.Duration) <-chan time.Time {
136 m := c.mock
137 if m == nil {
138 return globalClock.Tick(d)
139 }
140 return m.Tick(d)
143func (c *Clock) Ticker(d time.Duration) *clockapi.Ticker {
144 m := c.mock
145 if m == nil {
146 return globalClock.Ticker(d)
147 }
148 return m.Ticker(d)
151func (c *Clock) Timer(d time.Duration) *clockapi.Timer {
152 m := c.mock
153 if m == nil {
154 return globalClock.Timer(d)
155 }
156 return m.Timer(d)