[p2p] Peer behaviour test tweaks (#3662)

* Peer behaviour test tweaks:

    Address the remaining test issues mentioned in ##3552 notably:
    + switch to p2p_test package
    + Use `Error` instead of `Errorf` when not using formatting
    + Add expected/got errors to
    `TestMockPeerBehaviourReporterConcurrency` test

* Peer behaviour equal behaviours test

    + slices of PeerBehaviours should be compared as histograms to
    ensure they have the same set of PeerBehaviours at the same
    freequncy.

* TestEqualPeerBehaviours:

    + Add tests for the equivalence between sets of PeerBehaviours
This commit is contained in:
Sean Braithwaite
2019-05-27 21:44:56 +02:00
committed by Ethan Buchman
parent a6ac611e77
commit b9508ffecb

View File

@ -1,58 +1,121 @@
package p2p package p2p_test
import ( import (
"net"
"sync" "sync"
"testing" "testing"
"github.com/tendermint/tendermint/p2p"
) )
// TestMockPeerBehaviour tests the MockPeerBehaviour' ability to store reported // TestMockPeerBehaviour tests the MockPeerBehaviour' ability to store reported
// peer behaviour in memory indexed by the peerID // peer behaviour in memory indexed by the peerID
func TestMockPeerBehaviourReporter(t *testing.T) { func TestMockPeerBehaviourReporter(t *testing.T) {
peer := newMockPeer(net.IP{127, 0, 0, 1}) var peerID p2p.ID = "MockPeer"
pr := NewMockPeerBehaviourReporter() pr := p2p.NewMockPeerBehaviourReporter()
behaviours := pr.GetBehaviours(peer.ID()) behaviours := pr.GetBehaviours(peerID)
if len(behaviours) != 0 { if len(behaviours) != 0 {
t.Errorf("Expected to have no behaviours reported") t.Error("Expected to have no behaviours reported")
} }
pr.Report(peer.ID(), PeerBehaviourBadMessage) pr.Report(peerID, p2p.PeerBehaviourBadMessage)
behaviours = pr.GetBehaviours(peer.ID()) behaviours = pr.GetBehaviours(peerID)
if len(behaviours) != 1 { if len(behaviours) != 1 {
t.Errorf("Expected the peer have one reported behaviour") t.Error("Expected the peer have one reported behaviour")
} }
if behaviours[0] != PeerBehaviourBadMessage { if behaviours[0] != p2p.PeerBehaviourBadMessage {
t.Errorf("Expected PeerBehaviourBadMessage to have been reported") t.Error("Expected PeerBehaviourBadMessage to have been reported")
} }
} }
type scriptedBehaviours struct { type scriptedBehaviours struct {
PeerID ID PeerID p2p.ID
Behaviours []PeerBehaviour Behaviours []p2p.PeerBehaviour
} }
type scriptItem struct { type scriptItem struct {
PeerID ID PeerID p2p.ID
Behaviour PeerBehaviour Behaviour p2p.PeerBehaviour
} }
func equalBehaviours(a []PeerBehaviour, b []PeerBehaviour) bool { // equalBehaviours returns true if a and b contain the same PeerBehaviours with
if len(a) != len(b) { // the same freequency and otherwise false.
func equalBehaviours(a []p2p.PeerBehaviour, b []p2p.PeerBehaviour) bool {
aHistogram := map[p2p.PeerBehaviour]int{}
bHistogram := map[p2p.PeerBehaviour]int{}
for _, behaviour := range a {
aHistogram[behaviour] += 1
}
for _, behaviour := range b {
bHistogram[behaviour] += 1
}
if len(aHistogram) != len(bHistogram) {
return false return false
} }
same := make([]PeerBehaviour, len(a))
for i, aBehaviour := range a { for _, behaviour := range a {
for _, bBehaviour := range b { if aHistogram[behaviour] != bHistogram[behaviour] {
if aBehaviour == bBehaviour { return false
same[i] = aBehaviour
}
} }
} }
return len(same) == len(a) for _, behaviour := range b {
if bHistogram[behaviour] != aHistogram[behaviour] {
return false
}
}
return true
}
// TestEqualPeerBehaviours tests that equalBehaviours can tell that two slices
// of peer behaviours can be compared for the behaviours they contain and the
// freequencies that those behaviours occur.
func TestEqualPeerBehaviours(t *testing.T) {
equals := []struct {
left []p2p.PeerBehaviour
right []p2p.PeerBehaviour
}{
// Empty sets
{[]p2p.PeerBehaviour{}, []p2p.PeerBehaviour{}},
// Single behaviours
{[]p2p.PeerBehaviour{p2p.PeerBehaviourVote}, []p2p.PeerBehaviour{p2p.PeerBehaviourVote}},
// Equal Frequencies
{[]p2p.PeerBehaviour{p2p.PeerBehaviourVote, p2p.PeerBehaviourVote},
[]p2p.PeerBehaviour{p2p.PeerBehaviourVote, p2p.PeerBehaviourVote}},
// Equal frequencies different orders
{[]p2p.PeerBehaviour{p2p.PeerBehaviourVote, p2p.PeerBehaviourBlockPart},
[]p2p.PeerBehaviour{p2p.PeerBehaviourBlockPart, p2p.PeerBehaviourVote}},
}
for _, test := range equals {
if !equalBehaviours(test.left, test.right) {
t.Errorf("Expected %#v and %#v to be equal", test.left, test.right)
}
}
unequals := []struct {
left []p2p.PeerBehaviour
right []p2p.PeerBehaviour
}{
// Comparing empty sets to non empty sets
{[]p2p.PeerBehaviour{}, []p2p.PeerBehaviour{p2p.PeerBehaviourVote}},
// Different behaviours
{[]p2p.PeerBehaviour{p2p.PeerBehaviourVote}, []p2p.PeerBehaviour{p2p.PeerBehaviourBlockPart}},
// Same behaviour with different frequencies
{[]p2p.PeerBehaviour{p2p.PeerBehaviourVote},
[]p2p.PeerBehaviour{p2p.PeerBehaviourVote, p2p.PeerBehaviourVote}},
}
for _, test := range unequals {
if equalBehaviours(test.left, test.right) {
t.Errorf("Expected %#v and %#v to be unequal", test.left, test.right)
}
}
} }
// TestPeerBehaviourConcurrency constructs a scenario in which // TestPeerBehaviourConcurrency constructs a scenario in which
@ -61,15 +124,15 @@ func equalBehaviours(a []PeerBehaviour, b []PeerBehaviour) bool {
// be used within a Reactor Receive method tests to ensure thread safety. // be used within a Reactor Receive method tests to ensure thread safety.
func TestMockPeerBehaviourReporterConcurrency(t *testing.T) { func TestMockPeerBehaviourReporterConcurrency(t *testing.T) {
behaviourScript := []scriptedBehaviours{ behaviourScript := []scriptedBehaviours{
{"1", []PeerBehaviour{PeerBehaviourVote}}, {"1", []p2p.PeerBehaviour{p2p.PeerBehaviourVote}},
{"2", []PeerBehaviour{PeerBehaviourVote, PeerBehaviourVote, PeerBehaviourVote, PeerBehaviourVote}}, {"2", []p2p.PeerBehaviour{p2p.PeerBehaviourVote, p2p.PeerBehaviourVote, p2p.PeerBehaviourVote, p2p.PeerBehaviourVote}},
{"3", []PeerBehaviour{PeerBehaviourBlockPart, PeerBehaviourVote, PeerBehaviourBlockPart, PeerBehaviourVote}}, {"3", []p2p.PeerBehaviour{p2p.PeerBehaviourBlockPart, p2p.PeerBehaviourVote, p2p.PeerBehaviourBlockPart, p2p.PeerBehaviourVote}},
{"4", []PeerBehaviour{PeerBehaviourVote, PeerBehaviourVote, PeerBehaviourVote, PeerBehaviourVote}}, {"4", []p2p.PeerBehaviour{p2p.PeerBehaviourVote, p2p.PeerBehaviourVote, p2p.PeerBehaviourVote, p2p.PeerBehaviourVote}},
{"5", []PeerBehaviour{PeerBehaviourBlockPart, PeerBehaviourVote, PeerBehaviourBlockPart, PeerBehaviourVote}}, {"5", []p2p.PeerBehaviour{p2p.PeerBehaviourBlockPart, p2p.PeerBehaviourVote, p2p.PeerBehaviourBlockPart, p2p.PeerBehaviourVote}},
} }
var receiveWg sync.WaitGroup var receiveWg sync.WaitGroup
pr := NewMockPeerBehaviourReporter() pr := p2p.NewMockPeerBehaviourReporter()
scriptItems := make(chan scriptItem) scriptItems := make(chan scriptItem)
done := make(chan int) done := make(chan int)
numConsumers := 3 numConsumers := 3
@ -108,8 +171,10 @@ func TestMockPeerBehaviourReporterConcurrency(t *testing.T) {
receiveWg.Wait() receiveWg.Wait()
for _, items := range behaviourScript { for _, items := range behaviourScript {
if !equalBehaviours(pr.GetBehaviours(items.PeerID), items.Behaviours) { reported := pr.GetBehaviours(items.PeerID)
t.Errorf("Expected peer %s to have behaved \n", items.PeerID) if !equalBehaviours(reported, items.Behaviours) {
t.Errorf("Expected peer %s to have behaved \nExpected: %#v \nGot %#v \n",
items.PeerID, items.Behaviours, reported)
} }
} }
} }