2014-08-10 21:40:17 -07:00
|
|
|
package dht
|
|
|
|
|
|
|
|
import (
|
2014-12-16 14:35:52 -08:00
|
|
|
"math/rand"
|
2014-08-10 21:40:17 -07:00
|
|
|
"testing"
|
|
|
|
|
2014-11-20 18:45:05 -08:00
|
|
|
inet "github.com/jbenet/go-ipfs/net"
|
2014-12-17 08:04:02 -08:00
|
|
|
mocknet "github.com/jbenet/go-ipfs/net/mock"
|
2014-12-29 05:43:56 -08:00
|
|
|
peer "github.com/jbenet/go-ipfs/p2p/peer"
|
2014-12-08 14:32:52 -08:00
|
|
|
routing "github.com/jbenet/go-ipfs/routing"
|
2014-10-25 04:13:28 -07:00
|
|
|
pb "github.com/jbenet/go-ipfs/routing/dht/pb"
|
2014-08-11 09:06:20 -07:00
|
|
|
u "github.com/jbenet/go-ipfs/util"
|
2014-08-10 21:40:17 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
2014-12-17 08:02:59 -08:00
|
|
|
ggio "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/gogoprotobuf/io"
|
2014-12-16 14:35:52 -08:00
|
|
|
ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
|
2014-12-19 12:19:56 -08:00
|
|
|
dssync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
|
2014-12-16 14:35:52 -08:00
|
|
|
|
2014-08-10 21:40:17 -07:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2014-08-11 09:06:20 -07:00
|
|
|
func TestGetFailures(t *testing.T) {
|
2014-11-15 00:19:47 -08:00
|
|
|
if testing.Short() {
|
|
|
|
t.SkipNow()
|
|
|
|
}
|
2014-09-19 18:11:05 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
ctx := context.Background()
|
2014-12-17 08:02:59 -08:00
|
|
|
mn, err := mocknet.FullMeshConnected(ctx, 2)
|
2014-12-16 14:35:52 -08:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-12-17 08:02:59 -08:00
|
|
|
nets := mn.Nets()
|
|
|
|
peers := mn.Peers()
|
2014-11-20 18:45:05 -08:00
|
|
|
|
2014-12-19 12:19:56 -08:00
|
|
|
tsds := dssync.MutexWrap(ds.NewMapDatastore())
|
|
|
|
d := NewDHT(ctx, peers[0], nets[0], tsds)
|
2014-12-16 14:35:52 -08:00
|
|
|
d.Update(ctx, peers[1])
|
2014-08-11 09:06:20 -07:00
|
|
|
|
|
|
|
// This one should time out
|
2014-09-18 19:30:04 -07:00
|
|
|
// u.POut("Timout Test\n")
|
2014-09-21 18:04:43 -07:00
|
|
|
ctx1, _ := context.WithTimeout(context.Background(), time.Second)
|
2014-12-16 14:35:52 -08:00
|
|
|
if _, err := d.GetValue(ctx1, u.Key("test")); err != nil {
|
2014-09-18 19:30:04 -07:00
|
|
|
if err != context.DeadlineExceeded {
|
|
|
|
t.Fatal("Got different error than we expected", err)
|
2014-08-11 09:06:20 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Fatal("Did not get expected error!")
|
2014-08-10 21:40:17 -07:00
|
|
|
}
|
|
|
|
|
2014-12-14 00:50:49 +00:00
|
|
|
t.Log("Timeout test passed.")
|
2014-12-16 14:35:52 -08:00
|
|
|
|
2014-08-11 20:11:23 -07:00
|
|
|
// Reply with failures to every message
|
2014-12-16 14:35:52 -08:00
|
|
|
nets[1].SetHandler(inet.ProtocolDHT, func(s inet.Stream) {
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
|
|
|
|
pbw := ggio.NewDelimitedWriter(s)
|
|
|
|
|
2014-10-25 04:13:28 -07:00
|
|
|
pmes := new(pb.Message)
|
2014-12-16 14:35:52 -08:00
|
|
|
if err := pbr.ReadMsg(pmes); err != nil {
|
|
|
|
panic(err)
|
2014-08-11 09:06:20 -07:00
|
|
|
}
|
|
|
|
|
2014-10-25 04:13:28 -07:00
|
|
|
resp := &pb.Message{
|
2014-09-17 10:30:38 -07:00
|
|
|
Type: pmes.Type,
|
2014-08-11 09:06:20 -07:00
|
|
|
}
|
2014-12-16 14:35:52 -08:00
|
|
|
if err := pbw.WriteMsg(resp); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2014-08-11 09:06:20 -07:00
|
|
|
})
|
|
|
|
|
|
|
|
// This one should fail with NotFound
|
2014-12-24 03:24:28 -08:00
|
|
|
ctx2, _ := context.WithTimeout(context.Background(), 3*time.Second)
|
2014-09-21 18:04:43 -07:00
|
|
|
_, err = d.GetValue(ctx2, u.Key("test"))
|
2014-08-11 09:06:20 -07:00
|
|
|
if err != nil {
|
2014-10-28 02:17:46 -07:00
|
|
|
if err != routing.ErrNotFound {
|
2014-08-15 09:39:38 -07:00
|
|
|
t.Fatalf("Expected ErrNotFound, got: %s", err)
|
2014-08-11 09:06:20 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Fatal("expected error, got none.")
|
|
|
|
}
|
2014-08-11 20:11:23 -07:00
|
|
|
|
2014-12-14 00:50:49 +00:00
|
|
|
t.Log("ErrNotFound check passed!")
|
|
|
|
|
2014-08-11 20:11:23 -07:00
|
|
|
// Now we test this DHT's handleGetValue failure
|
2014-12-16 14:35:52 -08:00
|
|
|
{
|
|
|
|
typ := pb.Message_GET_VALUE
|
|
|
|
str := "hello"
|
|
|
|
rec, err := d.makePutRecord(u.Key(str), []byte("blah"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
req := pb.Message{
|
|
|
|
Type: &typ,
|
|
|
|
Key: &str,
|
|
|
|
Record: rec,
|
|
|
|
}
|
2014-09-17 10:30:38 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
// u.POut("handleGetValue Test\n")
|
|
|
|
s, err := nets[1].NewStream(inet.ProtocolDHT, peers[0])
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer s.Close()
|
2014-09-17 10:30:38 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
|
|
|
|
pbw := ggio.NewDelimitedWriter(s)
|
2014-08-11 20:11:23 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
if err := pbw.WriteMsg(&req); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-09-18 19:30:04 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
pmes := new(pb.Message)
|
|
|
|
if err := pbr.ReadMsg(pmes); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if pmes.GetRecord() != nil {
|
|
|
|
t.Fatal("shouldnt have value")
|
|
|
|
}
|
|
|
|
if pmes.GetProviderPeers() != nil {
|
|
|
|
t.Fatal("shouldnt have provider peers")
|
|
|
|
}
|
|
|
|
}
|
2014-08-10 21:40:17 -07:00
|
|
|
}
|
2014-08-19 19:14:52 -07:00
|
|
|
|
|
|
|
func TestNotFound(t *testing.T) {
|
2014-11-15 00:19:47 -08:00
|
|
|
if testing.Short() {
|
|
|
|
t.SkipNow()
|
|
|
|
}
|
2014-09-19 18:11:05 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
ctx := context.Background()
|
2014-12-17 08:02:59 -08:00
|
|
|
mn, err := mocknet.FullMeshConnected(ctx, 16)
|
2014-12-16 14:35:52 -08:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-12-17 08:02:59 -08:00
|
|
|
nets := mn.Nets()
|
|
|
|
peers := mn.Peers()
|
2014-12-19 12:19:56 -08:00
|
|
|
tsds := dssync.MutexWrap(ds.NewMapDatastore())
|
|
|
|
d := NewDHT(ctx, peers[0], nets[0], tsds)
|
2014-08-19 19:14:52 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
for _, p := range peers {
|
|
|
|
d.Update(ctx, p)
|
2014-08-19 19:14:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reply with random peers to every message
|
2014-12-16 14:35:52 -08:00
|
|
|
for _, neti := range nets {
|
2014-12-19 12:19:56 -08:00
|
|
|
neti := neti // shadow loop var
|
2014-12-16 14:35:52 -08:00
|
|
|
neti.SetHandler(inet.ProtocolDHT, func(s inet.Stream) {
|
|
|
|
defer s.Close()
|
2014-08-19 19:14:52 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
|
|
|
|
pbw := ggio.NewDelimitedWriter(s)
|
2014-08-19 19:14:52 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
pmes := new(pb.Message)
|
|
|
|
if err := pbr.ReadMsg(pmes); err != nil {
|
|
|
|
panic(err)
|
2014-08-19 19:14:52 -07:00
|
|
|
}
|
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
switch pmes.GetType() {
|
|
|
|
case pb.Message_GET_VALUE:
|
|
|
|
resp := &pb.Message{Type: pmes.Type}
|
|
|
|
|
2014-12-19 12:19:56 -08:00
|
|
|
ps := []peer.PeerInfo{}
|
2014-12-16 14:35:52 -08:00
|
|
|
for i := 0; i < 7; i++ {
|
2014-12-19 12:19:56 -08:00
|
|
|
p := peers[rand.Intn(len(peers))]
|
|
|
|
pi := neti.Peerstore().PeerInfo(p)
|
|
|
|
ps = append(ps, pi)
|
2014-12-16 14:35:52 -08:00
|
|
|
}
|
|
|
|
|
2014-12-19 12:19:56 -08:00
|
|
|
resp.CloserPeers = pb.PeerInfosToPBPeers(d.network, ps)
|
2014-12-16 14:35:52 -08:00
|
|
|
if err := pbw.WriteMsg(resp); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
panic("Shouldnt recieve this.")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2014-08-19 19:14:52 -07:00
|
|
|
|
2014-10-18 04:19:12 -07:00
|
|
|
ctx, _ = context.WithTimeout(ctx, time.Second*5)
|
2014-09-21 18:04:43 -07:00
|
|
|
v, err := d.GetValue(ctx, u.Key("hello"))
|
2014-10-30 06:35:29 -07:00
|
|
|
log.Debugf("get value got %v", v)
|
2014-08-19 19:14:52 -07:00
|
|
|
if err != nil {
|
|
|
|
switch err {
|
2014-10-28 02:17:46 -07:00
|
|
|
case routing.ErrNotFound:
|
2014-08-19 19:14:52 -07:00
|
|
|
//Success!
|
|
|
|
return
|
|
|
|
case u.ErrTimeout:
|
|
|
|
t.Fatal("Should not have gotten timeout!")
|
|
|
|
default:
|
|
|
|
t.Fatalf("Got unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t.Fatal("Expected to recieve an error.")
|
|
|
|
}
|
2014-08-19 22:05:49 -07:00
|
|
|
|
|
|
|
// If less than K nodes are in the entire network, it should fail when we make
|
|
|
|
// a GET rpc and nobody has the value
|
|
|
|
func TestLessThanKResponses(t *testing.T) {
|
2014-09-19 18:11:05 -07:00
|
|
|
// t.Skip("skipping test because it makes a lot of output")
|
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
ctx := context.Background()
|
2014-12-17 08:02:59 -08:00
|
|
|
mn, err := mocknet.FullMeshConnected(ctx, 6)
|
2014-12-16 14:35:52 -08:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-12-17 08:02:59 -08:00
|
|
|
nets := mn.Nets()
|
|
|
|
peers := mn.Peers()
|
2014-11-20 18:45:05 -08:00
|
|
|
|
2014-12-19 12:19:56 -08:00
|
|
|
tsds := dssync.MutexWrap(ds.NewMapDatastore())
|
|
|
|
d := NewDHT(ctx, peers[0], nets[0], tsds)
|
2014-08-19 22:05:49 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
for i := 1; i < 5; i++ {
|
|
|
|
d.Update(ctx, peers[i])
|
2014-08-19 22:05:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reply with random peers to every message
|
2014-12-16 14:35:52 -08:00
|
|
|
for _, neti := range nets {
|
2014-12-19 12:19:56 -08:00
|
|
|
neti := neti // shadow loop var
|
2014-12-16 14:35:52 -08:00
|
|
|
neti.SetHandler(inet.ProtocolDHT, func(s inet.Stream) {
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
|
|
|
|
pbw := ggio.NewDelimitedWriter(s)
|
2014-08-19 22:05:49 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
pmes := new(pb.Message)
|
|
|
|
if err := pbr.ReadMsg(pmes); err != nil {
|
|
|
|
panic(err)
|
2014-08-19 22:05:49 -07:00
|
|
|
}
|
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
switch pmes.GetType() {
|
|
|
|
case pb.Message_GET_VALUE:
|
2014-12-19 12:19:56 -08:00
|
|
|
pi := neti.Peerstore().PeerInfo(peers[1])
|
2014-12-16 14:35:52 -08:00
|
|
|
resp := &pb.Message{
|
|
|
|
Type: pmes.Type,
|
2014-12-19 12:19:56 -08:00
|
|
|
CloserPeers: pb.PeerInfosToPBPeers(d.network, []peer.PeerInfo{pi}),
|
2014-12-16 14:35:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := pbw.WriteMsg(resp); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic("Shouldnt recieve this.")
|
2014-09-17 10:30:38 -07:00
|
|
|
}
|
2014-08-19 22:05:49 -07:00
|
|
|
|
2014-12-16 14:35:52 -08:00
|
|
|
})
|
|
|
|
}
|
2014-08-19 22:05:49 -07:00
|
|
|
|
2014-10-18 04:19:12 -07:00
|
|
|
ctx, _ = context.WithTimeout(ctx, time.Second*30)
|
2014-12-16 14:35:52 -08:00
|
|
|
if _, err := d.GetValue(ctx, u.Key("hello")); err != nil {
|
2014-08-19 22:05:49 -07:00
|
|
|
switch err {
|
2014-10-28 02:17:46 -07:00
|
|
|
case routing.ErrNotFound:
|
2014-08-19 22:05:49 -07:00
|
|
|
//Success!
|
|
|
|
return
|
|
|
|
case u.ErrTimeout:
|
|
|
|
t.Fatal("Should not have gotten timeout!")
|
|
|
|
default:
|
|
|
|
t.Fatalf("Got unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t.Fatal("Expected to recieve an error.")
|
|
|
|
}
|