|
|
@ -0,0 +1,115 @@ |
|
|
|
package p2p |
|
|
|
|
|
|
|
import ( |
|
|
|
"net" |
|
|
|
"sync" |
|
|
|
"testing" |
|
|
|
) |
|
|
|
|
|
|
|
// TestMockPeerBehaviour tests the MockPeerBehaviour' ability to store reported
|
|
|
|
// peer behaviour in memory indexed by the peerID
|
|
|
|
func TestMockPeerBehaviourReporter(t *testing.T) { |
|
|
|
peer := newMockPeer(net.IP{127, 0, 0, 1}) |
|
|
|
pr := NewMockPeerBehaviourReporter() |
|
|
|
|
|
|
|
behaviours := pr.GetBehaviours(peer.ID()) |
|
|
|
if len(behaviours) != 0 { |
|
|
|
t.Errorf("Expected to have no behaviours reported") |
|
|
|
} |
|
|
|
|
|
|
|
pr.Report(peer.ID(), PeerBehaviourBadMessage) |
|
|
|
behaviours = pr.GetBehaviours(peer.ID()) |
|
|
|
if len(behaviours) != 1 { |
|
|
|
t.Errorf("Expected the peer have one reported behaviour") |
|
|
|
} |
|
|
|
|
|
|
|
if behaviours[0] != PeerBehaviourBadMessage { |
|
|
|
t.Errorf("Expected PeerBehaviourBadMessage to have been reported") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
type scriptedBehaviours struct { |
|
|
|
PeerID ID |
|
|
|
Behaviours []PeerBehaviour |
|
|
|
} |
|
|
|
|
|
|
|
type scriptItem struct { |
|
|
|
PeerID ID |
|
|
|
Behaviour PeerBehaviour |
|
|
|
} |
|
|
|
|
|
|
|
func equalBehaviours(a []PeerBehaviour, b []PeerBehaviour) bool { |
|
|
|
if len(a) != len(b) { |
|
|
|
return false |
|
|
|
} |
|
|
|
same := make([]PeerBehaviour, len(a)) |
|
|
|
|
|
|
|
for i, aBehaviour := range a { |
|
|
|
for _, bBehaviour := range b { |
|
|
|
if aBehaviour == bBehaviour { |
|
|
|
same[i] = aBehaviour |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return len(same) == len(a) |
|
|
|
} |
|
|
|
|
|
|
|
// TestPeerBehaviourConcurrency constructs a scenario in which
|
|
|
|
// multiple goroutines are using the same MockPeerBehaviourReporter instance.
|
|
|
|
// This test reproduces the conditions in which MockPeerBehaviourReporter will
|
|
|
|
// be used within a Reactor Receive method tests to ensure thread safety.
|
|
|
|
func TestMockPeerBehaviourReporterConcurrency(t *testing.T) { |
|
|
|
behaviourScript := []scriptedBehaviours{ |
|
|
|
{"1", []PeerBehaviour{PeerBehaviourVote}}, |
|
|
|
{"2", []PeerBehaviour{PeerBehaviourVote, PeerBehaviourVote, PeerBehaviourVote, PeerBehaviourVote}}, |
|
|
|
{"3", []PeerBehaviour{PeerBehaviourBlockPart, PeerBehaviourVote, PeerBehaviourBlockPart, PeerBehaviourVote}}, |
|
|
|
{"4", []PeerBehaviour{PeerBehaviourVote, PeerBehaviourVote, PeerBehaviourVote, PeerBehaviourVote}}, |
|
|
|
{"5", []PeerBehaviour{PeerBehaviourBlockPart, PeerBehaviourVote, PeerBehaviourBlockPart, PeerBehaviourVote}}, |
|
|
|
} |
|
|
|
|
|
|
|
var receiveWg sync.WaitGroup |
|
|
|
pr := NewMockPeerBehaviourReporter() |
|
|
|
scriptItems := make(chan scriptItem) |
|
|
|
done := make(chan int) |
|
|
|
numConsumers := 3 |
|
|
|
for i := 0; i < numConsumers; i++ { |
|
|
|
receiveWg.Add(1) |
|
|
|
go func() { |
|
|
|
defer receiveWg.Done() |
|
|
|
for { |
|
|
|
select { |
|
|
|
case pb := <-scriptItems: |
|
|
|
pr.Report(pb.PeerID, pb.Behaviour) |
|
|
|
case <-done: |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
}() |
|
|
|
} |
|
|
|
|
|
|
|
var sendingWg sync.WaitGroup |
|
|
|
sendingWg.Add(1) |
|
|
|
go func() { |
|
|
|
defer sendingWg.Done() |
|
|
|
for _, item := range behaviourScript { |
|
|
|
for _, reason := range item.Behaviours { |
|
|
|
scriptItems <- scriptItem{item.PeerID, reason} |
|
|
|
} |
|
|
|
} |
|
|
|
}() |
|
|
|
|
|
|
|
sendingWg.Wait() |
|
|
|
|
|
|
|
for i := 0; i < numConsumers; i++ { |
|
|
|
done <- 1 |
|
|
|
} |
|
|
|
|
|
|
|
receiveWg.Wait() |
|
|
|
|
|
|
|
for _, items := range behaviourScript { |
|
|
|
if !equalBehaviours(pr.GetBehaviours(items.PeerID), items.Behaviours) { |
|
|
|
t.Errorf("Expected peer %s to have behaved \n", items.PeerID) |
|
|
|
} |
|
|
|
} |
|
|
|
} |