|
|
@ -4,6 +4,7 @@ import ( |
|
|
|
"fmt" |
|
|
|
"io/ioutil" |
|
|
|
"os" |
|
|
|
"path/filepath" |
|
|
|
"testing" |
|
|
|
"time" |
|
|
|
|
|
|
@ -12,12 +13,11 @@ import ( |
|
|
|
|
|
|
|
crypto "github.com/tendermint/go-crypto" |
|
|
|
wire "github.com/tendermint/go-wire" |
|
|
|
cmn "github.com/tendermint/tmlibs/common" |
|
|
|
"github.com/tendermint/tmlibs/log" |
|
|
|
|
|
|
|
cfg "github.com/tendermint/tendermint/config" |
|
|
|
"github.com/tendermint/tendermint/p2p" |
|
|
|
"github.com/tendermint/tendermint/p2p/conn" |
|
|
|
cmn "github.com/tendermint/tmlibs/common" |
|
|
|
"github.com/tendermint/tmlibs/log" |
|
|
|
) |
|
|
|
|
|
|
|
var ( |
|
|
@ -30,49 +30,33 @@ func init() { |
|
|
|
} |
|
|
|
|
|
|
|
func TestPEXReactorBasic(t *testing.T) { |
|
|
|
assert, require := assert.New(t), require.New(t) |
|
|
|
|
|
|
|
dir, err := ioutil.TempDir("", "pex_reactor") |
|
|
|
require.Nil(err) |
|
|
|
defer os.RemoveAll(dir) // nolint: errcheck
|
|
|
|
book := NewAddrBook(dir+"addrbook.json", true) |
|
|
|
book.SetLogger(log.TestingLogger()) |
|
|
|
r, book := createReactor(&PEXReactorConfig{}) |
|
|
|
defer teardownReactor(book) |
|
|
|
|
|
|
|
r := NewPEXReactor(book, &PEXReactorConfig{}) |
|
|
|
r.SetLogger(log.TestingLogger()) |
|
|
|
|
|
|
|
assert.NotNil(r) |
|
|
|
assert.NotEmpty(r.GetChannels()) |
|
|
|
assert.NotNil(t, r) |
|
|
|
assert.NotEmpty(t, r.GetChannels()) |
|
|
|
} |
|
|
|
|
|
|
|
func TestPEXReactorAddRemovePeer(t *testing.T) { |
|
|
|
assert, require := assert.New(t), require.New(t) |
|
|
|
|
|
|
|
dir, err := ioutil.TempDir("", "pex_reactor") |
|
|
|
require.Nil(err) |
|
|
|
defer os.RemoveAll(dir) // nolint: errcheck
|
|
|
|
book := NewAddrBook(dir+"addrbook.json", true) |
|
|
|
book.SetLogger(log.TestingLogger()) |
|
|
|
|
|
|
|
r := NewPEXReactor(book, &PEXReactorConfig{}) |
|
|
|
r.SetLogger(log.TestingLogger()) |
|
|
|
r, book := createReactor(&PEXReactorConfig{}) |
|
|
|
defer teardownReactor(book) |
|
|
|
|
|
|
|
size := book.Size() |
|
|
|
peer := p2p.CreateRandomPeer(false) |
|
|
|
|
|
|
|
r.AddPeer(peer) |
|
|
|
assert.Equal(size+1, book.Size()) |
|
|
|
assert.Equal(t, size+1, book.Size()) |
|
|
|
|
|
|
|
r.RemovePeer(peer, "peer not available") |
|
|
|
assert.Equal(size+1, book.Size()) |
|
|
|
assert.Equal(t, size+1, book.Size()) |
|
|
|
|
|
|
|
outboundPeer := p2p.CreateRandomPeer(true) |
|
|
|
|
|
|
|
r.AddPeer(outboundPeer) |
|
|
|
assert.Equal(size+1, book.Size(), "outbound peers should not be added to the address book") |
|
|
|
assert.Equal(t, size+1, book.Size(), "outbound peers should not be added to the address book") |
|
|
|
|
|
|
|
r.RemovePeer(outboundPeer, "peer not available") |
|
|
|
assert.Equal(size+1, book.Size()) |
|
|
|
assert.Equal(t, size+1, book.Size()) |
|
|
|
} |
|
|
|
|
|
|
|
func TestPEXReactorRunning(t *testing.T) { |
|
|
@ -82,7 +66,7 @@ func TestPEXReactorRunning(t *testing.T) { |
|
|
|
dir, err := ioutil.TempDir("", "pex_reactor") |
|
|
|
require.Nil(t, err) |
|
|
|
defer os.RemoveAll(dir) // nolint: errcheck
|
|
|
|
book := NewAddrBook(dir+"addrbook.json", false) |
|
|
|
book := NewAddrBook(filepath.Join(dir, "addrbook.json"), false) |
|
|
|
book.SetLogger(log.TestingLogger()) |
|
|
|
|
|
|
|
// create switches
|
|
|
@ -120,16 +104,8 @@ func TestPEXReactorRunning(t *testing.T) { |
|
|
|
} |
|
|
|
|
|
|
|
func TestPEXReactorReceive(t *testing.T) { |
|
|
|
assert, require := assert.New(t), require.New(t) |
|
|
|
|
|
|
|
dir, err := ioutil.TempDir("", "pex_reactor") |
|
|
|
require.Nil(err) |
|
|
|
defer os.RemoveAll(dir) // nolint: errcheck
|
|
|
|
book := NewAddrBook(dir+"addrbook.json", false) |
|
|
|
book.SetLogger(log.TestingLogger()) |
|
|
|
|
|
|
|
r := NewPEXReactor(book, &PEXReactorConfig{}) |
|
|
|
r.SetLogger(log.TestingLogger()) |
|
|
|
r, book := createReactor(&PEXReactorConfig{}) |
|
|
|
defer teardownReactor(book) |
|
|
|
|
|
|
|
peer := p2p.CreateRandomPeer(false) |
|
|
|
|
|
|
@ -140,98 +116,77 @@ func TestPEXReactorReceive(t *testing.T) { |
|
|
|
addrs := []*p2p.NetAddress{peer.NodeInfo().NetAddress()} |
|
|
|
msg := wire.BinaryBytes(struct{ PexMessage }{&pexAddrsMessage{Addrs: addrs}}) |
|
|
|
r.Receive(PexChannel, peer, msg) |
|
|
|
assert.Equal(size+1, book.Size()) |
|
|
|
assert.Equal(t, size+1, book.Size()) |
|
|
|
|
|
|
|
msg = wire.BinaryBytes(struct{ PexMessage }{&pexRequestMessage{}}) |
|
|
|
r.Receive(PexChannel, peer, msg) |
|
|
|
} |
|
|
|
|
|
|
|
func TestPEXReactorRequestMessageAbuse(t *testing.T) { |
|
|
|
assert, require := assert.New(t), require.New(t) |
|
|
|
r, book := createReactor(&PEXReactorConfig{}) |
|
|
|
defer teardownReactor(book) |
|
|
|
|
|
|
|
dir, err := ioutil.TempDir("", "pex_reactor") |
|
|
|
require.Nil(err) |
|
|
|
defer os.RemoveAll(dir) // nolint: errcheck
|
|
|
|
book := NewAddrBook(dir+"addrbook.json", true) |
|
|
|
book.SetLogger(log.TestingLogger()) |
|
|
|
|
|
|
|
r := NewPEXReactor(book, &PEXReactorConfig{}) |
|
|
|
sw := p2p.MakeSwitch(config, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { return sw }) |
|
|
|
sw.SetLogger(log.TestingLogger()) |
|
|
|
sw.AddReactor("PEX", r) |
|
|
|
r.SetSwitch(sw) |
|
|
|
r.SetLogger(log.TestingLogger()) |
|
|
|
sw := createSwitchAndAddReactors(r) |
|
|
|
|
|
|
|
peer := newMockPeer() |
|
|
|
p2p.AddPeerToSwitch(sw, peer) |
|
|
|
assert.True(sw.Peers().Has(peer.ID())) |
|
|
|
assert.True(t, sw.Peers().Has(peer.ID())) |
|
|
|
|
|
|
|
id := string(peer.ID()) |
|
|
|
msg := wire.BinaryBytes(struct{ PexMessage }{&pexRequestMessage{}}) |
|
|
|
|
|
|
|
// first time creates the entry
|
|
|
|
r.Receive(PexChannel, peer, msg) |
|
|
|
assert.True(r.lastReceivedRequests.Has(id)) |
|
|
|
assert.True(sw.Peers().Has(peer.ID())) |
|
|
|
assert.True(t, r.lastReceivedRequests.Has(id)) |
|
|
|
assert.True(t, sw.Peers().Has(peer.ID())) |
|
|
|
|
|
|
|
// next time sets the last time value
|
|
|
|
r.Receive(PexChannel, peer, msg) |
|
|
|
assert.True(r.lastReceivedRequests.Has(id)) |
|
|
|
assert.True(sw.Peers().Has(peer.ID())) |
|
|
|
assert.True(t, r.lastReceivedRequests.Has(id)) |
|
|
|
assert.True(t, sw.Peers().Has(peer.ID())) |
|
|
|
|
|
|
|
// third time is too many too soon - peer is removed
|
|
|
|
r.Receive(PexChannel, peer, msg) |
|
|
|
assert.False(r.lastReceivedRequests.Has(id)) |
|
|
|
assert.False(sw.Peers().Has(peer.ID())) |
|
|
|
assert.False(t, r.lastReceivedRequests.Has(id)) |
|
|
|
assert.False(t, sw.Peers().Has(peer.ID())) |
|
|
|
} |
|
|
|
|
|
|
|
func TestPEXReactorAddrsMessageAbuse(t *testing.T) { |
|
|
|
assert, require := assert.New(t), require.New(t) |
|
|
|
r, book := createReactor(&PEXReactorConfig{}) |
|
|
|
defer teardownReactor(book) |
|
|
|
|
|
|
|
dir, err := ioutil.TempDir("", "pex_reactor") |
|
|
|
require.Nil(err) |
|
|
|
defer os.RemoveAll(dir) // nolint: errcheck
|
|
|
|
book := NewAddrBook(dir+"addrbook.json", true) |
|
|
|
book.SetLogger(log.TestingLogger()) |
|
|
|
|
|
|
|
r := NewPEXReactor(book, &PEXReactorConfig{}) |
|
|
|
sw := p2p.MakeSwitch(config, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { return sw }) |
|
|
|
sw.SetLogger(log.TestingLogger()) |
|
|
|
sw.AddReactor("PEX", r) |
|
|
|
r.SetSwitch(sw) |
|
|
|
r.SetLogger(log.TestingLogger()) |
|
|
|
sw := createSwitchAndAddReactors(r) |
|
|
|
|
|
|
|
peer := newMockPeer() |
|
|
|
p2p.AddPeerToSwitch(sw, peer) |
|
|
|
assert.True(sw.Peers().Has(peer.ID())) |
|
|
|
assert.True(t, sw.Peers().Has(peer.ID())) |
|
|
|
|
|
|
|
id := string(peer.ID()) |
|
|
|
|
|
|
|
// request addrs from the peer
|
|
|
|
r.RequestAddrs(peer) |
|
|
|
assert.True(r.requestsSent.Has(id)) |
|
|
|
assert.True(sw.Peers().Has(peer.ID())) |
|
|
|
assert.True(t, r.requestsSent.Has(id)) |
|
|
|
assert.True(t, sw.Peers().Has(peer.ID())) |
|
|
|
|
|
|
|
addrs := []*p2p.NetAddress{peer.NodeInfo().NetAddress()} |
|
|
|
msg := wire.BinaryBytes(struct{ PexMessage }{&pexAddrsMessage{Addrs: addrs}}) |
|
|
|
|
|
|
|
// receive some addrs. should clear the request
|
|
|
|
r.Receive(PexChannel, peer, msg) |
|
|
|
assert.False(r.requestsSent.Has(id)) |
|
|
|
assert.True(sw.Peers().Has(peer.ID())) |
|
|
|
assert.False(t, r.requestsSent.Has(id)) |
|
|
|
assert.True(t, sw.Peers().Has(peer.ID())) |
|
|
|
|
|
|
|
// receiving more addrs causes a disconnect
|
|
|
|
r.Receive(PexChannel, peer, msg) |
|
|
|
assert.False(sw.Peers().Has(peer.ID())) |
|
|
|
assert.False(t, sw.Peers().Has(peer.ID())) |
|
|
|
} |
|
|
|
|
|
|
|
func TestPEXReactorUsesSeedsIfNeeded(t *testing.T) { |
|
|
|
|
|
|
|
dir, err := ioutil.TempDir("", "pex_reactor") |
|
|
|
require.Nil(t, err) |
|
|
|
defer os.RemoveAll(dir) // nolint: errcheck
|
|
|
|
|
|
|
|
book := NewAddrBook(dir+"addrbook.json", false) |
|
|
|
book := NewAddrBook(filepath.Join(dir, "addrbook.json"), false) |
|
|
|
book.SetLogger(log.TestingLogger()) |
|
|
|
|
|
|
|
// 1. create seed
|
|
|
@ -288,22 +243,11 @@ func TestPEXReactorUsesSeedsIfNeeded(t *testing.T) { |
|
|
|
} |
|
|
|
|
|
|
|
func TestPEXReactorCrawlStatus(t *testing.T) { |
|
|
|
assert, require := assert.New(t), require.New(t) |
|
|
|
pexR, book := createReactor(&PEXReactorConfig{SeedMode: true}) |
|
|
|
defer teardownReactor(book) |
|
|
|
|
|
|
|
dir, err := ioutil.TempDir("", "pex_reactor") |
|
|
|
require.Nil(err) |
|
|
|
defer os.RemoveAll(dir) // nolint: errcheck
|
|
|
|
book := NewAddrBook(dir+"addrbook.json", false) |
|
|
|
book.SetLogger(log.TestingLogger()) |
|
|
|
|
|
|
|
pexR := NewPEXReactor(book, &PEXReactorConfig{SeedMode: true}) |
|
|
|
// Seed/Crawler mode uses data from the Switch
|
|
|
|
p2p.MakeSwitch(config, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { |
|
|
|
pexR.SetLogger(log.TestingLogger()) |
|
|
|
sw.SetLogger(log.TestingLogger().With("switch", i)) |
|
|
|
sw.AddReactor("pex", pexR) |
|
|
|
return sw |
|
|
|
}) |
|
|
|
_ = createSwitchAndAddReactors(pexR) |
|
|
|
|
|
|
|
// Create a peer, add it to the peer set and the addrbook.
|
|
|
|
peer := p2p.CreateRandomPeer(false) |
|
|
@ -319,11 +263,34 @@ func TestPEXReactorCrawlStatus(t *testing.T) { |
|
|
|
peerInfos := pexR.getPeersToCrawl() |
|
|
|
|
|
|
|
// Make sure it has the proper number of elements
|
|
|
|
assert.Equal(2, len(peerInfos)) |
|
|
|
assert.Equal(t, 2, len(peerInfos)) |
|
|
|
|
|
|
|
// TODO: test
|
|
|
|
} |
|
|
|
|
|
|
|
func TestPEXReactorDialPeer(t *testing.T) { |
|
|
|
pexR, book := createReactor(&PEXReactorConfig{}) |
|
|
|
defer teardownReactor(book) |
|
|
|
|
|
|
|
_ = createSwitchAndAddReactors(pexR) |
|
|
|
|
|
|
|
peer := newMockPeer() |
|
|
|
addr := peer.NodeInfo().NetAddress() |
|
|
|
|
|
|
|
assert.Equal(t, 0, pexR.AttemptsToDial(addr)) |
|
|
|
|
|
|
|
// 1st unsuccessful attempt
|
|
|
|
pexR.dialPeer(addr) |
|
|
|
|
|
|
|
assert.Equal(t, 1, pexR.AttemptsToDial(addr)) |
|
|
|
|
|
|
|
// 2nd unsuccessful attempt
|
|
|
|
pexR.dialPeer(addr) |
|
|
|
|
|
|
|
// must be skipped because it is too early
|
|
|
|
assert.Equal(t, 1, pexR.AttemptsToDial(addr)) |
|
|
|
} |
|
|
|
|
|
|
|
type mockPeer struct { |
|
|
|
*cmn.BaseService |
|
|
|
pubKey crypto.PubKey |
|
|
@ -400,3 +367,33 @@ func assertPeersWithTimeout( |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func createReactor(config *PEXReactorConfig) (r *PEXReactor, book *addrBook) { |
|
|
|
dir, err := ioutil.TempDir("", "pex_reactor") |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
book = NewAddrBook(filepath.Join(dir, "addrbook.json"), true) |
|
|
|
book.SetLogger(log.TestingLogger()) |
|
|
|
|
|
|
|
r = NewPEXReactor(book, &PEXReactorConfig{}) |
|
|
|
r.SetLogger(log.TestingLogger()) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
func teardownReactor(book *addrBook) { |
|
|
|
err := os.RemoveAll(filepath.Dir(book.FilePath())) |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func createSwitchAndAddReactors(reactors ...p2p.Reactor) *p2p.Switch { |
|
|
|
sw := p2p.MakeSwitch(config, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { return sw }) |
|
|
|
sw.SetLogger(log.TestingLogger()) |
|
|
|
for _, r := range reactors { |
|
|
|
sw.AddReactor(r.String(), r) |
|
|
|
r.SetSwitch(sw) |
|
|
|
} |
|
|
|
return sw |
|
|
|
} |