go-libp2p-kad-dht/dht_test.go

562 lines
11 KiB
Go
Raw Normal View History

package dht
2014-09-19 07:51:03 -07:00
import (
2014-09-19 14:31:10 -07:00
"bytes"
2014-12-16 14:35:52 -08:00
"math/rand"
2014-11-24 14:58:51 -05:00
"sort"
2014-09-19 07:51:03 -07:00
"testing"
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
2014-10-21 15:10:58 -07:00
ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
2014-09-19 07:51:03 -07:00
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
ci "github.com/jbenet/go-ipfs/crypto"
inet "github.com/jbenet/go-ipfs/net"
peer "github.com/jbenet/go-ipfs/peer"
u "github.com/jbenet/go-ipfs/util"
testutil "github.com/jbenet/go-ipfs/util/testutil"
2014-09-19 07:51:03 -07:00
"fmt"
"time"
)
2014-12-16 14:35:52 -08:00
func randMultiaddr(t *testing.T) ma.Multiaddr {
s := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", 10000+rand.Intn(40000))
a, err := ma.NewMultiaddr(s)
if err != nil {
t.Fatal(err)
}
return a
}
func setupDHT(ctx context.Context, t *testing.T, p peer.Peer) *IpfsDHT {
2014-09-19 07:51:03 -07:00
peerstore := peer.NewPeerstore()
2014-12-16 08:55:46 -08:00
n, err := inet.NewNetwork(ctx, p.Addresses(), p, peerstore)
2014-09-19 07:51:03 -07:00
if err != nil {
t.Fatal(err)
}
2014-12-16 08:55:46 -08:00
d := NewDHT(ctx, p, peerstore, n, ds.NewMapDatastore())
2014-11-10 14:22:56 -08:00
d.Validators["v"] = func(u.Key, []byte) error {
return nil
}
2014-09-19 07:51:03 -07:00
return d
}
func setupDHTS(ctx context.Context, n int, t *testing.T) ([]ma.Multiaddr, []peer.Peer, []*IpfsDHT) {
2014-10-06 04:13:39 -07:00
var addrs []ma.Multiaddr
2014-09-19 14:31:10 -07:00
for i := 0; i < n; i++ {
2014-12-16 14:35:52 -08:00
r := rand.Intn(40000)
a, err := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", 10000+r))
2014-09-19 07:51:03 -07:00
if err != nil {
t.Fatal(err)
}
addrs = append(addrs, a)
}
var peers []peer.Peer
2014-09-19 14:31:10 -07:00
for i := 0; i < n; i++ {
2014-09-19 07:51:03 -07:00
p := makePeer(addrs[i])
peers = append(peers, p)
}
2014-09-19 14:31:10 -07:00
dhts := make([]*IpfsDHT, n)
for i := 0; i < n; i++ {
2014-10-18 04:19:12 -07:00
dhts[i] = setupDHT(ctx, t, peers[i])
2014-09-19 07:51:03 -07:00
}
return addrs, peers, dhts
}
func makePeerString(t *testing.T, addr string) peer.Peer {
maddr, err := ma.NewMultiaddr(addr)
if err != nil {
t.Fatal(err)
}
return makePeer(maddr)
}
func makePeer(addr ma.Multiaddr) peer.Peer {
2014-09-19 07:51:03 -07:00
sk, pk, err := ci.GenerateKeyPair(ci.RSA, 512)
if err != nil {
panic(err)
}
p, err := testutil.NewPeerWithKeyPair(sk, pk)
2014-09-19 07:51:03 -07:00
if err != nil {
panic(err)
}
p.AddAddress(addr)
2014-09-19 07:51:03 -07:00
return p
}
func TestPing(t *testing.T) {
2014-09-19 18:11:05 -07:00
// t.Skip("skipping test to debug another")
2014-10-18 04:19:12 -07:00
ctx := context.Background()
2014-12-16 14:35:52 -08:00
addrA := randMultiaddr(t)
addrB := randMultiaddr(t)
2014-09-19 07:51:03 -07:00
peerA := makePeer(addrA)
peerB := makePeer(addrB)
2014-10-18 04:19:12 -07:00
dhtA := setupDHT(ctx, t, peerA)
dhtB := setupDHT(ctx, t, peerB)
2014-09-19 07:51:03 -07:00
2014-10-25 07:12:01 -07:00
defer dhtA.Close()
defer dhtB.Close()
2014-12-16 08:55:46 -08:00
defer dhtA.network.Close()
defer dhtB.network.Close()
2014-09-19 07:51:03 -07:00
2014-12-16 14:35:52 -08:00
if err := dhtA.Connect(ctx, peerB); err != nil {
2014-09-19 07:51:03 -07:00
t.Fatal(err)
}
2014-12-16 14:35:52 -08:00
// if err := dhtB.Connect(ctx, peerA); err != nil {
// t.Fatal(err)
// }
2014-09-19 07:51:03 -07:00
//Test that we can ping the node
2014-10-19 02:05:29 -07:00
ctxT, _ := context.WithTimeout(ctx, 100*time.Millisecond)
2014-12-16 14:35:52 -08:00
if err := dhtA.Ping(ctxT, peerB); err != nil {
2014-09-19 07:51:03 -07:00
t.Fatal(err)
}
2014-10-19 02:05:29 -07:00
ctxT, _ = context.WithTimeout(ctx, 100*time.Millisecond)
2014-12-16 14:35:52 -08:00
if err := dhtB.Ping(ctxT, peerA); err != nil {
t.Fatal(err)
}
2014-09-19 07:51:03 -07:00
}
func TestValueGetSet(t *testing.T) {
2014-09-19 18:11:05 -07:00
// t.Skip("skipping test to debug another")
2014-10-18 04:19:12 -07:00
ctx := context.Background()
2014-12-16 14:35:52 -08:00
addrA := randMultiaddr(t)
addrB := randMultiaddr(t)
2014-09-19 07:51:03 -07:00
peerA := makePeer(addrA)
peerB := makePeer(addrB)
2014-10-18 04:19:12 -07:00
dhtA := setupDHT(ctx, t, peerA)
dhtB := setupDHT(ctx, t, peerB)
2014-09-19 07:51:03 -07:00
2014-11-10 14:22:56 -08:00
vf := func(u.Key, []byte) error {
return nil
}
dhtA.Validators["v"] = vf
dhtB.Validators["v"] = vf
2014-10-25 07:12:01 -07:00
defer dhtA.Close()
defer dhtB.Close()
2014-12-16 08:55:46 -08:00
defer dhtA.network.Close()
defer dhtB.network.Close()
2014-09-19 07:51:03 -07:00
2014-12-16 14:35:52 -08:00
err := dhtA.Connect(ctx, peerB)
2014-09-19 07:51:03 -07:00
if err != nil {
t.Fatal(err)
}
2014-10-18 04:19:12 -07:00
ctxT, _ := context.WithTimeout(ctx, time.Second)
2014-11-10 14:22:56 -08:00
dhtA.PutValue(ctxT, "/v/hello", []byte("world"))
2014-09-19 07:51:03 -07:00
2014-10-18 04:19:12 -07:00
ctxT, _ = context.WithTimeout(ctx, time.Second*2)
2014-11-10 14:22:56 -08:00
val, err := dhtA.GetValue(ctxT, "/v/hello")
2014-09-19 07:51:03 -07:00
if err != nil {
t.Fatal(err)
}
if string(val) != "world" {
t.Fatalf("Expected 'world' got '%s'", string(val))
}
2014-10-18 04:19:12 -07:00
ctxT, _ = context.WithTimeout(ctx, time.Second*2)
2014-11-10 14:22:56 -08:00
val, err = dhtB.GetValue(ctxT, "/v/hello")
if err != nil {
t.Fatal(err)
}
if string(val) != "world" {
t.Fatalf("Expected 'world' got '%s'", string(val))
}
2014-09-19 07:51:03 -07:00
}
2014-09-19 18:11:05 -07:00
func TestProvides(t *testing.T) {
// t.Skip("skipping test to debug another")
2014-10-18 04:19:12 -07:00
ctx := context.Background()
2014-09-19 18:11:05 -07:00
2014-10-18 04:19:12 -07:00
_, peers, dhts := setupDHTS(ctx, 4, t)
2014-09-19 18:11:05 -07:00
defer func() {
for i := 0; i < 4; i++ {
2014-10-25 07:12:01 -07:00
dhts[i].Close()
2014-12-16 08:55:46 -08:00
defer dhts[i].network.Close()
2014-09-19 18:11:05 -07:00
}
}()
err := dhts[0].Connect(ctx, peers[1])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
err = dhts[1].Connect(ctx, peers[2])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
err = dhts[1].Connect(ctx, peers[3])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
err = dhts[3].putLocal(u.Key("hello"), []byte("world"))
if err != nil {
t.Fatal(err)
}
bits, err := dhts[3].getLocal(u.Key("hello"))
if err != nil && bytes.Equal(bits, []byte("world")) {
t.Fatal(err)
}
2014-10-18 04:19:12 -07:00
err = dhts[3].Provide(ctx, u.Key("hello"))
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
time.Sleep(time.Millisecond * 60)
2014-10-18 04:19:12 -07:00
ctxT, _ := context.WithTimeout(ctx, time.Second)
2014-10-11 10:43:54 -07:00
provchan := dhts[0].FindProvidersAsync(ctxT, u.Key("hello"), 1)
2014-09-19 18:11:05 -07:00
2014-10-11 10:43:54 -07:00
after := time.After(time.Second)
select {
case prov := <-provchan:
if prov == nil {
t.Fatal("Got back nil provider")
}
case <-after:
t.Fatal("Did not get a provider back.")
2014-09-19 18:11:05 -07:00
}
}
func TestProvidesAsync(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
2014-10-18 04:19:12 -07:00
ctx := context.Background()
2014-10-18 04:19:12 -07:00
_, peers, dhts := setupDHTS(ctx, 4, t)
defer func() {
for i := 0; i < 4; i++ {
2014-10-25 07:12:01 -07:00
dhts[i].Close()
2014-12-16 08:55:46 -08:00
defer dhts[i].network.Close()
}
}()
err := dhts[0].Connect(ctx, peers[1])
if err != nil {
t.Fatal(err)
}
err = dhts[1].Connect(ctx, peers[2])
if err != nil {
t.Fatal(err)
}
err = dhts[1].Connect(ctx, peers[3])
if err != nil {
t.Fatal(err)
}
err = dhts[3].putLocal(u.Key("hello"), []byte("world"))
if err != nil {
t.Fatal(err)
}
bits, err := dhts[3].getLocal(u.Key("hello"))
if err != nil && bytes.Equal(bits, []byte("world")) {
t.Fatal(err)
}
2014-10-18 04:19:12 -07:00
err = dhts[3].Provide(ctx, u.Key("hello"))
if err != nil {
t.Fatal(err)
}
time.Sleep(time.Millisecond * 60)
2014-10-18 04:19:12 -07:00
ctxT, _ := context.WithTimeout(ctx, time.Millisecond*300)
provs := dhts[0].FindProvidersAsync(ctxT, u.Key("hello"), 5)
select {
2014-10-24 18:32:28 -07:00
case p, ok := <-provs:
if !ok {
t.Fatal("Provider channel was closed...")
}
if p == nil {
t.Fatal("Got back nil provider!")
}
if !p.ID().Equal(dhts[3].self.ID()) {
t.Fatalf("got a provider, but not the right one. %s", p)
}
2014-10-18 04:19:12 -07:00
case <-ctxT.Done():
t.Fatal("Didnt get back providers")
}
}
2014-09-19 18:11:05 -07:00
func TestLayeredGet(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
2014-09-19 18:11:05 -07:00
2014-10-18 04:19:12 -07:00
ctx := context.Background()
2014-12-16 14:35:52 -08:00
2014-10-18 04:19:12 -07:00
_, peers, dhts := setupDHTS(ctx, 4, t)
2014-09-19 18:11:05 -07:00
defer func() {
for i := 0; i < 4; i++ {
2014-10-25 07:12:01 -07:00
dhts[i].Close()
2014-12-16 08:55:46 -08:00
defer dhts[i].network.Close()
2014-09-19 18:11:05 -07:00
}
}()
err := dhts[0].Connect(ctx, peers[1])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatalf("Failed to connect: %s", err)
}
err = dhts[1].Connect(ctx, peers[2])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
err = dhts[1].Connect(ctx, peers[3])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
2014-11-10 14:22:56 -08:00
err = dhts[3].putLocal(u.Key("/v/hello"), []byte("world"))
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
2014-11-10 14:22:56 -08:00
err = dhts[3].Provide(ctx, u.Key("/v/hello"))
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
time.Sleep(time.Millisecond * 60)
2014-10-18 04:19:12 -07:00
ctxT, _ := context.WithTimeout(ctx, time.Second)
2014-11-10 14:22:56 -08:00
val, err := dhts[0].GetValue(ctxT, u.Key("/v/hello"))
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
if string(val) != "world" {
t.Fatal("Got incorrect value.")
}
}
func TestFindPeer(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
2014-09-19 18:11:05 -07:00
2014-10-18 04:19:12 -07:00
ctx := context.Background()
2014-09-19 18:11:05 -07:00
2014-10-18 04:19:12 -07:00
_, peers, dhts := setupDHTS(ctx, 4, t)
2014-09-19 18:11:05 -07:00
defer func() {
for i := 0; i < 4; i++ {
2014-10-25 07:12:01 -07:00
dhts[i].Close()
2014-12-16 08:55:46 -08:00
dhts[i].network.Close()
2014-09-19 18:11:05 -07:00
}
}()
err := dhts[0].Connect(ctx, peers[1])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
err = dhts[1].Connect(ctx, peers[2])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
err = dhts[1].Connect(ctx, peers[3])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
2014-10-18 04:19:12 -07:00
ctxT, _ := context.WithTimeout(ctx, time.Second)
p, err := dhts[0].FindPeer(ctxT, peers[2].ID())
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
if p == nil {
t.Fatal("Failed to find peer.")
}
if !p.ID().Equal(peers[2].ID()) {
2014-09-19 18:11:05 -07:00
t.Fatal("Didnt find expected peer.")
}
}
2014-11-24 14:58:51 -05:00
func TestFindPeersConnectedToPeer(t *testing.T) {
2014-12-16 14:35:52 -08:00
t.Skip("not quite correct (see note)")
2014-11-24 14:58:51 -05:00
if testing.Short() {
t.SkipNow()
}
ctx := context.Background()
_, peers, dhts := setupDHTS(ctx, 4, t)
defer func() {
for i := 0; i < 4; i++ {
dhts[i].Close()
2014-12-16 08:55:46 -08:00
dhts[i].network.Close()
2014-11-24 14:58:51 -05:00
}
}()
// topology:
// 0-1, 1-2, 1-3, 2-3
err := dhts[0].Connect(ctx, peers[1])
if err != nil {
t.Fatal(err)
}
err = dhts[1].Connect(ctx, peers[2])
if err != nil {
t.Fatal(err)
}
err = dhts[1].Connect(ctx, peers[3])
if err != nil {
t.Fatal(err)
}
err = dhts[2].Connect(ctx, peers[3])
if err != nil {
t.Fatal(err)
}
// fmt.Println("0 is", peers[0])
// fmt.Println("1 is", peers[1])
// fmt.Println("2 is", peers[2])
// fmt.Println("3 is", peers[3])
ctxT, _ := context.WithTimeout(ctx, time.Second)
pchan, err := dhts[0].FindPeersConnectedToPeer(ctxT, peers[2].ID())
if err != nil {
t.Fatal(err)
}
// shouldFind := []peer.Peer{peers[1], peers[3]}
found := []peer.Peer{}
for nextp := range pchan {
found = append(found, nextp)
}
// fmt.Printf("querying 0 (%s) FindPeersConnectedToPeer 2 (%s)\n", peers[0], peers[2])
// fmt.Println("should find 1, 3", shouldFind)
// fmt.Println("found", found)
// testPeerListsMatch(t, shouldFind, found)
log.Warning("TestFindPeersConnectedToPeer is not quite correct")
if len(found) == 0 {
t.Fatal("didn't find any peers.")
}
}
func testPeerListsMatch(t *testing.T, p1, p2 []peer.Peer) {
if len(p1) != len(p2) {
t.Fatal("did not find as many peers as should have", p1, p2)
}
ids1 := make([]string, len(p1))
ids2 := make([]string, len(p2))
for i, p := range p1 {
ids1[i] = p.ID().Pretty()
}
for i, p := range p2 {
ids2[i] = p.ID().Pretty()
}
sort.Sort(sort.StringSlice(ids1))
sort.Sort(sort.StringSlice(ids2))
for i := range ids1 {
if ids1[i] != ids2[i] {
t.Fatal("Didnt find expected peer", ids1[i], ids2)
}
}
}
func TestConnectCollision(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
2014-10-19 06:29:18 -07:00
runTimes := 10
2014-10-19 02:05:29 -07:00
for rtime := 0; rtime < runTimes; rtime++ {
log.Notice("Running Time: ", rtime)
2014-10-19 02:05:29 -07:00
ctx := context.Background()
2014-12-16 14:35:52 -08:00
addrA := randMultiaddr(t)
addrB := randMultiaddr(t)
2014-10-19 02:05:29 -07:00
peerA := makePeer(addrA)
peerB := makePeer(addrB)
dhtA := setupDHT(ctx, t, peerA)
dhtB := setupDHT(ctx, t, peerB)
done := make(chan struct{})
go func() {
err := dhtA.Connect(ctx, peerB)
2014-10-19 02:05:29 -07:00
if err != nil {
t.Fatal(err)
}
done <- struct{}{}
}()
go func() {
err := dhtB.Connect(ctx, peerA)
2014-10-19 02:05:29 -07:00
if err != nil {
t.Fatal(err)
}
done <- struct{}{}
}()
timeout := time.After(time.Second)
select {
case <-done:
case <-timeout:
t.Fatal("Timeout received!")
}
select {
case <-done:
case <-timeout:
t.Fatal("Timeout received!")
}
2014-10-25 07:12:01 -07:00
dhtA.Close()
dhtB.Close()
2014-12-16 08:55:46 -08:00
dhtA.network.Close()
dhtB.network.Close()
2014-10-19 06:29:18 -07:00
<-time.After(200 * time.Millisecond)
2014-10-14 17:46:11 -07:00
}
}