github.com/evdatsion/aphelion-dpos-bft@v0.32.1/p2p/pex/pex_reactor_test.go (about) 1 package pex 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 14 "github.com/evdatsion/aphelion-dpos-bft/config" 15 "github.com/evdatsion/aphelion-dpos-bft/libs/log" 16 "github.com/evdatsion/aphelion-dpos-bft/p2p" 17 "github.com/evdatsion/aphelion-dpos-bft/p2p/mock" 18 ) 19 20 var ( 21 cfg *config.P2PConfig 22 ) 23 24 func init() { 25 cfg = config.DefaultP2PConfig() 26 cfg.PexReactor = true 27 cfg.AllowDuplicateIP = true 28 } 29 30 func TestPEXReactorBasic(t *testing.T) { 31 r, book := createReactor(&PEXReactorConfig{}) 32 defer teardownReactor(book) 33 34 assert.NotNil(t, r) 35 assert.NotEmpty(t, r.GetChannels()) 36 } 37 38 func TestPEXReactorAddRemovePeer(t *testing.T) { 39 r, book := createReactor(&PEXReactorConfig{}) 40 defer teardownReactor(book) 41 42 size := book.Size() 43 peer := p2p.CreateRandomPeer(false) 44 45 r.AddPeer(peer) 46 assert.Equal(t, size+1, book.Size()) 47 48 r.RemovePeer(peer, "peer not available") 49 50 outboundPeer := p2p.CreateRandomPeer(true) 51 52 r.AddPeer(outboundPeer) 53 assert.Equal(t, size+1, book.Size(), "outbound peers should not be added to the address book") 54 55 r.RemovePeer(outboundPeer, "peer not available") 56 } 57 58 // --- FAIL: TestPEXReactorRunning (11.10s) 59 // pex_reactor_test.go:411: expected all switches to be connected to at 60 // least one peer (switches: 0 => {outbound: 1, inbound: 0}, 1 => 61 // {outbound: 0, inbound: 1}, 2 => {outbound: 0, inbound: 0}, ) 62 // 63 // EXPLANATION: peers are getting rejected because in switch#addPeer we check 64 // if any peer (who we already connected to) has the same IP. Even though local 65 // peers have different IP addresses, they all have the same underlying remote 66 // IP: 127.0.0.1. 67 // 68 func TestPEXReactorRunning(t *testing.T) { 69 N := 3 70 switches := make([]*p2p.Switch, N) 71 72 // directory to store address books 73 dir, err := ioutil.TempDir("", "pex_reactor") 74 require.Nil(t, err) 75 defer os.RemoveAll(dir) // nolint: errcheck 76 77 books := make([]*addrBook, N) 78 logger := log.TestingLogger() 79 80 // create switches 81 for i := 0; i < N; i++ { 82 switches[i] = p2p.MakeSwitch(cfg, i, "testing", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { 83 books[i] = NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", i)), false) 84 books[i].SetLogger(logger.With("pex", i)) 85 sw.SetAddrBook(books[i]) 86 87 sw.SetLogger(logger.With("pex", i)) 88 89 r := NewPEXReactor(books[i], &PEXReactorConfig{}) 90 r.SetLogger(logger.With("pex", i)) 91 r.SetEnsurePeersPeriod(250 * time.Millisecond) 92 sw.AddReactor("pex", r) 93 94 return sw 95 }) 96 } 97 98 addOtherNodeAddrToAddrBook := func(switchIndex, otherSwitchIndex int) { 99 addr := switches[otherSwitchIndex].NetAddress() 100 books[switchIndex].AddAddress(addr, addr) 101 } 102 103 addOtherNodeAddrToAddrBook(0, 1) 104 addOtherNodeAddrToAddrBook(1, 0) 105 addOtherNodeAddrToAddrBook(2, 1) 106 107 for _, sw := range switches { 108 err := sw.Start() // start switch and reactors 109 require.Nil(t, err) 110 } 111 112 assertPeersWithTimeout(t, switches, 10*time.Millisecond, 10*time.Second, N-1) 113 114 // stop them 115 for _, s := range switches { 116 s.Stop() 117 } 118 } 119 120 func TestPEXReactorReceive(t *testing.T) { 121 r, book := createReactor(&PEXReactorConfig{}) 122 defer teardownReactor(book) 123 124 peer := p2p.CreateRandomPeer(false) 125 126 // we have to send a request to receive responses 127 r.RequestAddrs(peer) 128 129 size := book.Size() 130 addrs := []*p2p.NetAddress{peer.SocketAddr()} 131 msg := cdc.MustMarshalBinaryBare(&pexAddrsMessage{Addrs: addrs}) 132 r.Receive(PexChannel, peer, msg) 133 assert.Equal(t, size+1, book.Size()) 134 135 msg = cdc.MustMarshalBinaryBare(&pexRequestMessage{}) 136 r.Receive(PexChannel, peer, msg) // should not panic. 137 } 138 139 func TestPEXReactorRequestMessageAbuse(t *testing.T) { 140 r, book := createReactor(&PEXReactorConfig{}) 141 defer teardownReactor(book) 142 143 sw := createSwitchAndAddReactors(r) 144 sw.SetAddrBook(book) 145 146 peer := mock.NewPeer(nil) 147 p2p.AddPeerToSwitchPeerSet(sw, peer) 148 assert.True(t, sw.Peers().Has(peer.ID())) 149 150 id := string(peer.ID()) 151 msg := cdc.MustMarshalBinaryBare(&pexRequestMessage{}) 152 153 // first time creates the entry 154 r.Receive(PexChannel, peer, msg) 155 assert.True(t, r.lastReceivedRequests.Has(id)) 156 assert.True(t, sw.Peers().Has(peer.ID())) 157 158 // next time sets the last time value 159 r.Receive(PexChannel, peer, msg) 160 assert.True(t, r.lastReceivedRequests.Has(id)) 161 assert.True(t, sw.Peers().Has(peer.ID())) 162 163 // third time is too many too soon - peer is removed 164 r.Receive(PexChannel, peer, msg) 165 assert.False(t, r.lastReceivedRequests.Has(id)) 166 assert.False(t, sw.Peers().Has(peer.ID())) 167 } 168 169 func TestPEXReactorAddrsMessageAbuse(t *testing.T) { 170 r, book := createReactor(&PEXReactorConfig{}) 171 defer teardownReactor(book) 172 173 sw := createSwitchAndAddReactors(r) 174 sw.SetAddrBook(book) 175 176 peer := mock.NewPeer(nil) 177 p2p.AddPeerToSwitchPeerSet(sw, peer) 178 assert.True(t, sw.Peers().Has(peer.ID())) 179 180 id := string(peer.ID()) 181 182 // request addrs from the peer 183 r.RequestAddrs(peer) 184 assert.True(t, r.requestsSent.Has(id)) 185 assert.True(t, sw.Peers().Has(peer.ID())) 186 187 addrs := []*p2p.NetAddress{peer.SocketAddr()} 188 msg := cdc.MustMarshalBinaryBare(&pexAddrsMessage{Addrs: addrs}) 189 190 // receive some addrs. should clear the request 191 r.Receive(PexChannel, peer, msg) 192 assert.False(t, r.requestsSent.Has(id)) 193 assert.True(t, sw.Peers().Has(peer.ID())) 194 195 // receiving more addrs causes a disconnect 196 r.Receive(PexChannel, peer, msg) 197 assert.False(t, sw.Peers().Has(peer.ID())) 198 } 199 200 func TestCheckSeeds(t *testing.T) { 201 // directory to store address books 202 dir, err := ioutil.TempDir("", "pex_reactor") 203 require.Nil(t, err) 204 defer os.RemoveAll(dir) // nolint: errcheck 205 206 // 1. test creating peer with no seeds works 207 peerSwitch := testCreateDefaultPeer(dir, 0) 208 require.Nil(t, peerSwitch.Start()) 209 peerSwitch.Stop() 210 211 // 2. create seed 212 seed := testCreateSeed(dir, 1, []*p2p.NetAddress{}, []*p2p.NetAddress{}) 213 214 // 3. test create peer with online seed works 215 peerSwitch = testCreatePeerWithSeed(dir, 2, seed) 216 require.Nil(t, peerSwitch.Start()) 217 peerSwitch.Stop() 218 219 // 4. test create peer with all seeds having unresolvable DNS fails 220 badPeerConfig := &PEXReactorConfig{ 221 Seeds: []string{"ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657", 222 "d824b13cb5d40fa1d8a614e089357c7eff31b670@anotherbad.network.addr:26657"}, 223 } 224 peerSwitch = testCreatePeerWithConfig(dir, 2, badPeerConfig) 225 require.Error(t, peerSwitch.Start()) 226 peerSwitch.Stop() 227 228 // 5. test create peer with one good seed address succeeds 229 badPeerConfig = &PEXReactorConfig{ 230 Seeds: []string{"ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657", 231 "d824b13cb5d40fa1d8a614e089357c7eff31b670@anotherbad.network.addr:26657", 232 seed.NetAddress().String()}, 233 } 234 peerSwitch = testCreatePeerWithConfig(dir, 2, badPeerConfig) 235 require.Nil(t, peerSwitch.Start()) 236 peerSwitch.Stop() 237 } 238 239 func TestPEXReactorUsesSeedsIfNeeded(t *testing.T) { 240 // directory to store address books 241 dir, err := ioutil.TempDir("", "pex_reactor") 242 require.Nil(t, err) 243 defer os.RemoveAll(dir) // nolint: errcheck 244 245 // 1. create seed 246 seed := testCreateSeed(dir, 0, []*p2p.NetAddress{}, []*p2p.NetAddress{}) 247 require.Nil(t, seed.Start()) 248 defer seed.Stop() 249 250 // 2. create usual peer with only seed configured. 251 peer := testCreatePeerWithSeed(dir, 1, seed) 252 require.Nil(t, peer.Start()) 253 defer peer.Stop() 254 255 // 3. check that the peer connects to seed immediately 256 assertPeersWithTimeout(t, []*p2p.Switch{peer}, 10*time.Millisecond, 3*time.Second, 1) 257 } 258 259 func TestConnectionSpeedForPeerReceivedFromSeed(t *testing.T) { 260 // directory to store address books 261 dir, err := ioutil.TempDir("", "pex_reactor") 262 require.Nil(t, err) 263 defer os.RemoveAll(dir) // nolint: errcheck 264 265 // 1. create peer 266 peerSwitch := testCreateDefaultPeer(dir, 1) 267 require.Nil(t, peerSwitch.Start()) 268 defer peerSwitch.Stop() 269 270 // 2. Create seed which knows about the peer 271 peerAddr := peerSwitch.NetAddress() 272 seed := testCreateSeed(dir, 2, []*p2p.NetAddress{peerAddr}, []*p2p.NetAddress{peerAddr}) 273 require.Nil(t, seed.Start()) 274 defer seed.Stop() 275 276 // 3. create another peer with only seed configured. 277 secondPeer := testCreatePeerWithSeed(dir, 3, seed) 278 require.Nil(t, secondPeer.Start()) 279 defer secondPeer.Stop() 280 281 // 4. check that the second peer connects to seed immediately 282 assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 10*time.Millisecond, 3*time.Second, 1) 283 284 // 5. check that the second peer connects to the first peer immediately 285 assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 10*time.Millisecond, 1*time.Second, 2) 286 } 287 288 func TestPEXReactorSeedMode(t *testing.T) { 289 // directory to store address books 290 dir, err := ioutil.TempDir("", "pex_reactor") 291 require.Nil(t, err) 292 defer os.RemoveAll(dir) // nolint: errcheck 293 294 pexRConfig := &PEXReactorConfig{SeedMode: true, SeedDisconnectWaitPeriod: 10 * time.Millisecond} 295 pexR, book := createReactor(pexRConfig) 296 defer teardownReactor(book) 297 298 sw := createSwitchAndAddReactors(pexR) 299 sw.SetAddrBook(book) 300 err = sw.Start() 301 require.NoError(t, err) 302 defer sw.Stop() 303 304 assert.Zero(t, sw.Peers().Size()) 305 306 peerSwitch := testCreateDefaultPeer(dir, 1) 307 require.NoError(t, peerSwitch.Start()) 308 defer peerSwitch.Stop() 309 310 // 1. Test crawlPeers dials the peer 311 pexR.crawlPeers([]*p2p.NetAddress{peerSwitch.NetAddress()}) 312 assert.Equal(t, 1, sw.Peers().Size()) 313 assert.True(t, sw.Peers().Has(peerSwitch.NodeInfo().ID())) 314 315 // 2. attemptDisconnects should not disconnect because of wait period 316 pexR.attemptDisconnects() 317 assert.Equal(t, 1, sw.Peers().Size()) 318 319 // sleep for SeedDisconnectWaitPeriod 320 time.Sleep(pexRConfig.SeedDisconnectWaitPeriod + 1*time.Millisecond) 321 322 // 3. attemptDisconnects should disconnect after wait period 323 pexR.attemptDisconnects() 324 assert.Equal(t, 0, sw.Peers().Size()) 325 } 326 327 func TestPEXReactorDoesNotDisconnectFromPersistentPeerInSeedMode(t *testing.T) { 328 // directory to store address books 329 dir, err := ioutil.TempDir("", "pex_reactor") 330 require.Nil(t, err) 331 defer os.RemoveAll(dir) // nolint: errcheck 332 333 pexRConfig := &PEXReactorConfig{SeedMode: true, SeedDisconnectWaitPeriod: 1 * time.Millisecond} 334 pexR, book := createReactor(pexRConfig) 335 defer teardownReactor(book) 336 337 sw := createSwitchAndAddReactors(pexR) 338 sw.SetAddrBook(book) 339 err = sw.Start() 340 require.NoError(t, err) 341 defer sw.Stop() 342 343 assert.Zero(t, sw.Peers().Size()) 344 345 peerSwitch := testCreateDefaultPeer(dir, 1) 346 require.NoError(t, peerSwitch.Start()) 347 defer peerSwitch.Stop() 348 349 err = sw.AddPersistentPeers([]string{peerSwitch.NetAddress().String()}) 350 require.NoError(t, err) 351 352 // 1. Test crawlPeers dials the peer 353 pexR.crawlPeers([]*p2p.NetAddress{peerSwitch.NetAddress()}) 354 assert.Equal(t, 1, sw.Peers().Size()) 355 assert.True(t, sw.Peers().Has(peerSwitch.NodeInfo().ID())) 356 357 // sleep for SeedDisconnectWaitPeriod 358 time.Sleep(pexRConfig.SeedDisconnectWaitPeriod + 1*time.Millisecond) 359 360 // 2. attemptDisconnects should not disconnect because the peer is persistent 361 pexR.attemptDisconnects() 362 assert.Equal(t, 1, sw.Peers().Size()) 363 } 364 365 func TestPEXReactorDialsPeerUpToMaxAttemptsInSeedMode(t *testing.T) { 366 // directory to store address books 367 dir, err := ioutil.TempDir("", "pex_reactor") 368 require.Nil(t, err) 369 defer os.RemoveAll(dir) // nolint: errcheck 370 371 pexR, book := createReactor(&PEXReactorConfig{SeedMode: true}) 372 defer teardownReactor(book) 373 374 sw := createSwitchAndAddReactors(pexR) 375 sw.SetAddrBook(book) 376 err = sw.Start() 377 require.NoError(t, err) 378 defer sw.Stop() 379 380 peer := mock.NewPeer(nil) 381 addr := peer.SocketAddr() 382 383 err = book.AddAddress(addr, addr) 384 require.NoError(t, err) 385 386 assert.True(t, book.HasAddress(addr)) 387 // imitate maxAttemptsToDial reached 388 pexR.attemptsToDial.Store(addr.DialString(), _attemptsToDial{maxAttemptsToDial + 1, time.Now()}) 389 pexR.crawlPeers([]*p2p.NetAddress{addr}) 390 assert.False(t, book.HasAddress(addr)) 391 } 392 393 // connect a peer to a seed, wait a bit, then stop it. 394 // this should give it time to request addrs and for the seed 395 // to call FlushStop, and allows us to test calling Stop concurrently 396 // with FlushStop. Before a fix, this non-deterministically reproduced 397 // https://github.com/evdatsion/aphelion-dpos-bft/issues/3231. 398 func TestPEXReactorSeedModeFlushStop(t *testing.T) { 399 N := 2 400 switches := make([]*p2p.Switch, N) 401 402 // directory to store address books 403 dir, err := ioutil.TempDir("", "pex_reactor") 404 require.Nil(t, err) 405 defer os.RemoveAll(dir) // nolint: errcheck 406 407 books := make([]*addrBook, N) 408 logger := log.TestingLogger() 409 410 // create switches 411 for i := 0; i < N; i++ { 412 switches[i] = p2p.MakeSwitch(cfg, i, "testing", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { 413 books[i] = NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", i)), false) 414 books[i].SetLogger(logger.With("pex", i)) 415 sw.SetAddrBook(books[i]) 416 417 sw.SetLogger(logger.With("pex", i)) 418 419 config := &PEXReactorConfig{} 420 if i == 0 { 421 // first one is a seed node 422 config = &PEXReactorConfig{SeedMode: true} 423 } 424 r := NewPEXReactor(books[i], config) 425 r.SetLogger(logger.With("pex", i)) 426 r.SetEnsurePeersPeriod(250 * time.Millisecond) 427 sw.AddReactor("pex", r) 428 429 return sw 430 }) 431 } 432 433 for _, sw := range switches { 434 err := sw.Start() // start switch and reactors 435 require.Nil(t, err) 436 } 437 438 reactor := switches[0].Reactors()["pex"].(*PEXReactor) 439 peerID := switches[1].NodeInfo().ID() 440 441 err = switches[1].DialPeerWithAddress(switches[0].NetAddress()) 442 assert.NoError(t, err) 443 444 // sleep up to a second while waiting for the peer to send us a message. 445 // this isn't perfect since it's possible the peer sends us a msg and we FlushStop 446 // before this loop catches it. but non-deterministically it works pretty well. 447 for i := 0; i < 1000; i++ { 448 v := reactor.lastReceivedRequests.Get(string(peerID)) 449 if v != nil { 450 break 451 } 452 time.Sleep(time.Millisecond) 453 } 454 455 // by now the FlushStop should have happened. Try stopping the peer. 456 // it should be safe to do this. 457 peers := switches[0].Peers().List() 458 for _, peer := range peers { 459 peer.Stop() 460 } 461 462 // stop the switches 463 for _, s := range switches { 464 s.Stop() 465 } 466 } 467 468 func TestPEXReactorDoesNotAddPrivatePeersToAddrBook(t *testing.T) { 469 peer := p2p.CreateRandomPeer(false) 470 471 pexR, book := createReactor(&PEXReactorConfig{}) 472 book.AddPrivateIDs([]string{string(peer.NodeInfo().ID())}) 473 defer teardownReactor(book) 474 475 // we have to send a request to receive responses 476 pexR.RequestAddrs(peer) 477 478 size := book.Size() 479 addrs := []*p2p.NetAddress{peer.SocketAddr()} 480 msg := cdc.MustMarshalBinaryBare(&pexAddrsMessage{Addrs: addrs}) 481 pexR.Receive(PexChannel, peer, msg) 482 assert.Equal(t, size, book.Size()) 483 484 pexR.AddPeer(peer) 485 assert.Equal(t, size, book.Size()) 486 } 487 488 func TestPEXReactorDialPeer(t *testing.T) { 489 pexR, book := createReactor(&PEXReactorConfig{}) 490 defer teardownReactor(book) 491 492 sw := createSwitchAndAddReactors(pexR) 493 sw.SetAddrBook(book) 494 495 peer := mock.NewPeer(nil) 496 addr := peer.SocketAddr() 497 498 assert.Equal(t, 0, pexR.AttemptsToDial(addr)) 499 500 // 1st unsuccessful attempt 501 pexR.dialPeer(addr) 502 503 assert.Equal(t, 1, pexR.AttemptsToDial(addr)) 504 505 // 2nd unsuccessful attempt 506 pexR.dialPeer(addr) 507 508 // must be skipped because it is too early 509 assert.Equal(t, 1, pexR.AttemptsToDial(addr)) 510 511 if !testing.Short() { 512 time.Sleep(3 * time.Second) 513 514 // 3rd attempt 515 pexR.dialPeer(addr) 516 517 assert.Equal(t, 2, pexR.AttemptsToDial(addr)) 518 } 519 } 520 521 func assertPeersWithTimeout( 522 t *testing.T, 523 switches []*p2p.Switch, 524 checkPeriod, timeout time.Duration, 525 nPeers int, 526 ) { 527 var ( 528 ticker = time.NewTicker(checkPeriod) 529 remaining = timeout 530 ) 531 532 for { 533 select { 534 case <-ticker.C: 535 // check peers are connected 536 allGood := true 537 for _, s := range switches { 538 outbound, inbound, _ := s.NumPeers() 539 if outbound+inbound < nPeers { 540 allGood = false 541 break 542 } 543 } 544 remaining -= checkPeriod 545 if remaining < 0 { 546 remaining = 0 547 } 548 if allGood { 549 return 550 } 551 case <-time.After(remaining): 552 numPeersStr := "" 553 for i, s := range switches { 554 outbound, inbound, _ := s.NumPeers() 555 numPeersStr += fmt.Sprintf("%d => {outbound: %d, inbound: %d}, ", i, outbound, inbound) 556 } 557 t.Errorf( 558 "expected all switches to be connected to at least %d peer(s) (switches: %s)", 559 nPeers, numPeersStr, 560 ) 561 return 562 } 563 } 564 } 565 566 // Creates a peer with the provided config 567 func testCreatePeerWithConfig(dir string, id int, config *PEXReactorConfig) *p2p.Switch { 568 peer := p2p.MakeSwitch( 569 cfg, 570 id, 571 "127.0.0.1", 572 "123.123.123", 573 func(i int, sw *p2p.Switch) *p2p.Switch { 574 book := NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", id)), false) 575 book.SetLogger(log.TestingLogger()) 576 sw.SetAddrBook(book) 577 578 sw.SetLogger(log.TestingLogger()) 579 580 r := NewPEXReactor( 581 book, 582 config, 583 ) 584 r.SetLogger(log.TestingLogger()) 585 sw.AddReactor("pex", r) 586 return sw 587 }, 588 ) 589 return peer 590 } 591 592 // Creates a peer with the default config 593 func testCreateDefaultPeer(dir string, id int) *p2p.Switch { 594 return testCreatePeerWithConfig(dir, id, &PEXReactorConfig{}) 595 } 596 597 // Creates a seed which knows about the provided addresses / source address pairs. 598 // Starting and stopping the seed is left to the caller 599 func testCreateSeed(dir string, id int, knownAddrs, srcAddrs []*p2p.NetAddress) *p2p.Switch { 600 seed := p2p.MakeSwitch( 601 cfg, 602 id, 603 "127.0.0.1", 604 "123.123.123", 605 func(i int, sw *p2p.Switch) *p2p.Switch { 606 book := NewAddrBook(filepath.Join(dir, "addrbookSeed.json"), false) 607 book.SetLogger(log.TestingLogger()) 608 for j := 0; j < len(knownAddrs); j++ { 609 book.AddAddress(knownAddrs[j], srcAddrs[j]) 610 book.MarkGood(knownAddrs[j].ID) 611 } 612 sw.SetAddrBook(book) 613 614 sw.SetLogger(log.TestingLogger()) 615 616 r := NewPEXReactor(book, &PEXReactorConfig{}) 617 r.SetLogger(log.TestingLogger()) 618 sw.AddReactor("pex", r) 619 return sw 620 }, 621 ) 622 return seed 623 } 624 625 // Creates a peer which knows about the provided seed. 626 // Starting and stopping the peer is left to the caller 627 func testCreatePeerWithSeed(dir string, id int, seed *p2p.Switch) *p2p.Switch { 628 conf := &PEXReactorConfig{ 629 Seeds: []string{seed.NetAddress().String()}, 630 } 631 return testCreatePeerWithConfig(dir, id, conf) 632 } 633 634 func createReactor(conf *PEXReactorConfig) (r *PEXReactor, book *addrBook) { 635 // directory to store address book 636 dir, err := ioutil.TempDir("", "pex_reactor") 637 if err != nil { 638 panic(err) 639 } 640 book = NewAddrBook(filepath.Join(dir, "addrbook.json"), true) 641 book.SetLogger(log.TestingLogger()) 642 643 r = NewPEXReactor(book, conf) 644 r.SetLogger(log.TestingLogger()) 645 return 646 } 647 648 func teardownReactor(book *addrBook) { 649 err := os.RemoveAll(filepath.Dir(book.FilePath())) 650 if err != nil { 651 panic(err) 652 } 653 } 654 655 func createSwitchAndAddReactors(reactors ...p2p.Reactor) *p2p.Switch { 656 sw := p2p.MakeSwitch(cfg, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { return sw }) 657 sw.SetLogger(log.TestingLogger()) 658 for _, r := range reactors { 659 sw.AddReactor(r.String(), r) 660 r.SetSwitch(sw) 661 } 662 return sw 663 }