mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
swarm/storage/feed/lookup: Add comments to tests
This commit is contained in:
parent
daf5126401
commit
34bf9c4993
2 changed files with 255 additions and 192 deletions
File diff suppressed because one or more lines are too long
|
|
@ -1,44 +1,54 @@
|
||||||
package lookup_test
|
package lookup_test
|
||||||
|
|
||||||
|
// This file contains simple time simulation tools for testing
|
||||||
|
// and measuring time-aware algorithms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Timer tracks information about a simulated timer
|
||||||
type Timer struct {
|
type Timer struct {
|
||||||
deadline time.Time
|
deadline time.Time
|
||||||
signal chan time.Time
|
signal chan time.Time
|
||||||
id int32
|
id int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stopwatch measures simulated execution time and manages simulated timers
|
||||||
type Stopwatch struct {
|
type Stopwatch struct {
|
||||||
t time.Time
|
t time.Time
|
||||||
r time.Duration
|
resolution time.Duration
|
||||||
timers map[int32]*Timer
|
timers map[int]*Timer
|
||||||
timerCounter int32
|
timerCounter int
|
||||||
stopSignal chan struct{}
|
stopSignal chan struct{}
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewStopwatch returns a simulated clock that ticks on `resolution` intervals
|
||||||
func NewStopwatch(resolution time.Duration) *Stopwatch {
|
func NewStopwatch(resolution time.Duration) *Stopwatch {
|
||||||
s := &Stopwatch{
|
s := &Stopwatch{
|
||||||
r: resolution,
|
resolution: resolution,
|
||||||
}
|
}
|
||||||
s.Reset()
|
s.Reset()
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset clears all timers and sents the stopwatch to zero
|
||||||
func (s *Stopwatch) Reset() {
|
func (s *Stopwatch) Reset() {
|
||||||
s.t = time.Time{}
|
s.t = time.Time{}
|
||||||
s.timers = make(map[int32]*Timer)
|
s.timers = make(map[int]*Timer)
|
||||||
s.Stop()
|
s.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tick advances simulated time by the stopwatch's resolution and triggers
|
||||||
|
// all due timers
|
||||||
func (s *Stopwatch) Tick() {
|
func (s *Stopwatch) Tick() {
|
||||||
s.t = s.t.Add(s.r)
|
s.t = s.t.Add(s.resolution)
|
||||||
|
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
for id, timer := range s.timers {
|
for id, timer := range s.timers {
|
||||||
if s.t.After(timer.deadline) || s.t.Equal(timer.deadline) {
|
if s.t.After(timer.deadline) || s.t.Equal(timer.deadline) {
|
||||||
timer.signal <- s.t
|
timer.signal <- s.t
|
||||||
|
|
@ -48,33 +58,45 @@ func (s *Stopwatch) Tick() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTimer returns a new timer that will trigger after `duration` elapses in the
|
||||||
|
// simulation
|
||||||
func (s *Stopwatch) GetTimer(duration time.Duration) <-chan time.Time {
|
func (s *Stopwatch) GetTimer(duration time.Duration) <-chan time.Time {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
s.timerCounter++
|
||||||
timer := &Timer{
|
timer := &Timer{
|
||||||
deadline: s.t.Add(duration),
|
deadline: s.t.Add(duration),
|
||||||
signal: make(chan time.Time, 1),
|
signal: make(chan time.Time, 1),
|
||||||
id: atomic.AddInt32(&s.timerCounter, 1),
|
id: s.timerCounter,
|
||||||
}
|
}
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
s.timers[timer.id] = timer
|
s.timers[timer.id] = timer
|
||||||
return timer.signal
|
return timer.signal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TimeAfter returns a simulated timer factory that can replace `time.After`
|
||||||
func (s *Stopwatch) TimeAfter() func(d time.Duration) <-chan time.Time {
|
func (s *Stopwatch) TimeAfter() func(d time.Duration) <-chan time.Time {
|
||||||
return func(d time.Duration) <-chan time.Time {
|
return func(d time.Duration) <-chan time.Time {
|
||||||
return s.GetTimer(d)
|
return s.GetTimer(d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Elapsed returns the time that has passed in the simulation
|
||||||
func (s *Stopwatch) Elapsed() time.Duration {
|
func (s *Stopwatch) Elapsed() time.Duration {
|
||||||
return s.t.Sub(time.Time{})
|
return s.t.Sub(time.Time{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run starts the time simulation
|
||||||
func (s *Stopwatch) Run() {
|
func (s *Stopwatch) Run() {
|
||||||
go func() {
|
go func() {
|
||||||
stopSignal := make(chan struct{})
|
stopSignal := make(chan struct{})
|
||||||
|
s.lock.Lock()
|
||||||
|
if s.stopSignal != nil {
|
||||||
|
close(s.stopSignal)
|
||||||
|
}
|
||||||
s.stopSignal = stopSignal
|
s.stopSignal = stopSignal
|
||||||
|
s.lock.Unlock()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-time.After(1 * time.Millisecond):
|
case <-time.After(1 * time.Millisecond):
|
||||||
|
|
@ -86,9 +108,21 @@ func (s *Stopwatch) Run() {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop stops the time simulation
|
||||||
func (s *Stopwatch) Stop() {
|
func (s *Stopwatch) Stop() {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
if s.stopSignal != nil {
|
if s.stopSignal != nil {
|
||||||
close(s.stopSignal)
|
close(s.stopSignal)
|
||||||
s.stopSignal = nil
|
s.stopSignal = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Stopwatch) Measure(measuredFunc func()) time.Duration {
|
||||||
|
s.Reset()
|
||||||
|
s.Run()
|
||||||
|
defer s.Stop()
|
||||||
|
measuredFunc()
|
||||||
|
return s.Elapsed()
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue