mirror of
https://github.com/tendermint/tendermint.git
synced 2026-08-16 20:26:12 +00:00
fixed the racy test and removed all the calls to Sleep
This commit is contained in:
@@ -73,8 +73,17 @@ type TrustMetric struct {
|
||||
// While true, history data is not modified
|
||||
paused bool
|
||||
|
||||
// Set to true once the metric has been stopped
|
||||
stopped bool
|
||||
|
||||
// Signal channel for stopping the trust metric go-routine
|
||||
stop chan struct{}
|
||||
|
||||
// Slice of signal channels fired when the metric is stopped
|
||||
waitForStop []chan struct{}
|
||||
|
||||
// Slice of signal channels fired when the metric time interval ticker is fired
|
||||
waitForTimeInterval []chan struct{}
|
||||
}
|
||||
|
||||
// NewMetric returns a trust metric with the default configuration
|
||||
@@ -259,6 +268,83 @@ func (tm *TrustMetric) Copy() *TrustMetric {
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForTimeIntervalToPass blocks until the metric
|
||||
// go-routine ticker fire again
|
||||
func (tm *TrustMetric) WaitForTimeIntervalToPass() {
|
||||
interval := make(chan struct{})
|
||||
|
||||
if tm.AddTimeIntervalWaitChannel(interval) {
|
||||
<-interval
|
||||
}
|
||||
}
|
||||
|
||||
// SignalTimeIntervalPassed fires all the maintained signal channels
|
||||
// and clears the group of signal channels
|
||||
func (tm *TrustMetric) SignalTimeIntervalPassed() {
|
||||
tm.mtx.Lock()
|
||||
defer tm.mtx.Unlock()
|
||||
|
||||
for _, interval := range tm.waitForTimeInterval {
|
||||
interval <- struct{}{}
|
||||
}
|
||||
|
||||
tm.waitForTimeInterval = []chan struct{}{}
|
||||
}
|
||||
|
||||
// AddTimeIntervalWaitChannel adds a signal channel to a group of
|
||||
// waiters for this metric. This method returns true if the channel
|
||||
// was added to the group before the metric was stopped
|
||||
func (tm *TrustMetric) AddTimeIntervalWaitChannel(interval chan struct{}) bool {
|
||||
tm.mtx.Lock()
|
||||
defer tm.mtx.Unlock()
|
||||
|
||||
var added bool
|
||||
|
||||
if !tm.stopped {
|
||||
tm.waitForTimeInterval = append(tm.waitForTimeInterval, interval)
|
||||
added = true
|
||||
}
|
||||
return added
|
||||
}
|
||||
|
||||
// WaitForStop blocks until the metric has completely stopped
|
||||
func (tm *TrustMetric) WaitForStop() {
|
||||
stop := make(chan struct{})
|
||||
|
||||
if tm.AddStopWaitChannel(stop) {
|
||||
<-stop
|
||||
}
|
||||
}
|
||||
|
||||
// SignalStopped fires all the maintained signal channels and sets
|
||||
// metric stopped status to true
|
||||
func (tm *TrustMetric) SignalStopped() {
|
||||
tm.mtx.Lock()
|
||||
defer tm.mtx.Unlock()
|
||||
|
||||
for _, stop := range tm.waitForStop {
|
||||
stop <- struct{}{}
|
||||
}
|
||||
|
||||
tm.stopped = true
|
||||
}
|
||||
|
||||
// AddStopWaitChannel adds a signal channel to a group of waiters
|
||||
// for this metric. This method returns true if the channel was
|
||||
// added to the group before the metric was stopped
|
||||
func (tm *TrustMetric) AddStopWaitChannel(stop chan struct{}) bool {
|
||||
tm.mtx.Lock()
|
||||
defer tm.mtx.Unlock()
|
||||
|
||||
var added bool
|
||||
|
||||
if !tm.stopped {
|
||||
tm.waitForStop = append(tm.waitForStop, stop)
|
||||
added = true
|
||||
}
|
||||
return added
|
||||
}
|
||||
|
||||
/* Private methods */
|
||||
|
||||
// This method is for a goroutine that handles all requests on the metric
|
||||
@@ -270,11 +356,15 @@ loop:
|
||||
select {
|
||||
case <-t.C:
|
||||
tm.NextTimeInterval()
|
||||
tm.SignalTimeIntervalPassed()
|
||||
case <-tm.stop:
|
||||
// Stop all further tracking for this metric
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
// Change the status to stopped and signal the waiters
|
||||
tm.SignalStopped()
|
||||
}
|
||||
|
||||
// Wakes the trust metric up if it is currently paused
|
||||
|
||||
+14
-12
@@ -61,30 +61,32 @@ func TestTrustMetricStopPause(t *testing.T) {
|
||||
tm := NewMetricWithConfig(config)
|
||||
|
||||
// Allow some time intervals to pass and pause
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
tm.NextTimeInterval()
|
||||
tm.NextTimeInterval()
|
||||
tm.Pause()
|
||||
// Give the pause some time to take place
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
first := tm.Copy().numIntervals
|
||||
// Allow more time to pass and check the intervals are unchanged
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
assert.Equal(t, first, tm.numIntervals)
|
||||
tm.WaitForTimeIntervalToPass()
|
||||
tm.WaitForTimeIntervalToPass()
|
||||
assert.Equal(t, first, tm.Copy().numIntervals)
|
||||
|
||||
// Get the trust metric activated again
|
||||
tm.GoodEvents(5)
|
||||
// Allow some time intervals to pass and stop
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
tm.NextTimeInterval()
|
||||
tm.NextTimeInterval()
|
||||
tm.Stop()
|
||||
// Give the stop some time to take place
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
// Wait for the stop to take place
|
||||
tm.WaitForStop()
|
||||
|
||||
second := tm.Copy().numIntervals
|
||||
// Allow more time to pass and check the intervals are unchanged
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
assert.Equal(t, second, tm.numIntervals)
|
||||
// Allow more intervals to pass and check that the number of intervals match
|
||||
tm.NextTimeInterval()
|
||||
tm.NextTimeInterval()
|
||||
assert.Equal(t, second+2, tm.Copy().numIntervals)
|
||||
|
||||
if first >= second {
|
||||
if first > second {
|
||||
t.Fatalf("numIntervals should always increase or stay the same over time")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user