@@ -22,9 +22,14 @@ import (
22
22
"testing"
23
23
"time"
24
24
25
+ "github.com/ethereum/go-ethereum/common"
26
+ "github.com/ethereum/go-ethereum/common/hexutil"
25
27
"github.com/ethereum/go-ethereum/crypto"
26
28
"github.com/ethereum/go-ethereum/p2p"
29
+ "github.com/ethereum/go-ethereum/p2p/enode"
30
+ "github.com/ethersphere/swarm/log"
27
31
p2ptest "github.com/ethersphere/swarm/p2p/testing"
32
+ "github.com/ethersphere/swarm/pot"
28
33
"github.com/ethersphere/swarm/state"
29
34
)
30
35
@@ -175,3 +180,139 @@ func TestHiveStatePersistence(t *testing.T) {
175
180
t .Fatalf ("%d peers left over: %v" , len (peers ), peers )
176
181
}
177
182
}
183
+
184
+ // TestHiveStateConnections connect the node to some peers and then after cleanup/save in store those peers
185
+ // are retrieved and used as suggested peer initially.
186
+ func TestHiveStateConnections (t * testing.T ) {
187
+ dir , err := ioutil .TempDir ("" , "hive_test_store" )
188
+ if err != nil {
189
+ t .Fatal (err )
190
+ }
191
+ defer os .RemoveAll (dir )
192
+
193
+ const peersCount = 5
194
+
195
+ nodeIdToBzzAddr := make (map [string ]* BzzAddr )
196
+ addedChan := make (chan struct {}, 5 )
197
+ startHive := func (t * testing.T , dir string ) (h * Hive , cleanupFunc func ()) {
198
+ store , err := state .NewDBStore (dir )
199
+ if err != nil {
200
+ t .Fatal (err )
201
+ }
202
+
203
+ params := NewHiveParams ()
204
+ params .Discovery = false
205
+
206
+ prvkey , err := crypto .GenerateKey ()
207
+ if err != nil {
208
+ t .Fatal (err )
209
+ }
210
+
211
+ h = NewHive (params , NewKademlia (PrivateKeyToBzzKey (prvkey ), NewKadParams ()), store )
212
+ s := p2ptest .NewProtocolTester (prvkey , 0 , func (p * p2p.Peer , rw p2p.MsgReadWriter ) error { return nil })
213
+
214
+ if err := h .Start (s .Server ); err != nil {
215
+ t .Fatal (err )
216
+ }
217
+ //Close ticker to avoid interference with initial peer suggestion
218
+ h .ticker .Stop ()
219
+ //Overwrite addPeer so the Node is added as a peer automatically.
220
+ // The related Overlay address is retrieved from nodeIdToBzzAddr where it has been saved before
221
+ h .addPeer = func (node * enode.Node ) {
222
+ bzzAddr := nodeIdToBzzAddr [encodeId (node .ID ())]
223
+ if bzzAddr == nil {
224
+ t .Fatalf ("Enode [%v] not found in saved peers!" , encodeId (node .ID ()))
225
+ }
226
+ bzzPeer := newConnPeerLocal (bzzAddr .Address (), h .Kademlia )
227
+ h .On (bzzPeer )
228
+ addedChan <- struct {}{}
229
+ }
230
+
231
+ cleanupFunc = func () {
232
+ err := h .Stop ()
233
+ if err != nil {
234
+ t .Fatal (err )
235
+ }
236
+
237
+ s .Stop ()
238
+ }
239
+ return h , cleanupFunc
240
+ }
241
+
242
+ h1 , cleanup1 := startHive (t , dir )
243
+ peers := make (map [string ]bool )
244
+ for i := 0 ; i < peersCount ; i ++ {
245
+ raddr := RandomBzzAddr ()
246
+ h1 .Register (raddr )
247
+ peers [raddr .String ()] = true
248
+ }
249
+ const initialPeers = 5
250
+ for i := 0 ; i < initialPeers ; i ++ {
251
+ suggestedPeer , _ , _ := h1 .SuggestPeer ()
252
+ if suggestedPeer != nil {
253
+ testAddPeer (suggestedPeer , h1 , nodeIdToBzzAddr )
254
+ }
255
+
256
+ }
257
+ numConns := h1 .conns .Size ()
258
+ connAddresses := make (map [string ]string )
259
+ h1 .EachConn (h1 .base , 255 , func (peer * Peer , i int ) bool {
260
+ key := hexutil .Encode (peer .Address ())
261
+ connAddresses [key ] = key
262
+ return true
263
+ })
264
+ log .Warn ("After 5 suggestions" , "numConns" , numConns )
265
+ cleanup1 ()
266
+
267
+ // start the hive and check that we suggest previous connected peers
268
+ h2 , _ := startHive (t , dir )
269
+ // there should be at some point 5 conns
270
+ connsAfterLoading := 0
271
+ iterations := 0
272
+ connsAfterLoading = h2 .conns .Size ()
273
+ for connsAfterLoading != numConns && iterations < 5 {
274
+ select {
275
+ case <- addedChan :
276
+ connsAfterLoading = h2 .conns .Size ()
277
+ case <- time .After (1 * time .Second ):
278
+ iterations ++
279
+ }
280
+ log .Trace ("Iteration waiting for initial connections" , "numConns" , connsAfterLoading , "iterations" , iterations )
281
+ }
282
+ if connsAfterLoading != numConns {
283
+ t .Errorf ("Expected 5 peer connecteds from previous execution but got %v" , connsAfterLoading )
284
+ }
285
+ h2 .EachConn (h2 .base , 255 , func (peer * Peer , i int ) bool {
286
+ key := hexutil .Encode (peer .Address ())
287
+ if connAddresses [key ] != key {
288
+ t .Errorf ("Expected address %v to be in connections as it was a previous peer connected" , key )
289
+ } else {
290
+ log .Warn ("Previous peer connected again" , "addr" , key )
291
+ }
292
+ return true
293
+ })
294
+ }
295
+
296
+ // Create a Peer with the suggested address and store the relationshsip enode -> BzzAddr for later retrieval
297
+ func testAddPeer (suggestedPeer * BzzAddr , h1 * Hive , nodeIdToBzzAddr map [string ]* BzzAddr ) {
298
+ byteAddresses := suggestedPeer .Address ()
299
+ bzzPeer := newConnPeerLocal (byteAddresses , h1 .Kademlia )
300
+ nodeIdToBzzAddr [encodeId (bzzPeer .ID ())] = bzzPeer .BzzAddr
301
+ bzzPeer .kad = h1 .Kademlia
302
+ h1 .On (bzzPeer )
303
+ }
304
+
305
+ func encodeId (id enode.ID ) string {
306
+ addr := id [:]
307
+ return hexutil .Encode (addr )
308
+ }
309
+
310
+ // We create a test Peer with underlay address to localhost and using overlay address provided
311
+ func newConnPeerLocal (addr []byte , kademlia * Kademlia ) * Peer {
312
+ hash := [common .HashLength ]byte {}
313
+ copy (hash [:], addr )
314
+ potAddress := pot .Address (hash )
315
+ peer := newDiscPeer (potAddress )
316
+ peer .kad = kademlia
317
+ return peer
318
+ }
0 commit comments