go-libp2p-kad-dht/dht_test.go

479 lines
9.8 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-11-24 14:58:51 -05:00
"sort"
2014-09-19 07:51:03 -07:00
"testing"
"time"
2014-09-19 07:51:03 -07:00
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"
dssync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
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"
2014-09-19 07:51:03 -07:00
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
)
func setupDHT(ctx context.Context, t *testing.T, addr ma.Multiaddr) *IpfsDHT {
2014-12-16 14:35:52 -08:00
sk, pk, err := testutil.RandKeyPair(512)
if err != nil {
t.Fatal(err)
}
p, err := peer.IDFromPublicKey(pk)
2014-12-16 14:35:52 -08:00
if err != nil {
t.Fatal(err)
}
2014-09-19 07:51:03 -07:00
peerstore := peer.NewPeerstore()
peerstore.AddPrivKey(p, sk)
peerstore.AddPubKey(p, pk)
peerstore.AddAddress(p, addr)
2014-09-19 07:51:03 -07:00
n, err := inet.NewNetwork(ctx, []ma.Multiaddr{addr}, p, peerstore)
2014-09-19 07:51:03 -07:00
if err != nil {
t.Fatal(err)
}
dss := dssync.MutexWrap(ds.NewMapDatastore())
d := NewDHT(ctx, p, n, dss)
2014-12-16 08:55:46 -08:00
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.ID, []*IpfsDHT) {
addrs := make([]ma.Multiaddr, n)
2014-09-19 14:31:10 -07:00
dhts := make([]*IpfsDHT, n)
peers := make([]peer.ID, n)
2014-09-19 14:31:10 -07:00
for i := 0; i < n; i++ {
addrs[i] = testutil.RandLocalTCPAddress()
dhts[i] = setupDHT(ctx, t, addrs[i])
peers[i] = dhts[i].self
2014-09-19 07:51:03 -07:00
}
return addrs, peers, dhts
}
func connect(t *testing.T, ctx context.Context, a, b *IpfsDHT) {
idB := b.self
addrB := b.peerstore.Addresses(idB)
if len(addrB) == 0 {
t.Fatal("peers setup incorrectly: no local address")
2014-09-19 07:51:03 -07:00
}
a.peerstore.AddAddresses(idB, addrB)
if err := a.Connect(ctx, idB); err != nil {
t.Fatal(err)
2014-09-19 07:51:03 -07:00
}
}
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 := testutil.RandLocalTCPAddress()
addrB := testutil.RandLocalTCPAddress()
2014-09-19 07:51:03 -07:00
dhtA := setupDHT(ctx, t, addrA)
dhtB := setupDHT(ctx, t, addrB)
2014-09-19 07:51:03 -07:00
peerA := dhtA.self
peerB := dhtB.self
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
connect(t, ctx, dhtA, dhtB)
2014-12-16 14:35:52 -08:00
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 := testutil.RandLocalTCPAddress()
addrB := testutil.RandLocalTCPAddress()
2014-09-19 07:51:03 -07:00
dhtA := setupDHT(ctx, t, addrA)
dhtB := setupDHT(ctx, t, addrB)
2014-09-19 07:51:03 -07:00
defer dhtA.Close()
defer dhtB.Close()
defer dhtA.network.Close()
defer dhtB.network.Close()
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
connect(t, ctx, dhtA, dhtB)
2014-09-19 07:51:03 -07:00
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
_, _, 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
}
}()
connect(t, ctx, dhts[0], dhts[1])
connect(t, ctx, dhts[1], dhts[2])
connect(t, ctx, dhts[1], dhts[3])
2014-09-19 18:11:05 -07:00
err := dhts[3].putLocal(u.Key("hello"), []byte("world"))
2014-09-19 18:11:05 -07:00
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)
}
// what is this timeout for? was 60ms before.
time.Sleep(time.Millisecond * 6)
2014-09-19 18:11:05 -07:00
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
select {
case prov := <-provchan:
if prov.ID == "" {
2014-10-11 10:43:54 -07:00
t.Fatal("Got back nil provider")
}
if prov.ID != dhts[3].self {
t.Fatal("Got back nil provider")
}
case <-ctxT.Done():
2014-10-11 10:43:54 -07:00
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()
_, _, 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()
}
}()
connect(t, ctx, dhts[0], dhts[1])
connect(t, ctx, dhts[1], dhts[2])
connect(t, ctx, dhts[1], dhts[3])
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.ID == "" {
2014-10-24 18:32:28 -07:00
t.Fatal("Got back nil provider!")
}
if p.ID != dhts[3].self {
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
_, _, 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
}
}()
connect(t, ctx, dhts[0], dhts[1])
connect(t, ctx, dhts[1], dhts[2])
connect(t, ctx, dhts[1], dhts[3])
2014-09-19 18:11:05 -07: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
}
}()
connect(t, ctx, dhts[0], dhts[1])
connect(t, ctx, dhts[1], dhts[2])
connect(t, ctx, dhts[1], dhts[3])
2014-09-19 18:11:05 -07:00
2014-10-18 04:19:12 -07:00
ctxT, _ := context.WithTimeout(ctx, time.Second)
p, err := dhts[0].FindPeer(ctxT, peers[2])
2014-09-19 18:11:05 -07:00
if err != nil {
t.Fatal(err)
}
if p.ID == "" {
2014-09-19 18:11:05 -07:00
t.Fatal("Failed to find peer.")
}
if p.ID != peers[2] {
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
connect(t, ctx, dhts[0], dhts[1])
connect(t, ctx, dhts[1], dhts[2])
connect(t, ctx, dhts[1], dhts[3])
connect(t, ctx, dhts[2], dhts[3])
2014-11-24 14:58:51 -05:00
// 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])
2014-11-24 14:58:51 -05:00
if err != nil {
t.Fatal(err)
}
// shouldFind := []peer.ID{peers[1], peers[3]}
found := []peer.PeerInfo{}
2014-11-24 14:58:51 -05:00
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.ID) {
2014-11-24 14:58:51 -05:00
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] = string(p)
2014-11-24 14:58:51 -05:00
}
for i, p := range p2 {
ids2[i] = string(p)
2014-11-24 14:58:51 -05:00
}
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 := testutil.RandLocalTCPAddress()
addrB := testutil.RandLocalTCPAddress()
dhtA := setupDHT(ctx, t, addrA)
dhtB := setupDHT(ctx, t, addrB)
2014-10-19 02:05:29 -07:00
peerA := dhtA.self
peerB := dhtB.self
2014-10-19 02:05:29 -07:00
errs := make(chan error)
2014-10-19 02:05:29 -07:00
go func() {
dhtA.peerstore.AddAddress(peerB, addrB)
err := dhtA.Connect(ctx, peerB)
errs <- err
2014-10-19 02:05:29 -07:00
}()
go func() {
dhtB.peerstore.AddAddress(peerA, addrA)
err := dhtB.Connect(ctx, peerA)
errs <- err
2014-10-19 02:05:29 -07:00
}()
timeout := time.After(time.Second)
select {
case e := <-errs:
if e != nil {
t.Fatal(e)
}
2014-10-19 02:05:29 -07:00
case <-timeout:
t.Fatal("Timeout received!")
}
select {
case e := <-errs:
if e != nil {
t.Fatal(e)
}
2014-10-19 02:05:29 -07:00
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-14 17:46:11 -07:00
}
}