table_test.go 4.08 KB
Newer Older
1 2 3 4 5 6 7
package dht

import (
	crand "crypto/rand"
	"crypto/sha256"
	"math/rand"
	"testing"
8
	"time"
9 10 11 12

	peer "github.com/jbenet/go-ipfs/peer"
)

13 14 15 16
func _randPeer() peer.Peer {
	id := make(peer.ID, 16)
	crand.Read(id)
	return peer.WithID(id)
17 18 19 20 21 22 23 24 25 26 27 28
}

func _randID() ID {
	buf := make([]byte, 16)
	crand.Read(buf)

	hash := sha256.Sum256(buf)
	return ID(hash[:])
}

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

31
	peers := make([]peer.Peer, 100)
32 33
	for i := 0; i < 100; i++ {
		peers[i] = _randPeer()
34
		b.pushFront(peers[i])
35 36 37
	}

	local := _randPeer()
38
	localID := ConvertPeerID(local.ID())
39 40

	i := rand.Intn(len(peers))
41
	e := b.find(peers[i].ID())
42 43 44 45
	if e == nil {
		t.Errorf("Failed to find peer: %v", peers[i])
	}

46
	spl := b.Split(0, ConvertPeerID(local.ID()))
47
	llist := b.list
48
	for e := llist.Front(); e != nil; e = e.Next() {
49
		p := ConvertPeerID(e.Value.(peer.Peer).ID())
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
50
		cpl := commonPrefixLen(p, localID)
51 52 53 54 55
		if cpl > 0 {
			t.Fatalf("Split failed. found id with cpl > 0 in 0 bucket")
		}
	}

56
	rlist := spl.list
57
	for e := rlist.Front(); e != nil; e = e.Next() {
58
		p := ConvertPeerID(e.Value.(peer.Peer).ID())
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
59
		cpl := commonPrefixLen(p, localID)
60 61 62 63 64 65 66 67 68
		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) {
	local := _randPeer()
69
	rt := NewRoutingTable(10, ConvertPeerID(local.ID()), time.Hour)
70

71
	peers := make([]peer.Peer, 100)
72 73 74 75 76 77 78 79
	for i := 0; i < 100; i++ {
		peers[i] = _randPeer()
	}

	// Testing Update
	for i := 0; i < 10000; i++ {
		p := rt.Update(peers[rand.Intn(len(peers))])
		if p != nil {
80
			//t.Log("evicted peer.")
81 82 83 84 85 86 87 88 89 90 91 92 93 94
		}
	}

	for i := 0; i < 100; i++ {
		id := _randID()
		ret := rt.NearestPeers(id, 5)
		if len(ret) == 0 {
			t.Fatal("Failed to find node near ID.")
		}
	}
}

func TestTableFind(t *testing.T) {
	local := _randPeer()
95
	rt := NewRoutingTable(10, ConvertPeerID(local.ID()), time.Hour)
96

97
	peers := make([]peer.Peer, 100)
98 99 100 101 102
	for i := 0; i < 5; i++ {
		peers[i] = _randPeer()
		rt.Update(peers[i])
	}

103
	t.Logf("Searching for peer: '%s'", peers[2])
104 105
	found := rt.NearestPeer(ConvertPeerID(peers[2].ID()))
	if !found.ID().Equal(peers[2].ID()) {
106 107 108 109 110 111
		t.Fatalf("Failed to lookup known node...")
	}
}

func TestTableFindMultiple(t *testing.T) {
	local := _randPeer()
112
	rt := NewRoutingTable(20, ConvertPeerID(local.ID()), time.Hour)
113

114
	peers := make([]peer.Peer, 100)
115 116 117 118 119
	for i := 0; i < 18; i++ {
		peers[i] = _randPeer()
		rt.Update(peers[i])
	}

120
	t.Logf("Searching for peer: '%s'", peers[2])
121
	found := rt.NearestPeers(ConvertPeerID(peers[2].ID()), 15)
122 123 124 125
	if len(found) != 15 {
		t.Fatalf("Got back different number of peers than we expected.")
	}
}
126 127 128 129 130 131

// 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")
Chas Leichner's avatar
Chas Leichner committed
132
	tab := NewRoutingTable(20, ConvertPeerID(local), time.Hour)
133
	var peers []peer.Peer
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
	for i := 0; i < 500; i++ {
		peers = append(peers, _randPeer())
	}

	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))
158
			tab.Find(peers[n].ID())
159 160 161 162 163 164 165 166 167 168
		}
		done <- struct{}{}
	}()
	<-done
	<-done
	<-done
}

func BenchmarkUpdates(b *testing.B) {
	b.StopTimer()
Chas Leichner's avatar
Chas Leichner committed
169 170
	local := ConvertKey("localKey")
	tab := NewRoutingTable(20, local, time.Hour)
171

172
	var peers []peer.Peer
173 174 175 176 177 178 179 180 181 182 183 184
	for i := 0; i < b.N; i++ {
		peers = append(peers, _randPeer())
	}

	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
185 186
	local := ConvertKey("localKey")
	tab := NewRoutingTable(20, local, time.Hour)
187

188
	var peers []peer.Peer
189 190 191 192 193 194 195
	for i := 0; i < b.N; i++ {
		peers = append(peers, _randPeer())
		tab.Update(peers[i])
	}

	b.StartTimer()
	for i := 0; i < b.N; i++ {
196
		tab.Find(peers[i].ID())
197 198
	}
}