Skip to content

Commit

Permalink
Merge pull request #22 from wetterj/master
Browse files Browse the repository at this point in the history
Improve Test Coverage
  • Loading branch information
Stebalien authored Sep 19, 2018
2 parents c5de9b3 + 2e2a793 commit 6f4d058
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 1 deletion.
6 changes: 5 additions & 1 deletion p2p/net/connmgr/connmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ var log = logging.Logger("connmgr")
// to trimming. Trims are automatically run on demand, only if the time from the
// previous trim is higher than 10 seconds. Furthermore, trims can be explicitly
// requested through the public interface of this struct (see TrimOpenConns).

//
// See configuration parameters in NewConnManager.
type BasicConnMgr struct {
highWater int
Expand Down Expand Up @@ -129,6 +129,8 @@ func (cm *BasicConnMgr) getConnsToClose(ctx context.Context) []inet.Conn {
return closed
}

// GetTagInfo is called to fetch the tag information associated with a given
// peer, nil is returned if p refers to an unknown peer.
func (cm *BasicConnMgr) GetTagInfo(p peer.ID) *ifconnmgr.TagInfo {
cm.lk.Lock()
defer cm.lk.Unlock()
Expand All @@ -155,6 +157,7 @@ func (cm *BasicConnMgr) GetTagInfo(p peer.ID) *ifconnmgr.TagInfo {
return out
}

// TagPeer is called to associate a string and integer with a given peer.
func (cm *BasicConnMgr) TagPeer(p peer.ID, tag string, val int) {
cm.lk.Lock()
defer cm.lk.Unlock()
Expand All @@ -170,6 +173,7 @@ func (cm *BasicConnMgr) TagPeer(p peer.ID, tag string, val int) {
pi.tags[tag] = val
}

// UntagPeer is called to disassociate a string and integer from a given peer.
func (cm *BasicConnMgr) UntagPeer(p peer.ID, tag string) {
cm.lk.Lock()
defer cm.lk.Unlock()
Expand Down
229 changes: 229 additions & 0 deletions p2p/net/connmgr/connmgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package connmgr
import (
"context"
"testing"
"time"

inet "github.com/libp2p/go-libp2p-net"
peer "github.com/libp2p/go-libp2p-peer"
tu "github.com/libp2p/go-testutil"
ma "github.com/multiformats/go-multiaddr"
)

type tconn struct {
Expand All @@ -24,6 +26,14 @@ func (c *tconn) RemotePeer() peer.ID {
return c.peer
}

func (c *tconn) RemoteMultiaddr() ma.Multiaddr {
addr, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234")
if err != nil {
panic("cannot create multiaddr")
}
return addr
}

func randConn(t *testing.T) inet.Conn {
pid := tu.RandPeerIDFatal(t)
return &tconn{peer: pid}
Expand Down Expand Up @@ -65,3 +75,222 @@ func TestConnTrimming(t *testing.T) {
t.Fatal("conn with bad tag should have gotten closed")
}
}

func TestConnsToClose(t *testing.T) {
cm := NewConnManager(0, 10, 0)
conns := cm.getConnsToClose(context.Background())
if conns != nil {
t.Fatal("expected no connections")
}

cm = NewConnManager(10, 0, 0)
conns = cm.getConnsToClose(context.Background())
if conns != nil {
t.Fatal("expected no connections")
}

cm = NewConnManager(1, 1, 0)
conns = cm.getConnsToClose(context.Background())
if conns != nil {
t.Fatal("expected no connections")
}

cm = NewConnManager(1, 1, time.Duration(10*time.Minute))
not := cm.Notifee()
for i := 0; i < 5; i++ {
conn := randConn(t)
not.Connected(nil, conn)
}
conns = cm.getConnsToClose(context.Background())
if len(conns) != 0 {
t.Fatal("expected no connections")
}
}

func TestGetTagInfo(t *testing.T) {
start := time.Now()
cm := NewConnManager(1, 1, time.Duration(10*time.Minute))
not := cm.Notifee()
conn := randConn(t)
not.Connected(nil, conn)
end := time.Now()

other := tu.RandPeerIDFatal(t)
tag := cm.GetTagInfo(other)
if tag != nil {
t.Fatal("expected no tag")
}

tag = cm.GetTagInfo(conn.RemotePeer())
if tag == nil {
t.Fatal("expected tag")
}
if tag.FirstSeen.Before(start) || tag.FirstSeen.After(end) {
t.Fatal("expected first seen time")
}
if tag.Value != 0 {
t.Fatal("expected zero value")
}
if len(tag.Tags) != 0 {
t.Fatal("expected no tags")
}
if len(tag.Conns) != 1 {
t.Fatal("expected one connection")
}
for s, tm := range tag.Conns {
if s != conn.RemoteMultiaddr().String() {
t.Fatal("unexpected multiaddr")
}
if tm.Before(start) || tm.After(end) {
t.Fatal("unexpected connection time")
}
}

cm.TagPeer(conn.RemotePeer(), "tag", 5)
tag = cm.GetTagInfo(conn.RemotePeer())
if tag == nil {
t.Fatal("expected tag")
}
if tag.FirstSeen.Before(start) || tag.FirstSeen.After(end) {
t.Fatal("expected first seen time")
}
if tag.Value != 5 {
t.Fatal("expected five value")
}
if len(tag.Tags) != 1 {
t.Fatal("expected no tags")
}
for tString, v := range tag.Tags {
if tString != "tag" || v != 5 {
t.Fatal("expected tag value")
}
}
if len(tag.Conns) != 1 {
t.Fatal("expected one connection")
}
for s, tm := range tag.Conns {
if s != conn.RemoteMultiaddr().String() {
t.Fatal("unexpected multiaddr")
}
if tm.Before(start) || tm.After(end) {
t.Fatal("unexpected connection time")
}
}
}

func TestTagPeerNonExistant(t *testing.T) {
cm := NewConnManager(1, 1, time.Duration(10*time.Minute))

id := tu.RandPeerIDFatal(t)
cm.TagPeer(id, "test", 1)

if len(cm.peers) != 0 {
t.Fatal("expected zero peers")
}
}

func TestUntagPeer(t *testing.T) {
cm := NewConnManager(1, 1, time.Duration(10*time.Minute))
not := cm.Notifee()
conn := randConn(t)
not.Connected(nil, conn)
rp := conn.RemotePeer()
cm.TagPeer(rp, "tag", 5)
cm.TagPeer(rp, "tag two", 5)

id := tu.RandPeerIDFatal(t)
cm.UntagPeer(id, "test")
if len(cm.peers[rp].tags) != 2 {
t.Fatal("expected tags to be uneffected")
}

cm.UntagPeer(conn.RemotePeer(), "test")
if len(cm.peers[rp].tags) != 2 {
t.Fatal("expected tags to be uneffected")
}

cm.UntagPeer(conn.RemotePeer(), "tag")
if len(cm.peers[rp].tags) != 1 {
t.Fatal("expected tag to be removed")
}
if cm.peers[rp].value != 5 {
t.Fatal("expected aggreagte tag value to be 5")
}
}

func TestGetInfo(t *testing.T) {
start := time.Now()
gp := time.Duration(10 * time.Minute)
cm := NewConnManager(1, 5, gp)
not := cm.Notifee()
conn := randConn(t)
not.Connected(nil, conn)
cm.TrimOpenConns(context.Background())
end := time.Now()

info := cm.GetInfo()
if info.HighWater != 5 {
t.Fatal("expected highwater to be 5")
}
if info.LowWater != 1 {
t.Fatal("expected highwater to be 1")
}
if info.LastTrim.Before(start) || info.LastTrim.After(end) {
t.Fatal("unexpected last trim time")
}
if info.GracePeriod != gp {
t.Fatal("unexpected grace period")
}
if info.ConnCount != 1 {
t.Fatal("unexpected number of connections")
}
}

func TestDoubleConnection(t *testing.T) {
gp := time.Duration(10 * time.Minute)
cm := NewConnManager(1, 5, gp)
not := cm.Notifee()
conn := randConn(t)
not.Connected(nil, conn)
cm.TagPeer(conn.RemotePeer(), "foo", 10)
not.Connected(nil, conn)
if cm.connCount != 1 {
t.Fatal("unexpected number of connections")
}
if cm.peers[conn.RemotePeer()].value != 10 {
t.Fatal("unexpected peer value")
}
}

func TestDisconnected(t *testing.T) {
gp := time.Duration(10 * time.Minute)
cm := NewConnManager(1, 5, gp)
not := cm.Notifee()
conn := randConn(t)
not.Connected(nil, conn)
cm.TagPeer(conn.RemotePeer(), "foo", 10)

not.Disconnected(nil, randConn(t))
if cm.connCount != 1 {
t.Fatal("unexpected number of connections")
}
if cm.peers[conn.RemotePeer()].value != 10 {
t.Fatal("unexpected peer value")
}

not.Disconnected(nil, &tconn{peer: conn.RemotePeer()})
if cm.connCount != 1 {
t.Fatal("unexpected number of connections")
}
if cm.peers[conn.RemotePeer()].value != 10 {
t.Fatal("unexpected peer value")
}

not.Disconnected(nil, conn)
if cm.connCount != 0 {
t.Fatal("unexpected number of connections")
}
if len(cm.peers) != 0 {
t.Fatal("unexpected number of peers")
}
}

0 comments on commit 6f4d058

Please sign in to comment.