peerwantmanager_test.go 9.79 KB
Newer Older
dirkmc's avatar
dirkmc committed
1 2 3 4 5
package peermanager

import (
	"testing"

6
	"github.com/ipfs/go-bitswap/internal/testutil"
dirkmc's avatar
dirkmc committed
7
	cid "github.com/ipfs/go-cid"
8
	peer "github.com/libp2p/go-libp2p-core/peer"
dirkmc's avatar
dirkmc committed
9 10 11 12 13 14 15 16 17 18 19 20 21
)

type gauge struct {
	count int
}

func (g *gauge) Inc() {
	g.count++
}
func (g *gauge) Dec() {
	g.count--
}

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
type mockPQ struct {
	bcst    []cid.Cid
	wbs     []cid.Cid
	whs     []cid.Cid
	cancels []cid.Cid
}

func (mpq *mockPQ) clear() {
	mpq.bcst = nil
	mpq.wbs = nil
	mpq.whs = nil
	mpq.cancels = nil
}

func (mpq *mockPQ) Startup()  {}
func (mpq *mockPQ) Shutdown() {}

func (mpq *mockPQ) AddBroadcastWantHaves(whs []cid.Cid) {
	mpq.bcst = append(mpq.bcst, whs...)
}
func (mpq *mockPQ) AddWants(wbs []cid.Cid, whs []cid.Cid) {
	mpq.wbs = append(mpq.wbs, wbs...)
	mpq.whs = append(mpq.whs, whs...)
}
func (mpq *mockPQ) AddCancels(cs []cid.Cid) {
	mpq.cancels = append(mpq.cancels, cs...)
}
func (mpq *mockPQ) ResponseReceived(ks []cid.Cid) {
}

func clearSent(pqs map[peer.ID]PeerQueue) {
	for _, pqi := range pqs {
		pqi.(*mockPQ).clear()
	}
}

dirkmc's avatar
dirkmc committed
58 59 60
func TestEmpty(t *testing.T) {
	pwm := newPeerWantManager(&gauge{})

61
	if len(pwm.getWantBlocks()) > 0 {
dirkmc's avatar
dirkmc committed
62 63
		t.Fatal("Expected GetWantBlocks() to have length 0")
	}
64
	if len(pwm.getWantHaves()) > 0 {
dirkmc's avatar
dirkmc committed
65 66 67 68
		t.Fatal("Expected GetWantHaves() to have length 0")
	}
}

69
func TestPWMBroadcastWantHaves(t *testing.T) {
dirkmc's avatar
dirkmc committed
70 71 72 73 74 75 76
	pwm := newPeerWantManager(&gauge{})

	peers := testutil.GeneratePeers(3)
	cids := testutil.GenerateCids(2)
	cids2 := testutil.GenerateCids(2)
	cids3 := testutil.GenerateCids(2)

77 78 79 80 81 82 83 84
	peerQueues := make(map[peer.ID]PeerQueue)
	for _, p := range peers[:2] {
		pq := &mockPQ{}
		peerQueues[p] = pq
		pwm.addPeer(pq, p)
		if len(pq.bcst) > 0 {
			t.Errorf("expected no broadcast wants")
		}
85
	}
dirkmc's avatar
dirkmc committed
86 87

	// Broadcast 2 cids to 2 peers
88 89 90 91 92 93 94
	pwm.broadcastWantHaves(cids)
	for _, pqi := range peerQueues {
		pq := pqi.(*mockPQ)
		if len(pq.bcst) != 2 {
			t.Fatal("Expected 2 want-haves")
		}
		if !testutil.MatchKeysIgnoreOrder(pq.bcst, cids) {
dirkmc's avatar
dirkmc committed
95 96 97 98 99
			t.Fatal("Expected all cids to be broadcast")
		}
	}

	// Broadcasting same cids should have no effect
100 101 102 103 104 105 106
	clearSent(peerQueues)
	pwm.broadcastWantHaves(cids)
	for _, pqi := range peerQueues {
		pq := pqi.(*mockPQ)
		if len(pq.bcst) != 0 {
			t.Fatal("Expected 0 want-haves")
		}
dirkmc's avatar
dirkmc committed
107 108 109
	}

	// Broadcast 2 other cids
110 111 112 113 114 115 116 117
	clearSent(peerQueues)
	pwm.broadcastWantHaves(cids2)
	for _, pqi := range peerQueues {
		pq := pqi.(*mockPQ)
		if len(pq.bcst) != 2 {
			t.Fatal("Expected 2 want-haves")
		}
		if !testutil.MatchKeysIgnoreOrder(pq.bcst, cids2) {
dirkmc's avatar
dirkmc committed
118 119 120 121 122
			t.Fatal("Expected all new cids to be broadcast")
		}
	}

	// Broadcast mix of old and new cids
123 124 125 126 127 128 129 130 131
	clearSent(peerQueues)
	pwm.broadcastWantHaves(append(cids, cids3...))
	for _, pqi := range peerQueues {
		pq := pqi.(*mockPQ)
		if len(pq.bcst) != 2 {
			t.Fatal("Expected 2 want-haves")
		}
		// Only new cids should be broadcast
		if !testutil.MatchKeysIgnoreOrder(pq.bcst, cids3) {
dirkmc's avatar
dirkmc committed
132 133 134 135 136
			t.Fatal("Expected all new cids to be broadcast")
		}
	}

	// Sending want-block for a cid should prevent broadcast to that peer
137
	clearSent(peerQueues)
dirkmc's avatar
dirkmc committed
138 139
	cids4 := testutil.GenerateCids(4)
	wantBlocks := []cid.Cid{cids4[0], cids4[2]}
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
	p0 := peers[0]
	p1 := peers[1]
	pwm.sendWants(p0, wantBlocks, []cid.Cid{})

	pwm.broadcastWantHaves(cids4)
	pq0 := peerQueues[p0].(*mockPQ)
	if len(pq0.bcst) != 2 { // only broadcast 2 / 4 want-haves
		t.Fatal("Expected 2 want-haves")
	}
	if !testutil.MatchKeysIgnoreOrder(pq0.bcst, []cid.Cid{cids4[1], cids4[3]}) {
		t.Fatalf("Expected unsent cids to be broadcast")
	}
	pq1 := peerQueues[p1].(*mockPQ)
	if len(pq1.bcst) != 4 { // broadcast all 4 want-haves
		t.Fatal("Expected 4 want-haves")
	}
	if !testutil.MatchKeysIgnoreOrder(pq1.bcst, cids4) {
		t.Fatal("Expected all cids to be broadcast")
dirkmc's avatar
dirkmc committed
158 159
	}

160 161 162 163 164
	allCids := cids
	allCids = append(allCids, cids2...)
	allCids = append(allCids, cids3...)
	allCids = append(allCids, cids4...)

dirkmc's avatar
dirkmc committed
165
	// Add another peer
166 167 168 169 170
	peer2 := peers[2]
	pq2 := &mockPQ{}
	peerQueues[peer2] = pq2
	pwm.addPeer(pq2, peer2)
	if !testutil.MatchKeysIgnoreOrder(pq2.bcst, allCids) {
171
		t.Fatalf("Expected all cids to be broadcast.")
dirkmc's avatar
dirkmc committed
172
	}
173

174 175 176
	clearSent(peerQueues)
	pwm.broadcastWantHaves(allCids)
	if len(pq2.bcst) != 0 {
177
		t.Errorf("did not expect to have CIDs to broadcast")
dirkmc's avatar
dirkmc committed
178 179 180
	}
}

181
func TestPWMSendWants(t *testing.T) {
dirkmc's avatar
dirkmc committed
182 183 184 185 186 187 188 189
	pwm := newPeerWantManager(&gauge{})

	peers := testutil.GeneratePeers(2)
	p0 := peers[0]
	p1 := peers[1]
	cids := testutil.GenerateCids(2)
	cids2 := testutil.GenerateCids(2)

190 191 192 193 194 195 196 197
	peerQueues := make(map[peer.ID]PeerQueue)
	for _, p := range peers[:2] {
		pq := &mockPQ{}
		peerQueues[p] = pq
		pwm.addPeer(pq, p)
	}
	pq0 := peerQueues[p0].(*mockPQ)
	pq1 := peerQueues[p1].(*mockPQ)
dirkmc's avatar
dirkmc committed
198 199

	// Send 2 want-blocks and 2 want-haves to p0
200 201 202
	clearSent(peerQueues)
	pwm.sendWants(p0, cids, cids2)
	if !testutil.MatchKeysIgnoreOrder(pq0.wbs, cids) {
dirkmc's avatar
dirkmc committed
203 204
		t.Fatal("Expected 2 want-blocks")
	}
205
	if !testutil.MatchKeysIgnoreOrder(pq0.whs, cids2) {
dirkmc's avatar
dirkmc committed
206 207 208 209 210 211
		t.Fatal("Expected 2 want-haves")
	}

	// Send to p0
	// - 1 old want-block and 2 new want-blocks
	// - 1 old want-have  and 2 new want-haves
212
	clearSent(peerQueues)
dirkmc's avatar
dirkmc committed
213 214
	cids3 := testutil.GenerateCids(2)
	cids4 := testutil.GenerateCids(2)
215 216
	pwm.sendWants(p0, append(cids3, cids[0]), append(cids4, cids2[0]))
	if !testutil.MatchKeysIgnoreOrder(pq0.wbs, cids3) {
dirkmc's avatar
dirkmc committed
217 218
		t.Fatal("Expected 2 want-blocks")
	}
219
	if !testutil.MatchKeysIgnoreOrder(pq0.whs, cids4) {
dirkmc's avatar
dirkmc committed
220 221 222 223
		t.Fatal("Expected 2 want-haves")
	}

	// Send to p0 as want-blocks: 1 new want-block, 1 old want-have
224
	clearSent(peerQueues)
dirkmc's avatar
dirkmc committed
225 226
	cids5 := testutil.GenerateCids(1)
	newWantBlockOldWantHave := append(cids5, cids2[0])
227
	pwm.sendWants(p0, newWantBlockOldWantHave, []cid.Cid{})
dirkmc's avatar
dirkmc committed
228 229
	// If a want was sent as a want-have, it should be ok to now send it as a
	// want-block
230
	if !testutil.MatchKeysIgnoreOrder(pq0.wbs, newWantBlockOldWantHave) {
dirkmc's avatar
dirkmc committed
231 232
		t.Fatal("Expected 2 want-blocks")
	}
233
	if len(pq0.whs) != 0 {
dirkmc's avatar
dirkmc committed
234 235 236 237
		t.Fatal("Expected 0 want-haves")
	}

	// Send to p0 as want-haves: 1 new want-have, 1 old want-block
238
	clearSent(peerQueues)
dirkmc's avatar
dirkmc committed
239 240
	cids6 := testutil.GenerateCids(1)
	newWantHaveOldWantBlock := append(cids6, cids[0])
241
	pwm.sendWants(p0, []cid.Cid{}, newWantHaveOldWantBlock)
dirkmc's avatar
dirkmc committed
242 243
	// If a want was previously sent as a want-block, it should not be
	// possible to now send it as a want-have
244
	if !testutil.MatchKeysIgnoreOrder(pq0.whs, cids6) {
dirkmc's avatar
dirkmc committed
245 246
		t.Fatal("Expected 1 want-have")
	}
247
	if len(pq0.wbs) != 0 {
dirkmc's avatar
dirkmc committed
248 249 250 251
		t.Fatal("Expected 0 want-blocks")
	}

	// Send 2 want-blocks and 2 want-haves to p1
252 253
	pwm.sendWants(p1, cids, cids2)
	if !testutil.MatchKeysIgnoreOrder(pq1.wbs, cids) {
dirkmc's avatar
dirkmc committed
254 255
		t.Fatal("Expected 2 want-blocks")
	}
256
	if !testutil.MatchKeysIgnoreOrder(pq1.whs, cids2) {
dirkmc's avatar
dirkmc committed
257 258 259 260
		t.Fatal("Expected 2 want-haves")
	}
}

261
func TestPWMSendCancels(t *testing.T) {
dirkmc's avatar
dirkmc committed
262 263 264 265 266 267 268 269 270 271 272 273
	pwm := newPeerWantManager(&gauge{})

	peers := testutil.GeneratePeers(2)
	p0 := peers[0]
	p1 := peers[1]
	wb1 := testutil.GenerateCids(2)
	wh1 := testutil.GenerateCids(2)
	wb2 := testutil.GenerateCids(2)
	wh2 := testutil.GenerateCids(2)
	allwb := append(wb1, wb2...)
	allwh := append(wh1, wh2...)

274 275 276 277 278 279 280 281
	peerQueues := make(map[peer.ID]PeerQueue)
	for _, p := range peers[:2] {
		pq := &mockPQ{}
		peerQueues[p] = pq
		pwm.addPeer(pq, p)
	}
	pq0 := peerQueues[p0].(*mockPQ)
	pq1 := peerQueues[p1].(*mockPQ)
dirkmc's avatar
dirkmc committed
282 283

	// Send 2 want-blocks and 2 want-haves to p0
284
	pwm.sendWants(p0, wb1, wh1)
dirkmc's avatar
dirkmc committed
285 286
	// Send 3 want-blocks and 3 want-haves to p1
	// (1 overlapping want-block / want-have with p0)
287
	pwm.sendWants(p1, append(wb2, wb1[1]), append(wh2, wh1[1]))
dirkmc's avatar
dirkmc committed
288

289
	if !testutil.MatchKeysIgnoreOrder(pwm.getWantBlocks(), allwb) {
dirkmc's avatar
dirkmc committed
290 291
		t.Fatal("Expected 4 cids to be wanted")
	}
292
	if !testutil.MatchKeysIgnoreOrder(pwm.getWantHaves(), allwh) {
dirkmc's avatar
dirkmc committed
293 294 295 296
		t.Fatal("Expected 4 cids to be wanted")
	}

	// Cancel 1 want-block and 1 want-have that were sent to p0
297 298
	clearSent(peerQueues)
	pwm.sendCancels([]cid.Cid{wb1[0], wh1[0]})
dirkmc's avatar
dirkmc committed
299
	// Should cancel the want-block and want-have
300 301
	if len(pq1.cancels) != 0 {
		t.Fatal("Expected no cancels sent to p1")
dirkmc's avatar
dirkmc committed
302
	}
303
	if !testutil.MatchKeysIgnoreOrder(pq0.cancels, []cid.Cid{wb1[0], wh1[0]}) {
dirkmc's avatar
dirkmc committed
304 305
		t.Fatal("Expected 2 cids to be cancelled")
	}
306
	if !testutil.MatchKeysIgnoreOrder(pwm.getWantBlocks(), append(wb2, wb1[1])) {
dirkmc's avatar
dirkmc committed
307 308
		t.Fatal("Expected 3 want-blocks")
	}
309
	if !testutil.MatchKeysIgnoreOrder(pwm.getWantHaves(), append(wh2, wh1[1])) {
dirkmc's avatar
dirkmc committed
310 311 312 313
		t.Fatal("Expected 3 want-haves")
	}

	// Cancel everything
314
	clearSent(peerQueues)
dirkmc's avatar
dirkmc committed
315
	allCids := append(allwb, allwh...)
316 317 318
	pwm.sendCancels(allCids)
	// Should cancel the remaining want-blocks and want-haves for p0
	if !testutil.MatchKeysIgnoreOrder(pq0.cancels, []cid.Cid{wb1[1], wh1[1]}) {
dirkmc's avatar
dirkmc committed
319 320
		t.Fatal("Expected un-cancelled cids to be cancelled")
	}
321 322 323 324 325 326 327 328

	// Should cancel the remaining want-blocks and want-haves for p1
	remainingP1 := append(wb2, wh2...)
	remainingP1 = append(remainingP1, wb1[1], wh1[1])
	if len(pq1.cancels) != len(remainingP1) {
		t.Fatal("mismatch", len(pq1.cancels), len(remainingP1))
	}
	if !testutil.MatchKeysIgnoreOrder(pq1.cancels, remainingP1) {
dirkmc's avatar
dirkmc committed
329 330
		t.Fatal("Expected un-cancelled cids to be cancelled")
	}
331
	if len(pwm.getWantBlocks()) != 0 {
dirkmc's avatar
dirkmc committed
332 333
		t.Fatal("Expected 0 want-blocks")
	}
334
	if len(pwm.getWantHaves()) != 0 {
dirkmc's avatar
dirkmc committed
335 336 337 338 339 340 341 342 343 344 345 346 347
		t.Fatal("Expected 0 want-haves")
	}
}

func TestStats(t *testing.T) {
	g := &gauge{}
	pwm := newPeerWantManager(g)

	peers := testutil.GeneratePeers(2)
	p0 := peers[0]
	cids := testutil.GenerateCids(2)
	cids2 := testutil.GenerateCids(2)

348 349 350 351
	peerQueues := make(map[peer.ID]PeerQueue)
	pq := &mockPQ{}
	peerQueues[p0] = pq
	pwm.addPeer(pq, p0)
dirkmc's avatar
dirkmc committed
352 353

	// Send 2 want-blocks and 2 want-haves to p0
354
	pwm.sendWants(p0, cids, cids2)
dirkmc's avatar
dirkmc committed
355 356 357 358 359 360 361

	if g.count != 2 {
		t.Fatal("Expected 2 want-blocks")
	}

	// Send 1 old want-block and 2 new want-blocks to p0
	cids3 := testutil.GenerateCids(2)
362
	pwm.sendWants(p0, append(cids3, cids[0]), []cid.Cid{})
dirkmc's avatar
dirkmc committed
363 364 365 366 367 368 369 370

	if g.count != 4 {
		t.Fatal("Expected 4 want-blocks")
	}

	// Cancel 1 want-block that was sent to p0
	// and 1 want-block that was not sent
	cids4 := testutil.GenerateCids(1)
371
	pwm.sendCancels(append(cids4, cids[0]))
dirkmc's avatar
dirkmc committed
372 373 374 375

	if g.count != 3 {
		t.Fatal("Expected 3 want-blocks", g.count)
	}
376 377 378 379 380 381

	pwm.removePeer(p0)

	if g.count != 0 {
		t.Fatal("Expected all want-blocks to be removed with peer", g.count)
	}
dirkmc's avatar
dirkmc committed
382
}