mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
p2p/simulations: Add node property (e.g bootnode, etc) support to simulation networks + Expanded node getter utility functions
This commit is contained in:
parent
cf8d752c41
commit
d7bc2a8ad1
3 changed files with 304 additions and 279 deletions
|
|
@ -89,12 +89,6 @@ type NodeConfig struct {
|
|||
// Enable peer events for Msgs
|
||||
EnableMsgEvents bool
|
||||
|
||||
// Node will run services as a bootnode
|
||||
BootNode bool
|
||||
|
||||
// Node will run services as a lightnode
|
||||
LightNode bool
|
||||
|
||||
// Name is a human friendly name for the node like "node01"
|
||||
Name string
|
||||
|
||||
|
|
@ -107,6 +101,11 @@ type NodeConfig struct {
|
|||
// services registered by calling the RegisterService function)
|
||||
Services []string
|
||||
|
||||
// Properties are the names of the properties this node should hold
|
||||
// within running services (e.g. "bootnode", "lightnode" or any custom values)
|
||||
// These values need to be checked and acted upon by node Services
|
||||
Properties []string
|
||||
|
||||
// Enode
|
||||
node *enode.Node
|
||||
|
||||
|
|
@ -126,9 +125,8 @@ type nodeConfigJSON struct {
|
|||
PrivateKey string `json:"private_key"`
|
||||
Name string `json:"name"`
|
||||
Services []string `json:"services"`
|
||||
Properties []string `json:"properties"`
|
||||
EnableMsgEvents bool `json:"enable_msg_events"`
|
||||
BootNode bool `json:"bootnode"`
|
||||
LightNode bool `json:"lightnode"`
|
||||
Port uint16 `json:"port"`
|
||||
}
|
||||
|
||||
|
|
@ -139,10 +137,9 @@ func (n *NodeConfig) MarshalJSON() ([]byte, error) {
|
|||
ID: n.ID.String(),
|
||||
Name: n.Name,
|
||||
Services: n.Services,
|
||||
Properties: n.Properties,
|
||||
Port: n.Port,
|
||||
EnableMsgEvents: n.EnableMsgEvents,
|
||||
BootNode: n.BootNode,
|
||||
LightNode: n.LightNode,
|
||||
}
|
||||
if n.PrivateKey != nil {
|
||||
confJSON.PrivateKey = hex.EncodeToString(crypto.FromECDSA(n.PrivateKey))
|
||||
|
|
@ -178,10 +175,9 @@ func (n *NodeConfig) UnmarshalJSON(data []byte) error {
|
|||
|
||||
n.Name = confJSON.Name
|
||||
n.Services = confJSON.Services
|
||||
n.Properties = confJSON.Properties
|
||||
n.Port = confJSON.Port
|
||||
n.EnableMsgEvents = confJSON.EnableMsgEvents
|
||||
n.BootNode = confJSON.BootNode
|
||||
n.LightNode = confJSON.LightNode
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,9 +56,8 @@ type Network struct {
|
|||
Nodes []*Node `json:"nodes"`
|
||||
nodeMap map[enode.ID]int
|
||||
|
||||
// Node subtypes are also mapped separately, so they can be distinguished quickly
|
||||
bootNodeMap map[enode.ID]int
|
||||
lightNodeMap map[enode.ID]int
|
||||
// Maps a node property string to node indexes of all nodes that hold this property
|
||||
propertyMap map[string][]int
|
||||
|
||||
Conns []*Conn `json:"conns"`
|
||||
connMap map[string]int
|
||||
|
|
@ -75,8 +74,7 @@ func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network
|
|||
NetworkConfig: *conf,
|
||||
nodeAdapter: nodeAdapter,
|
||||
nodeMap: make(map[enode.ID]int),
|
||||
bootNodeMap: make(map[enode.ID]int),
|
||||
lightNodeMap: make(map[enode.ID]int),
|
||||
propertyMap: make(map[string][]int),
|
||||
connMap: make(map[string]int),
|
||||
quitc: make(chan struct{}),
|
||||
}
|
||||
|
|
@ -128,15 +126,14 @@ func (net *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error)
|
|||
log.Trace("Node created", "id", conf.ID)
|
||||
|
||||
nodeIndex := len(net.Nodes)
|
||||
if conf.BootNode {
|
||||
net.bootNodeMap[conf.ID] = nodeIndex
|
||||
} else if conf.LightNode {
|
||||
net.lightNodeMap[conf.ID] = nodeIndex
|
||||
}
|
||||
|
||||
net.nodeMap[conf.ID] = nodeIndex
|
||||
net.Nodes = append(net.Nodes, node)
|
||||
|
||||
// Register any node properties with the network-level propertyMap
|
||||
for _, property := range conf.Properties {
|
||||
net.propertyMap[property] = append(net.propertyMap[property], nodeIndex)
|
||||
}
|
||||
|
||||
// emit a "control" event
|
||||
net.events.Send(ControlEvent(node))
|
||||
|
||||
|
|
@ -424,7 +421,7 @@ func (net *Network) getNode(id enode.ID) *Node {
|
|||
return net.Nodes[i]
|
||||
}
|
||||
|
||||
// GetNode gets the node with the given name, returning nil if the node does
|
||||
// GetNodeByName gets the node with the given name, returning nil if the node does
|
||||
// not exist
|
||||
func (net *Network) GetNodeByName(name string) *Node {
|
||||
net.lock.RLock()
|
||||
|
|
@ -441,6 +438,30 @@ func (net *Network) getNodeByName(name string) *Node {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetNodeIDs returns the IDs of all existing nodes
|
||||
// Nodes can optionally be excluded by specifying their enode.ID.
|
||||
func (net *Network) GetNodeIDs(excludeIDs ...enode.ID) []enode.ID {
|
||||
net.lock.RLock()
|
||||
defer net.lock.RUnlock()
|
||||
|
||||
return net.getNodeIDs(excludeIDs)
|
||||
}
|
||||
|
||||
func (net *Network) getNodeIDs(excludeIDs []enode.ID) []enode.ID {
|
||||
// Get all curent nodeIDs
|
||||
nodeIDs := make([]enode.ID, 0, len(net.nodeMap))
|
||||
for id := range net.nodeMap {
|
||||
nodeIDs = append(nodeIDs, id)
|
||||
}
|
||||
|
||||
if len(excludeIDs) > 0 {
|
||||
// Return the difference of nodeIDs and excludeIDs
|
||||
return filterIDs(nodeIDs, excludeIDs)
|
||||
} else {
|
||||
return nodeIDs
|
||||
}
|
||||
}
|
||||
|
||||
// GetNodes returns the existing nodes.
|
||||
// Nodes can optionally be excluded by specifying their enode.ID.
|
||||
func (net *Network) GetNodes(excludeIDs ...enode.ID) []*Node {
|
||||
|
|
@ -452,15 +473,8 @@ func (net *Network) GetNodes(excludeIDs ...enode.ID) []*Node {
|
|||
|
||||
func (net *Network) getNodes(excludeIDs []enode.ID) []*Node {
|
||||
if len(excludeIDs) > 0 {
|
||||
// Get all curent nodeIDs
|
||||
nodeIDs := make([]enode.ID, 0, len(net.nodeMap))
|
||||
for id := range net.nodeMap {
|
||||
nodeIDs = append(nodeIDs, id)
|
||||
}
|
||||
|
||||
// Return the difference of nodeIDs and excludeIDs
|
||||
filteredIDs := filterIDs(nodeIDs, excludeIDs)
|
||||
return net.getNodesByID(filteredIDs)
|
||||
nodeIDs := net.getNodeIDs(excludeIDs)
|
||||
return net.getNodesByID(nodeIDs)
|
||||
} else {
|
||||
return net.Nodes
|
||||
}
|
||||
|
|
@ -487,116 +501,39 @@ func (net *Network) getNodesByID(nodeIDs []enode.ID) []*Node {
|
|||
return nodes
|
||||
}
|
||||
|
||||
// GetBootNodes returns all configured bootnodes in the network.
|
||||
func (net *Network) GetBootNodes() []*Node {
|
||||
// GetNodesByProperty returns existing nodes that have the given property string registered in their NodeConfig
|
||||
func (net *Network) GetNodesByProperty(property string) []*Node {
|
||||
net.lock.RLock()
|
||||
defer net.lock.RUnlock()
|
||||
|
||||
return net.getBootNodes()
|
||||
return net.getNodesByProperty(property)
|
||||
}
|
||||
|
||||
func (net *Network) getBootNodes() []*Node {
|
||||
bootNodes := make([]*Node, 0, len(net.bootNodeMap))
|
||||
for _, i := range net.bootNodeMap {
|
||||
bootNodes = append(bootNodes, net.Nodes[i])
|
||||
func (net *Network) getNodesByProperty(property string) []*Node {
|
||||
nodes := make([]*Node, 0, len(net.propertyMap[property]))
|
||||
for _, nodeIndex := range net.propertyMap[property] {
|
||||
nodes = append(nodes, net.Nodes[nodeIndex])
|
||||
}
|
||||
|
||||
return bootNodes
|
||||
return nodes
|
||||
}
|
||||
|
||||
// GetBootNodeIDs returns a slice of all bootnode enode.ID
|
||||
func (net *Network) GetBootNodeIDs() []enode.ID {
|
||||
// GetNodeIDsByProperty returns existing node's enode IDs that have the given property string registered in the NodeConfig
|
||||
func (net *Network) GetNodeIDsByProperty(property string) []enode.ID {
|
||||
net.lock.RLock()
|
||||
defer net.lock.RUnlock()
|
||||
|
||||
return net.getBootNodeIDs()
|
||||
return net.getNodeIDsByProperty(property)
|
||||
}
|
||||
|
||||
func (net *Network) getBootNodeIDs() []enode.ID {
|
||||
bootNodeIDs := make([]enode.ID, 0, len(net.bootNodeMap))
|
||||
for id := range net.bootNodeMap {
|
||||
bootNodeIDs = append(bootNodeIDs, id)
|
||||
func (net *Network) getNodeIDsByProperty(property string) []enode.ID {
|
||||
nodeIDs := make([]enode.ID, 0, len(net.propertyMap[property]))
|
||||
for _, nodeIndex := range net.propertyMap[property] {
|
||||
node := net.Nodes[nodeIndex]
|
||||
nodeIDs = append(nodeIDs, node.ID())
|
||||
}
|
||||
|
||||
return bootNodeIDs
|
||||
}
|
||||
|
||||
// GetLightNodes returns all configured light nodes in the network.
|
||||
func (net *Network) GetLightNodes() []*Node {
|
||||
net.lock.RLock()
|
||||
defer net.lock.RUnlock()
|
||||
|
||||
return net.getLightNodes()
|
||||
}
|
||||
|
||||
func (net *Network) getLightNodes() []*Node {
|
||||
lightNodes := make([]*Node, 0, len(net.lightNodeMap))
|
||||
for _, i := range net.lightNodeMap {
|
||||
lightNodes = append(lightNodes, net.Nodes[i])
|
||||
}
|
||||
|
||||
return lightNodes
|
||||
}
|
||||
|
||||
// GetLightNodeIDs returns a slice of all light node enode.ID
|
||||
func (net *Network) GetLightNodeIDs() []enode.ID {
|
||||
net.lock.RLock()
|
||||
defer net.lock.RUnlock()
|
||||
|
||||
return net.getLightNodeIDs()
|
||||
}
|
||||
|
||||
func (net *Network) getLightNodeIDs() []enode.ID {
|
||||
lightNodeIDs := make([]enode.ID, 0, len(net.lightNodeMap))
|
||||
for id := range net.lightNodeMap {
|
||||
lightNodeIDs = append(lightNodeIDs, id)
|
||||
}
|
||||
|
||||
return lightNodeIDs
|
||||
}
|
||||
|
||||
// GetFullNodes returns all configured full nodes in the network.
|
||||
// This excludes bootnodes and lightnodes.
|
||||
func (net *Network) GetFullNodes() []*Node {
|
||||
net.lock.RLock()
|
||||
defer net.lock.RUnlock()
|
||||
|
||||
return net.getFullNodes()
|
||||
}
|
||||
|
||||
// Collect the enode.IDs of all nodes types that are not full nodes and provide them to getNodes for exclusion
|
||||
func (net *Network) getFullNodes() []*Node {
|
||||
excludeNodeCount := len(net.lightNodeMap) + len(net.bootNodeMap)
|
||||
excludeIDs := make([]enode.ID, 0, excludeNodeCount)
|
||||
for ID := range net.lightNodeMap {
|
||||
excludeIDs = append(excludeIDs, ID)
|
||||
}
|
||||
|
||||
for ID := range net.bootNodeMap {
|
||||
excludeIDs = append(excludeIDs, ID)
|
||||
}
|
||||
|
||||
return net.getNodes(excludeIDs)
|
||||
}
|
||||
|
||||
// GetFullNodeIDs returns a slice of all full node enode.ID
|
||||
func (net *Network) GetFullNodeIDs() []enode.ID {
|
||||
net.lock.RLock()
|
||||
defer net.lock.RUnlock()
|
||||
|
||||
return net.getFullNodeIDs()
|
||||
}
|
||||
|
||||
func (net *Network) getFullNodeIDs() []enode.ID {
|
||||
// The number of full nodes is the total number minus all sub mapping counts
|
||||
fullNodeCount := len(net.nodeMap) - len(net.lightNodeMap) - len(net.bootNodeMap)
|
||||
fullNodeIDs := make([]enode.ID, 0, fullNodeCount)
|
||||
|
||||
for _, node := range net.getFullNodes() {
|
||||
fullNodeIDs = append(fullNodeIDs, node.ID())
|
||||
}
|
||||
|
||||
return fullNodeIDs
|
||||
return nodeIDs
|
||||
}
|
||||
|
||||
// GetRandomUpNode returns a random node on the network, which is running.
|
||||
|
|
@ -636,6 +573,13 @@ func (net *Network) getDownNodeIDs() (ids []enode.ID) {
|
|||
return ids
|
||||
}
|
||||
|
||||
// GetRandomNode returns a random node on the network, regardless of whether it is running or not
|
||||
func (net *Network) GetRandomNode(excludeIDs ...enode.ID) *Node {
|
||||
net.lock.RLock()
|
||||
defer net.lock.RUnlock()
|
||||
return net.getRandomNode(net.getNodeIDs(nil), excludeIDs) // no need to exclude twice
|
||||
}
|
||||
|
||||
func (net *Network) getRandomNode(ids []enode.ID, excludeIDs []enode.ID) *Node {
|
||||
filtered := filterIDs(ids, excludeIDs)
|
||||
|
||||
|
|
@ -775,8 +719,7 @@ func (net *Network) Reset() {
|
|||
//re-initialize the maps
|
||||
net.connMap = make(map[string]int)
|
||||
net.nodeMap = make(map[enode.ID]int)
|
||||
net.bootNodeMap = make(map[enode.ID]int)
|
||||
net.lightNodeMap = make(map[enode.ID]int)
|
||||
net.propertyMap = make(map[string][]int)
|
||||
|
||||
net.Nodes = nil
|
||||
net.Conns = nil
|
||||
|
|
@ -795,12 +738,14 @@ type Node struct {
|
|||
upMu sync.RWMutex
|
||||
}
|
||||
|
||||
// Up returns whether the node is currently up (online)
|
||||
func (n *Node) Up() bool {
|
||||
n.upMu.RLock()
|
||||
defer n.upMu.RUnlock()
|
||||
return n.up
|
||||
}
|
||||
|
||||
// SetUp sets the up (online) status of the nodes with the given value
|
||||
func (n *Node) SetUp(up bool) {
|
||||
n.upMu.Lock()
|
||||
defer n.upMu.Unlock()
|
||||
|
|
|
|||
|
|
@ -394,10 +394,46 @@ func TestNetworkSimulation(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestMultiNodeRetrieval creates a multi-node simulation network.
|
||||
// Full nodes, bootnodes and lightnodes are created.
|
||||
// Functions for retrieving specific subgroups of nodes are then tested for correctness.
|
||||
func TestMultiNodeRetrieval(t *testing.T) {
|
||||
func createTestNodes(count int, network *Network) (nodes []*Node, err error) {
|
||||
for i := 0; i < count; i++ {
|
||||
nodeConf := adapters.RandomNodeConfig()
|
||||
node, err := network.NewNodeWithConfig(nodeConf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := network.Start(node.ID()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func createTestNodesWithProperty(property string, count int, network *Network) (propertyNodes []*Node, err error) {
|
||||
for i := 0; i < count; i++ {
|
||||
nodeConf := adapters.RandomNodeConfig()
|
||||
nodeConf.Properties = append(nodeConf.Properties, property)
|
||||
|
||||
node, err := network.NewNodeWithConfig(nodeConf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := network.Start(node.ID()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
propertyNodes = append(propertyNodes, node)
|
||||
}
|
||||
|
||||
return propertyNodes, nil
|
||||
}
|
||||
|
||||
// TestGetNodeIDs creates a set of nodes and attempts to retrieve their IDs,.
|
||||
// It then tests again whilst excluding a node ID from being returned.
|
||||
// If a node ID is not returned, or more node IDs than expected are returned, the test fails.
|
||||
func TestGetNodeIDs(t *testing.T) {
|
||||
adapter := adapters.NewSimAdapter(adapters.Services{
|
||||
"test": newTestService,
|
||||
})
|
||||
|
|
@ -406,98 +442,215 @@ func TestMultiNodeRetrieval(t *testing.T) {
|
|||
})
|
||||
defer network.Shutdown()
|
||||
|
||||
// Create a bootnode
|
||||
bootNodeConf := adapters.RandomNodeConfig()
|
||||
bootNodeConf.BootNode = true
|
||||
bootNode, err := network.NewNodeWithConfig(bootNodeConf)
|
||||
numNodes := 5
|
||||
nodes, err := createTestNodes(numNodes, network)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating bootnode: %s", err)
|
||||
}
|
||||
if err := network.Start(bootNode.ID()); err != nil {
|
||||
t.Fatalf("error starting bootnode: %s", err)
|
||||
t.Fatalf("Could not creat test nodes %v", err)
|
||||
}
|
||||
|
||||
// Create 20 light nodes
|
||||
lightNodeCount := 20
|
||||
lightNodes := make(map[enode.ID]*Node, lightNodeCount)
|
||||
for i := 0; i < lightNodeCount; i++ {
|
||||
conf := adapters.RandomNodeConfig()
|
||||
conf.LightNode = true
|
||||
node, err := network.NewNodeWithConfig(conf)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating light node: %s", err)
|
||||
}
|
||||
if err := network.Start(node.ID()); err != nil {
|
||||
t.Fatalf("error starting light node: %s", err)
|
||||
}
|
||||
lightNodes[node.ID()] = node
|
||||
gotNodeIDs := network.GetNodeIDs()
|
||||
if len(gotNodeIDs) != numNodes {
|
||||
t.Fatalf("Expected %d nodes, got %d", numNodes, len(gotNodeIDs))
|
||||
}
|
||||
|
||||
// Create 20 full nodes
|
||||
fullNodeCount := 20
|
||||
fullNodes := make(map[enode.ID]*Node, fullNodeCount)
|
||||
for i := 0; i < fullNodeCount; i++ {
|
||||
conf := adapters.RandomNodeConfig()
|
||||
node, err := network.NewNodeWithConfig(conf)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating node: %s", err)
|
||||
}
|
||||
if err := network.Start(node.ID()); err != nil {
|
||||
t.Fatalf("error starting node: %s", err)
|
||||
}
|
||||
fullNodes[node.ID()] = node
|
||||
}
|
||||
|
||||
// Check that network.GetBootNodes returns the boot node we created and only that bootnode
|
||||
bootNodes := network.GetBootNodes()
|
||||
if len(bootNodes) == 0 {
|
||||
t.Fatal("GetBootNodes returned empty when size of one was expected")
|
||||
}
|
||||
|
||||
for _, bn := range bootNodes {
|
||||
if !bytes.Equal(bn.ID().Bytes(), bootNode.ID().Bytes()) {
|
||||
t.Fatalf("Found an unexpected node in GetBootNodes: %s", bn.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the boot node's ID is the only one returned by GetBoodNodeIDs()
|
||||
// If a non-matching ID is found, the test fails
|
||||
bootNodeIDs := network.GetBootNodeIDs()
|
||||
if len(bootNodeIDs) == 0 {
|
||||
t.Fatal("GetBootNodeIDs returned empty when one ID was expected")
|
||||
}
|
||||
|
||||
for _, id := range bootNodeIDs {
|
||||
if !bytes.Equal(id.Bytes(), bootNode.ID().Bytes()) {
|
||||
t.Fatalf("Found an unexpected enode.ID in GetBootNodeIDs: %s", id.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Check that each of lightNodes (the light nodes we just created) are available from the GetLightNodes method.
|
||||
// If a light node isn't found in GetLightNodes, the test fails.
|
||||
for _, ln1 := range lightNodes {
|
||||
for _, node1 := range nodes {
|
||||
match := false
|
||||
lightNode1IDBytes := ln1.ID().Bytes()
|
||||
|
||||
for _, ln2 := range network.GetLightNodes() {
|
||||
lightNode2IDBytes := ln2.ID().Bytes()
|
||||
if bytes.Equal(lightNode1IDBytes, lightNode2IDBytes) {
|
||||
for _, node2ID := range gotNodeIDs {
|
||||
if bytes.Equal(node1.ID().Bytes(), node2ID.Bytes()) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !match {
|
||||
t.Fatalf("A created light node was not returned by GetLightNodes(), ID: %s", ln1.ID().String())
|
||||
t.Fatalf("A created node was not returned by GetNodes(), ID: %s", node1.ID().String())
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the IDs of each of fullNodes are returned by GetFullNodeIDs()
|
||||
// If a full not isn't found in GetFullNodeIDs(), the test fails
|
||||
lightNodeIDs := network.GetLightNodeIDs()
|
||||
for id1 := range lightNodes {
|
||||
excludeNodeID := nodes[3].ID()
|
||||
gotNodeIDsExcl := network.GetNodeIDs(excludeNodeID)
|
||||
if len(gotNodeIDsExcl) != numNodes-1 {
|
||||
t.Fatalf("Expected one less node ID to be returned")
|
||||
}
|
||||
for _, nodeID := range gotNodeIDsExcl {
|
||||
if bytes.Equal(excludeNodeID.Bytes(), nodeID.Bytes()) {
|
||||
t.Fatalf("GetNodeIDs returned the node ID we excluded, ID: %s", nodeID.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetNodes creates a set of nodes and attempts to retrieve them again.
|
||||
// It then tests again whilst excluding a node from being returned.
|
||||
// If a node is not returned, or more nodes than expected are returned, the test fails.
|
||||
func TestGetNodes(t *testing.T) {
|
||||
adapter := adapters.NewSimAdapter(adapters.Services{
|
||||
"test": newTestService,
|
||||
})
|
||||
network := NewNetwork(adapter, &NetworkConfig{
|
||||
DefaultService: "test",
|
||||
})
|
||||
defer network.Shutdown()
|
||||
|
||||
numNodes := 5
|
||||
nodes, err := createTestNodes(numNodes, network)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not creat test nodes %v", err)
|
||||
}
|
||||
|
||||
gotNodes := network.GetNodes()
|
||||
if len(gotNodes) != numNodes {
|
||||
t.Fatalf("Expected %d nodes, got %d", numNodes, len(gotNodes))
|
||||
}
|
||||
|
||||
for _, node1 := range nodes {
|
||||
match := false
|
||||
for _, id2 := range lightNodeIDs {
|
||||
for _, node2 := range gotNodes {
|
||||
if bytes.Equal(node1.ID().Bytes(), node2.ID().Bytes()) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !match {
|
||||
t.Fatalf("A created node was not returned by GetNodes(), ID: %s", node1.ID().String())
|
||||
}
|
||||
}
|
||||
|
||||
excludeNodeID := nodes[3].ID()
|
||||
gotNodesExcl := network.GetNodes(excludeNodeID)
|
||||
if len(gotNodesExcl) != numNodes-1 {
|
||||
t.Fatalf("Expected one less node to be returned")
|
||||
}
|
||||
for _, node := range gotNodesExcl {
|
||||
if bytes.Equal(excludeNodeID.Bytes(), node.ID().Bytes()) {
|
||||
t.Fatalf("GetNodes returned the node we excluded, ID: %s", node.ID().String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetNodesByID creates a set of nodes and attempts to retrieve a subset of them by ID
|
||||
// If a node is not returned, or more nodes than expected are returned, the test fails.
|
||||
func TestGetNodesByID(t *testing.T) {
|
||||
adapter := adapters.NewSimAdapter(adapters.Services{
|
||||
"test": newTestService,
|
||||
})
|
||||
network := NewNetwork(adapter, &NetworkConfig{
|
||||
DefaultService: "test",
|
||||
})
|
||||
defer network.Shutdown()
|
||||
|
||||
numNodes := 5
|
||||
nodes, err := createTestNodes(numNodes, network)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create test nodes: %v", err)
|
||||
}
|
||||
|
||||
numSubsetNodes := 2
|
||||
subsetNodes := nodes[0:numSubsetNodes]
|
||||
var subsetNodeIDs []enode.ID
|
||||
for _, node := range subsetNodes {
|
||||
subsetNodeIDs = append(subsetNodeIDs, node.ID())
|
||||
}
|
||||
|
||||
gotNodesByID := network.GetNodesByID(subsetNodeIDs)
|
||||
if len(gotNodesByID) != numSubsetNodes {
|
||||
t.Fatalf("Expected %d nodes, got %d", numSubsetNodes, len(gotNodesByID))
|
||||
}
|
||||
|
||||
for _, node1 := range subsetNodes {
|
||||
match := false
|
||||
for _, node2 := range gotNodesByID {
|
||||
if bytes.Equal(node1.ID().Bytes(), node2.ID().Bytes()) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !match {
|
||||
t.Fatalf("A created node was not returned by GetNodesByID(), ID: %s", node1.ID().String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetNodesByProperty creates a subset of nodes with a property assigned.
|
||||
// GetNodesByProperty is then checked for correctness by comparing the nodes returned to those initially created.
|
||||
// If a node with a property is not found, or more nodes than expected are returned, the test fails.
|
||||
func TestGetNodesByProperty(t *testing.T) {
|
||||
adapter := adapters.NewSimAdapter(adapters.Services{
|
||||
"test": newTestService,
|
||||
})
|
||||
network := NewNetwork(adapter, &NetworkConfig{
|
||||
DefaultService: "test",
|
||||
})
|
||||
defer network.Shutdown()
|
||||
|
||||
numNodes := 3
|
||||
_, err := createTestNodes(numNodes, network)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create nodes: %v", err)
|
||||
}
|
||||
|
||||
numPropertyNodes := 3
|
||||
propertyTest := "test"
|
||||
propertyNodes, err := createTestNodesWithProperty(propertyTest, numPropertyNodes, network)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create nodes with property: %v", err)
|
||||
}
|
||||
|
||||
gotNodesByProperty := network.GetNodesByProperty(propertyTest)
|
||||
if len(gotNodesByProperty) != numPropertyNodes {
|
||||
t.Fatalf("Expected %d nodes with a property, got %d", numPropertyNodes, len(gotNodesByProperty))
|
||||
}
|
||||
|
||||
for _, node1 := range propertyNodes {
|
||||
match := false
|
||||
for _, node2 := range gotNodesByProperty {
|
||||
if bytes.Equal(node1.ID().Bytes(), node2.ID().Bytes()) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !match {
|
||||
t.Fatalf("A created node with property was not returned by GetNodesByProperty(), ID: %s", node1.ID().String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetNodeIDsByProperty creates a subset of nodes with a property assigned.
|
||||
// GetNodeIDsByProperty is then checked for correctness by comparing the node IDs returned to those initially created.
|
||||
// If a node ID with a property is not found, or more nodes IDs than expected are returned, the test fails.
|
||||
func TestGetNodeIDsByProperty(t *testing.T) {
|
||||
adapter := adapters.NewSimAdapter(adapters.Services{
|
||||
"test": newTestService,
|
||||
})
|
||||
network := NewNetwork(adapter, &NetworkConfig{
|
||||
DefaultService: "test",
|
||||
})
|
||||
defer network.Shutdown()
|
||||
|
||||
numNodes := 3
|
||||
_, err := createTestNodes(numNodes, network)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create nodes: %v", err)
|
||||
}
|
||||
|
||||
numPropertyNodes := 3
|
||||
propertyTest := "test"
|
||||
propertyNodes, err := createTestNodesWithProperty(propertyTest, numPropertyNodes, network)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to created nodes with property: %v", err)
|
||||
}
|
||||
|
||||
gotNodeIDsByProperty := network.GetNodeIDsByProperty(propertyTest)
|
||||
if len(gotNodeIDsByProperty) != numPropertyNodes {
|
||||
t.Fatalf("Expected %d nodes with a property, got %d", numPropertyNodes, len(gotNodeIDsByProperty))
|
||||
}
|
||||
|
||||
for _, node1 := range propertyNodes {
|
||||
match := false
|
||||
id1 := node1.ID()
|
||||
for _, id2 := range gotNodeIDsByProperty {
|
||||
if bytes.Equal(id1.Bytes(), id2.Bytes()) {
|
||||
match = true
|
||||
break
|
||||
|
|
@ -505,76 +658,7 @@ func TestMultiNodeRetrieval(t *testing.T) {
|
|||
}
|
||||
|
||||
if !match {
|
||||
t.Fatalf("Not all light nodes were returned by GetLightNodeIDs(), ID: %s", id1.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Check that each of fullNodes (the full nodes we just created) are available from the GetFullNodes method.
|
||||
// If a full node isn't found in GetFullNodes, the test fails.
|
||||
for _, fn1 := range fullNodes {
|
||||
match := false
|
||||
fullNode1IDBytes := fn1.ID().Bytes()
|
||||
|
||||
for _, fn2 := range network.GetFullNodes() {
|
||||
fullNode2IDBytes := fn2.ID().Bytes()
|
||||
if bytes.Equal(fullNode1IDBytes, fullNode2IDBytes) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !match {
|
||||
t.Fatalf("A created full node was not returned by GetFullNodes(), ID: %s", fn1.ID().String())
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the IDs of each of fullNodes are returned by GetFullNodeIDs()
|
||||
// If a full not isn't found in GetFullNodeIDs(), the test fails
|
||||
fullNodeIDs := network.GetFullNodeIDs()
|
||||
for id1 := range fullNodes {
|
||||
match := false
|
||||
for _, id2 := range fullNodeIDs {
|
||||
if bytes.Equal(id1.Bytes(), id2.Bytes()) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !match {
|
||||
t.Fatalf("Not all full nodes were returned by GetFullNodeIDs(), ID: %s", id1.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Get all nodes, excluding the bootnode by passing the bootnode ID.
|
||||
// Checks that the bootnode is excluded as expected and fails the test if not.
|
||||
nodesExclBootNode := network.GetNodes(bootNode.ID())
|
||||
for _, node := range nodesExclBootNode {
|
||||
if bytes.Equal(node.ID().Bytes(), bootNode.ID().Bytes()) {
|
||||
t.Fatalf("Bootnode still found in GetNodes when it has been explicitly excluded.")
|
||||
}
|
||||
}
|
||||
|
||||
// Get all node IDs and call GetNodesByID using them.
|
||||
// The test then confirms that the nodes returned from GetNodes() match those returned from GetNodesByID(allIDs)
|
||||
var nodeIDs []enode.ID
|
||||
for _, node := range network.GetNodes() {
|
||||
nodeIDs = append(nodeIDs, node.ID())
|
||||
}
|
||||
|
||||
nodesByID := network.GetNodesByID(nodeIDs)
|
||||
for _, node1 := range network.GetNodes() {
|
||||
match := false
|
||||
node1IDBytes := node1.ID().Bytes()
|
||||
for _, node2 := range nodesByID {
|
||||
node2IDBytes := node2.ID().Bytes()
|
||||
if bytes.Equal(node1IDBytes, node2IDBytes) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !match {
|
||||
t.Fatalf("A node was found in GetNodes() that was not returned by GetNodesByID() for all node IDs")
|
||||
t.Fatalf("Not all nodes IDs were returned by GetNodeIDsByProperty(), ID: %s", id1.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue