dht_test.go 13.6 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"

17
	// ci "github.com/jbenet/go-ipfs/crypto"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
18 19 20
	inet "github.com/jbenet/go-ipfs/net"
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
21
	testutil "github.com/jbenet/go-ipfs/util/testutil"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
22 23
)

24 25 26 27 28 29 30 31 32 33 34
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)
	}
}

35
func setupDHT(ctx context.Context, t *testing.T, addr ma.Multiaddr) *IpfsDHT {
36

37 38 39 40 41 42
	sk, pk, err := testutil.RandKeyPair(512)
	if err != nil {
		t.Fatal(err)
	}

	p, err := peer.IDFromPublicKey(pk)
43 44 45 46
	if err != nil {
		t.Fatal(err)
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
47
	peerstore := peer.NewPeerstore()
48 49 50
	peerstore.AddPrivKey(p, sk)
	peerstore.AddPubKey(p, pk)
	peerstore.AddAddress(p, addr)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
51

52
	n, err := inet.NewNetwork(ctx, []ma.Multiaddr{addr}, p, peerstore)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
53 54 55 56
	if err != nil {
		t.Fatal(err)
	}

57 58
	dss := dssync.MutexWrap(ds.NewMapDatastore())
	d := NewDHT(ctx, p, n, dss)
59

Jeromy's avatar
Jeromy committed
60 61 62
	d.Validators["v"] = func(u.Key, []byte) error {
		return nil
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
63 64 65
	return d
}

66 67
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
68
	dhts := make([]*IpfsDHT, n)
69 70
	peers := make([]peer.ID, n)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
71
	for i := 0; i < n; i++ {
72 73 74
		addrs[i] = testutil.RandLocalTCPAddress()
		dhts[i] = setupDHT(ctx, t, addrs[i])
		peers[i] = dhts[i].self
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
75 76 77 78 79
	}

	return addrs, peers, dhts
}

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

82 83 84 85
	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
86
	}
87 88 89 90

	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
91 92 93
	}
}

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

	// try multiple rounds...
97
	rounds := 1
98 99 100 101 102 103
	for i := 0; i < rounds; i++ {
		fmt.Printf("bootstrapping round %d/%d\n", i, rounds)

		var wg sync.WaitGroup
		for _, dht := range dhts {
			wg.Add(1)
104
			go func(i int) {
105
				defer wg.Done()
106 107
				<-time.After(time.Duration(i) * time.Millisecond) // stagger them to avoid overwhelming
				fmt.Printf("bootstrapping round %d/%d -- %s\n", i, rounds, dht.self)
108
				dht.Bootstrap(ctx)
109
			}(i)
110 111 112
		}
		wg.Wait()

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
113 114 115
	}
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
116
func TestPing(t *testing.T) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
117
	// t.Skip("skipping test to debug another")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
118
	ctx := context.Background()
119

120 121
	addrA := testutil.RandLocalTCPAddress()
	addrB := testutil.RandLocalTCPAddress()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
122

123 124
	dhtA := setupDHT(ctx, t, addrA)
	dhtB := setupDHT(ctx, t, addrB)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
125

126 127
	peerA := dhtA.self
	peerB := dhtB.self
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
128

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
129 130
	defer dhtA.Close()
	defer dhtB.Close()
131 132
	defer dhtA.network.Close()
	defer dhtB.network.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
133

134
	connect(t, ctx, dhtA, dhtB)
135

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
136
	//Test that we can ping the node
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
137
	ctxT, _ := context.WithTimeout(ctx, 100*time.Millisecond)
138
	if err := dhtA.Ping(ctxT, peerB); err != nil {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
139 140
		t.Fatal(err)
	}
141

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
142
	ctxT, _ = context.WithTimeout(ctx, 100*time.Millisecond)
143
	if err := dhtB.Ping(ctxT, peerA); err != nil {
144 145
		t.Fatal(err)
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
146 147 148
}

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

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

153 154
	addrA := testutil.RandLocalTCPAddress()
	addrB := testutil.RandLocalTCPAddress()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
155

156 157
	dhtA := setupDHT(ctx, t, addrA)
	dhtB := setupDHT(ctx, t, addrB)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
158

159 160 161 162
	defer dhtA.Close()
	defer dhtB.Close()
	defer dhtA.network.Close()
	defer dhtB.network.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
163

Jeromy's avatar
Jeromy committed
164 165 166 167 168 169
	vf := func(u.Key, []byte) error {
		return nil
	}
	dhtA.Validators["v"] = vf
	dhtB.Validators["v"] = vf

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

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

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
175
	ctxT, _ = context.WithTimeout(ctx, time.Second*2)
Jeromy's avatar
Jeromy committed
176
	val, err := dhtA.GetValue(ctxT, "/v/hello")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
177 178 179 180 181 182 183 184
	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
185
	ctxT, _ = context.WithTimeout(ctx, time.Second*2)
Jeromy's avatar
Jeromy committed
186
	val, err = dhtB.GetValue(ctxT, "/v/hello")
