@ -2,8 +2,11 @@ package p2p
import (
"math/rand"
"sync"
"testing"
"github.com/stretchr/testify/assert"
cmn "github.com/tendermint/tmlibs/common"
)
@ -18,28 +21,47 @@ func randPeer() *Peer {
}
}
func TestAddRemoveOne ( t * testing . T ) {
func TestPeerSetAddRemoveOne ( t * testing . T ) {
t . Parallel ( )
peerSet := NewPeerSet ( )
peer := randPeer ( )
err := peerSet . Add ( peer )
if err != nil {
t . Errorf ( "Failed to add new peer" )
var peerList [ ] * Peer
for i := 0 ; i < 5 ; i ++ {
p := randPeer ( )
peerSet . Add ( p )
peerList = append ( peerList , p )
}
if peerSet . Size ( ) != 1 {
t . Errorf ( "Failed to add new peer and increment size" )
n := len ( peerList )
// 1. Test removing from the front
for i , peerAtFront := range peerList {
peerSet . Remove ( peerAtFront )
wantSize := n - i - 1
for j := 0 ; j < 2 ; j ++ {
assert . Equal ( t , false , peerSet . Has ( peerAtFront . Key ) , "#%d Run #%d: failed to remove peer" , i , j )
assert . Equal ( t , wantSize , peerSet . Size ( ) , "#%d Run #%d: failed to remove peer and decrement size" , i , j )
// Test the route of removing the now non-existent element
peerSet . Remove ( peerAtFront )
}
}
peerSet . Remove ( peer )
if peerSet . Has ( peer . Key ) {
t . Errorf ( "Failed to remove peer" )
// 2. Next we are testing removing the peer at the end
// a) Replenish the peerSet
for _ , peer := range peerList {
peerSet . Add ( peer )
}
if peerSet . Size ( ) != 0 {
t . Errorf ( "Failed to remove peer and decrement size" )
// b) In reverse, remove each element
for i := n - 1 ; i >= 0 ; i -- {
peerAtEnd := peerList [ i ]
peerSet . Remove ( peerAtEnd )
assert . Equal ( t , false , peerSet . Has ( peerAtEnd . Key ) , "#%d: failed to remove item at end" , i )
assert . Equal ( t , i , peerSet . Size ( ) , "#%d: differing sizes after peerSet.Remove(atEndPeer)" , i )
}
}
func TestAddRemoveMany ( t * testing . T ) {
func TestPeerSetAddRemoveMany ( t * testing . T ) {
t . Parallel ( )
peerSet := NewPeerSet ( )
peers := [ ] * Peer { }
@ -65,3 +87,61 @@ func TestAddRemoveMany(t *testing.T) {
}
}
}
func TestPeerSetAddDuplicate ( t * testing . T ) {
t . Parallel ( )
peerSet := NewPeerSet ( )
peer := randPeer ( )
n := 20
errsChan := make ( chan error )
// Add the same asynchronously to test the
// concurrent guarantees of our APIs, and
// our expectation in the end is that only
// one addition succeeded, but the rest are
// instances of ErrSwitchDuplicatePeer.
for i := 0 ; i < n ; i ++ {
go func ( ) {
errsChan <- peerSet . Add ( peer )
} ( )
}
// Now collect and tally the results
errsTally := make ( map [ error ] int )
for i := 0 ; i < n ; i ++ {
err := <- errsChan
errsTally [ err ] += 1
}
// Our next procedure is to ensure that only one addition
// succeeded and that the rest are each ErrSwitchDuplicatePeer.
wantErrCount , gotErrCount := n - 1 , errsTally [ ErrSwitchDuplicatePeer ]
assert . Equal ( t , wantErrCount , gotErrCount , "invalid ErrSwitchDuplicatePeer count" )
wantNilErrCount , gotNilErrCount := 1 , errsTally [ nil ]
assert . Equal ( t , wantNilErrCount , gotNilErrCount , "invalid nil errCount" )
}
func TestPeerSetGet ( t * testing . T ) {
t . Parallel ( )
peerSet := NewPeerSet ( )
peer := randPeer ( )
assert . Nil ( t , peerSet . Get ( peer . Key ) , "expecting a nil lookup, before .Add" )
if err := peerSet . Add ( peer ) ; err != nil {
t . Fatalf ( "Failed to add new peer: %v" , err )
}
var wg sync . WaitGroup
for i := 0 ; i < 10 ; i ++ {
// Add them asynchronously to test the
// concurrent guarantees of our APIs.
wg . Add ( 1 )
go func ( i int ) {
defer wg . Done ( )
got , want := peerSet . Get ( peer . Key ) , peer
assert . Equal ( t , got , want , "#%d: got=%v want=%v" , i , got , want )
} ( i )
}
wg . Wait ( )
}