prysm-pulse/beacon-chain/p2p/peers/scorer_test.go
Victor Farazdagi f0ffd5af03
Introduces peer scorer service (#6579)
* introduces peer scorer service
* gazelle
* Merge branch 'master' into peer-scoring-service
* fixes comment
* fix build error
* linter suggestions
* Merge branch 'master' into peer-scoring-service
* updates tests
* Merge branch 'master' into peer-scoring-service
* badresponses scorer tests
* gazelle
* Merge branch 'master' into peer-scoring-service
* Merge branch 'master' into peer-scoring-service
* adds scorer_test
* gazelle
* updates bad response default penalty
* more comments
* Merge branch 'master' into peer-scoring-service
* Merge branch 'master' into peer-scoring-service
* Merge branch 'master' into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* introduces peerdatastore into status
* makes sure that commong peer data store is used
* Merge branch 'peer-scoring-service' of github.com:prysmaticlabs/prysm into peer-scoring-service
* linter
* gazelle
* updates tests
* Merge branch 'master' into peer-scoring-service
* fixes tests
* Nishant's suggestions
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge refs/heads/master into peer-scoring-service
* Merge branch 'master' into peer-scoring-service
* gofmt
* Nishant's suggestion to use isBadPeer
* Merge refs/heads/master into peer-scoring-service
2020-07-20 15:12:59 +00:00

138 lines
4.3 KiB
Go

package peers_test
import (
"context"
"sort"
"testing"
"time"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
)
func TestPeerScorer_NewPeerScorer(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
t.Run("default config", func(t *testing.T) {
peerStatuses := peers.NewStatus(ctx, &peers.StatusConfig{
PeerLimit: 30,
ScorerParams: &peers.PeerScorerConfig{},
})
scorer := peerStatuses.Scorer()
assert.Equal(t, peers.DefaultBadResponsesThreshold, scorer.Params().BadResponsesThreshold, "Unexpected threshold value")
assert.Equal(t, peers.DefaultBadResponsesWeight, scorer.Params().BadResponsesWeight, "Unexpected weight value")
assert.Equal(t, peers.DefaultBadResponsesDecayInterval, scorer.Params().BadResponsesDecayInterval, "Unexpected decay interval value")
})
t.Run("explicit config", func(t *testing.T) {
peerStatuses := peers.NewStatus(ctx, &peers.StatusConfig{
PeerLimit: 30,
ScorerParams: &peers.PeerScorerConfig{
BadResponsesThreshold: 2,
BadResponsesWeight: -1,
BadResponsesDecayInterval: 1 * time.Minute,
},
})
scorer := peerStatuses.Scorer()
assert.Equal(t, 2, scorer.Params().BadResponsesThreshold, "Unexpected threshold value")
assert.Equal(t, -1.0, scorer.Params().BadResponsesWeight, "Unexpected weight value")
assert.Equal(t, 1*time.Minute, scorer.Params().BadResponsesDecayInterval, "Unexpected decay interval value")
})
}
func TestPeerScorer_Score(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
peerStatuses := peers.NewStatus(ctx, &peers.StatusConfig{
PeerLimit: 30,
ScorerParams: &peers.PeerScorerConfig{
BadResponsesThreshold: 5,
BadResponsesWeight: -0.5,
BadResponsesDecayInterval: 50 * time.Millisecond,
},
})
scorer := peerStatuses.Scorer()
sortByScore := func(pids []peer.ID) []peer.ID {
sort.Slice(pids, func(i, j int) bool {
scr1, scr2 := scorer.Score(pids[i]), scorer.Score(pids[j])
if scr1 == scr2 {
// Sort by peer ID, whenever peers have equal score.
return pids[i] < pids[j]
}
return scr1 > scr2
})
return pids
}
pids := []peer.ID{"peer1", "peer2", "peer3"}
for _, pid := range pids {
peerStatuses.Add(nil, pid, nil, network.DirUnknown)
if score := scorer.Score(pid); score < 0 {
t.Errorf("Unexpected peer score, want: >=0, got: %v", score)
}
}
assert.DeepEqual(t, []peer.ID{"peer1", "peer2", "peer3"}, sortByScore(pids), "Unexpected scores")
// Update peers' stats and test the effect on peer order.
scorer.IncrementBadResponses("peer2")
assert.DeepEqual(t, []peer.ID{"peer1", "peer3", "peer2"}, sortByScore(pids), "Unexpected scores")
scorer.IncrementBadResponses("peer1")
scorer.IncrementBadResponses("peer1")
assert.DeepEqual(t, []peer.ID{"peer3", "peer2", "peer1"}, sortByScore(pids), "Unexpected scores")
// See how decaying affects order of peers.
scorer.DecayBadResponsesStats()
assert.DeepEqual(t, []peer.ID{"peer2", "peer3", "peer1"}, sortByScore(pids), "Unexpected scores")
scorer.DecayBadResponsesStats()
assert.DeepEqual(t, []peer.ID{"peer1", "peer2", "peer3"}, sortByScore(pids), "Unexpected scores")
}
func TestPeerScorer_loop(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
peerStatuses := peers.NewStatus(ctx, &peers.StatusConfig{
PeerLimit: 30,
ScorerParams: &peers.PeerScorerConfig{
BadResponsesThreshold: 5,
BadResponsesWeight: -0.5,
BadResponsesDecayInterval: 50 * time.Millisecond,
},
})
scorer := peerStatuses.Scorer()
pid1 := peer.ID("peer1")
peerStatuses.Add(nil, pid1, nil, network.DirUnknown)
for i := 0; i < scorer.Params().BadResponsesThreshold+5; i++ {
scorer.IncrementBadResponses(pid1)
}
assert.Equal(t, true, scorer.IsBadPeer(pid1), "Peer should be marked as bad")
done := make(chan struct{}, 1)
go func() {
defer func() {
done <- struct{}{}
}()
ticker := time.NewTicker(50 * time.Millisecond)
for {
select {
case <-ticker.C:
if scorer.IsBadPeer(pid1) == false {
return
}
case <-ctx.Done():
t.Error("Timed out")
return
}
}
}()
<-done
assert.Equal(t, false, scorer.IsBadPeer(pid1), "Peer should not be marked as bad")
}