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

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

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
10
	blocks "github.com/jbenet/go-ipfs/blocks"
11
	blocksutil "github.com/jbenet/go-ipfs/blocks/blocksutil"
12
	tn "github.com/jbenet/go-ipfs/exchange/bitswap/testnet"
13
	mock "github.com/jbenet/go-ipfs/routing/mock"
14
	delay "github.com/jbenet/go-ipfs/util/delay"
15
	testutil "github.com/jbenet/go-ipfs/util/testutil"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
16 17
)

18 19
const kNetworkDelay = 0 * time.Millisecond

20 21 22
func TestClose(t *testing.T) {
	// TODO
	t.Skip("TODO Bitswap's Close implementation is a WIP")
23
	vnet := tn.VirtualNetwork(delay.Fixed(kNetworkDelay))
24 25
	rout := mock.VirtualRoutingServer()
	sesgen := NewSessionGenerator(vnet, rout)
26
	bgen := blocksutil.NewBlockGenerator()
27 28 29 30

	block := bgen.Next()
	bitswap := sesgen.Next()

31 32
	bitswap.Exchange.Close()
	bitswap.Exchange.GetBlock(context.Background(), block.Key())
33 34
}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
35 36
func TestGetBlockTimeout(t *testing.T) {

37
	net := tn.VirtualNetwork(delay.Fixed(kNetworkDelay))
38
	rs := mock.VirtualRoutingServer()
39
	g := NewSessionGenerator(net, rs)
40

41
	self := g.Next()
42

Brian Tiger Chow's avatar
Brian Tiger Chow committed
43
	ctx, _ := context.WithTimeout(context.Background(), time.Nanosecond)
44
	block := blocks.NewBlock([]byte("block"))
45
	_, err := self.Exchange.GetBlock(ctx, block.Key())
Brian Tiger Chow's avatar
Brian Tiger Chow committed
46 47 48 49 50 51 52 53

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

func TestProviderForKeyButNetworkCannotFind(t *testing.T) {

54
	net := tn.VirtualNetwork(delay.Fixed(kNetworkDelay))
55
	rs := mock.VirtualRoutingServer()
56
	g := NewSessionGenerator(net, rs)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
57

58
	block := blocks.NewBlock([]byte("block"))
59
	rs.Announce(testutil.NewPeerWithIDString("testing"), block.Key()) // but not on network
Brian Tiger Chow's avatar
Brian Tiger Chow committed
60

61
	solo := g.Next()
Brian Tiger Chow's avatar
Brian Tiger Chow committed
62 63

	ctx, _ := context.WithTimeout(context.Background(), time.Nanosecond)
64
	_, err := solo.Exchange.GetBlock(ctx, block.Key())
Brian Tiger Chow's avatar
Brian Tiger Chow committed
65

Brian Tiger Chow's avatar
Brian Tiger Chow committed
66 67 68 69 70
	if err != context.DeadlineExceeded {
		t.Fatal("Expected DeadlineExceeded error")
	}
}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
71 72 73 74
// TestGetBlockAfterRequesting...

func TestGetBlockFromPeerAfterPeerAnnounces(t *testing.T) {

75
	net := tn.VirtualNetwork(delay.Fixed(kNetworkDelay))
76
	rs := mock.VirtualRoutingServer()
77
	block := blocks.NewBlock([]byte("block"))
78
	g := NewSessionGenerator(net, rs)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
79

80
	hasBlock := g.Next()
Brian Tiger Chow's avatar
Brian Tiger Chow committed
81

82
	if err := hasBlock.Blockstore().Put(block); err != nil {
83 84
		t.Fatal(err)
	}
85
	if err := hasBlock.Exchange.HasBlock(context.Background(), block); err != nil {
86 87
		t.Fatal(err)
	}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
88

89
	wantsBlock := g.Next()
Brian Tiger Chow's avatar
Brian Tiger Chow committed
90 91

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

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

103
func TestLargeSwarm(t *testing.T) {
104 105 106
	if testing.Short() {
		t.SkipNow()
	}
107
	t.Parallel()
108
	numInstances := 5
109
	numBlocks := 2
110 111
	PerformDistributionTest(t, numInstances, numBlocks)
}
112

113 114 115
func TestLargeFile(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
116
	}
117 118 119 120
	t.Parallel()
	numInstances := 10
	numBlocks := 100
	PerformDistributionTest(t, numInstances, numBlocks)
121 122
}

123
func PerformDistributionTest(t *testing.T, numInstances, numBlocks int) {
124 125 126
	if testing.Short() {
		t.SkipNow()
	}
127
	net := tn.VirtualNetwork(delay.Fixed(kNetworkDelay))
128 129
	rs := mock.VirtualRoutingServer()
	sg := NewSessionGenerator(net, rs)
130
	bg := blocksutil.NewBlockGenerator()
131 132 133 134 135 136 137 138 139 140

	t.Log("Test a few nodes trying to get one file with a lot of blocks")

	instances := sg.Instances(numInstances)
	blocks := bg.Blocks(numBlocks)

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

	first := instances[0]
	for _, b := range blocks {
141
		first.Blockstore().Put(b)
142 143
		first.Exchange.HasBlock(context.Background(), b)
		rs.Announce(first.Peer, b.Key())
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
	}

	t.Log("Distribute!")

	var wg sync.WaitGroup

	for _, inst := range instances {
		for _, b := range blocks {
			wg.Add(1)
			// NB: executing getOrFail concurrently puts tremendous pressure on
			// the goroutine scheduler
			getOrFail(inst, b, t, &wg)
		}
	}
	wg.Wait()

	t.Log("Verify!")

	for _, inst := range instances {
		for _, b := range blocks {
164
			if _, err := inst.Blockstore().Get(b.Key()); err != nil {
165 166 167 168 169 170
				t.Fatal(err)
			}
		}
	}
}

171
func getOrFail(bitswap Instance, b *blocks.Block, t *testing.T, wg *sync.WaitGroup) {
172
	if _, err := bitswap.Blockstore().Get(b.Key()); err != nil {
173
		_, err := bitswap.Exchange.GetBlock(context.Background(), b.Key())
174 175 176 177 178 179 180
		if err != nil {
			t.Fatal(err)
		}
	}
	wg.Done()
}

181
// TODO simplify this test. get to the _essence_!
182
func TestSendToWantingPeer(t *testing.T) {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
183 184 185 186
	if testing.Short() {
		t.SkipNow()
	}

187
	net := tn.VirtualNetwork(delay.Fixed(kNetworkDelay))
188
	rs := mock.VirtualRoutingServer()
189
	sg := NewSessionGenerator(net, rs)
190
	bg := blocksutil.NewBlockGenerator()
191 192 193 194 195

	me := sg.Next()
	w := sg.Next()
	o := sg.Next()

196 197 198
	t.Logf("Session %v\n", me.Peer)
	t.Logf("Session %v\n", w.Peer)
	t.Logf("Session %v\n", o.Peer)
199

200 201
	alpha := bg.Next()

Brian Tiger Chow's avatar
Brian Tiger Chow committed
202
	const timeout = 100 * time.Millisecond // FIXME don't depend on time
203

204
	t.Logf("Peer %v attempts to get %v. NB: not available\n", w.Peer, alpha.Key())
205
	ctx, _ := context.WithTimeout(context.Background(), timeout)
206
	_, err := w.Exchange.GetBlock(ctx, alpha.Key())
207
	if err == nil {
208
		t.Fatalf("Expected %v to NOT be available", alpha.Key())
209 210 211
	}

	beta := bg.Next()
212
	t.Logf("Peer %v announes availability  of %v\n", w.Peer, beta.Key())
213
	ctx, _ = context.WithTimeout(context.Background(), timeout)
214
	if err := w.Blockstore().Put(beta); err != nil {
215 216
		t.Fatal(err)
	}
217
	w.Exchange.HasBlock(ctx, beta)
218

219
	t.Logf("%v gets %v from %v and discovers it wants %v\n", me.Peer, beta.Key(), w.Peer, alpha.Key())
220
	ctx, _ = context.WithTimeout(context.Background(), timeout)
221
	if _, err := me.Exchange.GetBlock(ctx, beta.Key()); err != nil {
222 223
		t.Fatal(err)
	}
224

225
	t.Logf("%v announces availability of %v\n", o.Peer, alpha.Key())
226
	ctx, _ = context.WithTimeout(context.Background(), timeout)
227
	if err := o.Blockstore().Put(alpha); err != nil {
228 229
		t.Fatal(err)
	}
230
	o.Exchange.HasBlock(ctx, alpha)
231

232
	t.Logf("%v requests %v\n", me.Peer, alpha.Key())
233
	ctx, _ = context.WithTimeout(context.Background(), timeout)
234
	if _, err := me.Exchange.GetBlock(ctx, alpha.Key()); err != nil {
235 236
		t.Fatal(err)
	}
237

238
	t.Logf("%v should now have %v\n", w.Peer, alpha.Key())
239
	block, err := w.Blockstore().Get(alpha.Key())
240
	if err != nil {
241
		t.Fatalf("Should not have received an error: %s", err)
242 243
	}
	if block.Key() != alpha.Key() {
244
		t.Fatal("Expected to receive alpha from me")
245
	}
246
}