mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
WIP introduce snapshots in pss cmd can now set websocket host for pss removed binary log garbage moved baseaddr get to main pss api changed pssclient constructor sig to return error documentation
212 lines
5.5 KiB
Go
212 lines
5.5 KiB
Go
package discovery_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/log"
|
|
"github.com/ethereum/go-ethereum/node"
|
|
"github.com/ethereum/go-ethereum/p2p"
|
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
|
"github.com/ethereum/go-ethereum/p2p/simulations"
|
|
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
|
"github.com/ethereum/go-ethereum/swarm/network"
|
|
)
|
|
|
|
// serviceName is used with the exec adapter so the exec'd binary knows which
|
|
// service to execute
|
|
const serviceName = "discovery"
|
|
const testMinProxBinSize = 2
|
|
|
|
var services = adapters.Services{
|
|
serviceName: newService,
|
|
}
|
|
|
|
func init() {
|
|
// register the discovery service which will run as a devp2p
|
|
// protocol when using the exec adapter
|
|
adapters.RegisterServices(services)
|
|
|
|
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlError, log.StreamHandler(os.Stderr, log.TerminalFormat(false))))
|
|
log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(false))))
|
|
}
|
|
|
|
func TestDiscoverySimulationDockerAdapter(t *testing.T) {
|
|
adapter, err := adapters.NewDockerAdapter()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
testDiscoverySimulation(t, adapter)
|
|
}
|
|
|
|
func TestDiscoverySimulationExecAdapter(t *testing.T) {
|
|
baseDir, err := ioutil.TempDir("", "swarm-test")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(baseDir)
|
|
testDiscoverySimulation(t, adapters.NewExecAdapter(baseDir))
|
|
}
|
|
|
|
func TestDiscoverySimulationSimAdapter(t *testing.T) {
|
|
testDiscoverySimulation(t, adapters.NewSimAdapter(services))
|
|
}
|
|
|
|
func testDiscoverySimulation(t *testing.T, adapter adapters.NodeAdapter) {
|
|
// create network
|
|
nodeCount := 10
|
|
net := simulations.NewNetwork(adapter, &simulations.NetworkConfig{
|
|
ID: "0",
|
|
DefaultService: serviceName,
|
|
})
|
|
defer net.Shutdown()
|
|
trigger := make(chan discover.NodeID)
|
|
ids := make([]discover.NodeID, nodeCount)
|
|
for i := 0; i < nodeCount; i++ {
|
|
node, err := net.NewNode()
|
|
if err != nil {
|
|
t.Fatalf("error starting node: %s", err)
|
|
}
|
|
if err := net.Start(node.ID()); err != nil {
|
|
t.Fatalf("error starting node %s: %s", node.ID().TerminalString(), err)
|
|
}
|
|
if err := triggerChecks(trigger, net, node.ID()); err != nil {
|
|
t.Fatal("error triggering checks for node %s: %s", node.ID().TerminalString(), err)
|
|
}
|
|
ids[i] = node.ID()
|
|
}
|
|
|
|
// run a simulation which connects the 10 nodes in a ring and waits
|
|
// for full peer discovery
|
|
action := func(ctx context.Context) error {
|
|
for i, id := range ids {
|
|
var peerID discover.NodeID
|
|
if i == 0 {
|
|
peerID = ids[len(ids)-1]
|
|
} else {
|
|
peerID = ids[i-1]
|
|
}
|
|
if err := net.Connect(id, peerID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
nnmap := network.NewPeerPot(testMinProxBinSize, ids...)
|
|
check := func(ctx context.Context, id discover.NodeID) (bool, error) {
|
|
select {
|
|
case <-ctx.Done():
|
|
return false, ctx.Err()
|
|
default:
|
|
}
|
|
|
|
node := net.GetNode(id)
|
|
if node == nil {
|
|
return false, fmt.Errorf("unknown node: %s", id)
|
|
}
|
|
client, err := node.Client()
|
|
if err != nil {
|
|
return false, fmt.Errorf("error getting node client: %s", err)
|
|
}
|
|
var healthy bool
|
|
if err := client.Call(&healthy, "hive_healthy", nnmap[id]); err != nil {
|
|
return false, fmt.Errorf("error getting node health: %s", err)
|
|
}
|
|
return healthy, nil
|
|
}
|
|
|
|
timeout := 30 * time.Second
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
|
|
result := simulations.NewSimulation(net).Run(ctx, &simulations.Step{
|
|
Action: action,
|
|
Trigger: trigger,
|
|
Expect: &simulations.Expectation{
|
|
Nodes: ids,
|
|
Check: check,
|
|
},
|
|
})
|
|
if result.Error != nil {
|
|
t.Fatalf("simulation failed: %s", result.Error)
|
|
}
|
|
|
|
snap, err := net.Snapshot()
|
|
if err != nil {
|
|
t.Fatalf("no shapshot dude")
|
|
}
|
|
jsonsnapshot, err := json.Marshal(snap)
|
|
ioutil.WriteFile("jsonsnapshot.txt", jsonsnapshot, os.ModePerm)
|
|
|
|
t.Log("Simulation Passed:")
|
|
t.Logf("Duration: %s", result.FinishedAt.Sub(result.StartedAt))
|
|
for _, id := range ids {
|
|
t.Logf("Node %s passed in %s", id.TerminalString(), result.Passes[id].Sub(result.StartedAt))
|
|
}
|
|
t.Logf("Events:")
|
|
for _, event := range result.NetworkEvents {
|
|
t.Log(event)
|
|
}
|
|
}
|
|
|
|
// triggerChecks triggers a simulation step check whenever a peer is added or
|
|
// removed from the given node
|
|
func triggerChecks(trigger chan discover.NodeID, net *simulations.Network, id discover.NodeID) error {
|
|
node := net.GetNode(id)
|
|
if node == nil {
|
|
return fmt.Errorf("unknown node: %s", id)
|
|
}
|
|
client, err := node.Client()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
events := make(chan *p2p.PeerEvent)
|
|
sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents")
|
|
if err != nil {
|
|
return fmt.Errorf("error getting peer events for node %v: %s", id, err)
|
|
}
|
|
go func() {
|
|
defer sub.Unsubscribe()
|
|
for {
|
|
select {
|
|
case <-events:
|
|
trigger <- id
|
|
case err := <-sub.Err():
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("error getting peer events for node %v", id), "err", err)
|
|
}
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
func newService(ctx *adapters.ServiceContext) (node.Service, error) {
|
|
addr := network.NewAddrFromNodeID(ctx.Config.ID)
|
|
|
|
kp := network.NewKadParams()
|
|
kp.MinProxBinSize = testMinProxBinSize
|
|
kp.MaxBinSize = 3
|
|
kp.MinBinSize = 1
|
|
kp.MaxRetries = 1000
|
|
kp.RetryExponent = 2
|
|
kp.RetryInterval = 1000000
|
|
kad := network.NewKademlia(addr.Over(), kp)
|
|
|
|
hp := network.NewHiveParams()
|
|
hp.KeepAliveInterval = time.Second
|
|
|
|
config := &network.BzzConfig{
|
|
OverlayAddr: addr.Over(),
|
|
UnderlayAddr: addr.Under(),
|
|
HiveParams: hp,
|
|
}
|
|
|
|
return network.NewBzz(config, kad, nil), nil
|
|
}
|