mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
swarm/pss: snapshot test updated
This commit is contained in:
parent
243724eb26
commit
f322700b23
2 changed files with 52 additions and 93 deletions
|
|
@ -109,7 +109,7 @@ func (s *Simulation) WaitTillSnapshotRecreated(ctx context.Context, snap simulat
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
actual := listActualConnections(s.kademlias())
|
actual := s.listActualConnections()
|
||||||
if isAllDeployed(expected, actual) {
|
if isAllDeployed(expected, actual) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +117,8 @@ func (s *Simulation) WaitTillSnapshotRecreated(ctx context.Context, snap simulat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func listActualConnections(kademlias map[enode.ID]*network.Kademlia) (res []uint64) {
|
func (s *Simulation) listActualConnections() (res []uint64) {
|
||||||
|
kademlias := s.kademlias()
|
||||||
for base, k := range kademlias {
|
for base, k := range kademlias {
|
||||||
k.EachConn(base[:], 256, func(p *network.Peer, _ int) bool {
|
k.EachConn(base[:], 256, func(p *network.Peer, _ int) bool {
|
||||||
res = append(res, getConnectionHash(base, p.ID()))
|
res = append(res, getConnectionHash(base, p.ID()))
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,15 @@ var (
|
||||||
|
|
||||||
handlerDone bool // set to true on termination of the simulation run
|
handlerDone bool // set to true on termination of the simulation run
|
||||||
msgsToReceive int // total count of messages to receive, used for terminating the simulation run
|
msgsToReceive int // total count of messages to receive, used for terminating the simulation run
|
||||||
debugCnt int
|
maxMessages int
|
||||||
|
msgCnt int
|
||||||
|
|
||||||
kademlias map[enode.ID]*network.Kademlia
|
kademlias map[enode.ID]*network.Kademlia
|
||||||
nodeAddrs map[enode.ID][]byte // make predictable overlay addresses from the generated random enode ids
|
nodeAddrs map[enode.ID][]byte // make predictable overlay addresses from the generated random enode ids
|
||||||
recipients map[int][]enode.ID // for logging output only
|
recipients map[int][]enode.ID // for logging output only
|
||||||
|
allowed map[int][]enode.ID // allowed recipients
|
||||||
expectedMsgs map[enode.ID][]uint64 // message serials we expect respective nodes to receive
|
expectedMsgs map[enode.ID][]uint64 // message serials we expect respective nodes to receive
|
||||||
|
allowedMsgs map[enode.ID][]uint64 // message serials we expect respective nodes to receive
|
||||||
senders map[int]enode.ID // originating nodes of the messages (intention is to choose as far as possible from the receiving neighborhood)
|
senders map[int]enode.ID // originating nodes of the messages (intention is to choose as far as possible from the receiving neighborhood)
|
||||||
handlerC chan handlerNotification // passes message from pss message handler to simulation driver
|
handlerC chan handlerNotification // passes message from pss message handler to simulation driver
|
||||||
doneC chan struct{} // terminates the handler channel listener
|
doneC chan struct{} // terminates the handler channel listener
|
||||||
|
|
@ -70,13 +73,16 @@ var (
|
||||||
func resetTestVariables() {
|
func resetTestVariables() {
|
||||||
handlerDone = false
|
handlerDone = false
|
||||||
msgsToReceive = 0
|
msgsToReceive = 0
|
||||||
debugCnt = 0
|
maxMessages = 0
|
||||||
|
msgCnt = 0
|
||||||
msgs = nil
|
msgs = nil
|
||||||
|
|
||||||
kademlias = make(map[enode.ID]*network.Kademlia)
|
kademlias = make(map[enode.ID]*network.Kademlia)
|
||||||
nodeAddrs = make(map[enode.ID][]byte)
|
nodeAddrs = make(map[enode.ID][]byte)
|
||||||
recipients = make(map[int][]enode.ID)
|
recipients = make(map[int][]enode.ID)
|
||||||
|
allowed = make(map[int][]enode.ID)
|
||||||
expectedMsgs = make(map[enode.ID][]uint64)
|
expectedMsgs = make(map[enode.ID][]uint64)
|
||||||
|
allowedMsgs = make(map[enode.ID][]uint64)
|
||||||
senders = make(map[int]enode.ID)
|
senders = make(map[int]enode.ID)
|
||||||
handlerC = make(chan handlerNotification)
|
handlerC = make(chan handlerNotification)
|
||||||
doneC = make(chan struct{})
|
doneC = make(chan struct{})
|
||||||
|
|
@ -132,44 +138,53 @@ func readSnapshot(t *testing.T, nodeCount int) simulations.Snapshot {
|
||||||
|
|
||||||
func assingTestVariables(sim *simulation.Simulation, msgCount int) {
|
func assingTestVariables(sim *simulation.Simulation, msgCount int) {
|
||||||
log.Debug("-------------------------------------------------------------------------")
|
log.Debug("-------------------------------------------------------------------------")
|
||||||
var targets string
|
|
||||||
for _, nodeId := range sim.NodeIDs() {
|
for _, nodeId := range sim.NodeIDs() {
|
||||||
nodeAddrs[nodeId] = nodeIDToAddr(nodeId)
|
nodeAddrs[nodeId] = nodeIDToAddr(nodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < int(msgCount); i++ {
|
for i := 0; i < int(msgCount); i++ {
|
||||||
msgAddr := pot.RandomAddress() // we choose message addresses randomly
|
msgAddr := pot.RandomAddress() // we choose message addresses randomly
|
||||||
msgAddr[0] = byte(0x24)
|
|
||||||
|
|
||||||
msgs = append(msgs, msgAddr.Bytes())
|
msgs = append(msgs, msgAddr.Bytes())
|
||||||
smallestPo := 256
|
smallestPo := 256
|
||||||
|
var targets []enode.ID
|
||||||
|
var prev int
|
||||||
|
|
||||||
// loop through all nodes and add the message to recipient indices
|
// loop through all nodes and add the message to recipient indices
|
||||||
for _, nod := range sim.Net.GetNodes() {
|
for _, nod := range sim.Net.GetNodes() {
|
||||||
po, _ := pof(msgs[i], nodeAddrs[nod.ID()], 0)
|
po, _ := pof(msgs[i], nodeAddrs[nod.ID()], 0)
|
||||||
depth := kademlias[nod.ID()].NeighbourhoodDepth()
|
depth := kademlias[nod.ID()].NeighbourhoodDepth()
|
||||||
|
|
||||||
// node has message address within nearest neighborhood depth, that means it is a recipient
|
// only nodes with closest IDs (wrt msg) will receive the msg
|
||||||
if po >= depth {
|
if po > prev {
|
||||||
recipients[i] = append(recipients[i], nod.ID())
|
prev = po
|
||||||
expectedMsgs[nod.ID()] = append(expectedMsgs[nod.ID()], uint64(i))
|
targets = nil
|
||||||
msgsToReceive++
|
targets = append(targets, nod.ID())
|
||||||
id := nod.ID()
|
} else if po == prev {
|
||||||
targets += fmt.Sprintf("%x ", id[:4])
|
targets = append(targets, nod.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep track of the smallest po value in the iteration
|
if po >= depth {
|
||||||
// the first node in the smallest value bin will be the sender
|
maxMessages++
|
||||||
|
allowed[i] = append(recipients[i], nod.ID())
|
||||||
|
allowedMsgs[nod.ID()] = append(allowedMsgs[nod.ID()], uint64(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
// a node with the smallest PO (wrt msg) will be the sender
|
||||||
if po < smallestPo {
|
if po < smallestPo {
|
||||||
smallestPo = po
|
smallestPo = po
|
||||||
senders[i] = nod.ID()
|
senders[i] = nod.ID()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msgsToReceive += len(targets)
|
||||||
|
for _, id := range targets {
|
||||||
|
recipients[i] = append(recipients[i], id)
|
||||||
|
expectedMsgs[id] = append(expectedMsgs[id], uint64(i))
|
||||||
|
}
|
||||||
|
|
||||||
log.Debug("nn for msg", "targets", len(recipients[i]), "msgidx", i, "msg", common.Bytes2Hex(msgAddr[:8]), "sender", senders[i], "senderpo", smallestPo)
|
log.Debug("nn for msg", "targets", len(recipients[i]), "msgidx", i, "msg", common.Bytes2Hex(msgAddr[:8]), "sender", senders[i], "senderpo", smallestPo)
|
||||||
//log.Debug("nn for msg", "rcptcount", len(recipients[i]), "msgidx", i, "msg", common.Bytes2Hex(msgs[i][:8]), "sender", senders[i], "senderpo", smallestPo)
|
|
||||||
}
|
}
|
||||||
log.Debug("msgs to receive", "count", msgsToReceive)
|
log.Debug("msgs to receive", "count", msgsToReceive)
|
||||||
log.Debug("targets", "nodes", targets)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProxNetwork(t *testing.T) {
|
func TestProxNetwork(t *testing.T) {
|
||||||
|
|
@ -206,78 +221,20 @@ func testProxNetwork(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to recreate snapshot: %s", err)
|
t.Fatalf("failed to recreate snapshot: %s", err)
|
||||||
}
|
}
|
||||||
//waitTillSerenity(t, snap, sim, 1000)
|
|
||||||
assingTestVariables(sim, msgCount)
|
assingTestVariables(sim, msgCount)
|
||||||
result := sim.Run(ctx, runFunc)
|
result := sim.Run(ctx, runFunc)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Debug("--------------------------------------------------------------------------------", "rcv", debugCnt)
|
// context deadline exceeded
|
||||||
t.Fatal(result.Error)
|
// however, it might just mean that not all possible messages are received
|
||||||
|
// now we must check if all required messages are received
|
||||||
|
log.Debug("--------------------------------------------------------------------------------", "rcv", msgCnt)
|
||||||
|
if msgCnt < msgsToReceive {
|
||||||
|
t.Fatal(result.Error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.Logf("completed %d", result.Duration)
|
t.Logf("completed %d", result.Duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
func waitTillSerenity(t *testing.T, snap simulations.Snapshot, sim *simulation.Simulation, timeout int) {
|
|
||||||
interval := 16
|
|
||||||
expected := listSnapConnections(snap.Conns)
|
|
||||||
for ms := 0; ms < timeout; ms += interval {
|
|
||||||
actual := listSimConnections(sim.Net.Conns)
|
|
||||||
if isSerenity(expected, actual) {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
time.Sleep(time.Millisecond * time.Duration(interval))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * 16) // todo: remove this later
|
|
||||||
}
|
|
||||||
|
|
||||||
func listSnapConnections(conns []simulations.Conn) (res []uint64) {
|
|
||||||
for _, c := range conns {
|
|
||||||
res = append(res, getConnectionHash(c.One, c.Other))
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func listSimConnections(conns []*simulations.Conn) (res []uint64) {
|
|
||||||
for _, c := range conns {
|
|
||||||
res = append(res, getConnectionHash(c.One, c.Other))
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns an integer connection identifier (similar to 8-byte hash)
|
|
||||||
func getConnectionHash(a, b enode.ID) uint64 {
|
|
||||||
var h [8]byte
|
|
||||||
for i := 0; i < 8; i++ {
|
|
||||||
h[i] = a[i] ^ b[i]
|
|
||||||
}
|
|
||||||
res := binary.LittleEndian.Uint64(h[:])
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns true if all connections in expected are listed in actual
|
|
||||||
func isSerenity(expected []uint64, actual []uint64) bool {
|
|
||||||
exp := make([]uint64, len(expected))
|
|
||||||
copy(exp, expected)
|
|
||||||
if len(exp) > 0 {
|
|
||||||
for _, c := range actual {
|
|
||||||
// remove value c from exp
|
|
||||||
for i := 0; i < len(exp); i++ {
|
|
||||||
if exp[i] == c {
|
|
||||||
last := len(exp) - 1
|
|
||||||
if last == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
exp[i] = exp[last]
|
|
||||||
exp = exp[:last]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len(exp) == 0
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func sendAllMsgs(sim *simulation.Simulation, msgs [][]byte, senders map[int]enode.ID) {
|
func sendAllMsgs(sim *simulation.Simulation, msgs [][]byte, senders map[int]enode.ID) {
|
||||||
for i, msg := range msgs {
|
for i, msg := range msgs {
|
||||||
log.Debug("sending msg", "idx", i, "from", senders[i])
|
log.Debug("sending msg", "idx", i, "from", senders[i])
|
||||||
|
|
@ -294,10 +251,10 @@ func sendAllMsgs(sim *simulation.Simulation, msgs [][]byte, senders map[int]enod
|
||||||
|
|
||||||
func runFunc(ctx context.Context, sim *simulation.Simulation) error {
|
func runFunc(ctx context.Context, sim *simulation.Simulation) error {
|
||||||
go handlerChannelListener(ctx)
|
go handlerChannelListener(ctx)
|
||||||
time.Sleep(128 * time.Millisecond)
|
|
||||||
go sendAllMsgs(sim, msgs, senders)
|
go sendAllMsgs(sim, msgs, senders)
|
||||||
// collect incoming messages and terminate with corresponding status when message handler listener ends
|
|
||||||
received := 0
|
received := 0
|
||||||
|
|
||||||
|
// collect incoming messages and terminate with corresponding status when message handler listener ends
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case err := <-errC:
|
case err := <-errC:
|
||||||
|
|
@ -305,7 +262,7 @@ func runFunc(ctx context.Context, sim *simulation.Simulation) error {
|
||||||
case hn := <-msgC:
|
case hn := <-msgC:
|
||||||
received++
|
received++
|
||||||
log.Debug("msg received", "msgs_received", received, "total_expected", msgsToReceive, "id", hn.id, "serial", hn.serial)
|
log.Debug("msg received", "msgs_received", received, "total_expected", msgsToReceive, "id", hn.id, "serial", hn.serial)
|
||||||
if received >= msgsToReceive {
|
if received >= maxMessages {
|
||||||
close(doneC)
|
close(doneC)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -330,8 +287,8 @@ func handlerChannelListener(ctx context.Context) {
|
||||||
// incoming message from pss message handler
|
// incoming message from pss message handler
|
||||||
case handlerNotification := <-handlerC:
|
case handlerNotification := <-handlerC:
|
||||||
// check if recipient has already received all its messages and notify to fail the test if so
|
// check if recipient has already received all its messages and notify to fail the test if so
|
||||||
xMsgs := expectedMsgs[handlerNotification.id]
|
aMsgs := allowedMsgs[handlerNotification.id]
|
||||||
if len(xMsgs) == 0 {
|
if len(aMsgs) == 0 {
|
||||||
setDone()
|
setDone()
|
||||||
errC <- fmt.Errorf("too many messages received by recipient %x", handlerNotification.id)
|
errC <- fmt.Errorf("too many messages received by recipient %x", handlerNotification.id)
|
||||||
return
|
return
|
||||||
|
|
@ -339,7 +296,7 @@ func handlerChannelListener(ctx context.Context) {
|
||||||
|
|
||||||
// check if message serial is in expected messages for this recipient and notify to fail the test if not
|
// check if message serial is in expected messages for this recipient and notify to fail the test if not
|
||||||
idx := -1
|
idx := -1
|
||||||
for i, msg := range xMsgs {
|
for i, msg := range aMsgs {
|
||||||
if handlerNotification.serial == msg {
|
if handlerNotification.serial == msg {
|
||||||
idx = i
|
idx = i
|
||||||
break
|
break
|
||||||
|
|
@ -352,8 +309,8 @@ func handlerChannelListener(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// message is ok, so remove that message serial from the recipient expectation array and notify the main sim thread
|
// message is ok, so remove that message serial from the recipient expectation array and notify the main sim thread
|
||||||
xMsgs[idx] = xMsgs[len(xMsgs)-1]
|
aMsgs[idx] = aMsgs[len(aMsgs)-1]
|
||||||
xMsgs = xMsgs[:len(xMsgs)-1]
|
aMsgs = aMsgs[:len(aMsgs)-1]
|
||||||
msgC <- handlerNotification
|
msgC <- handlerNotification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -362,8 +319,8 @@ func handlerChannelListener(ctx context.Context) {
|
||||||
func nodeMsgHandler(config *adapters.NodeConfig) *handler {
|
func nodeMsgHandler(config *adapters.NodeConfig) *handler {
|
||||||
return &handler{
|
return &handler{
|
||||||
f: func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error {
|
f: func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error {
|
||||||
debugCnt++
|
msgCnt++
|
||||||
log.Debug("nodeMsgHandler rcv", "cnt", debugCnt)
|
log.Debug("nodeMsgHandler rcv", "cnt", msgCnt)
|
||||||
|
|
||||||
// using simple serial in message body, makes it easy to keep track of who's getting what
|
// using simple serial in message body, makes it easy to keep track of who's getting what
|
||||||
serial, c := binary.Uvarint(msg)
|
serial, c := binary.Uvarint(msg)
|
||||||
|
|
@ -423,6 +380,7 @@ func newProxServices(allowRaw bool, handlerContextFuncs map[Topic]handlerContext
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
b.Store(simulation.BucketKeyKademlia, pskad)
|
||||||
|
|
||||||
// register the handlers we've been passed
|
// register the handlers we've been passed
|
||||||
var deregisters []func()
|
var deregisters []func()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue