kademlia_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright 2018 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package simulation
  17. import (
  18. "context"
  19. "sync"
  20. "testing"
  21. "time"
  22. "github.com/ethereum/go-ethereum/common"
  23. "github.com/ethereum/go-ethereum/log"
  24. "github.com/ethereum/go-ethereum/node"
  25. "github.com/ethereum/go-ethereum/p2p/simulations/adapters"
  26. "github.com/ethereum/go-ethereum/swarm/network"
  27. )
  28. /*
  29. TestWaitTillHealthy tests that we indeed get a healthy network after we wait for it.
  30. For this to be tested, a bit of a snake tail bite needs to happen:
  31. * First we create a first simulation
  32. * Run it as nodes connected in a ring
  33. * Wait until the network is healthy
  34. * Then we create a snapshot
  35. * With this snapshot we create a new simulation
  36. * This simulation is expected to have a healthy configuration, as it uses the snapshot
  37. * Thus we just iterate all nodes and check that their kademlias are healthy
  38. * If all kademlias are healthy, the test succeeded, otherwise it failed
  39. */
  40. func TestWaitTillHealthy(t *testing.T) {
  41. testNodesNum := 10
  42. // create the first simulation
  43. sim := New(createSimServiceMap(true))
  44. // connect and...
  45. nodeIDs, err := sim.AddNodesAndConnectRing(testNodesNum)
  46. if err != nil {
  47. t.Fatal(err)
  48. }
  49. // array of all overlay addresses
  50. var addrs [][]byte
  51. // iterate once to be able to build the peer map
  52. for _, node := range nodeIDs {
  53. //get the kademlia overlay address from this ID
  54. a := node.Bytes()
  55. //append it to the array of all overlay addresses
  56. addrs = append(addrs, a)
  57. }
  58. // build a PeerPot only once
  59. pp := network.NewPeerPotMap(network.NewKadParams().NeighbourhoodSize, addrs)
  60. ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
  61. defer cancel()
  62. // ...wait until healthy
  63. ill, err := sim.WaitTillHealthy(ctx)
  64. if err != nil {
  65. for id, kad := range ill {
  66. t.Log("Node", id)
  67. t.Log(kad.String())
  68. }
  69. t.Fatal(err)
  70. }
  71. // now create a snapshot of this network
  72. snap, err := sim.Net.Snapshot()
  73. if err != nil {
  74. t.Fatal(err)
  75. }
  76. // close the initial simulation
  77. sim.Close()
  78. // create a control simulation
  79. controlSim := New(createSimServiceMap(false))
  80. defer controlSim.Close()
  81. // load the snapshot into this control simulation
  82. err = controlSim.Net.Load(snap)
  83. if err != nil {
  84. t.Fatal(err)
  85. }
  86. _, err = controlSim.WaitTillHealthy(ctx)
  87. if err != nil {
  88. t.Fatal(err)
  89. }
  90. for _, node := range nodeIDs {
  91. // ...get its kademlia
  92. item, ok := controlSim.NodeItem(node, BucketKeyKademlia)
  93. if !ok {
  94. t.Fatal("No kademlia bucket item")
  95. }
  96. kad := item.(*network.Kademlia)
  97. // get its base address
  98. kid := common.Bytes2Hex(kad.BaseAddr())
  99. //get the health info
  100. info := kad.GetHealthInfo(pp[kid])
  101. log.Trace("Health info", "info", info)
  102. // check that it is healthy
  103. healthy := info.Healthy()
  104. if !healthy {
  105. t.Fatalf("Expected node %v of control simulation to be healthy, but it is not, unhealthy kademlias: %v", node, kad.String())
  106. }
  107. }
  108. }
  109. // createSimServiceMap returns the services map
  110. // this function will create the sim services with or without discovery enabled
  111. // based on the flag passed
  112. func createSimServiceMap(discovery bool) map[string]ServiceFunc {
  113. return map[string]ServiceFunc{
  114. "bzz": func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) {
  115. addr := network.NewAddr(ctx.Config.Node())
  116. hp := network.NewHiveParams()
  117. hp.Discovery = discovery
  118. config := &network.BzzConfig{
  119. OverlayAddr: addr.Over(),
  120. UnderlayAddr: addr.Under(),
  121. HiveParams: hp,
  122. }
  123. kad := network.NewKademlia(addr.Over(), network.NewKadParams())
  124. // store kademlia in node's bucket under BucketKeyKademlia
  125. // so that it can be found by WaitTillHealthy method.
  126. b.Store(BucketKeyKademlia, kad)
  127. return network.NewBzz(config, kad, nil, nil, nil), nil, nil
  128. },
  129. }
  130. }