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

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

8
	tu "github.com/ipfs/go-ipfs/thirdparty/testutil"
Jeromy's avatar
Jeromy committed
9

Jeromy's avatar
Jeromy committed
10
	peer "gx/ipfs/QmNefBbWHR9JEiP3KDVqZsBLQVRmH3GBG2D2Ke24SsFqfW/go-libp2p/p2p/peer"
11 12 13 14
)

// Test basic features of the bucket struct
func TestBucket(t *testing.T) {
15
	b := newBucket()
16

17
	peers := make([]peer.ID, 100)
18
	for i := 0; i < 100; i++ {
19
		peers[i] = tu.RandPeerIDFatal(t)
20
		b.PushFront(peers[i])
21 22
	}

23 24
	local := tu.RandPeerIDFatal(t)
	localID := ConvertPeerID(local)
25 26

	i := rand.Intn(len(peers))
27
	if !b.Has(peers[i]) {
28 29 30
		t.Errorf("Failed to find peer: %v", peers[i])
	}

31
	spl := b.Split(0, ConvertPeerID(local))
32
	llist := b.list
33
	for e := llist.Front(); e != nil; e = e.Next() {
34
		p := ConvertPeerID(e.Value.(peer.ID))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
35
		cpl := commonPrefixLen(p, localID)
36 37 38 39 40
		if cpl > 0 {
			t.Fatalf("Split failed. found id with cpl > 0 in 0 bucket")
		}
	}

41
	rlist := spl.list
42
	for e := rlist.Front(); e != nil; e = e.Next() {
43
		p := ConvertPeerID(e.Value.(peer.ID))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
44
		cpl := commonPrefixLen(p, localID)
45 46 47 48 49 50 51 52
		if cpl == 0 {
			t.Fatalf("Split failed. found id with cpl == 0 in non 0 bucket")
		}
	}
}

// Right now, this just makes sure that it doesnt hang or crash
func TestTableUpdate(t *testing.T) {
53 54 55
	local := tu.RandPeerIDFatal(t)
	m := peer.NewMetrics()
	rt := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m)
56

57
	peers := make([]peer.ID, 100)
58
	for i := 0; i < 100; i++ {
59
		peers[i] = tu.RandPeerIDFatal(t)
60 61 62 63
	}

	// Testing Update
	for i := 0; i < 10000; i++ {
64
		rt.Update(peers[rand.Intn(len(peers))])
65 66 67
	}

	for i := 0; i < 100; i++ {
68
		id := ConvertPeerID(tu.RandPeerIDFatal(t))
69 70 71 72 73 74 75 76
		ret := rt.NearestPeers(id, 5)
		if len(ret) == 0 {
			t.Fatal("Failed to find node near ID.")
		}
	}
}

func TestTableFind(t *testing.T) {
77 78 79
	local := tu.RandPeerIDFatal(t)
	m := peer.NewMetrics()
	rt := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m)
80

81
	peers := make([]peer.ID, 100)
82
	for i := 0; i < 5; i++ {
83
		peers[i] = tu.RandPeerIDFatal(t)
84 85 86
		rt.Update(peers[i])
	}

87
	t.Logf("Searching for peer: '%s'", peers[2])
88 89
	found := rt.NearestPeer(ConvertPeerID(peers[2]))
	if !(found == peers[2]) {
90 91 92 93 94
		t.Fatalf("Failed to lookup known node...")
	}
}

func TestTableFindMultiple(t *testing.T) {
95 96 97
	local := tu.RandPeerIDFatal(t)
	m := peer.NewMetrics()
	rt := NewRoutingTable(20, ConvertPeerID(local), time.Hour, m)
98

99
	peers := make([]peer.ID, 100)
100
	for i := 0; i < 18; i++ {
101
		peers[i] = tu.RandPeerIDFatal(t)
102 103 104
		rt.Update(peers[i])
	}

105
	t.Logf("Searching for peer: '%s'", peers[2])
106
	found := rt.NearestPeers(ConvertPeerID(peers[2]), 15)
107 108 109 110
	if len(found) != 15 {
		t.Fatalf("Got back different number of peers than we expected.")
	}
}
111 112 113 114 115 116

// 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) {
	local := peer.ID("localPeer")
117 118 119
	m := peer.NewMetrics()
	tab := NewRoutingTable(20, ConvertPeerID(local), time.Hour, m)
	var peers []peer.ID
120
	for i := 0; i < 500; i++ {
121
		peers = append(peers, tu.RandPeerIDFatal(t))
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
	}

	done := make(chan struct{})
	go func() {
		for i := 0; i < 1000; i++ {
			n := rand.Intn(len(peers))
			tab.Update(peers[n])
		}
		done <- struct{}{}
	}()

	go func() {
		for i := 0; i < 1000; i++ {
			n := rand.Intn(len(peers))
			tab.Update(peers[n])
		}
		done <- struct{}{}
	}()

	go func() {
		for i := 0; i < 1000; i++ {
			n := rand.Intn(len(peers))
144
			tab.Find(peers[n])
145 146 147 148 149 150 151 152 153 154
		}
		done <- struct{}{}
	}()
	<-done
	<-done
	<-done
}

func BenchmarkUpdates(b *testing.B) {
	b.StopTimer()
Chas Leichner's avatar
Chas Leichner committed
155
	local := ConvertKey("localKey")
156 157
	m := peer.NewMetrics()
	tab := NewRoutingTable(20, local, time.Hour, m)
158

159
	var peers []peer.ID
160
	for i := 0; i < b.N; i++ {
161
		peers = append(peers, tu.RandPeerIDFatal(b))
162 163 164 165 166 167 168 169 170 171
	}

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

func BenchmarkFinds(b *testing.B) {
	b.StopTimer()
Chas Leichner's avatar
Chas Leichner committed
172
	local := ConvertKey("localKey")
173 174
	m := peer.NewMetrics()
	tab := NewRoutingTable(20, local, time.Hour, m)
175

176
	var peers []peer.ID
177
	for i := 0; i < b.N; i++ {
178
		peers = append(peers, tu.RandPeerIDFatal(b))
179 180 181 182 183
		tab.Update(peers[i])
	}

	b.StartTimer()
	for i := 0; i < b.N; i++ {
184
		tab.Find(peers[i])
185 186
	}
}