Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

Leaner swarm/network and p2p/simulations #1076

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions p2p/simulations/adapters/inproc.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,17 +351,3 @@ func (sn *SimNode) NodeInfo() *p2p.NodeInfo {
}
return server.NodeInfo()
}

func setSocketBuffer(conn net.Conn, socketReadBuffer int, socketWriteBuffer int) error {
if v, ok := conn.(*net.UnixConn); ok {
err := v.SetReadBuffer(socketReadBuffer)
if err != nil {
return err
}
err = v.SetWriteBuffer(socketWriteBuffer)
if err != nil {
return err
}
}
return nil
}
52 changes: 4 additions & 48 deletions p2p/simulations/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,8 @@ import (

var (
ErrNodeNotFound = errors.New("node not found")
ErrNoPivotNode = errors.New("no pivot node set")
)

// ConnectToPivotNode connects the node with provided NodeID
// to the pivot node, already set by Network.SetPivotNode method.
// It is useful when constructing a star network topology
// when Network adds and removes nodes dynamically.
func (net *Network) ConnectToPivotNode(id enode.ID) (err error) {
pivot := net.GetPivotNode()
if pivot == nil {
return ErrNoPivotNode
}
return net.connect(pivot.ID(), id)
}

// ConnectToLastNode connects the node with provided NodeID
// to the last node that is up, and avoiding connection to self.
// It is useful when constructing a chain network topology
Expand Down Expand Up @@ -115,35 +102,23 @@ func (net *Network) ConnectNodesRing(ids []enode.ID) (err error) {
return net.connect(ids[l-1], ids[0])
}

// ConnectNodesStar connects all nodes in a star topology
// with the center at provided NodeID.
// ConnectNodesStar connects all nodes into a star topology
// If ids argument is nil, all nodes that are up will be connected.
func (net *Network) ConnectNodesStar(pivot enode.ID, ids []enode.ID) (err error) {
func (net *Network) ConnectNodesStar(ids []enode.ID, center enode.ID) (err error) {
if ids == nil {
ids = net.getUpNodeIDs()
}
for _, id := range ids {
if pivot == id {
if center == id {
continue
}
if err := net.connect(pivot, id); err != nil {
if err := net.connect(center, id); err != nil {
return err
}
}
return nil
}

// ConnectNodesStarPivot connects all nodes in a star topology
// with the center at already set pivot node.
// If ids argument is nil, all nodes that are up will be connected.
func (net *Network) ConnectNodesStarPivot(ids []enode.ID) (err error) {
pivot := net.GetPivotNode()
if pivot == nil {
return ErrNoPivotNode
}
return net.ConnectNodesStar(pivot.ID(), ids)
}

// connect connects two nodes but ignores already connected error.
func (net *Network) connect(oneID, otherID enode.ID) error {
return ignoreAlreadyConnectedErr(net.Connect(oneID, otherID))
Expand All @@ -155,22 +130,3 @@ func ignoreAlreadyConnectedErr(err error) error {
}
return err
}

// SetPivotNode sets the NodeID of the network's pivot node.
// Pivot node is just a specific node that should be treated
// differently then other nodes in test. SetPivotNode and
// GetPivotNode are just a convenient functions to set and
// retrieve it.
func (net *Network) SetPivotNode(id enode.ID) {
net.lock.Lock()
defer net.lock.Unlock()
net.pivotNodeID = id
}

// GetPivotNode returns NodeID of the pivot node set by
// Network.SetPivotNode method.
func (net *Network) GetPivotNode() (node *Node) {
net.lock.RLock()
defer net.lock.RUnlock()
return net.getNode(net.pivotNodeID)
}
138 changes: 97 additions & 41 deletions p2p/simulations/connect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,24 +57,6 @@ func newTestNetwork(t *testing.T, nodeCount int) (*Network, []enode.ID) {
return network, ids
}

func TestConnectToPivotNode(t *testing.T) {
net, ids := newTestNetwork(t, 2)
defer net.Shutdown()

pivot := ids[0]
net.SetPivotNode(pivot)

other := ids[1]
err := net.ConnectToPivotNode(other)
if err != nil {
t.Fatal(err)
}

if net.GetConn(pivot, other) == nil {
t.Error("pivot and the other node are not connected")
}
}

func TestConnectToLastNode(t *testing.T) {
net, ids := newTestNetwork(t, 10)
defer net.Shutdown()
Expand Down Expand Up @@ -124,15 +106,48 @@ func TestConnectToRandomNode(t *testing.T) {
}

func TestConnectNodesFull(t *testing.T) {
net, ids := newTestNetwork(t, 12)
defer net.Shutdown()
tests := []struct {
name string
nodeCount int
}{
{name: "no node", nodeCount: 0},
{name: "single node", nodeCount: 1},
{name: "2 nodes", nodeCount: 2},
{name: "3 nodes", nodeCount: 2},
frncmx marked this conversation as resolved.
Show resolved Hide resolved
{name: "even number of nodes", nodeCount: 12},
{name: "odd number of nodes", nodeCount: 13},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
net, ids := newTestNetwork(t, test.nodeCount)
defer net.Shutdown()

err := net.ConnectNodesFull(ids)
if err != nil {
t.Fatal(err)
}

err := net.ConnectNodesFull(ids)
if err != nil {
t.Fatal(err)
verifyFull(t, net, ids)
})
}
}

func verifyFull(t *testing.T, net *Network, ids []enode.ID) {
t.Helper()
n := len(ids)
var connections int
for i, lid := range ids {
for _, rid := range ids[i+1:] {
if net.GetConn(lid, rid) != nil {
connections++
}
}
}

VerifyFull(t, net, ids)
want := n * (n - 1) / 2
if connections != want {
t.Errorf("wrong number of connections, got: %v, want: %v", connections, want)
}
}

func TestConnectNodesChain(t *testing.T) {
Expand All @@ -144,7 +159,26 @@ func TestConnectNodesChain(t *testing.T) {
t.Fatal(err)
}

VerifyChain(t, net, ids)
verifyChain(t, net, ids)
}

func verifyChain(t *testing.T, net *Network, ids []enode.ID) {
t.Helper()
n := len(ids)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
c := net.GetConn(ids[i], ids[j])
if i == j-1 {
if c == nil {
t.Errorf("nodes %v and %v are not connected, but they should be", i, j)
}
} else {
if c != nil {
t.Errorf("nodes %v and %v are connected, but they should not be", i, j)
}
}
}
}
}

func TestConnectNodesRing(t *testing.T) {
Expand All @@ -156,7 +190,26 @@ func TestConnectNodesRing(t *testing.T) {
t.Fatal(err)
}

VerifyRing(t, net, ids)
verifyRing(t, net, ids)
}

func verifyRing(t *testing.T, net *Network, ids []enode.ID) {
t.Helper()
n := len(ids)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
c := net.GetConn(ids[i], ids[j])
if i == j-1 || (i == 0 && j == n-1) {
if c == nil {
t.Errorf("nodes %v and %v are not connected, but they should be", i, j)
}
} else {
if c != nil {
t.Errorf("nodes %v and %v are connected, but they should not be", i, j)
}
}
}
}
}

