- 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)
- }
- }
- }
|