dht_test.go 14.5 KB
Newer Older
1 2
package dht

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
3
import (
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
4
	"bytes"
5
	"fmt"
6
	"sort"
7
	"sync"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
8
	"testing"
9
	"time"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
10 11 12

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"

13
	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
14
	dssync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
15 16
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
17
	peer "github.com/jbenet/go-ipfs/p2p/peer"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
18
	netutil "github.com/jbenet/go-ipfs/p2p/test/util"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
19
	routing "github.com/jbenet/go-ipfs/routing"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
20 21 22
	u "github.com/jbenet/go-ipfs/util"
)

23 24 25 26 27 28 29 30 31 32 33
var testCaseValues = map[u.Key][]byte{}

func init() {
	testCaseValues["hello"] = []byte("world")
	for i := 0; i < 100; i++ {
		k := fmt.Sprintf("%d -- key", i)
		v := fmt.Sprintf("%d -- value", i)
		testCaseValues[u.Key(k)] = []byte(v)
	}
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
34 35
func setupDHT(ctx context.Context, t *testing.T) *IpfsDHT {
	h := netutil.GenHostSwarm(t, ctx)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
36

37
	dss := dssync.MutexWrap(ds.NewMapDatastore())
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
38
	d := NewDHT(ctx, h, dss)
39

Jeromy's avatar
Jeromy committed
40 41 42
	d.Validators["v"] = func(u.Key, []byte) error {
		return nil
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
43 44 45
	return d
}

46 47
func setupDHTS(ctx context.Context, n int, t *testing.T) ([]ma.Multiaddr, []peer.ID, []*IpfsDHT) {
	addrs := make([]ma.Multiaddr, n)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
48
	dhts := make([]*IpfsDHT, n)
49 50
	peers := make([]peer.ID, n)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
51
	for i := 0; i < n; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
52
		dhts[i] = setupDHT(ctx, t)
53
		peers[i] = dhts[i].self
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
54
		addrs[i] = dhts[i].peerstore.Addresses(dhts[i].self)[0]
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
55 56 57 58 59
	}

	return addrs, peers, dhts
}

60
func connect(t *testing.T, ctx context.Context, a, b *IpfsDHT) {
61

62 63 64 65
	idB := b.self
	addrB := b.peerstore.Addresses(idB)
	if len(addrB) == 0 {
		t.Fatal("peers setup incorrectly: no local address")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
66
	}
67 68 69 70

	a.peerstore.AddAddresses(idB, addrB)
	if err := a.Connect(ctx, idB); err != nil {
		t.Fatal(err)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
71 72 73
	}
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
74
func bootstrap(t *testing.T, ctx context.Context, dhts []*IpfsDHT) {
75

76 77
	ctx, cancel := context.WithCancel(ctx)

78
	rounds := 1
79
	for i := 0; i < rounds; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
80
		log.Debugf("bootstrapping round %d/%d\n", i, rounds)
81

82 83 84 85
		// tried async. sequential fares much better. compare:
		// 100 async https://gist.github.com/jbenet/56d12f0578d5f34810b2
		// 100 sync https://gist.github.com/jbenet/6c59e7c15426e48aaedd
		// probably because results compound
86
		for _, dht := range dhts {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
87
			log.Debugf("bootstrapping round %d/%d -- %s\n", i, rounds, dht.self)
88
			dht.Bootstrap(ctx, 3)
89
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
90
	}
91 92

	cancel()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
93 94
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
95
func TestPing(t *testing.T) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
96
	// t.Skip("skipping test to debug another")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
97
	ctx := context.Background()
98

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
99 100
	dhtA := setupDHT(ctx, t)
	dhtB := setupDHT(ctx, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
101

102 103
	peerA := dhtA.self
	peerB := dhtB.self
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
104

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
105 106
	defer dhtA.Close()
	defer dhtB.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
107 108
	defer dhtA.host.Close()
	defer dhtB.host.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
109

110
	connect(t, ctx, dhtA, dhtB)
111

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
112
	//Test that we can ping the node
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
113
	ctxT, _ := context.WithTimeout(ctx, 100*time.Millisecond)
114
	if err := dhtA.Ping(ctxT, peerB); err != nil {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
115 116
		t.Fatal(err)
	}
117

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
118
	ctxT, _ = context.WithTimeout(ctx, 100*time.Millisecond)
119
	if err := dhtB.Ping(ctxT, peerA); err != nil {
120 121
		t.Fatal(err)
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
122 123 124
}

func TestValueGetSet(t *testing.T) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
125 126
	// t.Skip("skipping test to debug another")

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
127
	ctx := context.Background()
128

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
129 130
	dhtA := setupDHT(ctx, t)
	dhtB := setupDHT(ctx, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
131

132 133
	defer dhtA.Close()
	defer dhtB.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
134 135
	defer dhtA.host.Close()
	defer dhtB.host.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
136

Jeromy's avatar
Jeromy committed
137 138 139 140 141 142
	vf := func(u.Key, []byte) error {
		return nil
	}
	dhtA.Validators["v"] = vf
	dhtB.Validators["v"] = vf

143
	connect(t, ctx, dhtA, dhtB)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
144

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
145
	ctxT, _ := context.WithTimeout(ctx, time.Second)
Jeromy's avatar
Jeromy committed
146
	dhtA.PutValue(ctxT, "/v/hello", []byte("world"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
147

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
148
	ctxT, _ = context.WithTimeout(ctx, time.Second*2)
Jeromy's avatar
Jeromy committed
149
	val, err := dhtA.GetValue(ctxT, "/v/hello")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
150 151 152 153 154 155 156 157
	if err != nil {
		t.Fatal(err)
	}

	if string(val) != "world" {
		t.Fatalf("Expected 'world' got '%s'", string(val))
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
158
	ctxT, _ = context.WithTimeout(ctx, time.Second*2)
Jeromy's avatar
Jeromy committed
159
	val, err = dhtB.GetValue(ctxT, "/v/hello")
160 161 162 163 164 165 166
	if err != nil {
		t.Fatal(err)
	}

	if string(val) != "world" {
		t.Fatalf("Expected 'world' got '%s'", string(val))
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
167 168
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
169 170
func TestProvides(t *testing.T) {
	// t.Skip("skipping test to debug another")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
171
	ctx := context.Background()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
172

173
	_, _, dhts := setupDHTS(ctx, 4, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
174 175
	defer func() {
		for i := 0; i < 4; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
176
			dhts[i].Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
177
			defer dhts[i].host.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
178 179 180
		}
	}()

181 182 183
	connect(t, ctx, dhts[0], dhts[1])
	connect(t, ctx, dhts[1], dhts[2])
	connect(t, ctx, dhts[1], dhts[3])
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
184

185
	for k, v := range testCaseValues {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
186
		log.Debugf("adding local values for %s = %s", k, v)
187 188 189 190 191 192 193 194 195 196 197 198
		err := dhts[3].putLocal(k, v)
		if err != nil {
			t.Fatal(err)
		}

		bits, err := dhts[3].getLocal(k)
		if err != nil {
			t.Fatal(err)
		}
		if !bytes.Equal(bits, v) {
			t.Fatal("didn't store the right bits (%s, %s)", k, v)
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
199 200
	}

201
	for k, _ := range testCaseValues {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
202
		log.Debugf("announcing provider for %s", k)
203 204 205
		if err := dhts[3].Provide(ctx, k); err != nil {
			t.Fatal(err)
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
206 207
	}

208 209 210 211 212 213 214
	// what is this timeout for? was 60ms before.
	time.Sleep(time.Millisecond * 6)

	n := 0
	for k, _ := range testCaseValues {
		n = (n + 1) % 3

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
215
		log.Debugf("getting providers for %s from %d", k, n)
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
		ctxT, _ := context.WithTimeout(ctx, time.Second)
		provchan := dhts[n].FindProvidersAsync(ctxT, k, 1)

		select {
		case prov := <-provchan:
			if prov.ID == "" {
				t.Fatal("Got back nil provider")
			}
			if prov.ID != dhts[3].self {
				t.Fatal("Got back wrong provider")
			}
		case <-ctxT.Done():
			t.Fatal("Did not get a provider back.")
		}
	}
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
233
func TestBootstrap(t *testing.T) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
234
	// t.Skip("skipping test to debug another")
235 236 237 238
	if testing.Short() {
		t.SkipNow()
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
239 240
	ctx := context.Background()

241
	nDHTs := 30
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
242 243 244 245
	_, _, dhts := setupDHTS(ctx, nDHTs, t)
	defer func() {
		for i := 0; i < nDHTs; i++ {
			dhts[i].Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
246
			defer dhts[i].host.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
247 248 249 250 251 252 253 254
		}
	}()

	t.Logf("connecting %d dhts in a ring", nDHTs)
	for i := 0; i < nDHTs; i++ {
		connect(t, ctx, dhts[i], dhts[(i+1)%len(dhts)])
	}

255
	<-time.After(100 * time.Millisecond)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
256
	t.Logf("bootstrapping them so they find each other", nDHTs)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
257 258
	ctxT, _ := context.WithTimeout(ctx, 5*time.Second)
	bootstrap(t, ctxT, dhts)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
259

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
260 261 262 263 264 265 266 267 268 269 270 271
	if u.Debug {
		// the routing tables should be full now. let's inspect them.
		<-time.After(5 * time.Second)
		t.Logf("checking routing table of %d", nDHTs)
		for _, dht := range dhts {
			fmt.Printf("checking routing table of %s\n", dht.self)
			dht.routingTable.Print()
			fmt.Println("")
		}
	}

	// test "well-formed-ness" (>= 3 peers in every routing table)
272
	avgsize := 0
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
273
	for _, dht := range dhts {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
274
		rtlen := dht.routingTable.Size()
275 276
		avgsize += rtlen
		t.Logf("routing table for %s has %d peers", dht.self, rtlen)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
277
		if rtlen < 4 {
278 279
			// currently, we dont have good bootstrapping guarantees.
			// t.Errorf("routing table for %s only has %d peers", dht.self, rtlen)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
280
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
281
	}
282 283 284 285 286 287 288
	avgsize = avgsize / len(dhts)
	avgsizeExpected := 6

	t.Logf("avg rt size: %d", avgsize)
	if avgsize < avgsizeExpected {
		t.Errorf("avg rt size: %d < %d", avgsize, avgsizeExpected)
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
289 290
}

291 292
func TestProvidesMany(t *testing.T) {
	t.Skip("this test doesn't work")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
293
	// t.Skip("skipping test to debug another")
294 295 296 297 298 299 300
	ctx := context.Background()

	nDHTs := 40
	_, _, dhts := setupDHTS(ctx, nDHTs, t)
	defer func() {
		for i := 0; i < nDHTs; i++ {
			dhts[i].Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
301
			defer dhts[i].host.Close()
302 303 304 305 306 307 308 309
		}
	}()

	t.Logf("connecting %d dhts in a ring", nDHTs)
	for i := 0; i < nDHTs; i++ {
		connect(t, ctx, dhts[i], dhts[(i+1)%len(dhts)])
	}

310
	<-time.After(100 * time.Millisecond)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
311
	t.Logf("bootstrapping them so they find each other", nDHTs)
312 313 314
	ctxT, _ := context.WithTimeout(ctx, 5*time.Second)
	bootstrap(t, ctxT, dhts)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
315 316 317 318 319 320 321 322 323
	if u.Debug {
		// the routing tables should be full now. let's inspect them.
		<-time.After(5 * time.Second)
		t.Logf("checking routing table of %d", nDHTs)
		for _, dht := range dhts {
			fmt.Printf("checking routing table of %s\n", dht.self)
			dht.routingTable.Print()
			fmt.Println("")
		}
324
	}
325

326 327
	var providers = map[u.Key]peer.ID{}

328 329 330 331
	d := 0
	for k, v := range testCaseValues {
		d = (d + 1) % len(dhts)
		dht := dhts[d]
332
		providers[k] = dht.self
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351

		t.Logf("adding local values for %s = %s (on %s)", k, v, dht.self)
		err := dht.putLocal(k, v)
		if err != nil {
			t.Fatal(err)
		}

		bits, err := dht.getLocal(k)
		if err != nil {
			t.Fatal(err)
		}
		if !bytes.Equal(bits, v) {
			t.Fatal("didn't store the right bits (%s, %s)", k, v)
		}

		t.Logf("announcing provider for %s", k)
		if err := dht.Provide(ctx, k); err != nil {
			t.Fatal(err)
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
352 353
	}

354 355
	// what is this timeout for? was 60ms before.
	time.Sleep(time.Millisecond * 6)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
356

357 358
	errchan := make(chan error)

359
	ctxT, _ = context.WithTimeout(ctx, 5*time.Second)
360 361 362 363

	var wg sync.WaitGroup
	getProvider := func(dht *IpfsDHT, k u.Key) {
		defer wg.Done()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
364

365 366
		expected := providers[k]

367 368 369
		provchan := dht.FindProvidersAsync(ctxT, k, 1)
		select {
		case prov := <-provchan:
370 371
			actual := prov.ID
			if actual == "" {
372
				errchan <- fmt.Errorf("Got back nil provider (%s at %s)", k, dht.self)
373 374 375
			} else if actual != expected {
				errchan <- fmt.Errorf("Got back wrong provider (%s != %s) (%s at %s)",
					expected, actual, k, dht.self)
376 377 378
			}
		case <-ctxT.Done():
			errchan <- fmt.Errorf("Did not get a provider back (%s at %s)", k, dht.self)
Jeromy's avatar
Jeromy committed
379
		}
380 381 382 383 384
	}

	for k, _ := range testCaseValues {
		// everyone should be able to find it...
		for _, dht := range dhts {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
385
			log.Debugf("getting providers for %s at %s", k, dht.self)
386 387
			wg.Add(1)
			go getProvider(dht, k)
388
		}
389 390 391 392 393 394 395 396 397 398
	}

	// we need this because of printing errors
	go func() {
		wg.Wait()
		close(errchan)
	}()

	for err := range errchan {
		t.Error(err)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
399 400 401
	}
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
402
func TestProvidesAsync(t *testing.T) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
403
	// t.Skip("skipping test to debug another")
404 405 406
	if testing.Short() {
		t.SkipNow()
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
407

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
408
	ctx := context.Background()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
409

410
	_, _, dhts := setupDHTS(ctx, 4, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
411 412
	defer func() {
		for i := 0; i < 4; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
413
			dhts[i].Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
414
			defer dhts[i].host.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
415 416 417
		}
	}()

418 419 420
	connect(t, ctx, dhts[0], dhts[1])
	connect(t, ctx, dhts[1], dhts[2])
	connect(t, ctx, dhts[1], dhts[3])
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
421

422
	err := dhts[3].putLocal(u.Key("hello"), []byte("world"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
423 424 425 426 427 428 429 430 431
	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)
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
432
	err = dhts[3].Provide(ctx, u.Key("hello"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
433 434 435 436 437 438
	if err != nil {
		t.Fatal(err)
	}

	time.Sleep(time.Millisecond * 60)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
439 440
	ctxT, _ := context.WithTimeout(ctx, time.Millisecond*300)
	provs := dhts[0].FindProvidersAsync(ctxT, u.Key("hello"), 5)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
441
	select {
Jeromy's avatar
Jeromy committed
442 443 444 445
	case p, ok := <-provs:
		if !ok {
			t.Fatal("Provider channel was closed...")
		}
446
		if p.ID == "" {
Jeromy's avatar
Jeromy committed
447 448
			t.Fatal("Got back nil provider!")
		}
449
		if p.ID != dhts[3].self {
450
			t.Fatalf("got a provider, but not the right one. %s", p)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
451
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
452
	case <-ctxT.Done():
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
453 454 455 456
		t.Fatal("Didnt get back providers")
	}
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
457
func TestLayeredGet(t *testing.T) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
458
	// t.Skip("skipping test to debug another")
459 460 461
	if testing.Short() {
		t.SkipNow()
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
462

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
463
	ctx := context.Background()
464

465
	_, _, dhts := setupDHTS(ctx, 4, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
466 467
	defer func() {
		for i := 0; i < 4; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
468
			dhts[i].Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
469
			defer dhts[i].host.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
470 471 472
		}
	}()

473 474 475
	connect(t, ctx, dhts[0], dhts[1])
	connect(t, ctx, dhts[1], dhts[2])
	connect(t, ctx, dhts[1], dhts[3])
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
476

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
477
	err := dhts[3].Provide(ctx, u.Key("/v/hello"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
478 479 480 481
	if err != nil {
		t.Fatal(err)
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
482
	time.Sleep(time.Millisecond * 6)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
483

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
484
	t.Log("interface was changed. GetValue should not use providers.")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
485
	ctxT, _ := context.WithTimeout(ctx, time.Second)
Jeromy's avatar
Jeromy committed
486
	val, err := dhts[0].GetValue(ctxT, u.Key("/v/hello"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
487 488
	if err != routing.ErrNotFound {
		t.Error(err)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
489
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
490 491 492 493 494
	if string(val) == "world" {
		t.Error("should not get value.")
	}
	if len(val) > 0 && string(val) != "world" {
		t.Error("worse, there's a value and its not even the right one.")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
495 496 497 498
	}
}

func TestFindPeer(t *testing.T) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
499
	// t.Skip("skipping test to debug another")
500 501 502
	if testing.Short() {
		t.SkipNow()
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
503

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
504
	ctx := context.Background()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
505

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
506
	_, peers, dhts := setupDHTS(ctx, 4, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
507 508
	defer func() {
		for i := 0; i < 4; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
509
			dhts[i].Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
510
			dhts[i].host.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
511 512 513
		}
	}()

514 515 516
	connect(t, ctx, dhts[0], dhts[1])
	connect(t, ctx, dhts[1], dhts[2])
	connect(t, ctx, dhts[1], dhts[3])
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
517

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
518
	ctxT, _ := context.WithTimeout(ctx, time.Second)
519
	p, err := dhts[0].FindPeer(ctxT, peers[2])
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
520 521 522 523
	if err != nil {
		t.Fatal(err)
	}

524
	if p.ID == "" {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
525 526 527
		t.Fatal("Failed to find peer.")
	}

528
	if p.ID != peers[2] {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
529 530 531
		t.Fatal("Didnt find expected peer.")
	}
}
532

533
func TestFindPeersConnectedToPeer(t *testing.T) {
534 535
	t.Skip("not quite correct (see note)")

536 537 538 539 540 541 542 543 544 545
	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()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
546
			dhts[i].host.Close()
547 548 549 550 551
		}
	}()

	// topology:
	// 0-1, 1-2, 1-3, 2-3
552 553 554 555
	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])
556 557 558 559 560 561 562

	// 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)
563
	pchan, err := dhts[0].FindPeersConnectedToPeer(ctxT, peers[2])
564 565 566 567
	if err != nil {
		t.Fatal(err)
	}

568 569
	// shouldFind := []peer.ID{peers[1], peers[3]}
	found := []peer.PeerInfo{}
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
	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.")
	}
}

586
func testPeerListsMatch(t *testing.T, p1, p2 []peer.ID) {
587 588 589 590 591 592 593 594 595

	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 {
596
		ids1[i] = string(p)
597 598 599
	}

	for i, p := range p2 {
600
		ids2[i] = string(p)
601 602 603 604 605 606 607 608 609 610 611 612
	}

	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)
		}
	}
}

613
func TestConnectCollision(t *testing.T) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
614
	// t.Skip("skipping test to debug another")
615 616 617
	if testing.Short() {
		t.SkipNow()
	}
618

619
	runTimes := 10
620

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
621 622
	for rtime := 0; rtime < runTimes; rtime++ {
		log.Notice("Running Time: ", rtime)
623

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
624
		ctx := context.Background()
625

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
626 627
		dhtA := setupDHT(ctx, t)
		dhtB := setupDHT(ctx, t)
628

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
629 630
		addrA := dhtA.peerstore.Addresses(dhtA.self)[0]
		addrB := dhtB.peerstore.Addresses(dhtB.self)[0]
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
631

632 633
		peerA := dhtA.self
		peerB := dhtB.self
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
634

635
		errs := make(chan error)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
636
		go func() {
637
			dhtA.peerstore.AddAddress(peerB, addrB)
638
			err := dhtA.Connect(ctx, peerB)
639
			errs <- err
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
640 641
		}()
		go func() {
642
			dhtB.peerstore.AddAddress(peerA, addrA)
643
			err := dhtB.Connect(ctx, peerA)
644
			errs <- err
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
645 646 647 648
		}()

		timeout := time.After(time.Second)
		select {
649 650 651 652
		case e := <-errs:
			if e != nil {
				t.Fatal(e)
			}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
653 654 655 656
		case <-timeout:
			t.Fatal("Timeout received!")
		}
		select {
657 658 659 660
		case e := <-errs:
			if e != nil {
				t.Fatal(e)
			}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
661 662 663 664
		case <-timeout:
			t.Fatal("Timeout received!")
		}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
665 666
		dhtA.Close()
		dhtB.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
667 668
		dhtA.host.Close()
		dhtB.host.Close()
Jeromy's avatar
Jeromy committed
669
	}
670
}