func TestConnectNodesStar(t *testing.T) {
Expand All @@ -165,26 +218,29 @@ func TestConnectNodesStar(t *testing.T) {

pivotIndex := 2

err := net.ConnectNodesStar(ids[pivotIndex], ids)
err := net.ConnectNodesStar(ids, ids[pivotIndex])
if err != nil {
t.Fatal(err)
}

VerifyStar(t, net, ids, pivotIndex)
verifyStar(t, net, ids, pivotIndex)
}

func TestConnectNodesStarPivot(t *testing.T) {
net, ids := newTestNetwork(t, 10)
defer net.Shutdown()

pivotIndex := 4

net.SetPivotNode(ids[pivotIndex])

err := net.ConnectNodesStarPivot(ids)
if err != nil {
t.Fatal(err)
func verifyStar(t *testing.T, net *Network, ids []enode.ID, centerIndex int) {
t.Helper()
n := len(ids)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
c := net.GetConn(ids[i], ids[j])
if i == centerIndex || j == centerIndex {
if c == nil {
t.Errorf("nodes %v and %v are not connected, but they should be", i, j)
}
} else {
if c != nil {
t.Errorf("nodes %v and %v are connected, but they should not be", i, j)
}
}
}
}

VerifyStar(t, net, ids, pivotIndex)
}
2 changes: 0 additions & 2 deletions p2p/simulations/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ type Network struct {
Conns []*Conn `json:"conns"`
connMap map[string]int

pivotNodeID enode.ID

nodeAdapter adapters.NodeAdapter
events event.Feed
lock sync.RWMutex
Expand Down
77 changes: 0 additions & 77 deletions p2p/simulations/test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package simulations

import (
"testing"

"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
Expand Down Expand Up @@ -57,78 +55,3 @@ func (t *NoopService) Start(server *p2p.Server) error {
func (t *NoopService) Stop() error {
return nil
}

func VerifyRing(t *testing.T, net *Network, ids []enode.ID) {
t.Helper()
n := len(ids)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
c := net.GetConn(ids[i], ids[j])
if i == j-1 || (i == 0 && j == n-1) {
if c == nil {
t.Errorf("nodes %v and %v are not connected, but they should be", i, j)
}
} else {
if c != nil {
t.Errorf("nodes %v and %v are connected, but they should not be", i, j)
}
}
}
}
}

func VerifyChain(t *testing.T, net *Network, ids []enode.ID) {
t.Helper()
n := len(ids)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
c := net.GetConn(ids[i], ids[j])
if i == j-1 {
if c == nil {
t.Errorf("nodes %v and %v are not connected, but they should be", i, j)
}
} else {
if c != nil {
t.Errorf("nodes %v and %v are connected, but they should not be", i, j)
}
}
}
}
}

func VerifyFull(t *testing.T, net *Network, ids []enode.ID) {
t.Helper()
n := len(ids)
var connections int
for i, lid := range ids {
for _, rid := range ids[i+1:] {
if net.GetConn(lid, rid) != nil {
connections++
}
}
}

want := n * (n - 1) / 2
if connections != want {
t.Errorf("wrong number of connections, got: %v, want: %v", connections, want)
}
}

func VerifyStar(t *testing.T, net *Network, ids []enode.ID, centerIndex int) {
t.Helper()
n := len(ids)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
c := net.GetConn(ids[i], ids[j])
if i == centerIndex || j == centerIndex {
if c == nil {
t.Errorf("nodes %v and %v are not connected, but they should be", i, j)
}
} else {
if c != nil {
t.Errorf("nodes %v and %v are connected, but they should not be", i, j)
}
}
}
}
}
2 changes: 1 addition & 1 deletion swarm/network/simulation/bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func TestServiceBucket(t *testing.T) {
}
})

if err := sim.StopNode(id2); err != nil {
if err := sim.Net.Stop(id2); err != nil {
t.Fatal(err)
}

Expand Down
Loading