table_test.go 15.4 KB
Newer Older
1
package kbucket
2 3 4 5

import (
	"math/rand"
	"testing"
6
	"time"
7

8 9
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/test"
10

Jeromy's avatar
Jeromy committed
11
	pstore "github.com/libp2p/go-libp2p-peerstore"
Aarsh Shah's avatar
Aarsh Shah committed
12
	"github.com/stretchr/testify/require"
13 14
)

15
var NoOpThreshold = 100 * time.Hour
16

Aarsh Shah's avatar
Aarsh Shah committed
17 18 19 20
func TestPrint(t *testing.T) {
	t.Parallel()
	local := test.RandPeerIDFatal(t)
	m := pstore.NewMetrics()
21
	rt, err := NewRoutingTable(1, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
Aarsh Shah's avatar
Aarsh Shah committed
22 23 24 25
	require.NoError(t, err)
	rt.Print()
}

26 27
// Test basic features of the bucket struct
func TestBucket(t *testing.T) {
Steven Allen's avatar
Steven Allen committed
28
	t.Parallel()
29
	testTime1 := time.Now()
Aarsh Shah's avatar
Aarsh Shah committed
30
	testTime2 := time.Now().AddDate(1, 0, 0)
Steven Allen's avatar
Steven Allen committed
31

32
	b := newBucket()
33

34
	peers := make([]peer.ID, 100)
35
	for i := 0; i < 100; i++ {
36
		peers[i] = test.RandPeerIDFatal(t)
Aarsh Shah's avatar
Aarsh Shah committed
37
		b.pushFront(&PeerInfo{peers[i], testTime1, testTime2, ConvertPeerID(peers[i])})
38 39
	}

40
	local := test.RandPeerIDFatal(t)
41
	localID := ConvertPeerID(local)
42

43 44
	infos := b.peers()
	require.Len(t, infos, 100)
45

46
	i := rand.Intn(len(peers))
Aarsh Shah's avatar
Aarsh Shah committed
47 48
	p := b.getPeer(peers[i])
	require.NotNil(t, p)
49
	require.Equal(t, peers[i], p.Id)
50
	require.Equal(t, ConvertPeerID(peers[i]), p.dhtId)
Aarsh Shah's avatar
Aarsh Shah committed
51 52
	require.EqualValues(t, testTime1, p.LastUsefulAt)
	require.EqualValues(t, testTime2, p.LastSuccessfulOutboundQueryAt)
53

54
	t2 := time.Now().Add(1 * time.Hour)
Aarsh Shah's avatar
Aarsh Shah committed
55 56 57
	t3 := t2.Add(1 * time.Hour)
	p.LastSuccessfulOutboundQueryAt = t2
	p.LastUsefulAt = t3
Aarsh Shah's avatar
Aarsh Shah committed
58 59
	p = b.getPeer(peers[i])
	require.NotNil(t, p)
Aarsh Shah's avatar
Aarsh Shah committed
60 61
	require.EqualValues(t, t2, p.LastSuccessfulOutboundQueryAt)
	require.EqualValues(t, t3, p.LastUsefulAt)
62 63

	spl := b.split(0, ConvertPeerID(local))
64
	llist := b.list
65
	for e := llist.Front(); e != nil; e = e.Next() {
Aarsh Shah's avatar
Aarsh Shah committed
66
		p := ConvertPeerID(e.Value.(*PeerInfo).Id)
Matt Joiner's avatar
Matt Joiner committed
67
		cpl := CommonPrefixLen(p, localID)
68
		if cpl > 0 {
69
			t.Fatalf("split failed. found id with cpl > 0 in 0 bucket")
70 71 72
		}
	}

73
	rlist := spl.list
74
	for e := rlist.Front(); e != nil; e = e.Next() {
Aarsh Shah's avatar
Aarsh Shah committed
75
		p := ConvertPeerID(e.Value.(*PeerInfo).Id)
Matt Joiner's avatar
Matt Joiner committed
76
		cpl := CommonPrefixLen(p, localID)
77
		if cpl == 0 {
78
			t.Fatalf("split failed. found id with cpl == 0 in non 0 bucket")
79 80 81 82
		}
	}
}

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
func TestNPeersForCpl(t *testing.T) {
	t.Parallel()
	local := test.RandPeerIDFatal(t)
	m := pstore.NewMetrics()
	rt, err := NewRoutingTable(2, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
	require.NoError(t, err)

	require.Equal(t, 0, rt.NPeersForCpl(0))
	require.Equal(t, 0, rt.NPeersForCpl(1))

	// one peer with cpl 1
	p, _ := rt.GenRandPeerID(1)
	rt.TryAddPeer(p, true)
	require.Equal(t, 0, rt.NPeersForCpl(0))
	require.Equal(t, 1, rt.NPeersForCpl(1))
	require.Equal(t, 0, rt.NPeersForCpl(2))

	// one peer with cpl 0
	p, _ = rt.GenRandPeerID(0)
	rt.TryAddPeer(p, true)
	require.Equal(t, 1, rt.NPeersForCpl(0))
	require.Equal(t, 1, rt.NPeersForCpl(1))
	require.Equal(t, 0, rt.NPeersForCpl(2))

	// split the bucket with a peer with cpl 1
	p, _ = rt.GenRandPeerID(1)
	rt.TryAddPeer(p, true)
	require.Equal(t, 1, rt.NPeersForCpl(0))
	require.Equal(t, 2, rt.NPeersForCpl(1))
	require.Equal(t, 0, rt.NPeersForCpl(2))

	p, _ = rt.GenRandPeerID(0)
	rt.TryAddPeer(p, true)
	require.Equal(t, 2, rt.NPeersForCpl(0))
}

func TestEmptyBucketCollapse(t *testing.T) {
	t.Parallel()
	local := test.RandPeerIDFatal(t)

	m := pstore.NewMetrics()
	rt, err := NewRoutingTable(1, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
	require.NoError(t, err)

	// generate peers with cpl 0,1,2 & 3
	p1, _ := rt.GenRandPeerID(0)
	p2, _ := rt.GenRandPeerID(1)
	p3, _ := rt.GenRandPeerID(2)
	p4, _ := rt.GenRandPeerID(3)

	// remove peer on an empty bucket should not panic.
	rt.RemovePeer(p1)

	// add peer with cpl 0 and remove it..bucket should still exist as it's the ONLY bucket we have
	b, err := rt.TryAddPeer(p1, true)
	require.True(t, b)
	require.NoError(t, err)
	rt.RemovePeer(p1)
	rt.tabLock.Lock()
	require.Len(t, rt.buckets, 1)
	rt.tabLock.Unlock()
	require.Empty(t, rt.ListPeers())

	// add peer with cpl 0 and cpl 1 and verify we have two buckets.
	b, err = rt.TryAddPeer(p1, true)
	require.True(t, b)
	b, err = rt.TryAddPeer(p2, true)
	require.True(t, b)
	rt.tabLock.Lock()
	require.Len(t, rt.buckets, 2)
	rt.tabLock.Unlock()

	// removing a peer from the last bucket collapses it.
	rt.RemovePeer(p2)
	rt.tabLock.Lock()
	require.Len(t, rt.buckets, 1)
	rt.tabLock.Unlock()
	require.Len(t, rt.ListPeers(), 1)
	require.Contains(t, rt.ListPeers(), p1)

	// add p2 again
	b, err = rt.TryAddPeer(p2, true)
	require.True(t, b)
	require.NoError(t, err)
	rt.tabLock.Lock()
	require.Len(t, rt.buckets, 2)
	rt.tabLock.Unlock()

	// now remove a peer from the second-last i.e. first bucket and ensure it collapses
	rt.RemovePeer(p1)
	rt.tabLock.Lock()
	require.Len(t, rt.buckets, 1)
	rt.tabLock.Unlock()
	require.Len(t, rt.ListPeers(), 1)
	require.Contains(t, rt.ListPeers(), p2)

	// let's have a total of 4 buckets now
	rt.TryAddPeer(p1, true)
	rt.TryAddPeer(p2, true)
	rt.TryAddPeer(p3, true)
	rt.TryAddPeer(p4, true)

	rt.tabLock.Lock()
	require.Len(t, rt.buckets, 4)
	rt.tabLock.Unlock()

	// removing from 2,3 and then 4 leaves us with ONLY one bucket
	rt.RemovePeer(p2)
	rt.RemovePeer(p3)
	rt.RemovePeer(p4)
	rt.tabLock.Lock()
	require.Len(t, rt.buckets, 1)
	rt.tabLock.Unlock()

	// an empty bucket in the middle DOES NOT collapse buckets
	rt.TryAddPeer(p1, true)
	rt.TryAddPeer(p2, true)
	rt.TryAddPeer(p3, true)
	rt.TryAddPeer(p4, true)

	rt.tabLock.Lock()
	require.Len(t, rt.buckets, 4)
	rt.tabLock.Unlock()

	rt.RemovePeer(p2)
	rt.tabLock.Lock()
	require.Len(t, rt.buckets, 4)
	rt.tabLock.Unlock()
	require.NotContains(t, rt.ListPeers(), p2)
}

214
func TestRemovePeer(t *testing.T) {
Steven Allen's avatar
Steven Allen committed
215
	t.Parallel()
216
	local := test.RandPeerIDFatal(t)
Aarsh Shah's avatar
Aarsh Shah committed
217

Aarsh Shah's avatar
Aarsh Shah committed
218
	m := pstore.NewMetrics()
219
	rt, err := NewRoutingTable(2, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
220 221
	require.NoError(t, err)

222 223
	p1, _ := rt.GenRandPeerID(0)
	p2, _ := rt.GenRandPeerID(0)
224 225 226 227 228 229
	b, err := rt.TryAddPeer(p1, true)
	require.True(t, b)
	require.NoError(t, err)
	b, err = rt.TryAddPeer(p2, true)
	require.True(t, b)
	require.NoError(t, err)
230 231 232 233 234

	// ensure p1 & p2 are in the RT
	require.Len(t, rt.ListPeers(), 2)
	require.Contains(t, rt.ListPeers(), p1)
	require.Contains(t, rt.ListPeers(), p2)
235

236
	// remove a peer and ensure it's not in the RT
237
	require.NotEmpty(t, rt.Find(p1))
238
	rt.RemovePeer(p1)
239
	require.Empty(t, rt.Find(p1))
Aarsh Shah's avatar
Aarsh Shah committed
240
	require.NotEmpty(t, rt.Find(p2))
241 242
}

Jeromy's avatar
Jeromy committed
243
func TestTableCallbacks(t *testing.T) {
Steven Allen's avatar
Steven Allen committed
244 245
	t.Parallel()

246
	local := test.RandPeerIDFatal(t)
Jeromy's avatar
Jeromy committed
247
	m := pstore.NewMetrics()
248
	rt, err := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
249
	require.NoError(t, err)
Jeromy's avatar
Jeromy committed
250 251 252

	peers := make([]peer.ID, 100)
	for i := 0; i < 100; i++ {
253
		peers[i] = test.RandPeerIDFatal(t)
Jeromy's avatar
Jeromy committed
254 255 256 257 258 259 260 261 262 263
	}

	pset := make(map[peer.ID]struct{})
	rt.PeerAdded = func(p peer.ID) {
		pset[p] = struct{}{}
	}
	rt.PeerRemoved = func(p peer.ID) {
		delete(pset, p)
	}

264
	rt.TryAddPeer(peers[0], true)
Jeromy's avatar
Jeromy committed
265 266 267 268
	if _, ok := pset[peers[0]]; !ok {
		t.Fatal("should have this peer")
	}

269
	rt.RemovePeer(peers[0])
Jeromy's avatar
Jeromy committed
270 271 272 273 274
	if _, ok := pset[peers[0]]; ok {
		t.Fatal("should not have this peer")
	}

	for _, p := range peers {
275
		rt.TryAddPeer(p, true)
Jeromy's avatar
Jeromy committed
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
	}

	out := rt.ListPeers()
	for _, outp := range out {
		if _, ok := pset[outp]; !ok {
			t.Fatal("should have peer in the peerset")
		}
		delete(pset, outp)
	}

	if len(pset) > 0 {
		t.Fatal("have peers in peerset that were not in the table", len(pset))
	}
}

291
// Right now, this just makes sure that it doesnt hang or crash
292
func TestTryAddPeerLoad(t *testing.T) {
Steven Allen's avatar
Steven Allen committed
293 294
	t.Parallel()

295
	local := test.RandPeerIDFatal(t)
Jeromy's avatar
Jeromy committed
296
	m := pstore.NewMetrics()
297
	rt, err := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
298
	require.NoError(t, err)
299

300
	peers := make([]peer.ID, 100)
301
	for i := 0; i < 100; i++ {
302
		peers[i] = test.RandPeerIDFatal(t)
303 304 305
	}

	for i := 0; i < 10000; i++ {
306
		rt.TryAddPeer(peers[rand.Intn(len(peers))], true)
307 308 309
	}

	for i := 0; i < 100; i++ {
310
		id := ConvertPeerID(test.RandPeerIDFatal(t))
311 312 313 314 315 316 317 318
		ret := rt.NearestPeers(id, 5)
		if len(ret) == 0 {
			t.Fatal("Failed to find node near ID.")
		}
	}
}

func TestTableFind(t *testing.T) {
Steven Allen's avatar
Steven Allen committed
319 320
	t.Parallel()

321
	local := test.RandPeerIDFatal(t)
Jeromy's avatar
Jeromy committed
322
	m := pstore.NewMetrics()
323
	rt, err := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
324
	require.NoError(t, err)
325

326
	peers := make([]peer.ID, 100)
327
	for i := 0; i < 5; i++ {
328
		peers[i] = test.RandPeerIDFatal(t)
329
		rt.TryAddPeer(peers[i], true)
330 331
	}

332
	t.Logf("Searching for peer: '%s'", peers[2])
333 334
	found := rt.NearestPeer(ConvertPeerID(peers[2]))
	if !(found == peers[2]) {
335
		t.Fatalf("Failed to lookup known node...")
336 337 338
	}
}

Aarsh Shah's avatar
Aarsh Shah committed
339
func TestUpdateLastSuccessfulOutboundQueryAt(t *testing.T) {
340 341
	local := test.RandPeerIDFatal(t)
	m := pstore.NewMetrics()
342
	rt, err := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
343 344
	require.NoError(t, err)

345 346 347 348
	p := test.RandPeerIDFatal(t)
	b, err := rt.TryAddPeer(p, true)
	require.True(t, b)
	require.NoError(t, err)
349

350 351
	// increment and assert
	t2 := time.Now().Add(1 * time.Hour)
Aarsh Shah's avatar
Aarsh Shah committed
352
	rt.UpdateLastSuccessfulOutboundQueryAt(p, t2)
353 354 355
	rt.tabLock.Lock()
	pi := rt.buckets[0].getPeer(p)
	require.NotNil(t, pi)
Aarsh Shah's avatar
Aarsh Shah committed
356
	require.EqualValues(t, t2, pi.LastSuccessfulOutboundQueryAt)
357
	rt.tabLock.Unlock()
358 359
}

Aarsh Shah's avatar
Aarsh Shah committed
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
func TestUpdateLastUsefulAt(t *testing.T) {
	local := test.RandPeerIDFatal(t)
	m := pstore.NewMetrics()
	rt, err := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
	require.NoError(t, err)

	p := test.RandPeerIDFatal(t)
	b, err := rt.TryAddPeer(p, true)
	require.True(t, b)
	require.NoError(t, err)

	// increment and assert
	t2 := time.Now().Add(1 * time.Hour)
	rt.UpdateLastUsefulAt(p, t2)
	rt.tabLock.Lock()
	pi := rt.buckets[0].getPeer(p)
	require.NotNil(t, pi)
	require.EqualValues(t, t2, pi.LastUsefulAt)
	rt.tabLock.Unlock()
}

381
func TestTryAddPeer(t *testing.T) {
382
	minThreshold := 24 * 1 * time.Hour
Steven Allen's avatar
Steven Allen committed
383 384
	t.Parallel()

385
	local := test.RandPeerIDFatal(t)
386
	m := pstore.NewMetrics()
387
	rt, err := NewRoutingTable(2, ConvertPeerID(local), time.Hour, m, minThreshold)
388
	require.NoError(t, err)
389

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
	// generate 2 peers to saturate the first bucket for cpl=0
	p1, _ := rt.GenRandPeerID(0)
	b, err := rt.TryAddPeer(p1, true)
	require.NoError(t, err)
	require.True(t, b)
	p2, _ := rt.GenRandPeerID(0)
	b, err = rt.TryAddPeer(p2, true)
	require.NoError(t, err)
	require.True(t, b)
	require.Equal(t, p1, rt.Find(p1))
	require.Equal(t, p2, rt.Find(p2))

	// trying to add a peer with cpl=0 fails
	p3, _ := rt.GenRandPeerID(0)
	b, err = rt.TryAddPeer(p3, true)
	require.Equal(t, ErrPeerRejectedNoCapacity, err)
	require.False(t, b)
	require.Empty(t, rt.Find(p3))
408

409 410 411 412 413 414 415
	// however, trying to add peer with cpl=1 works
	p4, _ := rt.GenRandPeerID(1)
	b, err = rt.TryAddPeer(p4, true)
	require.NoError(t, err)
	require.True(t, b)
	require.Equal(t, p4, rt.Find(p4))

Aarsh Shah's avatar
Aarsh Shah committed
416
	// adding a peer with cpl 0 works if an existing peer has LastUsefulAt above the max threshold
417
	// because that existing peer will get replaced
Aarsh Shah's avatar
Aarsh Shah committed
418
	require.True(t, rt.UpdateLastUsefulAt(p2, time.Now().AddDate(0, 0, -2)))
419 420 421 422 423 424 425 426 427 428 429
	b, err = rt.TryAddPeer(p3, true)
	require.NoError(t, err)
	require.True(t, b)
	require.Equal(t, p3, rt.Find(p3))
	require.Equal(t, p1, rt.Find(p1))
	// p2 has been removed
	require.Empty(t, rt.Find(p2))

	// however adding peer fails if below threshold
	p5, err := rt.GenRandPeerID(0)
	require.NoError(t, err)
Aarsh Shah's avatar
Aarsh Shah committed
430
	require.True(t, rt.UpdateLastUsefulAt(p1, time.Now()))
431 432 433 434 435 436 437 438 439 440 441 442 443
	b, err = rt.TryAddPeer(p5, true)
	require.Error(t, err)
	require.False(t, b)

	// adding non query peer
	p6, err := rt.GenRandPeerID(3)
	require.NoError(t, err)
	b, err = rt.TryAddPeer(p6, false)
	require.NoError(t, err)
	require.True(t, b)
	rt.tabLock.Lock()
	pi := rt.buckets[rt.bucketIdForPeer(p6)].getPeer(p6)
	require.NotNil(t, p6)
Aarsh Shah's avatar
Aarsh Shah committed
444
	require.True(t, pi.LastUsefulAt.IsZero())
445
	rt.tabLock.Unlock()
446

447 448 449
}

func TestTableFindMultiple(t *testing.T) {
Steven Allen's avatar
Steven Allen committed
450 451
	t.Parallel()

452
	local := test.RandPeerIDFatal(t)
Jeromy's avatar
Jeromy committed
453
	m := pstore.NewMetrics()
454
	rt, err := NewRoutingTable(20, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
455
	require.NoError(t, err)
456

457
	peers := make([]peer.ID, 100)
458
	for i := 0; i < 18; i++ {
459
		peers[i] = test.RandPeerIDFatal(t)
460
		rt.TryAddPeer(peers[i], true)
461 462
	}

463
	t.Logf("Searching for peer: '%s'", peers[2])
464
	found := rt.NearestPeers(ConvertPeerID(peers[2]), 15)
465 466 467 468
	if len(found) != 15 {
		t.Fatalf("Got back different number of peers than we expected.")
	}
}
469

470
func TestTableFindMultipleBuckets(t *testing.T) {
Steven Allen's avatar
Steven Allen committed
471 472
	t.Parallel()

473 474
	local := test.RandPeerIDFatal(t)
	m := pstore.NewMetrics()
475

Steven Allen's avatar
Steven Allen committed
476
	rt, err := NewRoutingTable(5, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
477
	require.NoError(t, err)
478 479 480 481

	peers := make([]peer.ID, 100)
	for i := 0; i < 100; i++ {
		peers[i] = test.RandPeerIDFatal(t)
482
		rt.TryAddPeer(peers[i], true)
483 484
	}

Steven Allen's avatar
Steven Allen committed
485
	closest := SortClosestPeers(rt.ListPeers(), ConvertPeerID(peers[2]))
486

Steven Allen's avatar
Steven Allen committed
487
	t.Logf("Searching for peer: '%s'", peers[2])
Steven Allen's avatar
Steven Allen committed
488

489 490
	// should be able to find at least 30
	// ~31 (logtwo(100) * 5)
Steven Allen's avatar
Steven Allen committed
491
	found := rt.NearestPeers(ConvertPeerID(peers[2]), 20)
492
	if len(found) != 20 {
Steven Allen's avatar
Steven Allen committed
493 494
		t.Fatalf("asked for 20 peers, got %d", len(found))
	}
Steven Allen's avatar
Steven Allen committed
495 496 497
	for i, p := range found {
		if p != closest[i] {
			t.Fatalf("unexpected peer %d", i)
498 499
		}
	}
Steven Allen's avatar
Steven Allen committed
500 501 502 503 504

	// Ok, now let's try finding all of them.
	found = rt.NearestPeers(ConvertPeerID(peers[2]), 100)
	if len(found) != rt.Size() {
		t.Fatalf("asked for %d peers, got %d", rt.Size(), len(found))
505
	}
506 507 508 509 510 511

	for i, p := range found {
		if p != closest[i] {
			t.Fatalf("unexpected peer %d", i)
		}
	}
512 513
}

514 515 516 517
// Looks for race conditions in table operations. For a more 'certain'
// test, increase the loop counter from 1000 to a much higher number
// and set GOMAXPROCS above 1
func TestTableMultithreaded(t *testing.T) {
Steven Allen's avatar
Steven Allen committed
518 519
	t.Parallel()

520
	local := peer.ID("localPeer")
Jeromy's avatar
Jeromy committed
521
	m := pstore.NewMetrics()
522
	tab, err := NewRoutingTable(20, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
523
	require.NoError(t, err)
524
	var peers []peer.ID
525
	for i := 0; i < 500; i++ {
526
		peers = append(peers, test.RandPeerIDFatal(t))
527 528 529 530 531 532
	}

	done := make(chan struct{})
	go func() {
		for i := 0; i < 1000; i++ {
			n := rand.Intn(len(peers))
533
			tab.TryAddPeer(peers[n], true)
534 535 536 537 538 539 540
		}
		done <- struct{}{}
	}()

	go func() {
		for i := 0; i < 1000; i++ {
			n := rand.Intn(len(peers))
541
			tab.TryAddPeer(peers[n], true)
542 543 544 545 546 547 548
		}
		done <- struct{}{}
	}()

	go func() {
		for i := 0; i < 1000; i++ {
			n := rand.Intn(len(peers))
549
			tab.Find(peers[n])
550 551 552 553 554 555 556 557
		}
		done <- struct{}{}
	}()
	<-done
	<-done
	<-done
}

Aarsh Shah's avatar
Aarsh Shah committed
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
func TestGetPeerInfos(t *testing.T) {
	local := test.RandPeerIDFatal(t)
	m := pstore.NewMetrics()
	rt, err := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m, NoOpThreshold)
	require.NoError(t, err)

	require.Empty(t, rt.GetPeerInfos())

	p1 := test.RandPeerIDFatal(t)
	p2 := test.RandPeerIDFatal(t)

	b, err := rt.TryAddPeer(p1, false)
	require.True(t, b)
	require.NoError(t, err)
	b, err = rt.TryAddPeer(p2, true)
	require.True(t, b)
	require.NoError(t, err)

	ps := rt.GetPeerInfos()
	require.Len(t, ps, 2)
	ms := make(map[peer.ID]PeerInfo)
	for _, p := range ps {
		ms[p.Id] = p
	}

	require.Equal(t, p1, ms[p1].Id)
Aarsh Shah's avatar
Aarsh Shah committed
584
	require.True(t, ms[p1].LastUsefulAt.IsZero())
Aarsh Shah's avatar
Aarsh Shah committed
585
	require.Equal(t, p2, ms[p2].Id)
Aarsh Shah's avatar
Aarsh Shah committed
586
	require.False(t, ms[p2].LastUsefulAt.IsZero())
Aarsh Shah's avatar
Aarsh Shah committed
587 588
}

589
func BenchmarkAddPeer(b *testing.B) {
590
	b.StopTimer()
Chas Leichner's avatar
Chas Leichner committed
591
	local := ConvertKey("localKey")
Jeromy's avatar
Jeromy committed
592
	m := pstore.NewMetrics()
593
	tab, err := NewRoutingTable(20, local, time.Hour, m, NoOpThreshold)
594
	require.NoError(b, err)
595

596
	var peers []peer.ID
597
	for i := 0; i < b.N; i++ {
598
		peers = append(peers, test.RandPeerIDFatal(b))
599 600 601 602
	}

	b.StartTimer()
	for i := 0; i < b.N; i++ {
603
		tab.TryAddPeer(peers[i], true)
604 605 606 607 608
	}
}

func BenchmarkFinds(b *testing.B) {
	b.StopTimer()
Chas Leichner's avatar
Chas Leichner committed
609
	local := ConvertKey("localKey")
Jeromy's avatar
Jeromy committed
610
	m := pstore.NewMetrics()
611
	tab, err := NewRoutingTable(20, local, time.Hour, m, NoOpThreshold)
612
	require.NoError(b, err)
613

614
	var peers []peer.ID
615
	for i := 0; i < b.N; i++ {
616
		peers = append(peers, test.RandPeerIDFatal(b))
617
		tab.TryAddPeer(peers[i], true)
618 619 620 621
	}

	b.StartTimer()
	for i := 0; i < b.N; i++ {
622
		tab.Find(peers[i])
623 624
	}
}