187 188 189 190 191 192 193
	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
194 195
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
196 197
func TestProvides(t *testing.T) {
	// t.Skip("skipping test to debug another")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
198
	ctx := context.Background()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
199

200
	_, _, dhts := setupDHTS(ctx, 4, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
201 202
	defer func() {
		for i := 0; i < 4; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
203
			dhts[i].Close()
204
			defer dhts[i].network.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
205 206 207
		}
	}()

208 209 210
	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
211

212 213 214 215 216 217 218 219 220 221 222 223 224 225
	for k, v := range testCaseValues {
		t.Logf("adding local values for %s = %s", k, v)
		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
226 227
	}

228 229 230 231 232
	for k, _ := range testCaseValues {
		t.Logf("announcing provider for %s", k)
		if err := dhts[3].Provide(ctx, k); err != nil {
			t.Fatal(err)
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
233 234
	}

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
	// what is this timeout for? was 60ms before.
	time.Sleep(time.Millisecond * 6)

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

		t.Logf("getting providers for %s from %d", k, n)
		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
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
func TestBootstrap(t *testing.T) {
	ctx := context.Background()

	nDHTs := 40
	_, _, dhts := setupDHTS(ctx, nDHTs, t)
	defer func() {
		for i := 0; i < nDHTs; i++ {
			dhts[i].Close()
			defer dhts[i].network.Close()
		}
	}()

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

277 278
	<-time.After(100 * time.Millisecond)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
279
	t.Logf("bootstrapping them so they find each other", nDHTs)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
280 281
	ctxT, _ := context.WithTimeout(ctx, 5*time.Second)
	bootstrap(t, ctxT, dhts)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
282 283 284 285 286 287 288 289 290 291

	// the routing tables should be full now. let's inspect them.
	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("")
	}
}

292 293
func TestProvidesMany(t *testing.T) {
	t.Skip("this test doesn't work")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
294
	// t.Skip("skipping test to debug another")
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
	ctx := context.Background()

	nDHTs := 40
	_, _, dhts := setupDHTS(ctx, nDHTs, t)
	defer func() {
		for i := 0; i < nDHTs; i++ {
			dhts[i].Close()
			defer dhts[i].network.Close()
		}
	}()

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

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
311 312
	t.Logf("bootstrapping them so they find each other", nDHTs)
	bootstrap(t, ctx, dhts)
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336

	d := 0
	for k, v := range testCaseValues {
		d = (d + 1) % len(dhts)
		dht := dhts[d]

		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
337 338
	}

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

342 343 344 345 346 347 348
	errchan := make(chan error)

	ctxT, _ := context.WithTimeout(ctx, 5*time.Second)

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

350 351 352 353 354 355 356 357 358 359
		provchan := dht.FindProvidersAsync(ctxT, k, 1)
		select {
		case prov := <-provchan:
			if prov.ID == "" {
				errchan <- fmt.Errorf("Got back nil provider (%s at %s)", k, dht.self)
			} else if prov.ID != dhts[3].self {
				errchan <- fmt.Errorf("Got back wrong provider (%s at %s)", k, dht.self)
			}
		case <-ctxT.Done():
			errchan <- fmt.Errorf("Did not get a provider back (%s at %s)", k, dht.self)
Jeromy's avatar
Jeromy committed
360
		}
361 362 363 364 365 366 367 368
	}

	for k, _ := range testCaseValues {
		// everyone should be able to find it...
		for _, dht := range dhts {
			t.Logf("getting providers for %s at %s", k, dht.self)
			wg.Add(1)
			go getProvider(dht, k)
369
		}
370 371 372 373 374 375 376 377 378 379 380
	}

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

	t.Logf("looking through errors")
	for err := range errchan {
		t.Error(err)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
381 382 383
	}
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
384
func TestProvidesAsync(t *testing.T) {
385 386 387
	if testing.Short() {
		t.SkipNow()
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
388

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

391
	_, _, dhts := setupDHTS(ctx, 4, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
392 393
	defer func() {
		for i := 0; i < 4; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
394
			dhts[i].Close()
395
			defer dhts[i].network.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
396 397 398
		}
	}()

399 400 401
	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
402

403
	err := dhts[3].putLocal(u.Key("hello"), []byte("world"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
404 405 406 407 408 409 410 411 412
	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
413
	err = dhts[3].Provide(ctx, u.Key("hello"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
414 415 416 417 418 419
	if err != nil {
		t.Fatal(err)
	}

	time.Sleep(time.Millisecond * 60)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
420 421
	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
422
	select {
Jeromy's avatar
Jeromy committed
423 424 425 426
	case p, ok := <-provs:
		if !ok {
			t.Fatal("Provider channel was closed...")
		}
427
		if p.ID == "" {
Jeromy's avatar
Jeromy committed
428 429
			t.Fatal("Got back nil provider!")
		}
430
		if p.ID != dhts[3].self {
431
			t.Fatalf("got a provider, but not the right one. %s", p)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
432
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
433
	case <-ctxT.Done():
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
434 435 436 437
		t.Fatal("Didnt get back providers")
	}
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
438
func TestLayeredGet(t *testing.T) {
439 440 441
	if testing.Short() {
		t.SkipNow()
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
442

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

445
	_, _, dhts := setupDHTS(ctx, 4, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
446 447
	defer func() {
		for i := 0; i < 4; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
448
			dhts[i].Close()
449
			defer dhts[i].network.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
450 451 452
		}
	}()

453 454 455
	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
456

457
	err := dhts[3].putLocal(u.Key("/v/hello"), []byte("world"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
458 459 460 461
	if err != nil {
		t.Fatal(err)
	}

Jeromy's avatar
Jeromy committed
462
	err = dhts[3].Provide(ctx, u.Key("/v/hello"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
463 464 465 466 467 468
	if err != nil {
		t.Fatal(err)
	}

	time.Sleep(time.Millisecond * 60)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
469
	ctxT, _ := context.WithTimeout(ctx, time.Second)
Jeromy's avatar
Jeromy committed
470
	val, err := dhts[0].GetValue(ctxT, u.Key("/v/hello"))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
471 472 473 474 475 476 477 478 479 480 481
	if err != nil {
		t.Fatal(err)
	}

	if string(val) != "world" {
		t.Fatal("Got incorrect value.")
	}

}

func TestFindPeer(t *testing.T) {
482 483 484
	if testing.Short() {
		t.SkipNow()
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
485

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

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
488
	_, peers, dhts := setupDHTS(ctx, 4, t)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
489 490
	defer func() {
		for i := 0; i < 4; i++ {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
491
			dhts[i].Close()
492
			dhts[i].network.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
493 494 495
		}
	}()

496 497 498
	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
499

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
500
	ctxT, _ := context.WithTimeout(ctx, time.Second)
501
	p, err := dhts[0].FindPeer(ctxT, peers[2])
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
502 503 504 505
	if err != nil {
		t.Fatal(err)
	}

506
	if p.ID == "" {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
507 508 509
		t.Fatal("Failed to find peer.")
	}

510
	if p.ID != peers[2] {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
511 512 513
		t.Fatal("Didnt find expected peer.")
	}
}
514

515
func TestFindPeersConnectedToPeer(t *testing.T) {
516 517
	t.Skip("not quite correct (see note)")

518 519 520 521 522 523 524 525 526 527
	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()
528
			dhts[i].network.Close()
529 530 531 532 533
		}
	}()

	// topology:
	// 0-1, 1-2, 1-3, 2-3
534 535 536 537
	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])
538 539 540 541 542 543 544

	// 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)
545
	pchan, err := dhts[0].FindPeersConnectedToPeer(ctxT, peers[2])
546 547 548 549
	if err != nil {
		t.Fatal(err)
	}

550 551
	// shouldFind := []peer.ID{peers[1], peers[3]}
	found := []peer.PeerInfo{}
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
	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.")
	}
}

568
func testPeerListsMatch(t *testing.T, p1, p2 []peer.ID) {
569 570 571 572 573 574 575 576 577

	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 {
578
		ids1[i] = string(p)
579 580 581
	}

	for i, p := range p2 {
582
		ids2[i] = string(p)
583 584 585 586 587 588 589 590 591 592 593 594
	}

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

595
func TestConnectCollision(t *testing.T) {
596 597 598
	if testing.Short() {
		t.SkipNow()
	}
599

600
	runTimes := 10
601

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

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

607 608
		addrA := testutil.RandLocalTCPAddress()
		addrB := testutil.RandLocalTCPAddress()
609

610 611
		dhtA := setupDHT(ctx, t, addrA)
		dhtB := setupDHT(ctx, t, addrB)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
612

613 614
		peerA := dhtA.self
		peerB := dhtB.self
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
615

616
		errs := make(chan error)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
617
		go func() {
618
			dhtA.peerstore.AddAddress(peerB, addrB)
619
			err := dhtA.Connect(ctx, peerB)
620
			errs <- err
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
621 622
		}()
		go func() {
623
			dhtB.peerstore.AddAddress(peerA, addrA)
624
			err := dhtB.Connect(ctx, peerA)
625
			errs <- err
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
626 627 628 629
		}()

		timeout := time.After(time.Second)
		select {
630 631 632 633
		case e := <-errs:
			if e != nil {
				t.Fatal(e)
			}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
634 635 636 637
		case <-timeout:
			t.Fatal("Timeout received!")
		}
		select {
638 639 640 641
		case e := <-errs:
			if e != nil {
				t.Fatal(e)
			}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
642 643 644 645
		case <-timeout:
			t.Fatal("Timeout received!")
		}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
646 647
		dhtA.Close()
		dhtB.Close()
648 649
		dhtA.network.Close()
		dhtB.network.Close()
Jeromy's avatar
Jeromy committed
650
	}
651
}