1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2025-01-10 04:18:14 +02:00
oauth2-proxy/pkg/clock/clock.go
Nick Meves baf6cf3816 Remove mutex from local Clock instances
They will only be used in tests, but it doesn't play
nice with copy operations many tests use. The linter was
not happy. While the global clock needs mutexes for parallelism,
local Clocks only used it for Set/Add and didn't even use the
mutex for actual time functions.
2021-06-22 17:04:42 -07:00

158 lines
3.1 KiB
Go

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
}
// Set sets the Clock to a clock.Mock at the given time.Time
func (c *Clock) Set(t time.Time) {
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 {
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 {
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)
}