bitswap_test.go 17.4 KB
Newer Older
1
package bitswap_test
Brian Tiger Chow's avatar
Brian Tiger Chow committed
2 3

import (
4
	"bytes"
5
	"context"
Jeromy's avatar
Jeromy committed
6
	"fmt"
7
	"sync"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
8 9 10
	"testing"
	"time"

11
	bitswap "github.com/ipfs/go-bitswap"
Jeromy's avatar
Jeromy committed
12
	decision "github.com/ipfs/go-bitswap/decision"
13
	"github.com/ipfs/go-bitswap/message"
14
	bssession "github.com/ipfs/go-bitswap/session"
15
	testinstance "github.com/ipfs/go-bitswap/testinstance"
Jeromy's avatar
Jeromy committed
16 17 18 19 20 21 22 23 24 25 26
	tn "github.com/ipfs/go-bitswap/testnet"
	blocks "github.com/ipfs/go-block-format"
	cid "github.com/ipfs/go-cid"
	detectrace "github.com/ipfs/go-detect-race"
	blockstore "github.com/ipfs/go-ipfs-blockstore"
	blocksutil "github.com/ipfs/go-ipfs-blocksutil"
	delay "github.com/ipfs/go-ipfs-delay"
	mockrouting "github.com/ipfs/go-ipfs-routing/mock"
	p2ptestutil "github.com/libp2p/go-libp2p-netutil"
	tu "github.com/libp2p/go-testutil"
	travis "github.com/libp2p/go-testutil/ci/travis"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
27 28
)

Brian Tiger Chow's avatar
Brian Tiger Chow committed
29 30
// FIXME the tests are really sensitive to the network delay. fix them to work
// well under varying conditions
31 32
const kNetworkDelay = 0 * time.Millisecond

33 34 35 36
func getVirtualNetwork() tn.Network {
	return tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
}

37
func TestClose(t *testing.T) {
38
	vnet := getVirtualNetwork()
39 40
	ig := testinstance.NewTestInstanceGenerator(vnet)
	defer ig.Close()
41
	bgen := blocksutil.NewBlockGenerator()
42 43

	block := bgen.Next()
44
	bitswap := ig.Next()
45

46
	bitswap.Exchange.Close()
47
	bitswap.Exchange.GetBlock(context.Background(), block.Cid())
48 49
}

Jeromy's avatar
Jeromy committed
50 51 52 53
func TestProviderForKeyButNetworkCannotFind(t *testing.T) { // TODO revisit this

	rs := mockrouting.NewServer()
	net := tn.VirtualNetwork(rs, delay.Fixed(kNetworkDelay))
54 55
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
Jeromy's avatar
Jeromy committed
56 57 58

	block := blocks.NewBlock([]byte("block"))
	pinfo := p2ptestutil.RandTestBogusIdentityOrFatal(t)
59
	rs.Client(pinfo).Provide(context.Background(), block.Cid(), true) // but not on network
Jeromy's avatar
Jeromy committed
60

61
	solo := ig.Next()
Jeromy's avatar
Jeromy committed
62 63
	defer solo.Exchange.Close()

rht's avatar
rht committed
64 65
	ctx, cancel := context.WithTimeout(context.Background(), time.Nanosecond)
	defer cancel()
66
	_, err := solo.Exchange.GetBlock(ctx, block.Cid())
Jeromy's avatar
Jeromy committed
67 68 69 70 71 72

	if err != context.DeadlineExceeded {
		t.Fatal("Expected DeadlineExceeded error")
	}
}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
73 74
func TestGetBlockFromPeerAfterPeerAnnounces(t *testing.T) {

75
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
76
	block := blocks.NewBlock([]byte("block"))
77 78
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
Brian Tiger Chow's avatar
Brian Tiger Chow committed
79

80
	peers := ig.Instances(2)
81
	hasBlock := peers[0]
Jeromy's avatar
Jeromy committed
82
	defer hasBlock.Exchange.Close()
Brian Tiger Chow's avatar
Brian Tiger Chow committed
83

84
	if err := hasBlock.Exchange.HasBlock(block); err != nil {
85 86
		t.Fatal(err)
	}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
87

88
	wantsBlock := peers[1]
Jeromy's avatar
Jeromy committed
89
	defer wantsBlock.Exchange.Close()
Brian Tiger Chow's avatar
Brian Tiger Chow committed
90

rht's avatar
rht committed
91 92
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
93
	received, err := wantsBlock.Exchange.GetBlock(ctx, block.Cid())
Brian Tiger Chow's avatar
Brian Tiger Chow committed
94 95 96 97
	if err != nil {
		t.Log(err)
		t.Fatal("Expected to succeed")
	}
98

Jeromy's avatar
Jeromy committed
99
	if !bytes.Equal(block.RawData(), received.RawData()) {
100 101
		t.Fatal("Data doesn't match")
	}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
102 103
}

