mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
swarm/network: WIP Create Healthy assertion tests
This commit is contained in:
parent
2990503d89
commit
cbf6d77a7f
4 changed files with 102 additions and 22 deletions
|
|
@ -17,6 +17,7 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
|
@ -248,17 +249,27 @@ func (h *Hive) savePeers() error {
|
|||
// It evaluates the healthiness based on the addresses passed as argument
|
||||
// in relation to the base address of the hive instance the method is called on
|
||||
func (h *Hive) Healthy(addrs [][]byte) *Health {
|
||||
k := NewKademlia(h.BaseAddr(), NewKadParams())
|
||||
//k := NewKademlia(h.BaseAddr(), NewKadParams())
|
||||
pivotK := *h.Kademlia
|
||||
kads := []*Kademlia{&pivotK}
|
||||
for _, a := range addrs {
|
||||
p := &Peer{
|
||||
BzzPeer: &BzzPeer{
|
||||
BzzAddr: &BzzAddr{
|
||||
OAddr: a,
|
||||
},
|
||||
},
|
||||
if bytes.Equal(a, h.BaseAddr()) {
|
||||
continue
|
||||
}
|
||||
k.On(p)
|
||||
kads = append(kads, NewKademlia(a, kadParamsFromInstance(h.Kademlia)))
|
||||
}
|
||||
pp := NewPeerPotMap([]*Kademlia{k})
|
||||
pp := NewPeerPotMap(kads)
|
||||
return pp[common.Bytes2Hex(h.BaseAddr())].Healthy()
|
||||
}
|
||||
|
||||
func kadParamsFromInstance(k *Kademlia) *KadParams {
|
||||
return &KadParams{
|
||||
MaxProxDisplay: k.MaxProxDisplay,
|
||||
MinProxBinSize: k.MinProxBinSize,
|
||||
MinBinSize: k.MinBinSize,
|
||||
MaxBinSize: k.MaxBinSize,
|
||||
RetryInterval: k.RetryInterval,
|
||||
RetryExponent: k.RetryExponent,
|
||||
MaxRetries: k.MaxRetries,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ func (k *Kademlia) eachConn(base []byte, o int, f func(*Peer, int, bool) bool) {
|
|||
}
|
||||
|
||||
// EachAddr called with (base, po, f) is an iterator applying f to each known peer
|
||||
// that has proximity order po or less as measured from the base
|
||||
// that has proximity order o or less as measured from the base
|
||||
// if base is nil, kademlia base address is used
|
||||
// It returns peers in order deepest to shallowest
|
||||
func (k *Kademlia) EachAddr(base []byte, o int, f func(*BzzAddr, int, bool) bool) {
|
||||
|
|
@ -444,6 +444,7 @@ func (k *Kademlia) NeighbourhoodDepth() (depth int) {
|
|||
// if there is altogether less than MinProxBinSize peers it returns 0
|
||||
// caller must hold the lock
|
||||
func depthForPot(p *pot.Pot, minProxBinSize int, pivotAddr []byte) (depth int) {
|
||||
log.Trace("pivot", "a", pivotAddr)
|
||||
if p.Size() <= minProxBinSize {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -470,7 +471,8 @@ func depthForPot(p *pot.Pot, minProxBinSize int, pivotAddr []byte) (depth int) {
|
|||
}
|
||||
p.EachNeighbour(pivotAddr, Pof, f)
|
||||
|
||||
p.EachBin(pivotAddr, Pof, 0, func(po int, _ int, _ func(func(pot.Val, int) bool) bool) bool {
|
||||
p.EachBin(pivotAddr, Pof, 0, func(po int, _ int, f func(func(pot.Val, int) bool) bool) bool {
|
||||
log.Trace("eachbin", "addr", pivotAddr, "po", po)
|
||||
if po == depth {
|
||||
if maxDepth == depth {
|
||||
return false
|
||||
|
|
@ -629,8 +631,8 @@ func NewPeerPotMap(kads []*Kademlia) map[string]*PeerPot {
|
|||
a := k.base
|
||||
|
||||
// actual kademlia depth
|
||||
depth := depthForPot(np, k.MinProxBinSize, a)
|
||||
|
||||
depth := depthForPot(k.addrs, k.MinProxBinSize, a)
|
||||
log.Trace("potmap", "k", k.BaseAddr(), "depth", depth)
|
||||
// all nn-peers
|
||||
var nns [][]byte
|
||||
|
||||
|
|
@ -652,7 +654,7 @@ func NewPeerPotMap(kads []*Kademlia) map[string]*PeerPot {
|
|||
return false
|
||||
})
|
||||
|
||||
log.Trace(fmt.Sprintf("%x NNS: %s", kads[i].base[:4], LogAddrs(nns)))
|
||||
log.Trace(fmt.Sprintf("%x PeerPotMap NNS: %s", kads[i].base[:4], LogAddrs(nns)))
|
||||
ppmap[common.Bytes2Hex(a)] = &PeerPot{
|
||||
Kademlia: k,
|
||||
NNSet: nns,
|
||||
|
|
@ -692,6 +694,7 @@ func (o *PeerPot) knowNeighbours() (got bool, n int, missing [][]byte) {
|
|||
// all bins (except self) are included (0 <= bin <= 255)
|
||||
depth := depthForPot(o.addrs, o.MinProxBinSize, o.base)
|
||||
o.eachAddr(nil, 255, func(p *BzzAddr, po int, nn bool) bool {
|
||||
log.Info("eachaddr", "depth", depth, "po", po)
|
||||
if po < depth {
|
||||
return false
|
||||
}
|
||||
|
|
@ -711,7 +714,7 @@ func (o *PeerPot) knowNeighbours() (got bool, n int, missing [][]byte) {
|
|||
if pm[pk] {
|
||||
gots++
|
||||
} else {
|
||||
log.Trace(fmt.Sprintf("%08x: known nearest neighbour %s not found", o.base, pk)) //(o.BaseAddr()[:4], pk[:8]))
|
||||
log.Trace(fmt.Sprintf("%08x: known nearest neighbour %s not found", o.base, pk))
|
||||
culprits = append(culprits, p)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,12 +41,17 @@ func testKadPeerAddr(s string) *BzzAddr {
|
|||
return &BzzAddr{OAddr: a, UAddr: a}
|
||||
}
|
||||
|
||||
func newTestKademlia(b string) *Kademlia {
|
||||
func newTestKademliaParams() *KadParams {
|
||||
params := NewKadParams()
|
||||
// TODO why is this 1?
|
||||
params.MinBinSize = 1
|
||||
params.MinProxBinSize = 2
|
||||
return params
|
||||
}
|
||||
|
||||
func newTestKademlia(b string) *Kademlia {
|
||||
base := pot.NewAddressFromString(b)
|
||||
return NewKademlia(base, params)
|
||||
return NewKademlia(base, newTestKademliaParams())
|
||||
}
|
||||
|
||||
func newTestKadPeer(k *Kademlia, s string, lightNode bool) *Peer {
|
||||
|
|
@ -157,6 +162,58 @@ func TestNeighbourhoodDepth(t *testing.T) {
|
|||
testNum++
|
||||
}
|
||||
|
||||
func TestHealth(t *testing.T) {
|
||||
k := newTestKademlia("00000000")
|
||||
assertHealth(t, k, false)
|
||||
Register(k, "00001000")
|
||||
log.Trace(k.String())
|
||||
assertHealth(t, k, false)
|
||||
On(k, "00001000")
|
||||
assertHealth(t, k, true)
|
||||
Register(k, "00000100")
|
||||
log.Trace(k.String())
|
||||
assertHealth(t, k, false)
|
||||
On(k, "00000100")
|
||||
assertHealth(t, k, true)
|
||||
Register(k, "10000000")
|
||||
log.Trace(k.String())
|
||||
assertHealth(t, k, false)
|
||||
On(k, "10000000")
|
||||
assertHealth(t, k, true)
|
||||
Register(k, "00100000")
|
||||
log.Trace(k.String())
|
||||
assertHealth(t, k, false)
|
||||
On(k, "00100000")
|
||||
assertHealth(t, k, true)
|
||||
Register(k, "01000000")
|
||||
log.Trace(k.String())
|
||||
assertHealth(t, k, false)
|
||||
On(k, "01000000")
|
||||
assertHealth(t, k, true)
|
||||
}
|
||||
|
||||
func assertHealth(t *testing.T, k *Kademlia, expectHealthy bool) {
|
||||
kid := common.Bytes2Hex(k.BaseAddr())
|
||||
kads := []*Kademlia{k}
|
||||
k.EachAddr(nil, 255, func(addr *BzzAddr, po int, _ bool) bool {
|
||||
kads = append(kads, NewKademlia(addr.Address(), newTestKademliaParams()))
|
||||
return true
|
||||
})
|
||||
|
||||
pp := NewPeerPotMap(kads)
|
||||
log.Trace("set", "pp", pp[kid].NNSet)
|
||||
healthParams := pp[kid].Healthy()
|
||||
|
||||
// definition of health, all conditions but be true:
|
||||
// - we at least know one peer
|
||||
// - we know all neighbors
|
||||
// - we are connected to all known neighbors
|
||||
health := healthParams.KnowNN && healthParams.GotNN && healthParams.CountKnowNN > 0
|
||||
if expectHealthy != health {
|
||||
t.Fatalf("expected kademlia health %v, is %v\n%v", expectHealthy, health, k.String())
|
||||
}
|
||||
}
|
||||
|
||||
func testSuggestPeer(k *Kademlia, expAddr string, expPo int, expWant bool) error {
|
||||
addr, o, want := k.SuggestPeer()
|
||||
log.Trace("suggestpeer return", "a", addr, "o", o, "want", want)
|
||||
|
|
@ -179,6 +236,7 @@ func binStr(a *BzzAddr) string {
|
|||
return pot.ToBin(a.Address())[:8]
|
||||
}
|
||||
|
||||
// TODO explain why this bug occurred and how it should have been mitigated
|
||||
func TestSuggestPeerBug(t *testing.T) {
|
||||
// 2 row gap, unsaturated proxbin, no callables -> want PO 0
|
||||
k := newTestKademlia("00000000")
|
||||
|
|
@ -557,7 +615,7 @@ func testKademliaCase(t *testing.T, pivotAddr string, addrs ...string) {
|
|||
}
|
||||
|
||||
h := pp.Healthy()
|
||||
if !(h.GotNN && h.KnowNN) {
|
||||
if !(h.GotNN && h.KnowNN && h.CountKnowNN > 0) {
|
||||
t.Fatalf("not healthy: %#v\n%v", h, k.String())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
|
|
@ -285,7 +286,7 @@ func discoverySimulation(nodes, conns int, adapter adapters.NodeAdapter) (*simul
|
|||
if err := client.Call(&healthy, "hive_healthy", addrs); err != nil {
|
||||
return false, fmt.Errorf("error getting node health: %s", err)
|
||||
}
|
||||
log.Debug(fmt.Sprintf("node %4s healthy: got nearest neighbours: %v, know nearest neighbours: %v,\n\n%v", id, healthy.GotNN, healthy.KnowNN, healthy.Hive))
|
||||
log.Info(fmt.Sprintf("node %4s healthy: got nearest neighbours: %v, know nearest neighbours: %v,\n\n%v", id, healthy.GotNN, healthy.KnowNN, healthy.Hive))
|
||||
return healthy.KnowNN && healthy.GotNN, nil
|
||||
}
|
||||
|
||||
|
|
@ -399,13 +400,20 @@ func discoveryPersistenceSimulation(nodes, conns int, adapter adapters.NodeAdapt
|
|||
}
|
||||
healthy := &network.Health{}
|
||||
addr := id.String()
|
||||
log.Error("before hive healthy call")
|
||||
if err := client.Call(&healthy, "hive_healthy", addrs); err != nil {
|
||||
return fmt.Errorf("error getting node health: %s", err)
|
||||
}
|
||||
|
||||
log.Info(fmt.Sprintf("NODE: %s, IS HEALTHY: %t", addr, healthy.GotNN && healthy.KnowNN))
|
||||
if !healthy.GotNN {
|
||||
log.Info(fmt.Sprintf("NODE: %s, IS HEALTHY: %t", addr, healthy.GotNN && healthy.KnowNN && healthy.CountKnowNN > 0))
|
||||
var nodeStr string
|
||||
if err := client.Call(&nodeStr, "hive_string"); err != nil {
|
||||
return fmt.Errorf("error getting node string %s", err)
|
||||
}
|
||||
log.Info(nodeStr)
|
||||
for _, a := range addrs {
|
||||
log.Info(common.Bytes2Hex(a))
|
||||
}
|
||||
if !healthy.GotNN || healthy.CountKnowNN == 0 {
|
||||
isHealthy = false
|
||||
break
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue