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

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

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

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
10
	peer "github.com/jbenet/go-ipfs/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
	e := b.find(peers[i])
28 29 30 31
	if e == nil {
		t.Errorf("Failed to find peer: %v", peers[i])
	}

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

42
	rlist := spl.list
43
	for e := rlist.Front(); e != nil; e = e.Next() {
44
		p := ConvertPeerID(e.Value.(peer.ID))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
45
		cpl := commonPrefixLen(p, localID)
46 47 48 49 50 51 52 53
		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) {
54 55 56
	local := tu.RandPeerIDFatal(t)
	m := peer.NewMetrics()
	rt := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m)
57

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

	// Testing Update
	for i := 0; i < 10000; i++ {
		p := rt.Update(peers[rand.Intn(len(peers))])
66
		if p != "" {
67
			//t.Log("evicted peer.")
68 69 70 71
		}
	}

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

func TestTableFind(t *testing.T) {
81 82 83
	local := tu.RandPeerIDFatal(t)
	m := peer.NewMetrics()
	rt := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m)
84

85
	peers := make([]peer.ID, 100)
86
	for i := 0; i < 5; i++ {
87
		peers[i] = tu.RandPeerIDFatal(t)
88 89 90
		rt.Update(peers[i])
	}

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

func TestTableFindMultiple(t *testing.T) {
99 100 101
	local := tu.RandPeerIDFatal(t)
	m := peer.NewMetrics()
	rt := NewRoutingTable(20, ConvertPeerID(local), time.Hour, m)
102

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

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

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

	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))
148
			tab.Find(peers[n])
149 150 151 152 153 154 155 156 157 158
		}
		done <- struct{}{}
	}()
	<-done
	<-done
	<-done
}

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

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

	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
176
	local := ConvertKey("localKey")
177 178
	m := peer.NewMetrics()
	tab := NewRoutingTable(20, local, time.Hour, m)
179

180
	var peers []peer.ID
181
	for i := 0; i < b.N; i++ {
182
		peers = append(peers, tu.RandPeerIDFatal(b))
183 184 185 186 187
		tab.Update(peers[i])
	}

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