104
func TestDoesNotProvideWhenConfiguredNotTo(t *testing.T) {
105 106
	bitswap.ProvideEnabled = false
	defer func() { bitswap.ProvideEnabled = true }()
107 108 109

	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
	block := blocks.NewBlock([]byte("block"))
110 111
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
112

113
	hasBlock := ig.Next()
114 115 116 117 118 119 120 121 122
	defer hasBlock.Exchange.Close()

	if err := hasBlock.Exchange.HasBlock(block); err != nil {
		t.Fatal(err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

123
	wantsBlock := ig.Next()
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
	defer wantsBlock.Exchange.Close()

	ns := wantsBlock.Exchange.NewSession(ctx).(*bssession.Session)
	// set find providers delay to less than timeout context of this test
	ns.SetBaseTickDelay(10 * time.Millisecond)

	received, err := ns.GetBlock(ctx, block.Cid())
	if received != nil {
		t.Fatalf("Expected to find nothing, found %s", received)
	}

	if err != context.DeadlineExceeded {
		t.Fatal("Expected deadline exceeded")
	}
}

140 141 142 143 144 145 146
func TestUnwantedBlockNotAdded(t *testing.T) {

	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
	block := blocks.NewBlock([]byte("block"))
	bsMessage := message.New(true)
	bsMessage.AddBlock(block)

147 148
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
149

150
	peers := ig.Instances(2)
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
	hasBlock := peers[0]
	defer hasBlock.Exchange.Close()

	if err := hasBlock.Exchange.HasBlock(block); err != nil {
		t.Fatal(err)
	}

	doesNotWantBlock := peers[1]
	defer doesNotWantBlock.Exchange.Close()

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	doesNotWantBlock.Exchange.ReceiveMessage(ctx, hasBlock.Peer, bsMessage)

166
	blockInStore, err := doesNotWantBlock.Blockstore().Has(block.Cid())
167 168 169 170 171
	if err != nil || blockInStore {
		t.Fatal("Unwanted block added to block store")
	}
}

172
func TestLargeSwarm(t *testing.T) {
173 174 175
	if testing.Short() {
		t.SkipNow()
	}
176
	numInstances := 100
177
	numBlocks := 2
178 179 180
	if detectrace.WithRace() {
		// when running with the race detector, 500 instances launches
		// well over 8k goroutines. This hits a race detector limit.
181
		numInstances = 50
182 183
	} else if travis.IsRunning() {
		numInstances = 200
184 185 186
	} else {
		t.Parallel()
	}
187 188
	PerformDistributionTest(t, numInstances, numBlocks)
}
189

190 191 192
func TestLargeFile(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
193
	}
194 195 196 197 198

	if !travis.IsRunning() {
		t.Parallel()
	}

199 200 201
	numInstances := 10
	numBlocks := 100
	PerformDistributionTest(t, numInstances, numBlocks)
202 203
}

204 205 206 207 208 209 210 211 212
func TestLargeFileTwoPeers(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	numInstances := 2
	numBlocks := 100
	PerformDistributionTest(t, numInstances, numBlocks)
}

213
func PerformDistributionTest(t *testing.T, numInstances, numBlocks int) {
214
	ctx := context.Background()
215 216 217
	if testing.Short() {
		t.SkipNow()
	}
218
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
219 220
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
221
	bg := blocksutil.NewBlockGenerator()
222

223
	instances := ig.Instances(numInstances)
224 225 226 227
	blocks := bg.Blocks(numBlocks)

	t.Log("Give the blocks to the first instance")

228
	var blkeys []cid.Cid
229 230
	first := instances[0]
	for _, b := range blocks {
231
		blkeys = append(blkeys, b.Cid())
232
		first.Exchange.HasBlock(b)
233 234 235 236
	}

	t.Log("Distribute!")

Jeromy's avatar
Jeromy committed
237
	wg := sync.WaitGroup{}
238 239
	errs := make(chan error)

240
	for _, inst := range instances[1:] {
Jeromy's avatar
Jeromy committed
241
		wg.Add(1)
242
		go func(inst testinstance.Instance) {
Jeromy's avatar
Jeromy committed
243
			defer wg.Done()
244
			outch, err := inst.Exchange.GetBlocks(ctx, blkeys)
Jeromy's avatar
Jeromy committed
245
			if err != nil {
246
				errs <- err
Jeromy's avatar
Jeromy committed
247
			}
248
			for range outch {
Jeromy's avatar
Jeromy committed
249 250
			}
		}(inst)
251
	}
252 253 254 255 256 257 258 259 260 261 262

	go func() {
		wg.Wait()
		close(errs)
	}()

	for err := range errs {
		if err != nil {
			t.Fatal(err)
		}
	}
263 264 265 266 267

	t.Log("Verify!")

	for _, inst := range instances {
		for _, b := range blocks {
268
			if _, err := inst.Blockstore().Get(b.Cid()); err != nil {
269 270 271 272 273 274
				t.Fatal(err)
			}
		}
	}
}

275
// TODO simplify this test. get to the _essence_!
276
func TestSendToWantingPeer(t *testing.T) {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
277 278 279 280
	if testing.Short() {
		t.SkipNow()
	}

281
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
282 283
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
284
	bg := blocksutil.NewBlockGenerator()
285

286
	peers := ig.Instances(2)
287 288
	peerA := peers[0]
	peerB := peers[1]
289

290 291
	t.Logf("Session %v\n", peerA.Peer)
	t.Logf("Session %v\n", peerB.Peer)
292

293
	waitTime := time.Second * 5
294

295 296
	alpha := bg.Next()
	// peerA requests and waits for block alpha
297
	ctx, cancel := context.WithTimeout(context.Background(), waitTime)
rht's avatar
rht committed
298
	defer cancel()
299
	alphaPromise, err := peerA.Exchange.GetBlocks(ctx, []cid.Cid{alpha.Cid()})
300
	if err != nil {
301 302
		t.Fatal(err)
	}
303

304
	// peerB announces to the network that he has block alpha
305
	err = peerB.Exchange.HasBlock(alpha)
306
	if err != nil {
307 308
		t.Fatal(err)
	}
309

310 311 312 313
	// At some point, peerA should get alpha (or timeout)
	blkrecvd, ok := <-alphaPromise
	if !ok {
		t.Fatal("context timed out and broke promise channel!")
314
	}
315

316
	if !blkrecvd.Cid().Equals(alpha.Cid()) {
317
		t.Fatal("Wrong block!")
318
	}
319

320
}
Jeromy's avatar
Jeromy committed
321

jbenet's avatar
jbenet committed
322 323
func TestEmptyKey(t *testing.T) {
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
324 325 326
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
	bs := ig.Instances(1)[0].Exchange
jbenet's avatar
jbenet committed
327

Jeromy's avatar
Jeromy committed
328 329 330
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()

331
	_, err := bs.GetBlock(ctx, cid.Cid{})
jbenet's avatar
jbenet committed
332 333 334 335 336
	if err != blockstore.ErrNotFound {
		t.Error("empty str key should return ErrNotFound")
	}
}

337
func assertStat(t *testing.T, st *bitswap.Stat, sblks, rblks, sdata, rdata uint64) {
Jeromy's avatar
Jeromy committed
338
	if sblks != st.BlocksSent {
Steven Allen's avatar
Steven Allen committed
339
		t.Errorf("mismatch in blocks sent: %d vs %d", sblks, st.BlocksSent)
Jeromy's avatar
Jeromy committed
340 341 342
	}

	if rblks != st.BlocksReceived {
Steven Allen's avatar
Steven Allen committed
343
		t.Errorf("mismatch in blocks recvd: %d vs %d", rblks, st.BlocksReceived)
Jeromy's avatar
Jeromy committed
344 345 346
	}

	if sdata != st.DataSent {
Steven Allen's avatar
Steven Allen committed
347
		t.Errorf("mismatch in data sent: %d vs %d", sdata, st.DataSent)
Jeromy's avatar
Jeromy committed
348 349 350
	}

	if rdata != st.DataReceived {
Steven Allen's avatar
Steven Allen committed
351
		t.Errorf("mismatch in data recvd: %d vs %d", rdata, st.DataReceived)
Jeromy's avatar
Jeromy committed
352 353 354
	}
}

Jeromy's avatar
Jeromy committed
355
func TestBasicBitswap(t *testing.T) {
356
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
357 358
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
Jeromy's avatar
Jeromy committed
359 360
	bg := blocksutil.NewBlockGenerator()

361
	t.Log("Test a one node trying to get one block from another")
Jeromy's avatar
Jeromy committed
362

363
	instances := ig.Instances(3)
Jeromy's avatar
Jeromy committed
364
	blocks := bg.Blocks(1)
365
	err := instances[0].Exchange.HasBlock(blocks[0])
Jeromy's avatar
Jeromy committed
366 367 368 369
	if err != nil {
		t.Fatal(err)
	}

370
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
rht's avatar
rht committed
371
	defer cancel()
372
	blk, err := instances[1].Exchange.GetBlock(ctx, blocks[0].Cid())
Jeromy's avatar
Jeromy committed
373 374 375 376
	if err != nil {
		t.Fatal(err)
	}

377 378 379 380 381 382 383 384 385 386
	if err = tu.WaitFor(ctx, func() error {
		if len(instances[2].Exchange.WantlistForPeer(instances[1].Peer)) != 0 {
			return fmt.Errorf("should have no items in other peers wantlist")
		}
		if len(instances[1].Exchange.GetWantlist()) != 0 {
			return fmt.Errorf("shouldnt have anything in wantlist")
		}
		return nil
	}); err != nil {
		t.Fatal(err)
Jeromy's avatar
Jeromy committed
387 388
	}

Jeromy's avatar
Jeromy committed
389 390 391 392 393 394 395 396 397 398
	st0, err := instances[0].Exchange.Stat()
	if err != nil {
		t.Fatal(err)
	}

	st1, err := instances[1].Exchange.Stat()
	if err != nil {
		t.Fatal(err)
	}

Steven Allen's avatar
Steven Allen committed
399 400
	st2, err := instances[2].Exchange.Stat()
	if err != nil {
Jeromy's avatar
Jeromy committed
401 402 403
		t.Fatal(err)
	}

Steven Allen's avatar
Steven Allen committed
404 405 406 407 408 409 410 411 412
	t.Log("stat node 0")
	assertStat(t, st0, 1, 0, uint64(len(blk.RawData())), 0)
	t.Log("stat node 1")
	assertStat(t, st1, 0, 1, 0, uint64(len(blk.RawData())))
	t.Log("stat node 2")
	assertStat(t, st2, 0, 0, 0, 0)

	if !bytes.Equal(blk.RawData(), blocks[0].RawData()) {
		t.Errorf("blocks aren't equal: expected %v, actual %v", blocks[0].RawData(), blk.RawData())
Jeromy's avatar
Jeromy committed
413 414
	}

Jeromy's avatar
Jeromy committed
415 416 417 418 419 420 421 422
	t.Log(blk)
	for _, inst := range instances {
		err := inst.Exchange.Close()
		if err != nil {
			t.Fatal(err)
		}
	}
}
Jeromy's avatar
Jeromy committed
423 424 425

func TestDoubleGet(t *testing.T) {
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
426 427
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
Jeromy's avatar
Jeromy committed
428 429 430 431
	bg := blocksutil.NewBlockGenerator()

	t.Log("Test a one node trying to get one block from another")

432
	instances := ig.Instances(2)
Jeromy's avatar
Jeromy committed
433 434
	blocks := bg.Blocks(1)

Jeromy's avatar
Jeromy committed
435 436 437
	// NOTE: A race condition can happen here where these GetBlocks requests go
	// through before the peers even get connected. This is okay, bitswap
	// *should* be able to handle this.
Jeromy's avatar
Jeromy committed
438
	ctx1, cancel1 := context.WithCancel(context.Background())
439
	blkch1, err := instances[1].Exchange.GetBlocks(ctx1, []cid.Cid{blocks[0].Cid()})
Jeromy's avatar
Jeromy committed
440 441 442 443 444 445 446
	if err != nil {
		t.Fatal(err)
	}

	ctx2, cancel2 := context.WithCancel(context.Background())
	defer cancel2()

447
	blkch2, err := instances[1].Exchange.GetBlocks(ctx2, []cid.Cid{blocks[0].Cid()})
Jeromy's avatar
Jeromy committed
448 449 450 451
	if err != nil {
		t.Fatal(err)
	}

452
	// ensure both requests make it into the wantlist at the same time
Jeromy's avatar
Jeromy committed
453
	time.Sleep(time.Millisecond * 20)
Jeromy's avatar
Jeromy committed
454 455 456 457 458 459 460 461 462 463 464 465
	cancel1()

	_, ok := <-blkch1
	if ok {
		t.Fatal("expected channel to be closed")
	}

	err = instances[0].Exchange.HasBlock(blocks[0])
	if err != nil {
		t.Fatal(err)
	}

466 467 468 469 470 471 472
	select {
	case blk, ok := <-blkch2:
		if !ok {
			t.Fatal("expected to get the block here")
		}
		t.Log(blk)
	case <-time.After(time.Second * 5):
Jeromy's avatar
Jeromy committed
473 474 475 476 477 478 479 480
		p1wl := instances[0].Exchange.WantlistForPeer(instances[1].Peer)
		if len(p1wl) != 1 {
			t.Logf("wantlist view didnt have 1 item (had %d)", len(p1wl))
		} else if !p1wl[0].Equals(blocks[0].Cid()) {
			t.Logf("had 1 item, it was wrong: %s %s", blocks[0].Cid(), p1wl[0])
		} else {
			t.Log("had correct wantlist, somehow")
		}
481
		t.Fatal("timed out waiting on block")
Jeromy's avatar
Jeromy committed
482 483 484 485 486 487 488 489 490
	}

	for _, inst := range instances {
		err := inst.Exchange.Close()
		if err != nil {
			t.Fatal(err)
		}
	}
}
491 492 493

func TestWantlistCleanup(t *testing.T) {
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
494 495
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
496 497
	bg := blocksutil.NewBlockGenerator()

498
	instances := ig.Instances(1)[0]
499 500 501
	bswap := instances.Exchange
	blocks := bg.Blocks(20)

502
	var keys []cid.Cid
503
	for _, b := range blocks {
504
		keys = append(keys, b.Cid())
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
	defer cancel()
	_, err := bswap.GetBlock(ctx, keys[0])
	if err != context.DeadlineExceeded {
		t.Fatal("shouldnt have fetched any blocks")
	}

	time.Sleep(time.Millisecond * 50)

	if len(bswap.GetWantlist()) > 0 {
		t.Fatal("should not have anyting in wantlist")
	}

	ctx, cancel = context.WithTimeout(context.Background(), time.Millisecond*50)
	defer cancel()
	_, err = bswap.GetBlocks(ctx, keys[:10])
	if err != nil {
		t.Fatal(err)
	}

	<-ctx.Done()
	time.Sleep(time.Millisecond * 50)

	if len(bswap.GetWantlist()) > 0 {
		t.Fatal("should not have anyting in wantlist")
	}

	_, err = bswap.GetBlocks(context.Background(), keys[:1])
	if err != nil {
		t.Fatal(err)
	}

	ctx, cancel = context.WithCancel(context.Background())
	_, err = bswap.GetBlocks(ctx, keys[10:])
	if err != nil {
		t.Fatal(err)
	}

	time.Sleep(time.Millisecond * 50)
546 547
	if len(bswap.GetWantlist()) != 5 {
		t.Fatal("should have 5 keys in wantlist")
548 549 550 551 552 553 554 555
	}

	cancel()
	time.Sleep(time.Millisecond * 50)
	if !(len(bswap.GetWantlist()) == 1 && bswap.GetWantlist()[0] == keys[0]) {
		t.Fatal("should only have keys[0] in wantlist")
	}
}
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572

func assertLedgerMatch(ra, rb *decision.Receipt) error {
	if ra.Sent != rb.Recv {
		return fmt.Errorf("mismatch in ledgers (exchanged bytes): %d sent vs %d recvd", ra.Sent, rb.Recv)
	}

	if ra.Recv != rb.Sent {
		return fmt.Errorf("mismatch in ledgers (exchanged bytes): %d recvd vs %d sent", ra.Recv, rb.Sent)
	}

	if ra.Exchanged != rb.Exchanged {
		return fmt.Errorf("mismatch in ledgers (exchanged blocks): %d vs %d ", ra.Exchanged, rb.Exchanged)
	}

	return nil
}

573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
func assertLedgerEqual(ra, rb *decision.Receipt) error {
	if ra.Value != rb.Value {
		return fmt.Errorf("mismatch in ledgers (value/debt ratio): %f vs %f ", ra.Value, rb.Value)
	}

	if ra.Sent != rb.Sent {
		return fmt.Errorf("mismatch in ledgers (sent bytes): %d vs %d", ra.Sent, rb.Sent)
	}

	if ra.Recv != rb.Recv {
		return fmt.Errorf("mismatch in ledgers (recvd bytes): %d vs %d", ra.Recv, rb.Recv)
	}

	if ra.Exchanged != rb.Exchanged {
		return fmt.Errorf("mismatch in ledgers (exchanged blocks): %d vs %d ", ra.Exchanged, rb.Exchanged)
	}

	return nil
}

func newReceipt(sent, recv, exchanged uint64) *decision.Receipt {
	return &decision.Receipt{
		Peer:      "test",
		Value:     float64(sent) / (1 + float64(recv)),
		Sent:      sent,
		Recv:      recv,
		Exchanged: exchanged,
	}
}

func TestBitswapLedgerOneWay(t *testing.T) {
604
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
605 606
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
607 608 609 610
	bg := blocksutil.NewBlockGenerator()

	t.Log("Test ledgers match when one peer sends block to another")

611
	instances := ig.Instances(2)
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
	blocks := bg.Blocks(1)
	err := instances[0].Exchange.HasBlock(blocks[0])
	if err != nil {
		t.Fatal(err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()
	blk, err := instances[1].Exchange.GetBlock(ctx, blocks[0].Cid())
	if err != nil {
		t.Fatal(err)
	}

	ra := instances[0].Exchange.LedgerForPeer(instances[1].Peer)
	rb := instances[1].Exchange.LedgerForPeer(instances[0].Peer)

628
	// compare peer ledger receipts
629 630 631 632 633
	err = assertLedgerMatch(ra, rb)
	if err != nil {
		t.Fatal(err)
	}

634 635 636 637 638 639 640 641 642 643 644 645
	// check that receipts have intended values
	ratest := newReceipt(1, 0, 1)
	err = assertLedgerEqual(ratest, ra)
	if err != nil {
		t.Fatal(err)
	}
	rbtest := newReceipt(0, 1, 1)
	err = assertLedgerEqual(rbtest, rb)
	if err != nil {
		t.Fatal(err)
	}

646 647 648 649 650 651 652 653 654
	t.Log(blk)
	for _, inst := range instances {
		err := inst.Exchange.Close()
		if err != nil {
			t.Fatal(err)
		}
	}
}

655
func TestBitswapLedgerTwoWay(t *testing.T) {
656
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
657 658
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
659 660 661 662
	bg := blocksutil.NewBlockGenerator()

	t.Log("Test ledgers match when two peers send one block to each other")

663
	instances := ig.Instances(2)
664 665 666 667 668 669 670 671 672 673 674 675 676
	blocks := bg.Blocks(2)
	err := instances[0].Exchange.HasBlock(blocks[0])
	if err != nil {
		t.Fatal(err)
	}

	err = instances[1].Exchange.HasBlock(blocks[1])
	if err != nil {
		t.Fatal(err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()
677
	_, err = instances[1].Exchange.GetBlock(ctx, blocks[0].Cid())
678 679 680 681 682 683
	if err != nil {
		t.Fatal(err)
	}

	ctx, cancel = context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()
684
	blk, err := instances[0].Exchange.GetBlock(ctx, blocks[1].Cid())
685 686 687 688 689 690 691
	if err != nil {
		t.Fatal(err)
	}

	ra := instances[0].Exchange.LedgerForPeer(instances[1].Peer)
	rb := instances[1].Exchange.LedgerForPeer(instances[0].Peer)

692
	// compare peer ledger receipts
693 694 695 696 697
	err = assertLedgerMatch(ra, rb)
	if err != nil {
		t.Fatal(err)
	}

698 699 700 701 702 703 704 705 706 707 708 709
	// check that receipts have intended values
	rtest := newReceipt(1, 1, 2)
	err = assertLedgerEqual(rtest, ra)
	if err != nil {
		t.Fatal(err)
	}

	err = assertLedgerEqual(rtest, rb)
	if err != nil {
		t.Fatal(err)
	}

710 711 712 713 714 715 716 717
	t.Log(blk)
	for _, inst := range instances {
		err := inst.Exchange.Close()
		if err != nil {
			t.Fatal(err)
		}
	}
}