tendermint/blockchain/peer_test.go

217 lines
5.6 KiB
Go
Raw Normal View History

2019-04-13 09:23:43 -04:00
package blockchain
2019-03-26 09:58:30 +01:00
import (
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/p2p"
)
2019-05-15 18:33:12 -04:00
// These vars are used to record and verify different events generated during tests
2019-03-26 09:58:30 +01:00
var (
2019-05-15 18:33:12 -04:00
numErrFuncCalls int // number of calls to the errFunc
lastErr error // last generated error
peerTestMtx sync.Mutex // needed as modifications of these variables are done from timer handler goroutine also
2019-03-26 09:58:30 +01:00
)
func resetErrors() {
2019-04-14 22:53:24 -04:00
peerTestMtx.Lock()
defer peerTestMtx.Unlock()
2019-03-26 09:58:30 +01:00
numErrFuncCalls = 0
lastErr = nil
}
func errFunc(err error, peerID p2p.ID) {
2019-04-14 22:53:24 -04:00
peerTestMtx.Lock()
defer peerTestMtx.Unlock()
2019-03-26 09:58:30 +01:00
_ = peerID
lastErr = err
numErrFuncCalls++
}
// check if peer timer is running or not (a running timer can be successfully stopped)
// Note: it does stop the timer!
func checkByStoppingPeerTimer(t *testing.T, peer *bpPeer, running bool) {
assert.NotPanics(t, func() {
stopped := peer.timeout.Stop()
if running {
assert.True(t, stopped)
} else {
assert.False(t, stopped)
}
})
}
func TestPeerResetMonitor(t *testing.T) {
2019-05-15 18:33:12 -04:00
peer := newBPPeer(p2p.ID(cmn.RandStr(12)), 10, errFunc)
peer.setLogger(log.TestingLogger())
2019-03-26 09:58:30 +01:00
peer.resetMonitor()
assert.NotNil(t, peer.recvMonitor)
}
func TestPeerTimer(t *testing.T) {
peerTimeout = 2 * time.Millisecond
2019-05-15 18:33:12 -04:00
peer := newBPPeer(p2p.ID(cmn.RandStr(12)), 10, errFunc)
peer.setLogger(log.TestingLogger())
2019-03-26 09:58:30 +01:00
assert.Nil(t, peer.timeout)
// initial reset call with peer having a nil timer
peer.resetTimeout()
assert.NotNil(t, peer.timeout)
// make sure timer is running and stop it
checkByStoppingPeerTimer(t, peer, true)
// reset with non nil expired timer
peer.resetTimeout()
assert.NotNil(t, peer.timeout)
// make sure timer is running and stop it
checkByStoppingPeerTimer(t, peer, true)
resetErrors()
// reset with running timer (started above)
time.Sleep(time.Millisecond)
peer.resetTimeout()
assert.NotNil(t, peer.timeout)
// let the timer expire and ...
time.Sleep(3 * time.Millisecond)
checkByStoppingPeerTimer(t, peer, false)
2019-04-14 22:53:24 -04:00
peerTestMtx.Lock()
2019-03-26 09:58:30 +01:00
// ... check an error has been sent, error is peerNonResponsive
assert.Equal(t, 1, numErrFuncCalls)
assert.Equal(t, lastErr, errNoPeerResponse)
2019-04-14 22:53:24 -04:00
peerTestMtx.Unlock()
2019-04-12 22:02:30 -04:00
// Restore the peerTimeout to its original value
2019-05-15 18:33:12 -04:00
peerTimeout = defaultPeerTimeout
2019-03-26 09:58:30 +01:00
}
2019-04-14 22:53:24 -04:00
func TestPeerIncrPending(t *testing.T) {
2019-03-26 09:58:30 +01:00
peerTimeout = 2 * time.Millisecond
2019-05-15 18:33:12 -04:00
peer := newBPPeer(p2p.ID(cmn.RandStr(12)), 10, errFunc)
peer.setLogger(log.TestingLogger())
2019-03-26 09:58:30 +01:00
peer.incrPending()
assert.NotNil(t, peer.recvMonitor)
assert.NotNil(t, peer.timeout)
assert.Equal(t, int32(1), peer.numPending)
peer.incrPending()
assert.NotNil(t, peer.recvMonitor)
assert.NotNil(t, peer.timeout)
assert.Equal(t, int32(2), peer.numPending)
2019-04-12 22:02:30 -04:00
// Restore the peerTimeout to its original value
2019-05-15 18:33:12 -04:00
peerTimeout = defaultPeerTimeout
2019-03-26 09:58:30 +01:00
}
2019-04-14 22:53:24 -04:00
func TestPeerDecrPending(t *testing.T) {
2019-03-26 09:58:30 +01:00
peerTimeout = 2 * time.Millisecond
2019-05-15 18:33:12 -04:00
peer := newBPPeer(p2p.ID(cmn.RandStr(12)), 10, errFunc)
peer.setLogger(log.TestingLogger())
2019-03-26 09:58:30 +01:00
// panic if numPending is 0 and try to decrement it
assert.Panics(t, func() { peer.decrPending(10) })
// decrement to zero
peer.incrPending()
peer.decrPending(10)
assert.Equal(t, int32(0), peer.numPending)
// make sure timer is not running
checkByStoppingPeerTimer(t, peer, false)
// decrement to non zero
peer.incrPending()
peer.incrPending()
peer.decrPending(10)
assert.Equal(t, int32(1), peer.numPending)
// make sure timer is running and stop it
checkByStoppingPeerTimer(t, peer, true)
2019-04-12 22:02:30 -04:00
// Restore the peerTimeout to its original value
2019-05-15 18:33:12 -04:00
peerTimeout = defaultPeerTimeout
2019-03-26 09:58:30 +01:00
}
2019-04-14 22:53:24 -04:00
func TestPeerCanBeRemovedDueToExpiration(t *testing.T) {
2019-03-26 09:58:30 +01:00
minRecvRate = int64(100) // 100 bytes/sec exponential moving average
2019-05-15 18:33:12 -04:00
peer := newBPPeer(p2p.ID(cmn.RandStr(12)), 10, errFunc)
peer.setLogger(log.TestingLogger())
2019-03-26 09:58:30 +01:00
peerTimeout = time.Millisecond
peer.incrPending()
time.Sleep(2 * time.Millisecond)
// timer expired, should be able to remove peer
2019-04-14 22:53:24 -04:00
peerTestMtx.Lock()
assert.Equal(t, errNoPeerResponse, lastErr)
peerTestMtx.Unlock()
2019-04-12 22:02:30 -04:00
// Restore the peerTimeout to its original value
2019-05-15 18:33:12 -04:00
peerTimeout = defaultPeerTimeout
2019-04-12 22:02:30 -04:00
2019-03-26 09:58:30 +01:00
}
2019-04-14 22:53:24 -04:00
func TestPeerCanBeRemovedDueToLowSpeed(t *testing.T) {
2019-03-26 09:58:30 +01:00
minRecvRate = int64(100) // 100 bytes/sec exponential moving average
2019-05-15 18:33:12 -04:00
peer := newBPPeer(p2p.ID(cmn.RandStr(12)), 10, errFunc)
peer.setLogger(log.TestingLogger())
2019-03-26 09:58:30 +01:00
peerTimeout = time.Second
peerSampleRate = 0
peerWindowSize = 0
peer.incrPending()
peer.numPending = 100
// monitor starts with a higher rEMA (~ 2*minRecvRate), wait for it to go down
time.Sleep(900 * time.Millisecond)
2019-05-15 18:33:12 -04:00
// normal peer - send a bit more than 100 bytes/sec, > 10 bytes/100msec, check peer is not considered slow
2019-03-26 09:58:30 +01:00
for i := 0; i < 10; i++ {
peer.decrPending(11)
time.Sleep(100 * time.Millisecond)
2019-03-26 14:51:37 +01:00
require.Nil(t, peer.isGood())
2019-03-26 09:58:30 +01:00
}
2019-05-15 18:33:12 -04:00
// slow peer - send a bit less than 10 bytes/100msec
2019-03-26 09:58:30 +01:00
for i := 0; i < 10; i++ {
peer.decrPending(9)
time.Sleep(100 * time.Millisecond)
}
// check peer is considered slow
2019-03-26 14:51:37 +01:00
assert.Equal(t, errSlowPeer, peer.isGood())
2019-03-26 09:58:30 +01:00
}
2019-04-14 22:53:24 -04:00
func TestPeerCleanup(t *testing.T) {
2019-05-15 18:33:12 -04:00
peer := newBPPeer(p2p.ID(cmn.RandStr(12)), 10, errFunc)
peer.setLogger(log.TestingLogger())
2019-03-26 09:58:30 +01:00
peerTimeout = 2 * time.Millisecond
assert.Nil(t, peer.timeout)
// initial reset call with peer having a nil timer
peer.resetTimeout()
assert.NotNil(t, peer.timeout)
2019-04-14 22:53:24 -04:00
peerTestMtx.Lock()
2019-03-26 09:58:30 +01:00
peer.cleanup()
2019-04-14 22:53:24 -04:00
peerTestMtx.Unlock()
2019-03-26 09:58:30 +01:00
checkByStoppingPeerTimer(t, peer, false)
2019-04-12 22:02:30 -04:00
// Restore the peerTimeout to its original value
2019-05-15 18:33:12 -04:00
peerTimeout = defaultPeerTimeout
2019-03-26 09:58:30 +01:00
}