mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
swarm/network/stream: refactored TestGetSubscriptionsRPC
This commit is contained in:
parent
072b42eb37
commit
180c33bd67
1 changed files with 70 additions and 65 deletions
|
|
@ -23,15 +23,21 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"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/enode"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
||||||
p2ptest "github.com/ethereum/go-ethereum/p2p/testing"
|
p2ptest "github.com/ethereum/go-ethereum/p2p/testing"
|
||||||
"github.com/ethereum/go-ethereum/swarm/network"
|
"github.com/ethereum/go-ethereum/swarm/network"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/network/simulation"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/state"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1120,20 +1126,32 @@ func TestRequestPeerSubscriptions(t *testing.T) {
|
||||||
TestGetSubscriptionsRPC sets up a simulation network of 16 nodes,
|
TestGetSubscriptionsRPC sets up a simulation network of 16 nodes,
|
||||||
starts the simulation, waits for SyncUpdateDelay in order to kick off
|
starts the simulation, waits for SyncUpdateDelay in order to kick off
|
||||||
stream registration, then tests that there are subscriptions.
|
stream registration, then tests that there are subscriptions.
|
||||||
If provided with the `-printstats = true` option, it will print
|
|
||||||
the information of who is subscribed to who to STDOUT
|
|
||||||
*/
|
*/
|
||||||
func TestGetSubscriptionsRPC(t *testing.T) {
|
func TestGetSubscriptionsRPC(t *testing.T) {
|
||||||
//arbitrarily set to 16
|
// arbitrarily set to 16
|
||||||
nodeCount := 16
|
nodeCount := 16
|
||||||
//set the syncUpdateDelay for sync registrations to start
|
// set the syncUpdateDelay for sync registrations to start
|
||||||
syncUpdateDelay := 500 * time.Millisecond
|
syncUpdateDelay := 500 * time.Millisecond
|
||||||
//we will later need the kad table for each node
|
// holds the msg code for SubscribeMsg
|
||||||
bucketKeyKad := simulation.BucketKey("kademlia")
|
|
||||||
//holds the msg code for SubscribeMsg
|
|
||||||
var subscribeMsgCode uint64
|
var subscribeMsgCode uint64
|
||||||
var ok bool
|
var ok bool
|
||||||
//create a standard sim
|
var expectedMsgCount = 0
|
||||||
|
|
||||||
|
// this channel signalizes that the expected amount of subscriptiosn is done
|
||||||
|
allSubscriptionsDone := make(chan struct{})
|
||||||
|
lock := sync.RWMutex{}
|
||||||
|
// after the test, we need to reset the subscriptionFunc to the default
|
||||||
|
defer func() { subscriptionFunc = doRequestSubscription }()
|
||||||
|
|
||||||
|
// we use this subscriptionFunc for this test: just increases count and calls the actual subscription
|
||||||
|
subscriptionFunc = func(r *Registry, p *network.Peer, bin uint8, subs map[enode.ID]map[Stream]struct{}) bool {
|
||||||
|
lock.Lock()
|
||||||
|
expectedMsgCount++
|
||||||
|
lock.Unlock()
|
||||||
|
doRequestSubscription(r, p, bin, subs)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// create a standard sim
|
||||||
sim := simulation.New(map[string]simulation.ServiceFunc{
|
sim := simulation.New(map[string]simulation.ServiceFunc{
|
||||||
"streamer": func(ctx *adapters.ServiceContext, bucket *sync.Map) (s node.Service, cleanup func(), err error) {
|
"streamer": func(ctx *adapters.ServiceContext, bucket *sync.Map) (s node.Service, cleanup func(), err error) {
|
||||||
n := ctx.Config.Node()
|
n := ctx.Config.Node()
|
||||||
|
|
@ -1148,23 +1166,20 @@ func TestGetSubscriptionsRPC(t *testing.T) {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
kad := network.NewKademlia(addr.Over(), network.NewKadParams())
|
kad := network.NewKademlia(addr.Over(), network.NewKadParams())
|
||||||
//store the kad table
|
|
||||||
bucket.Store(bucketKeyKad, kad)
|
|
||||||
delivery := NewDelivery(kad, netStore)
|
delivery := NewDelivery(kad, netStore)
|
||||||
netStore.NewNetFetcherFunc = network.NewFetcherFactory(dummyRequestFromPeers, true).New
|
netStore.NewNetFetcherFunc = network.NewFetcherFactory(dummyRequestFromPeers, true).New
|
||||||
//configure so that sync registrations actually happen
|
// configure so that sync registrations actually happen
|
||||||
r := NewRegistry(addr.ID(), delivery, netStore, state.NewInmemoryStore(), &RegistryOptions{
|
r := NewRegistry(addr.ID(), delivery, netStore, state.NewInmemoryStore(), &RegistryOptions{
|
||||||
Retrieval: RetrievalEnabled,
|
Retrieval: RetrievalEnabled,
|
||||||
Syncing: SyncingAutoSubscribe, //enable sync registrations
|
Syncing: SyncingAutoSubscribe, //enable sync registrations
|
||||||
SyncUpdateDelay: syncUpdateDelay,
|
SyncUpdateDelay: syncUpdateDelay,
|
||||||
}, nil)
|
}, nil)
|
||||||
//get the SubscribeMsg code
|
// get the SubscribeMsg code
|
||||||
subscribeMsgCode, ok = r.GetSpec().GetCode(SubscribeMsg{})
|
subscribeMsgCode, ok = r.GetSpec().GetCode(SubscribeMsg{})
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("Message code for SubscribeMsg not found")
|
t.Fatal("Message code for SubscribeMsg not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
bucket.Store(bucketKeyRegistry, r)
|
|
||||||
cleanup = func() {
|
cleanup = func() {
|
||||||
os.RemoveAll(datadir)
|
os.RemoveAll(datadir)
|
||||||
netStore.Close()
|
netStore.Close()
|
||||||
|
|
@ -1180,64 +1195,52 @@ func TestGetSubscriptionsRPC(t *testing.T) {
|
||||||
ctx, cancelSimRun := context.WithTimeout(context.Background(), 1*time.Minute)
|
ctx, cancelSimRun := context.WithTimeout(context.Background(), 1*time.Minute)
|
||||||
defer cancelSimRun()
|
defer cancelSimRun()
|
||||||
|
|
||||||
//upload a snapshot
|
// upload a snapshot
|
||||||
err := sim.UploadSnapshot(fmt.Sprintf("testing/snapshot_%d.json", nodeCount))
|
err := sim.UploadSnapshot(fmt.Sprintf("testing/snapshot_%d.json", nodeCount))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//run the simulation
|
// setup the filter for SubscribeMsg
|
||||||
result := sim.Run(ctx, func(ctx context.Context, sim *simulation.Simulation) error {
|
msgs := sim.PeerEvents(
|
||||||
log.Info("Simulation running")
|
context.Background(),
|
||||||
nodes := sim.Net.Nodes
|
sim.NodeIDs(),
|
||||||
//setup the filter for SubscribeMsg
|
simulation.NewPeerEventsFilter().ReceivedMessages().Protocol("stream").MsgCode(subscribeMsgCode),
|
||||||
msgs := sim.PeerEvents(
|
)
|
||||||
context.Background(),
|
|
||||||
sim.NodeIDs(),
|
|
||||||
simulation.NewPeerEventsFilter().ReceivedMessages().Protocol("stream").MsgCode(subscribeMsgCode),
|
|
||||||
)
|
|
||||||
|
|
||||||
//setup the vars we need
|
// strategy: listen to all SubscribeMsg events; after every event we wait
|
||||||
msgCount := 0
|
// if after 1 second no more messages are being received, we assume the
|
||||||
expectedMsgCount := 0
|
// subscription phase has terminated!
|
||||||
allSubscriptionsDone := make(chan struct{})
|
|
||||||
|
|
||||||
//in a loop, catch all SubscribeMsg and just add up
|
// the loop in this go routine will either wait for new message events
|
||||||
go func() {
|
// or times out after 1 second, which signals that we are not receiving
|
||||||
for m := range msgs {
|
// any new subscriptions any more
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case m := <-msgs: // just reset the loop
|
||||||
if m.Error != nil {
|
if m.Error != nil {
|
||||||
log.Error("stream message", "err", m.Error)
|
log.Error("stream message", "err", m.Error)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Trace("stream message", "node", m.NodeID, "peer", m.PeerID)
|
log.Trace("stream message", "node", m.NodeID, "peer", m.PeerID)
|
||||||
//add one
|
case <-time.After(time.Second):
|
||||||
msgCount += 1
|
// one second passed, don't assume more subscriptions
|
||||||
if msgCount == expectedMsgCount {
|
allSubscriptionsDone <- struct{}{}
|
||||||
//the expected amount is reached
|
log.Info("All subscriptions received")
|
||||||
allSubscriptionsDone <- struct{}{}
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
//first iterate all nodes to get the expected number of subscriptions from the kad table
|
|
||||||
for _, node := range nodes {
|
|
||||||
item, ok := sim.NodeItem(node.ID(), bucketKeyKad)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("No kademlia")
|
|
||||||
}
|
}
|
||||||
kad := item.(*network.Kademlia)
|
|
||||||
//define the function which should run for each connection - just count subscriptions
|
|
||||||
//this is not actually subscribing but iterating the same way as the subscriptions do,
|
|
||||||
//as we need just the number
|
|
||||||
eachBinFunc := func(p *network.Peer, bin int) bool {
|
|
||||||
expectedMsgCount += 1
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
//call the actual kademlia for the count
|
|
||||||
kad.EachBin(kad.BaseAddr(), pot.DefaultPof(kad.MaxProxDisplay), 0, eachBinFunc)
|
|
||||||
}
|
}
|
||||||
log.Debug("Expected message count: ", "expectedMsgCount", expectedMsgCount)
|
}()
|
||||||
|
|
||||||
|
//run the simulation
|
||||||
|
result := sim.Run(ctx, func(ctx context.Context, sim *simulation.Simulation) error {
|
||||||
|
log.Info("Simulation running")
|
||||||
|
nodes := sim.Net.Nodes
|
||||||
|
|
||||||
//wait until all subscriptions are done
|
//wait until all subscriptions are done
|
||||||
select {
|
select {
|
||||||
case <-allSubscriptionsDone:
|
case <-allSubscriptionsDone:
|
||||||
|
|
@ -1245,8 +1248,9 @@ func TestGetSubscriptionsRPC(t *testing.T) {
|
||||||
t.Fatal("Context timed out")
|
t.Fatal("Context timed out")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("All subscriptions received")
|
log.Debug("Expected message count: ", "expectedMsgCount", expectedMsgCount)
|
||||||
//now iterate again, this time we call each node via RPC to get its subscriptions
|
//now iterate again, this time we call each node via RPC to get its subscriptions
|
||||||
|
realCount := 0
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
//create rpc client
|
//create rpc client
|
||||||
client, err := node.Client()
|
client, err := node.Client()
|
||||||
|
|
@ -1254,11 +1258,6 @@ func TestGetSubscriptionsRPC(t *testing.T) {
|
||||||
t.Fatalf("create node 1 rpc client fail: %v", err)
|
t.Fatalf("create node 1 rpc client fail: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
item, ok := sim.NodeItem(node.ID(), bucketKeyRegistry)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("No registry")
|
|
||||||
}
|
|
||||||
registry := item.(*Registry)
|
|
||||||
//ask it for subscriptions
|
//ask it for subscriptions
|
||||||
pstreams := make(map[string][]string)
|
pstreams := make(map[string][]string)
|
||||||
err = client.Call(&pstreams, "stream_getPeerSubscriptions")
|
err = client.Call(&pstreams, "stream_getPeerSubscriptions")
|
||||||
|
|
@ -1266,17 +1265,23 @@ func TestGetSubscriptionsRPC(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
//length of the subscriptions can not be smaller than number of peers
|
//length of the subscriptions can not be smaller than number of peers
|
||||||
if len(pstreams) < len(registry.peers) {
|
|
||||||
t.Fatal("Subscription count is smaller than expected")
|
|
||||||
}
|
|
||||||
log.Debug(fmt.Sprintf("node %s subscriptions:", node.String()))
|
log.Debug(fmt.Sprintf("node %s subscriptions:", node.String()))
|
||||||
for p, ps := range pstreams {
|
for p, ps := range pstreams {
|
||||||
log.Debug(fmt.Sprintf("...with node %s: ", p))
|
log.Debug(fmt.Sprintf("...with node %s: ", p))
|
||||||
for _, s := range ps {
|
for _, s := range ps {
|
||||||
log.Debug(fmt.Sprintf("......%s", s))
|
log.Debug(fmt.Sprintf("......%s", s))
|
||||||
|
// each node also has subscriptions to RETRIEVE_REQUEST streams,
|
||||||
|
// we need to ignore those, we are only counting SYNC streams
|
||||||
|
if !strings.HasPrefix(s, "RETRIEVE_REQUEST") {
|
||||||
|
realCount++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// every node is mutually subscribed to each other, so the actual count is half of it
|
||||||
|
if realCount/2 != expectedMsgCount {
|
||||||
|
return errors.New(fmt.Sprintf("Real subscriptions and expected amount don't match; real: %d, expected: %d", realCount/2, expectedMsgCount))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue