peerwantmanager_test.go 7.84 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 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

	cid "github.com/ipfs/go-cid"
)

type gauge struct {
	count int
}

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

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

25
	if len(pwm.getWantBlocks()) > 0 {
dirkmc's avatar
dirkmc committed
26 27
		t.Fatal("Expected GetWantBlocks() to have length 0")
	}
28
	if len(pwm.getWantHaves()) > 0 {
dirkmc's avatar
dirkmc committed
29 30 31 32 33 34 35 36 37 38 39 40
		t.Fatal("Expected GetWantHaves() to have length 0")
	}
}

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

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

41 42
	pwm.addPeer(peers[0])
	pwm.addPeer(peers[1])
dirkmc's avatar
dirkmc committed
43 44

	// Broadcast 2 cids to 2 peers
45
	bcst := pwm.prepareBroadcastWantHaves(cids)
dirkmc's avatar
dirkmc committed
46 47 48 49 50 51 52 53 54 55
	if len(bcst) != 2 {
		t.Fatal("Expected 2 peers")
	}
	for p := range bcst {
		if !testutil.MatchKeysIgnoreOrder(bcst[p], cids) {
			t.Fatal("Expected all cids to be broadcast")
		}
	}

	// Broadcasting same cids should have no effect
56
	bcst2 := pwm.prepareBroadcastWantHaves(cids)
dirkmc's avatar
dirkmc committed
57 58 59 60 61
	if len(bcst2) != 0 {
		t.Fatal("Expected 0 peers")
	}

	// Broadcast 2 other cids
62
	bcst3 := pwm.prepareBroadcastWantHaves(cids2)
dirkmc's avatar
dirkmc committed
63 64 65 66 67 68 69 70 71 72
	if len(bcst3) != 2 {
		t.Fatal("Expected 2 peers")
	}
	for p := range bcst3 {
		if !testutil.MatchKeysIgnoreOrder(bcst3[p], cids2) {
			t.Fatal("Expected all new cids to be broadcast")
		}
	}

	// Broadcast mix of old and new cids
73
	bcst4 := pwm.prepareBroadcastWantHaves(append(cids, cids3...))
dirkmc's avatar
dirkmc committed
74 75 76 77 78 79 80 81 82 83 84 85 86
	if len(bcst4) != 2 {
		t.Fatal("Expected 2 peers")
	}
	// Only new cids should be broadcast
	for p := range bcst4 {
		if !testutil.MatchKeysIgnoreOrder(bcst4[p], cids3) {
			t.Fatal("Expected all new cids to be broadcast")
		}
	}

	// Sending want-block for a cid should prevent broadcast to that peer
	cids4 := testutil.GenerateCids(4)
	wantBlocks := []cid.Cid{cids4[0], cids4[2]}
87
	pwm.prepareSendWants(peers[0], wantBlocks, []cid.Cid{})
dirkmc's avatar
dirkmc committed
88

89
	bcst5 := pwm.prepareBroadcastWantHaves(cids4)
dirkmc's avatar
dirkmc committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
	if len(bcst4) != 2 {
		t.Fatal("Expected 2 peers")
	}
	// Only cids that were not sent as want-block to peer should be broadcast
	for p := range bcst5 {
		if p == peers[0] {
			if !testutil.MatchKeysIgnoreOrder(bcst5[p], []cid.Cid{cids4[1], cids4[3]}) {
				t.Fatal("Expected unsent cids to be broadcast")
			}
		}
		if p == peers[1] {
			if !testutil.MatchKeysIgnoreOrder(bcst5[p], cids4) {
				t.Fatal("Expected all cids to be broadcast")
			}
		}
	}

	// Add another peer
108 109
	pwm.addPeer(peers[2])
	bcst6 := pwm.prepareBroadcastWantHaves(cids)
dirkmc's avatar
dirkmc committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
	if len(bcst6) != 1 {
		t.Fatal("Expected 1 peer")
	}
	for p := range bcst6 {
		if !testutil.MatchKeysIgnoreOrder(bcst6[p], cids) {
			t.Fatal("Expected all cids to be broadcast")
		}
	}
}

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

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

129 130
	pwm.addPeer(p0)
	pwm.addPeer(p1)
dirkmc's avatar
dirkmc committed
131 132

	// Send 2 want-blocks and 2 want-haves to p0
133
	wb, wh := pwm.prepareSendWants(p0, cids, cids2)
dirkmc's avatar
dirkmc committed
134 135 136 137 138 139 140 141 142 143 144 145
	if !testutil.MatchKeysIgnoreOrder(wb, cids) {
		t.Fatal("Expected 2 want-blocks")
	}
	if !testutil.MatchKeysIgnoreOrder(wh, cids2) {
		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
	cids3 := testutil.GenerateCids(2)
	cids4 := testutil.GenerateCids(2)
146
	wb2, wh2 := pwm.prepareSendWants(p0, append(cids3, cids[0]), append(cids4, cids2[0]))
dirkmc's avatar
dirkmc committed
147 148 149 150 151 152 153 154 155 156
	if !testutil.MatchKeysIgnoreOrder(wb2, cids3) {
		t.Fatal("Expected 2 want-blocks")
	}
	if !testutil.MatchKeysIgnoreOrder(wh2, cids4) {
		t.Fatal("Expected 2 want-haves")
	}

	// Send to p0 as want-blocks: 1 new want-block, 1 old want-have
	cids5 := testutil.GenerateCids(1)
	newWantBlockOldWantHave := append(cids5, cids2[0])
157
	wb3, wh3 := pwm.prepareSendWants(p0, newWantBlockOldWantHave, []cid.Cid{})
dirkmc's avatar
dirkmc committed
158 159 160 161 162 163 164 165 166 167 168 169
	// If a want was sent as a want-have, it should be ok to now send it as a
	// want-block
	if !testutil.MatchKeysIgnoreOrder(wb3, newWantBlockOldWantHave) {
		t.Fatal("Expected 2 want-blocks")
	}
	if len(wh3) != 0 {
		t.Fatal("Expected 0 want-haves")
	}

	// Send to p0 as want-haves: 1 new want-have, 1 old want-block
	cids6 := testutil.GenerateCids(1)
	newWantHaveOldWantBlock := append(cids6, cids[0])
170
	wb4, wh4 := pwm.prepareSendWants(p0, []cid.Cid{}, newWantHaveOldWantBlock)
dirkmc's avatar
dirkmc committed
171 172 173 174 175 176 177 178 179 180
	// If a want was previously sent as a want-block, it should not be
	// possible to now send it as a want-have
	if !testutil.MatchKeysIgnoreOrder(wh4, cids6) {
		t.Fatal("Expected 1 want-have")
	}
	if len(wb4) != 0 {
		t.Fatal("Expected 0 want-blocks")
	}

	// Send 2 want-blocks and 2 want-haves to p1
181
	wb5, wh5 := pwm.prepareSendWants(p1, cids, cids2)
dirkmc's avatar
dirkmc committed
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
	if !testutil.MatchKeysIgnoreOrder(wb5, cids) {
		t.Fatal("Expected 2 want-blocks")
	}
	if !testutil.MatchKeysIgnoreOrder(wh5, cids2) {
		t.Fatal("Expected 2 want-haves")
	}
}

func TestPrepareSendCancels(t *testing.T) {
	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...)

203 204
	pwm.addPeer(p0)
	pwm.addPeer(p1)
dirkmc's avatar
dirkmc committed
205 206

	// Send 2 want-blocks and 2 want-haves to p0
207
	pwm.prepareSendWants(p0, wb1, wh1)
dirkmc's avatar
dirkmc committed
208 209
	// Send 3 want-blocks and 3 want-haves to p1
	// (1 overlapping want-block / want-have with p0)
210
	pwm.prepareSendWants(p1, append(wb2, wb1[1]), append(wh2, wh1[1]))
dirkmc's avatar
dirkmc committed
211

212
	if !testutil.MatchKeysIgnoreOrder(pwm.getWantBlocks(), allwb) {
dirkmc's avatar
dirkmc committed
213 214
		t.Fatal("Expected 4 cids to be wanted")
	}
215
	if !testutil.MatchKeysIgnoreOrder(pwm.getWantHaves(), allwh) {
dirkmc's avatar
dirkmc committed
216 217 218 219
		t.Fatal("Expected 4 cids to be wanted")
	}

	// Cancel 1 want-block and 1 want-have that were sent to p0
220
	res := pwm.prepareSendCancels([]cid.Cid{wb1[0], wh1[0]})
dirkmc's avatar
dirkmc committed
221 222 223 224 225 226 227
	// Should cancel the want-block and want-have
	if len(res) != 1 {
		t.Fatal("Expected 1 peer")
	}
	if !testutil.MatchKeysIgnoreOrder(res[p0], []cid.Cid{wb1[0], wh1[0]}) {
		t.Fatal("Expected 2 cids to be cancelled")
	}
228
	if !testutil.MatchKeysIgnoreOrder(pwm.getWantBlocks(), append(wb2, wb1[1])) {
dirkmc's avatar
dirkmc committed
229 230
		t.Fatal("Expected 3 want-blocks")
	}
231
	if !testutil.MatchKeysIgnoreOrder(pwm.getWantHaves(), append(wh2, wh1[1])) {
dirkmc's avatar
dirkmc committed
232 233 234 235 236
		t.Fatal("Expected 3 want-haves")
	}

	// Cancel everything
	allCids := append(allwb, allwh...)
237
	res2 := pwm.prepareSendCancels(allCids)
dirkmc's avatar
dirkmc committed
238 239 240 241 242 243 244 245 246 247 248 249
	// Should cancel the remaining want-blocks and want-haves
	if len(res2) != 2 {
		t.Fatal("Expected 2 peers", len(res2))
	}
	if !testutil.MatchKeysIgnoreOrder(res2[p0], []cid.Cid{wb1[1], wh1[1]}) {
		t.Fatal("Expected un-cancelled cids to be cancelled")
	}
	remainingP2 := append(wb2, wh2...)
	remainingP2 = append(remainingP2, wb1[1], wh1[1])
	if !testutil.MatchKeysIgnoreOrder(res2[p1], remainingP2) {
		t.Fatal("Expected un-cancelled cids to be cancelled")
	}
250
	if len(pwm.getWantBlocks()) != 0 {
dirkmc's avatar
dirkmc committed
251 252
		t.Fatal("Expected 0 want-blocks")
	}
253
	if len(pwm.getWantHaves()) != 0 {
dirkmc's avatar
dirkmc committed
254 255 256 257 258 259 260 261 262 263 264 265 266
		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)

267
	pwm.addPeer(p0)
dirkmc's avatar
dirkmc committed
268 269

	// Send 2 want-blocks and 2 want-haves to p0
270
	pwm.prepareSendWants(p0, cids, cids2)
dirkmc's avatar
dirkmc committed
271 272 273 274 275 276 277

	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)
278
	pwm.prepareSendWants(p0, append(cids3, cids[0]), []cid.Cid{})
dirkmc's avatar
dirkmc committed
279 280 281 282 283 284 285 286

	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)
287
	pwm.prepareSendCancels(append(cids4, cids[0]))
dirkmc's avatar
dirkmc committed
288 289 290 291

	if g.count != 3 {
		t.Fatal("Expected 3 want-blocks", g.count)
	}
292 293 294 295 296 297

	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
298
}