5ebdeb56ca
## Checklist - [x] I have read the [contribution guidelines](https://github.com/ooni/probe-cli/blob/master/CONTRIBUTING.md) - [x] reference issue for this pull request: https://github.com/ooni/probe/issues/2158 - [x] if you changed anything related how experiments work and you need to reflect these changes in the ooni/spec repository, please link to the related ooni/spec pull request: https://github.com/ooni/spec/pull/250 ## Description This diff refactors the codebase to reimplement tlsping and tcpping to use the step-by-step measurements style. See docs/design/dd-003-step-by-step.md for more information on the step-by-step measurement style.
49 lines
1.4 KiB
Go
49 lines
1.4 KiB
Go
package testingx
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// TimeDeterministic implements time.Now in a deterministic fashion
|
|
// such that every time.Time call returns a moment in time that occurs
|
|
// one second after the configured zeroTime.
|
|
//
|
|
// It's safe to use this struct from multiple goroutine contexts.
|
|
type TimeDeterministic struct {
|
|
// counter counts the number of "ticks" passed since the zero time: each
|
|
// call to Now increments this counter by one second.
|
|
counter time.Duration
|
|
|
|
// mu protects fields in this structure from concurrent access.
|
|
mu sync.Mutex
|
|
|
|
// zeroTime is the lazy-initialized zero time. The first call to Now
|
|
// will initialize this field with the current time.
|
|
zeroTime time.Time
|
|
}
|
|
|
|
// NewTimeDeterministic creates a new instance using the given zeroTime value.
|
|
func NewTimeDeterministic(zeroTime time.Time) *TimeDeterministic {
|
|
return &TimeDeterministic{
|
|
counter: 0,
|
|
mu: sync.Mutex{},
|
|
zeroTime: zeroTime,
|
|
}
|
|
}
|
|
|
|
// Now is like time.Now but more deterministic. The first call returns the
|
|
// configured zeroTime and subsequent calls return moments in time that occur
|
|
// exactly one second after the time returned by the previous call.
|
|
func (td *TimeDeterministic) Now() time.Time {
|
|
td.mu.Lock()
|
|
if td.zeroTime.IsZero() {
|
|
td.zeroTime = time.Now()
|
|
}
|
|
offset := td.counter
|
|
td.counter += time.Second
|
|
res := td.zeroTime.Add(offset)
|
|
td.mu.Unlock()
|
|
return res
|
|
}
|