diff --git a/p2p/simulations/adapters/exec.go b/p2p/simulations/adapters/exec.go index abb1967171..9b588db1be 100644 --- a/p2p/simulations/adapters/exec.go +++ b/p2p/simulations/adapters/exec.go @@ -46,7 +46,7 @@ import ( func init() { // Register a reexec function to start a simulation node when the current binary is - // executed as "p2p-node" (rather than whataver the main() function would normally do). + // executed as "p2p-node" (rather than whatever the main() function would normally do). reexec.Register("p2p-node", execP2PNode) } diff --git a/p2p/simulations/adapters/inproc.go b/p2p/simulations/adapters/inproc.go index 52a662be63..eada9579ed 100644 --- a/p2p/simulations/adapters/inproc.go +++ b/p2p/simulations/adapters/inproc.go @@ -130,7 +130,7 @@ func (s *SimAdapter) Dial(dest *enode.Node) (conn net.Conn, err error) { return nil, err } // this is simulated 'listening' - // asynchronously call the dialed destintion node's p2p server + // asynchronously call the dialed destination node's p2p server // to set up connection on the 'listening' side go srv.SetupConn(pipe1, 0, nil) return pipe2, nil @@ -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 -} diff --git a/p2p/simulations/connect.go b/p2p/simulations/connect.go index 606dda0567..b15f14b089 100644 --- a/p2p/simulations/connect.go +++ b/p2p/simulations/connect.go @@ -17,73 +17,11 @@ package simulations import ( - "errors" "strings" "github.com/ethereum/go-ethereum/p2p/enode" ) -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 -// when Network adds and removes nodes dynamically. -func (net *Network) ConnectToLastNode(id enode.ID) (err error) { - ids := net.getUpNodeIDs() - l := len(ids) - if l < 2 { - return nil - } - last := ids[l-1] - if last == id { - last = ids[l-2] - } - return net.connect(last, id) -} - -// ConnectToRandomNode connects the node with provided NodeID -// to a random node that is up. -func (net *Network) ConnectToRandomNode(id enode.ID) (err error) { - selected := net.GetRandomUpNode(id) - if selected == nil { - return ErrNodeNotFound - } - return net.connect(selected.ID(), id) -} - -// ConnectNodesFull connects all nodes one to another. -// It provides a complete connectivity in the network -// which should be rarely needed. -func (net *Network) ConnectNodesFull(ids []enode.ID) (err error) { - if ids == nil { - ids = net.getUpNodeIDs() - } - for i, lid := range ids { - for _, rid := range ids[i+1:] { - if err = net.connect(lid, rid); err != nil { - return err - } - } - } - return nil -} - // ConnectNodesChain connects all nodes in a chain topology. // If ids argument is nil, all nodes that are up will be connected. func (net *Network) ConnectNodesChain(ids []enode.ID) (err error) { @@ -115,35 +53,6 @@ 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. -// 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) { - if ids == nil { - ids = net.getUpNodeIDs() - } - for _, id := range ids { - if pivot == id { - continue - } - if err := net.connect(pivot, 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)) @@ -155,22 +64,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) -} diff --git a/p2p/simulations/connect_test.go b/p2p/simulations/connect_test.go index 36f9442a8a..0e30e88d2b 100644 --- a/p2p/simulations/connect_test.go +++ b/p2p/simulations/connect_test.go @@ -25,6 +25,7 @@ import ( ) func newTestNetwork(t *testing.T, nodeCount int) (*Network, []enode.ID) { + t.Helper() adapter := adapters.NewSimAdapter(adapters.Services{ "noopwoop": func(ctx *adapters.ServiceContext) (node.Service, error) { return NewNoopService(nil), nil @@ -57,94 +58,35 @@ 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) { +func TestConnectNodesChain(t *testing.T) { net, ids := newTestNetwork(t, 10) defer net.Shutdown() - first := ids[0] - if err := net.ConnectToLastNode(first); err != nil { + err := net.ConnectNodesChain(ids) + if err != nil { t.Fatal(err) } - last := ids[len(ids)-1] - for i, id := range ids { - if id == first || id == last { - continue - } - - if net.GetConn(first, id) != nil { - t.Errorf("connection must not exist with node(ind: %v, id: %v)", i, id) - } - } - - if net.GetConn(first, last) == nil { - t.Error("first and last node must be connected") - } + verifyChain(t, net, ids) } -func TestConnectToRandomNode(t *testing.T) { - net, ids := newTestNetwork(t, 10) - defer net.Shutdown() - - err := net.ConnectToRandomNode(ids[0]) - if err != nil { - t.Fatal(err) - } - - var cc int - for i, a := range ids { - for _, b := range ids[i:] { - if net.GetConn(a, b) != nil { - cc++ +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) + } } } } - - if cc != 1 { - t.Errorf("expected one connection, got %v", cc) - } -} - -func TestConnectNodesFull(t *testing.T) { - net, ids := newTestNetwork(t, 12) - defer net.Shutdown() - - err := net.ConnectNodesFull(ids) - if err != nil { - t.Fatal(err) - } - - VerifyFull(t, net, ids) -} - -func TestConnectNodesChain(t *testing.T) { - net, ids := newTestNetwork(t, 10) - defer net.Shutdown() - - err := net.ConnectNodesChain(ids) - if err != nil { - t.Fatal(err) - } - - VerifyChain(t, net, ids) } func TestConnectNodesRing(t *testing.T) { @@ -156,35 +98,24 @@ func TestConnectNodesRing(t *testing.T) { t.Fatal(err) } - VerifyRing(t, net, ids) + verifyRing(t, net, ids) } -func TestConnectNodesStar(t *testing.T) { - net, ids := newTestNetwork(t, 10) - defer net.Shutdown() - - pivotIndex := 2 - - err := net.ConnectNodesStar(ids[pivotIndex], ids) - if err != nil { - t.Fatal(err) - } - - 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 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) + } + } + } } - - VerifyStar(t, net, ids, pivotIndex) } diff --git a/p2p/simulations/http_test.go b/p2p/simulations/http_test.go index d9513caaa0..c0a5acb3d8 100644 --- a/p2p/simulations/http_test.go +++ b/p2p/simulations/http_test.go @@ -35,7 +35,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/simulations/adapters" "github.com/ethereum/go-ethereum/rpc" - colorable "github.com/mattn/go-colorable" + "github.com/mattn/go-colorable" ) var ( @@ -294,6 +294,7 @@ var testServices = adapters.Services{ } func testHTTPServer(t *testing.T) (*Network, *httptest.Server) { + t.Helper() adapter := adapters.NewSimAdapter(testServices) network := NewNetwork(adapter, &NetworkConfig{ DefaultService: "test", diff --git a/p2p/simulations/mocker_test.go b/p2p/simulations/mocker_test.go index 7c7016a5e6..192be1732c 100644 --- a/p2p/simulations/mocker_test.go +++ b/p2p/simulations/mocker_test.go @@ -15,7 +15,7 @@ // along with the go-ethereum library. If not, see . // Package simulations simulates p2p networks. -// A mokcer simulates starting and stopping real nodes in a network. +// A mocker simulates starting and stopping real nodes in a network. package simulations import ( @@ -135,13 +135,13 @@ func TestMocker(t *testing.T) { wg.Wait() //check there are nodeCount number of nodes in the network - nodes_info, err := client.GetNodes() + nodesInfo, err := client.GetNodes() if err != nil { t.Fatalf("Could not get nodes list: %s", err) } - if len(nodes_info) != nodeCount { - t.Fatalf("Expected %d number of nodes, got: %d", nodeCount, len(nodes_info)) + if len(nodesInfo) != nodeCount { + t.Fatalf("Expected %d number of nodes, got: %d", nodeCount, len(nodesInfo)) } //stop the mocker @@ -160,12 +160,12 @@ func TestMocker(t *testing.T) { } //now the number of nodes in the network should be zero - nodes_info, err = client.GetNodes() + nodesInfo, err = client.GetNodes() if err != nil { t.Fatalf("Could not get nodes list: %s", err) } - if len(nodes_info) != 0 { - t.Fatalf("Expected empty list of nodes, got: %d", len(nodes_info)) + if len(nodesInfo) != 0 { + t.Fatalf("Expected empty list of nodes, got: %d", len(nodesInfo)) } } diff --git a/p2p/simulations/network.go b/p2p/simulations/network.go index a6fac2c2af..86f7dc9bef 100644 --- a/p2p/simulations/network.go +++ b/p2p/simulations/network.go @@ -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 @@ -518,7 +516,7 @@ func (net *Network) getConn(oneID, otherID enode.ID) *Conn { return net.Conns[i] } -// InitConn(one, other) retrieves the connectiton model for the connection between +// InitConn(one, other) retrieves the connection model for the connection between // peers one and other, or creates a new one if it does not exist // the order of nodes does not matter, i.e., Conn(i,j) == Conn(j, i) // it checks if the connection is already up, and if the nodes are running @@ -564,8 +562,8 @@ func (net *Network) Shutdown() { close(net.quitc) } -//Reset resets all network properties: -//emtpies the nodes and the connection list +// Reset resets all network properties: +// empties the nodes and the connection list func (net *Network) Reset() { net.lock.Lock() defer net.lock.Unlock() diff --git a/p2p/simulations/test.go b/p2p/simulations/test.go index beeb414e41..6a646f9ecb 100644 --- a/p2p/simulations/test.go +++ b/p2p/simulations/test.go @@ -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" @@ -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) - } - } - } - } -} diff --git a/swarm/network/simulation/bucket.go b/swarm/network/simulation/bucket.go index bd15ea2ab1..49a1f43091 100644 --- a/swarm/network/simulation/bucket.go +++ b/swarm/network/simulation/bucket.go @@ -21,7 +21,7 @@ import "github.com/ethereum/go-ethereum/p2p/enode" // BucketKey is the type that should be used for keys in simulation buckets. type BucketKey string -// NodeItem returns an item set in ServiceFunc function for a particualar node. +// NodeItem returns an item set in ServiceFunc function for a particular node. func (s *Simulation) NodeItem(id enode.ID, key interface{}) (value interface{}, ok bool) { s.mu.Lock() defer s.mu.Unlock() diff --git a/swarm/network/simulation/bucket_test.go b/swarm/network/simulation/bucket_test.go index 69df19bfe4..e649e88164 100644 --- a/swarm/network/simulation/bucket_test.go +++ b/swarm/network/simulation/bucket_test.go @@ -24,7 +24,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/simulations/adapters" ) -// TestServiceBucket tests all bucket functionalities using subtests. +// TestServiceBucket tests all bucket functionality using subtests. // It constructs a simulation of two nodes by adding items to their buckets // in ServiceFunc constructor, then by SetNodeItem. Testing UpNodesItems // is done by stopping one node and validating availability of its items. @@ -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) } diff --git a/swarm/network/simulation/example_test.go b/swarm/network/simulation/example_test.go index a100ede516..e9a360dfd4 100644 --- a/swarm/network/simulation/example_test.go +++ b/swarm/network/simulation/example_test.go @@ -25,7 +25,7 @@ import ( // Every node can have a Kademlia associated using the node bucket under // BucketKeyKademlia key. This allows to use WaitTillHealthy to block until -// all nodes have the their Kadmlias healthy. +// all nodes have the their Kademlias healthy. func ExampleSimulation_WaitTillHealthy() { log.Error("temporarily disabled as simulations.WaitTillHealthy cannot be trusted") diff --git a/swarm/network/simulation/kademlia.go b/swarm/network/simulation/kademlia.go index 25bb0f6a9f..ebec468f14 100644 --- a/swarm/network/simulation/kademlia.go +++ b/swarm/network/simulation/kademlia.go @@ -28,7 +28,7 @@ import ( ) // BucketKeyKademlia is the key to be used for storing the kademlia -// instance for particuar node, usually inside the ServiceFunc function. +// instance for particular node, usually inside the ServiceFunc function. var BucketKeyKademlia BucketKey = "kademlia" // WaitTillHealthy is blocking until the health of all kademlias is true. diff --git a/swarm/network/simulation/kademlia_test.go b/swarm/network/simulation/kademlia_test.go index f02b0e5417..52e09c5fc9 100644 --- a/swarm/network/simulation/kademlia_test.go +++ b/swarm/network/simulation/kademlia_test.go @@ -47,11 +47,15 @@ func TestWaitTillHealthy(t *testing.T) { }) defer sim.Close() - _, err := sim.AddNodesAndConnectRing(10) + ids, err := sim.AddNodes(10) if err != nil { t.Fatal(err) } + if err := sim.Net.ConnectNodesRing(ids); err != nil { + t.Fatal(err) + } + ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) defer cancel() ill, err := sim.WaitTillHealthy(ctx, 2) diff --git a/swarm/network/simulation/node.go b/swarm/network/simulation/node.go index 24b6599762..5d70a1556c 100644 --- a/swarm/network/simulation/node.go +++ b/swarm/network/simulation/node.go @@ -18,7 +18,6 @@ package simulation import ( "encoding/json" - "errors" "io/ioutil" "math/rand" "os" @@ -74,20 +73,9 @@ func AddNodeWithMsgEvents(enable bool) AddNodeOption { } } -// AddNodeWithService specifies a service that should be -// started on a node. This option can be repeated as variadic -// argument toe AddNode and other add node related methods. -// If AddNodeWithService is not specified, all services will be started. -func AddNodeWithService(serviceName string) AddNodeOption { - return func(o *adapters.NodeConfig) { - o.Services = append(o.Services, serviceName) - } -} - -// AddNode creates a new node with random configuration, -// applies provided options to the config and adds the node to network. -// By default all services will be started on a node. If one or more -// AddNodeWithService option are provided, only specified services will be started. +// AddNode creates a new node with random configuration and adds that to +// the network. All services will be started on the node. Tweaking the node's +// configuration is possible through the opts parameter. func (s *Simulation) AddNode(opts ...AddNodeOption) (id enode.ID, err error) { conf := adapters.RandomNodeConfig() for _, o := range opts { @@ -117,87 +105,9 @@ func (s *Simulation) AddNodes(count int, opts ...AddNodeOption) (ids []enode.ID, return ids, nil } -// AddNodesAndConnectFull is a helpper method that combines -// AddNodes and ConnectNodesFull. Only new nodes will be connected. -func (s *Simulation) AddNodesAndConnectFull(count int, opts ...AddNodeOption) (ids []enode.ID, err error) { - if count < 2 { - return nil, errors.New("count of nodes must be at least 2") - } - ids, err = s.AddNodes(count, opts...) - if err != nil { - return nil, err - } - err = s.Net.ConnectNodesFull(ids) - if err != nil { - return nil, err - } - return ids, nil -} - -// AddNodesAndConnectChain is a helpper method that combines -// AddNodes and ConnectNodesChain. The chain will be continued from the last -// added node, if there is one in simulation using ConnectToLastNode method. -func (s *Simulation) AddNodesAndConnectChain(count int, opts ...AddNodeOption) (ids []enode.ID, err error) { - if count < 2 { - return nil, errors.New("count of nodes must be at least 2") - } - id, err := s.AddNode(opts...) - if err != nil { - return nil, err - } - err = s.Net.ConnectToLastNode(id) - if err != nil { - return nil, err - } - ids, err = s.AddNodes(count-1, opts...) - if err != nil { - return nil, err - } - ids = append([]enode.ID{id}, ids...) - err = s.Net.ConnectNodesChain(ids) - if err != nil { - return nil, err - } - return ids, nil -} - -// AddNodesAndConnectRing is a helpper method that combines -// AddNodes and ConnectNodesRing. -func (s *Simulation) AddNodesAndConnectRing(count int, opts ...AddNodeOption) (ids []enode.ID, err error) { - if count < 2 { - return nil, errors.New("count of nodes must be at least 2") - } - ids, err = s.AddNodes(count, opts...) - if err != nil { - return nil, err - } - err = s.Net.ConnectNodesRing(ids) - if err != nil { - return nil, err - } - return ids, nil -} - -// AddNodesAndConnectStar is a helpper method that combines -// AddNodes and ConnectNodesStar. -func (s *Simulation) AddNodesAndConnectStar(count int, opts ...AddNodeOption) (ids []enode.ID, err error) { - if count < 2 { - return nil, errors.New("count of nodes must be at least 2") - } - ids, err = s.AddNodes(count, opts...) - if err != nil { - return nil, err - } - err = s.Net.ConnectNodesStar(ids[0], ids[1:]) - if err != nil { - return nil, err - } - return ids, nil -} - -//UploadSnapshot uploads a snapshot to the simulation -//This method tries to open the json file provided, applies the config to all nodes -//and then loads the snapshot into the Simulation network +// UploadSnapshot uploads a snapshot to the simulation +// This method tries to open the json file provided, applies the config to +// all nodes and then loads the snapshot into the Simulation network func (s *Simulation) UploadSnapshot(snapshotFile string, opts ...AddNodeOption) error { f, err := os.Open(snapshotFile) if err != nil { @@ -241,39 +151,6 @@ func (s *Simulation) UploadSnapshot(snapshotFile string, opts ...AddNodeOption) return nil } -// 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 -// PivotNodeID are just a convenient functions to set and -// retrieve it. -func (s *Simulation) SetPivotNode(id enode.ID) { - s.mu.Lock() - defer s.mu.Unlock() - s.pivotNodeID = &id -} - -// PivotNodeID returns NodeID of the pivot node set by -// Simulation.SetPivotNode method. -func (s *Simulation) PivotNodeID() (id *enode.ID) { - s.mu.Lock() - defer s.mu.Unlock() - return s.pivotNodeID -} - -// StartNode starts a node by NodeID. -func (s *Simulation) StartNode(id enode.ID) (err error) { - return s.Net.Start(id) -} - -// StartRandomNode starts a random node. -func (s *Simulation) StartRandomNode() (id enode.ID, err error) { - n := s.Net.GetRandomDownNode() - if n == nil { - return id, ErrNodeNotFound - } - return n.ID(), s.Net.Start(n.ID()) -} - // StartRandomNodes starts random nodes. func (s *Simulation) StartRandomNodes(count int) (ids []enode.ID, err error) { ids = make([]enode.ID, 0, count) @@ -291,20 +168,6 @@ func (s *Simulation) StartRandomNodes(count int) (ids []enode.ID, err error) { return ids, nil } -// StopNode stops a node by NodeID. -func (s *Simulation) StopNode(id enode.ID) (err error) { - return s.Net.Stop(id) -} - -// StopRandomNode stops a random node. -func (s *Simulation) StopRandomNode() (id enode.ID, err error) { - n := s.Net.GetRandomUpNode() - if n == nil { - return id, ErrNodeNotFound - } - return n.ID(), s.Net.Stop(n.ID()) -} - // StopRandomNodes stops random nodes. func (s *Simulation) StopRandomNodes(count int) (ids []enode.ID, err error) { ids = make([]enode.ID, 0, count) diff --git a/swarm/network/simulation/node_test.go b/swarm/network/simulation/node_test.go index 8da32cf37f..4d682ab547 100644 --- a/swarm/network/simulation/node_test.go +++ b/swarm/network/simulation/node_test.go @@ -26,11 +26,33 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/simulations" "github.com/ethereum/go-ethereum/p2p/simulations/adapters" "github.com/ethereum/go-ethereum/swarm/network" ) +func TestAddNodeWithMsgEvents(t *testing.T) { + sim := New(noopServiceFuncMap) + defer sim.Close() + + id, err := sim.AddNode(AddNodeWithMsgEvents(true)) + if err != nil { + t.Fatal(err) + } + + if !sim.Net.GetNode(id).Config.EnableMsgEvents { + t.Error("EnableMsgEvents is false") + } + + id, err = sim.AddNode(AddNodeWithMsgEvents(false)) + if err != nil { + t.Fatal(err) + } + + if sim.Net.GetNode(id).Config.EnableMsgEvents { + t.Error("EnableMsgEvents is true") + } +} + func TestUpDownNodeIDs(t *testing.T) { sim := New(noopServiceFuncMap) defer sim.Close() @@ -117,50 +139,6 @@ func TestAddNode(t *testing.T) { } } -func TestAddNodeWithMsgEvents(t *testing.T) { - sim := New(noopServiceFuncMap) - defer sim.Close() - - id, err := sim.AddNode(AddNodeWithMsgEvents(true)) - if err != nil { - t.Fatal(err) - } - - if !sim.Net.GetNode(id).Config.EnableMsgEvents { - t.Error("EnableMsgEvents is false") - } - - id, err = sim.AddNode(AddNodeWithMsgEvents(false)) - if err != nil { - t.Fatal(err) - } - - if sim.Net.GetNode(id).Config.EnableMsgEvents { - t.Error("EnableMsgEvents is true") - } -} - -func TestAddNodeWithService(t *testing.T) { - sim := New(map[string]ServiceFunc{ - "noop1": noopServiceFunc, - "noop2": noopServiceFunc, - }) - defer sim.Close() - - id, err := sim.AddNode(AddNodeWithService("noop1")) - if err != nil { - t.Fatal(err) - } - - n := sim.Net.GetNode(id).Node.(*adapters.SimNode) - if n.Service("noop1") == nil { - t.Error("service noop1 not found on node") - } - if n.Service("noop2") != nil { - t.Error("service noop2 should not be found on node") - } -} - func TestAddNodeMultipleServices(t *testing.T) { sim := New(map[string]ServiceFunc{ "noop1": noopServiceFunc, @@ -218,63 +196,6 @@ func TestAddNodes(t *testing.T) { } } -func TestAddNodesAndConnectFull(t *testing.T) { - sim := New(noopServiceFuncMap) - defer sim.Close() - - n := 12 - - ids, err := sim.AddNodesAndConnectFull(n) - if err != nil { - t.Fatal(err) - } - - simulations.VerifyFull(t, sim.Net, ids) -} - -func TestAddNodesAndConnectChain(t *testing.T) { - sim := New(noopServiceFuncMap) - defer sim.Close() - - _, err := sim.AddNodesAndConnectChain(12) - if err != nil { - t.Fatal(err) - } - - // add another set of nodes to test - // if two chains are connected - _, err = sim.AddNodesAndConnectChain(7) - if err != nil { - t.Fatal(err) - } - - simulations.VerifyChain(t, sim.Net, sim.UpNodeIDs()) -} - -func TestAddNodesAndConnectRing(t *testing.T) { - sim := New(noopServiceFuncMap) - defer sim.Close() - - ids, err := sim.AddNodesAndConnectRing(12) - if err != nil { - t.Fatal(err) - } - - simulations.VerifyRing(t, sim.Net, ids) -} - -func TestAddNodesAndConnectStar(t *testing.T) { - sim := New(noopServiceFuncMap) - defer sim.Close() - - ids, err := sim.AddNodesAndConnectStar(12) - if err != nil { - t.Fatal(err) - } - - simulations.VerifyStar(t, sim.Net, ids, 0) -} - //To test that uploading a snapshot works func TestUploadSnapshot(t *testing.T) { log.Debug("Creating simulation") @@ -314,138 +235,6 @@ func TestUploadSnapshot(t *testing.T) { log.Debug("Done.") } -func TestPivotNode(t *testing.T) { - sim := New(noopServiceFuncMap) - defer sim.Close() - - id, err := sim.AddNode() - if err != nil { - t.Fatal(err) - } - - id2, err := sim.AddNode() - if err != nil { - t.Fatal(err) - } - - if sim.PivotNodeID() != nil { - t.Error("expected no pivot node") - } - - sim.SetPivotNode(id) - - pid := sim.PivotNodeID() - - if pid == nil { - t.Error("pivot node not set") - } else if *pid != id { - t.Errorf("expected pivot node %s, got %s", id, *pid) - } - - sim.SetPivotNode(id2) - - pid = sim.PivotNodeID() - - if pid == nil { - t.Error("pivot node not set") - } else if *pid != id2 { - t.Errorf("expected pivot node %s, got %s", id2, *pid) - } -} - -func TestStartStopNode(t *testing.T) { - sim := New(noopServiceFuncMap) - defer sim.Close() - - id, err := sim.AddNode() - if err != nil { - t.Fatal(err) - } - - n := sim.Net.GetNode(id) - if n == nil { - t.Fatal("node not found") - } - if !n.Up { - t.Error("node not started") - } - - err = sim.StopNode(id) - if err != nil { - t.Fatal(err) - } - if n.Up { - t.Error("node not stopped") - } - - // Sleep here to ensure that Network.watchPeerEvents defer function - // has set the `node.Up = false` before we start the node again. - // p2p/simulations/network.go:215 - // - // The same node is stopped and started again, and upon start - // watchPeerEvents is started in a goroutine. If the node is stopped - // and then very quickly started, that goroutine may be scheduled later - // then start and force `node.Up = false` in its defer function. - // This will make this test unreliable. - time.Sleep(time.Second) - - err = sim.StartNode(id) - if err != nil { - t.Fatal(err) - } - if !n.Up { - t.Error("node not started") - } -} - -func TestStartStopRandomNode(t *testing.T) { - sim := New(noopServiceFuncMap) - defer sim.Close() - - _, err := sim.AddNodes(3) - if err != nil { - t.Fatal(err) - } - - id, err := sim.StopRandomNode() - if err != nil { - t.Fatal(err) - } - - n := sim.Net.GetNode(id) - if n == nil { - t.Fatal("node not found") - } - if n.Up { - t.Error("node not stopped") - } - - id2, err := sim.StopRandomNode() - if err != nil { - t.Fatal(err) - } - - // Sleep here to ensure that Network.watchPeerEvents defer function - // has set the `node.Up = false` before we start the node again. - // p2p/simulations/network.go:215 - // - // The same node is stopped and started again, and upon start - // watchPeerEvents is started in a goroutine. If the node is stopped - // and then very quickly started, that goroutine may be scheduled later - // then start and force `node.Up = false` in its defer function. - // This will make this test unreliable. - time.Sleep(time.Second) - - idStarted, err := sim.StartRandomNode() - if err != nil { - t.Fatal(err) - } - - if idStarted != id && idStarted != id2 { - t.Error("unexpected started node ID") - } -} - func TestStartStopRandomNodes(t *testing.T) { sim := New(noopServiceFuncMap) defer sim.Close() diff --git a/swarm/network/simulation/simulation.go b/swarm/network/simulation/simulation.go index 106eeb71e9..bfa4498ee7 100644 --- a/swarm/network/simulation/simulation.go +++ b/swarm/network/simulation/simulation.go @@ -38,14 +38,13 @@ var ( // Simulation provides methods on network, nodes and services // to manage them. type Simulation struct { - // Net is exposed as a way to access lower level functionalities + // Net is exposed as a way to access lower level functionality // of p2p/simulations.Network. Net *simulations.Network serviceNames []string cleanupFuncs []func() buckets map[enode.ID]*sync.Map - pivotNodeID *enode.ID shutdownWG sync.WaitGroup done chan struct{} mu sync.RWMutex diff --git a/swarm/network/simulation/simulation_test.go b/swarm/network/simulation/simulation_test.go index 4667a2abc3..f837f93824 100644 --- a/swarm/network/simulation/simulation_test.go +++ b/swarm/network/simulation/simulation_test.go @@ -28,7 +28,7 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p/simulations" "github.com/ethereum/go-ethereum/p2p/simulations/adapters" - colorable "github.com/mattn/go-colorable" + "github.com/mattn/go-colorable" ) var ( @@ -177,7 +177,7 @@ var noopServiceFuncMap = map[string]ServiceFunc{ } // a helper function for most basic noop service -func noopServiceFunc(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) { +func noopServiceFunc(_ *adapters.ServiceContext, _ *sync.Map) (node.Service, func(), error) { return newNoopService(), nil, nil } @@ -188,7 +188,7 @@ func newNoopService() node.Service { // a helper function for most basic Noop service // of a different type then NoopService to test // multiple services on one node. -func noopService2Func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) { +func noopService2Func(_ *adapters.ServiceContext, _ *sync.Map) (node.Service, func(), error) { return new(noopService2), nil, nil } diff --git a/swarm/network/stream/delivery_test.go b/swarm/network/stream/delivery_test.go index 5c1f8c2512..9dd87adce5 100644 --- a/swarm/network/stream/delivery_test.go +++ b/swarm/network/stream/delivery_test.go @@ -442,17 +442,17 @@ func TestStreamerDownstreamChunkDeliveryMsgExchange(t *testing.T) { } func TestDeliveryFromNodes(t *testing.T) { - testDeliveryFromNodes(t, 2, 1, dataChunkCount, true) - testDeliveryFromNodes(t, 2, 1, dataChunkCount, false) - testDeliveryFromNodes(t, 4, 1, dataChunkCount, true) - testDeliveryFromNodes(t, 4, 1, dataChunkCount, false) - testDeliveryFromNodes(t, 8, 1, dataChunkCount, true) - testDeliveryFromNodes(t, 8, 1, dataChunkCount, false) - testDeliveryFromNodes(t, 16, 1, dataChunkCount, true) - testDeliveryFromNodes(t, 16, 1, dataChunkCount, false) + testDeliveryFromNodes(t, 2, dataChunkCount, true) + testDeliveryFromNodes(t, 2, dataChunkCount, false) + testDeliveryFromNodes(t, 4, dataChunkCount, true) + testDeliveryFromNodes(t, 4, dataChunkCount, false) + testDeliveryFromNodes(t, 8, dataChunkCount, true) + testDeliveryFromNodes(t, 8, dataChunkCount, false) + testDeliveryFromNodes(t, 16, dataChunkCount, true) + testDeliveryFromNodes(t, 16, dataChunkCount, false) } -func testDeliveryFromNodes(t *testing.T, nodes, conns, chunkCount int, skipCheck bool) { +func testDeliveryFromNodes(t *testing.T, numberOfNodes, chunkCount int, skipCheck bool) { sim := simulation.New(map[string]simulation.ServiceFunc{ "streamer": func(ctx *adapters.ServiceContext, bucket *sync.Map) (s node.Service, cleanup func(), err error) { node := ctx.Config.Node() @@ -493,10 +493,13 @@ func testDeliveryFromNodes(t *testing.T, nodes, conns, chunkCount int, skipCheck defer sim.Close() log.Info("Adding nodes to simulation") - _, err := sim.AddNodesAndConnectChain(nodes) + ids, err := sim.AddNodes(numberOfNodes) if err != nil { t.Fatal(err) } + if err := sim.Net.ConnectNodesChain(ids); err != nil { + t.Fatal(err) + } log.Info("Starting simulation") ctx := context.Background() @@ -609,7 +612,7 @@ func BenchmarkDeliveryFromNodesWithoutCheck(b *testing.B) { b.Run( fmt.Sprintf("nodes=%v,chunks=%v", i, chunks), func(b *testing.B) { - benchmarkDeliveryFromNodes(b, i, 1, chunks, true) + benchmarkDeliveryFromNodes(b, i, chunks, true) }, ) } @@ -622,14 +625,14 @@ func BenchmarkDeliveryFromNodesWithCheck(b *testing.B) { b.Run( fmt.Sprintf("nodes=%v,chunks=%v", i, chunks), func(b *testing.B) { - benchmarkDeliveryFromNodes(b, i, 1, chunks, false) + benchmarkDeliveryFromNodes(b, i, chunks, false) }, ) } } } -func benchmarkDeliveryFromNodes(b *testing.B, nodes, conns, chunkCount int, skipCheck bool) { +func benchmarkDeliveryFromNodes(b *testing.B, numberOfNodes, chunkCount int, skipCheck bool) { sim := simulation.New(map[string]simulation.ServiceFunc{ "streamer": func(ctx *adapters.ServiceContext, bucket *sync.Map) (s node.Service, cleanup func(), err error) { node := ctx.Config.Node() @@ -669,10 +672,13 @@ func benchmarkDeliveryFromNodes(b *testing.B, nodes, conns, chunkCount int, skip defer sim.Close() log.Info("Initializing test config") - _, err := sim.AddNodesAndConnectChain(nodes) + ids, err := sim.AddNodes(numberOfNodes) if err != nil { b.Fatal(err) } + if err := sim.Net.ConnectNodesChain(ids); err != nil { + b.Fatal(err) + } ctx := context.Background() result := sim.Run(ctx, func(ctx context.Context, sim *simulation.Simulation) error { diff --git a/swarm/network/stream/intervals_test.go b/swarm/network/stream/intervals_test.go index 7c7feeb112..027890d3dc 100644 --- a/swarm/network/stream/intervals_test.go +++ b/swarm/network/stream/intervals_test.go @@ -53,7 +53,6 @@ func TestIntervalsLiveAndHistory(t *testing.T) { func testIntervals(t *testing.T, live bool, history *Range, skipCheck bool) { - nodes := 2 chunkCount := dataChunkCount externalStreamName := "externalStream" externalStreamSessionAt := uint64(50) @@ -105,10 +104,13 @@ func testIntervals(t *testing.T, live bool, history *Range, skipCheck bool) { defer sim.Close() log.Info("Adding nodes to simulation") - _, err := sim.AddNodesAndConnectChain(nodes) + ids, err := sim.AddNodes(2) if err != nil { t.Fatal(err) } + if err := sim.Net.ConnectNodesChain(ids); err != nil { + t.Fatal(err) + } ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) defer cancel() diff --git a/swarm/network/stream/syncer_test.go b/swarm/network/stream/syncer_test.go index 27ed49ea48..ba6ec073c6 100644 --- a/swarm/network/stream/syncer_test.go +++ b/swarm/network/stream/syncer_test.go @@ -43,10 +43,10 @@ import ( const dataChunkCount = 200 func TestSyncerSimulation(t *testing.T) { - testSyncBetweenNodes(t, 2, 1, dataChunkCount, true, 1) - testSyncBetweenNodes(t, 4, 1, dataChunkCount, true, 1) - testSyncBetweenNodes(t, 8, 1, dataChunkCount, true, 1) - testSyncBetweenNodes(t, 16, 1, dataChunkCount, true, 1) + testSyncBetweenNodes(t, 2, dataChunkCount, true, 1) + testSyncBetweenNodes(t, 4, dataChunkCount, true, 1) + testSyncBetweenNodes(t, 8, dataChunkCount, true, 1) + testSyncBetweenNodes(t, 16, dataChunkCount, true, 1) } func createMockStore(globalStore mock.GlobalStorer, id enode.ID, addr *network.BzzAddr) (lstore storage.ChunkStore, datadir string, err error) { @@ -67,7 +67,7 @@ func createMockStore(globalStore mock.GlobalStorer, id enode.ID, addr *network.B return lstore, datadir, nil } -func testSyncBetweenNodes(t *testing.T, nodes, conns, chunkCount int, skipCheck bool, po uint8) { +func testSyncBetweenNodes(t *testing.T, nodes, chunkCount int, skipCheck bool, po uint8) { sim := simulation.New(map[string]simulation.ServiceFunc{ "streamer": func(ctx *adapters.ServiceContext, bucket *sync.Map) (s node.Service, cleanup func(), err error) { @@ -120,15 +120,18 @@ func testSyncBetweenNodes(t *testing.T, nodes, conns, chunkCount int, skipCheck defer sim.Close() // create context for simulation run - timeout := 30 * time.Second - ctx, cancel := context.WithTimeout(context.Background(), timeout) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // defer cancel should come before defer simulation teardown defer cancel() - _, err := sim.AddNodesAndConnectChain(nodes) + ids, err := sim.AddNodes(nodes) if err != nil { t.Fatal(err) } + if err := sim.Net.ConnectNodesChain(ids); err != nil { + t.Fatal(err) + } + result := sim.Run(ctx, func(ctx context.Context, sim *simulation.Simulation) error { nodeIDs := sim.UpNodeIDs() @@ -285,10 +288,13 @@ func TestSameVersionID(t *testing.T) { //connect just two nodes log.Info("Adding nodes to simulation") - _, err := sim.AddNodesAndConnectChain(2) + ids, err := sim.AddNodes(2) if err != nil { t.Fatal(err) } + if err := sim.Net.ConnectNodesChain(ids); err != nil { + t.Fatal(err) + } log.Info("Starting simulation") ctx := context.Background() @@ -369,10 +375,13 @@ func TestDifferentVersionID(t *testing.T) { //connect the nodes log.Info("Adding nodes to simulation") - _, err := sim.AddNodesAndConnectChain(2) + ids, err := sim.AddNodes(2) if err != nil { t.Fatal(err) } + if err := sim.Net.ConnectNodesChain(ids); err != nil { + t.Fatal(err) + } log.Info("Starting simulation") ctx := context.Background() diff --git a/swarm/network_test.go b/swarm/network_test.go index 8a162a219e..54b34a77ff 100644 --- a/swarm/network_test.go +++ b/swarm/network_test.go @@ -316,10 +316,7 @@ func testSwarmNetwork(t *testing.T, o *testSwarmNetworkOptions, steps ...testSwa change := step.nodeCount - len(sim.UpNodeIDs()) if change > 0 { - _, err := sim.AddNodesAndConnectChain(change) - if err != nil { - t.Fatal(err) - } + addNodesChain(t, sim, change) } else if change < 0 { _, err := sim.StopRandomNodes(-change) if err != nil { @@ -374,6 +371,34 @@ func testSwarmNetwork(t *testing.T, o *testSwarmNetworkOptions, steps ...testSwa } } +func addNodesChain(t *testing.T, s *simulation.Simulation, increment int) { + t.Helper() + + if increment < 1 { + t.Fatalf("change must be positive (increment: %v)", increment) + } + + oldNodeIDs := s.UpNodeIDs() + + newNodeIDs, err := s.AddNodes(increment) + if err != nil { + t.Fatal(err) + } + + if err := s.Net.ConnectNodesChain(newNodeIDs); err != nil { + t.Fatal(err) + } + + // If we had old nodes, then our cluster is split into two now. + // Let's connect the two components and preserve chain topology. + if len(oldNodeIDs) > 0 { + lastOld := oldNodeIDs[len(oldNodeIDs)-1] + if err := s.Net.Connect(lastOld, newNodeIDs[0]); err != nil { + t.Fatal(err) + } + } +} + // uploadFile, uploads a short file to the swarm instance // using the api.Put method. func uploadFile(swarm *Swarm) (storage.Address, string, error) {