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
	bssession.SetProviderSearchDelay(50 * time.Millisecond)
	defer bssession.SetProviderSearchDelay(time.Second)
107 108
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
	block := blocks.NewBlock([]byte("block"))
109
	ig := testinstance.NewTestInstanceGenerator(net, bitswap.ProvideEnabled(false))
110
	defer ig.Close()
111

112
	hasBlock := ig.Next()
113 114
	defer hasBlock.Exchange.Close()

115 116 117
	wantsBlock := ig.Next()
	defer wantsBlock.Exchange.Close()

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

122
	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Millisecond)
123 124 125 126 127 128 129 130 131 132 133 134 135 136
	defer cancel()

	ns := wantsBlock.Exchange.NewSession(ctx).(*bssession.Session)

	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")
	}
}

137 138 139 140 141 142 143
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)

144 145
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
146

147
	peers := ig.Instances(2)
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
	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)

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

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

187 188 189
func TestLargeFile(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
190
	}
191 192 193 194 195

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

196 197 198
	numInstances := 10
	numBlocks := 100
	PerformDistributionTest(t, numInstances, numBlocks)
199 200
}

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

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

220
	instances := ig.Instances(numInstances)
221 222 223 224
	blocks := bg.Blocks(numBlocks)

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

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

	t.Log("Distribute!")

Jeromy's avatar
Jeromy committed
234
	wg := sync.WaitGroup{}
235 236
	errs := make(chan error)

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

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

	for err := range errs {
		if err != nil {
			t.Fatal(err)
		}
	}
260 261 262 263 264

	t.Log("Verify!")

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

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

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

283
	peers := ig.Instances(2)
284 285
	peerA := peers[0]
	peerB := peers[1]
286

287 288
	t.Logf("Session %v\n", peerA.Peer)
	t.Logf("Session %v\n", peerB.Peer)
289

290
	waitTime := time.Second * 5
291

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

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

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

313
	if !blkrecvd.Cid().Equals(alpha.Cid()) {
314
		t.Fatal("Wrong block!")
315
	}
316

317
}
Jeromy's avatar
Jeromy committed
318

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

Jeromy's avatar
Jeromy committed
325 326 327
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()

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

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

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

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

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

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

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

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

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

374 375 376 377 378 379 380 381 382 383
	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
384 385
	}

Jeromy's avatar
Jeromy committed
386 387 388 389 390 391 392 393 394 395
	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
396 397
	st2, err := instances[2].Exchange.Stat()
	if err != nil {
Jeromy's avatar
Jeromy committed
398 399 400
		t.Fatal(err)
	}

Steven Allen's avatar
Steven Allen committed
401 402 403 404 405 406 407 408 409
	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
410 411
	}

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

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

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

429
	instances := ig.Instances(2)
Jeromy's avatar
Jeromy committed
430 431
	blocks := bg.Blocks(1)

Jeromy's avatar
Jeromy committed
432 433 434
	// 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
435
	ctx1, cancel1 := context.WithCancel(context.Background())
436
	blkch1, err := instances[1].Exchange.GetBlocks(ctx1, []cid.Cid{blocks[0].Cid()})
Jeromy's avatar
Jeromy committed
437 438 439 440 441 442 443
	if err != nil {
		t.Fatal(err)
	}

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

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

449
	// ensure both requests make it into the wantlist at the same time
Jeromy's avatar
Jeromy committed
450
	time.Sleep(time.Millisecond * 20)
Jeromy's avatar
Jeromy committed
451 452 453 454 455 456 457 458 459 460 461 462
	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)
	}

463 464 465 466 467 468 469
	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
470 471 472 473 474 475 476 477
		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")
		}
478
		t.Fatal("timed out waiting on block")
Jeromy's avatar
Jeromy committed
479 480 481 482 483 484 485 486 487
	}

	for _, inst := range instances {
		err := inst.Exchange.Close()
		if err != nil {
			t.Fatal(err)
		}
	}
}
488 489 490

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

495
	instances := ig.Instances(1)[0]
496 497 498
	bswap := instances.Exchange
	blocks := bg.Blocks(20)

499
	var keys []cid.Cid
500
	for _, b := range blocks {
501
		keys = append(keys, b.Cid())
502 503 504 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
	}

	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)
543 544
	if len(bswap.GetWantlist()) != 5 {
		t.Fatal("should have 5 keys in wantlist")
545 546 547 548 549 550 551 552
	}

	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")
	}
}
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569

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
}

570 571 572 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
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) {
601
	net := tn.VirtualNetwork(mockrouting.NewServer(), delay.Fixed(kNetworkDelay))
602 603
	ig := testinstance.NewTestInstanceGenerator(net)
	defer ig.Close()
604 605 606 607
	bg := blocksutil.NewBlockGenerator()

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

608
	instances := ig.Instances(2)
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
	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)

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

631 632 633 634 635 636 637 638 639 640 641 642
	// 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)
	}

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

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

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

660
	instances := ig.Instances(2)
661 662 663 664 665 666 667 668 669 670 671 672 673
	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()
674
	_, err = instances[1].Exchange.GetBlock(ctx, blocks[0].Cid())
675 676 677 678 679 680
	if err != nil {
		t.Fatal(err)
	}

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

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

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

695 696 697 698 699 700 701 702 703 704 705 706
	// 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)
	}

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