add a test to blockservice to demonstate GetBlocks failure.
Jeromy committed
Nov 23, 2014 at 19:14 UTC
07bb901ed5ad0ad3fb98f6f82d2f1696317b0538
4 files changed
+146
-104
blockservice/blocks_test.go
+40
@@ -11,7 +11,9 @@ import (
11
blocks "github.com/jbenet/go-ipfs/blocks"
12
blockstore "github.com/jbenet/go-ipfs/blocks/blockstore"
13
bitswap "github.com/jbenet/go-ipfs/exchange/bitswap"
14
+ tn "github.com/jbenet/go-ipfs/exchange/bitswap/testnet"
15
offline "github.com/jbenet/go-ipfs/exchange/offline"
16
+ "github.com/jbenet/go-ipfs/routing/mock"
17
u "github.com/jbenet/go-ipfs/util"
18
)
19
@@ -61,4 +63,42 @@ func TestBlocks(t *testing.T) {
63
}
64
65
func TestGetBlocks(t *testing.T) {
66
+ net := tn.VirtualNetwork()
67
+ rs := mock.VirtualRoutingServer()
68
+ sg := bitswap.NewSessionGenerator(net, rs)
69
+ bg := bitswap.NewBlockGenerator()
70
+
71
+ instances := sg.Instances(4)
72
+ blks := bg.Blocks(50)
73
+ // TODO: verify no duplicates
74
+
75
+ var servs []*BlockService
76
+ for _, i := range instances {
77
+ bserv, err := New(i.Blockstore, i.Exchange)
78
+ if err != nil {
79
+ t.Fatal(err)
80
+ }
81
+ servs = append(servs, bserv)
82
+ }
83
+
84
+ var keys []u.Key
85
+ for _, blk := range blks {
86
+ keys = append(keys, blk.Key())
87
+ servs[0].AddBlock(blk)
88
+ }
89
+
90
+ for i := 1; i < 4; i++ {
91
+ ctx, _ := context.WithTimeout(context.TODO(), time.Second*5)
92
+ out := servs[i].GetBlocks(ctx, keys)
93
+ gotten := make(map[u.Key]*blocks.Block)
94
+ for blk := range out {
95
+ if _, ok := gotten[blk.Key()]; ok {
96
+ t.Fatal("Got duplicate block!")
97
+ }
98
+ gotten[blk.Key()] = blk
99
+ }
100
+ if len(gotten) != len(blks) {
101
+ t.Fatalf("Didnt get enough blocks back: %d/%d", len(gotten), len(blks))
102
+ }
103
+ }
104
}
exchange/bitswap/bitswap.go
+3
-16
@@ -262,7 +262,6 @@ func (bs *bitswap) ReceiveMessage(ctx context.Context, p peer.Peer, incoming bsm
262
}
263
}
264
265
- first := true
265
for _, key := range incoming.Wantlist() {
266
// TODO: might be better to check if we have the block before checking
267
// if we should send it to someone
@@ -273,11 +272,9 @@ func (bs *bitswap) ReceiveMessage(ctx context.Context, p peer.Peer, incoming bsm
272
// Create a separate message to send this block in
273
blkmsg := bsmsg.New()
274
276
- if first {
277
- for _, k := range bs.wantlist.Keys() {
278
- blkmsg.AddWanted(k)
279
- }
280
- first = false
275
+ // TODO: only send this the first time
276
+ for _, k := range bs.wantlist.Keys() {
277
+ blkmsg.AddWanted(k)
278
}
279
280
blkmsg.AddBlock(block)
@@ -287,16 +284,6 @@ func (bs *bitswap) ReceiveMessage(ctx context.Context, p peer.Peer, incoming bsm
284
}
285
}
286
290
- // If they send us a block, we should guarantee that we send
291
- // them our updated want list one way or another
292
- if len(incoming.Blocks()) > 0 && first {
293
- message := bsmsg.New()
294
- for _, k := range bs.wantlist.Keys() {
295
- message.AddWanted(k)
296
- }
297
- return p, message
298
- }
299
-
287
return nil, nil
288
}
289
exchange/bitswap/bitswap_test.go
+2
-88
@@ -1,4 +1,4 @@
1
-package bitswap_test
1
+package bitswap
2
3
import (
4
"bytes"
@@ -7,13 +7,8 @@ import (
7
"time"
8
9
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
10
- . "github.com/jbenet/go-ipfs/exchange/bitswap"
10
12
- ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
13
- ds_sync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
11
blocks "github.com/jbenet/go-ipfs/blocks"
15
- blockstore "github.com/jbenet/go-ipfs/blocks/blockstore"
16
- exchange "github.com/jbenet/go-ipfs/exchange"
12
tn "github.com/jbenet/go-ipfs/exchange/bitswap/testnet"
13
peer "github.com/jbenet/go-ipfs/peer"
14
mock "github.com/jbenet/go-ipfs/routing/mock"
@@ -170,7 +165,7 @@ func PerformDistributionTest(t *testing.T, numInstances, numBlocks int) {
165
}
166
}
167
173
-func getOrFail(bitswap instance, b *blocks.Block, t *testing.T, wg *sync.WaitGroup) {
168
+func getOrFail(bitswap Instance, b *blocks.Block, t *testing.T, wg *sync.WaitGroup) {
169
if _, err := bitswap.blockstore.Get(b.Key()); err != nil {
170
_, err := bitswap.exchange.GetBlock(context.Background(), b.Key())
171
if err != nil {
@@ -246,84 +241,3 @@ func TestSendToWantingPeer(t *testing.T) {
241
t.Fatal("Expected to receive alpha from me")
242
}
243
}
249
-
250
-func NewBlockGenerator() BlockGenerator {
251
- return BlockGenerator{}
252
-}
253
-
254
-type BlockGenerator struct {
255
- seq int
256
-}
257
-
258
-func (bg *BlockGenerator) Next() *blocks.Block {
259
- bg.seq++
260
- return blocks.NewBlock([]byte(string(bg.seq)))
261
-}
262
-
263
-func (bg *BlockGenerator) Blocks(n int) []*blocks.Block {
264
- blocks := make([]*blocks.Block, 0)
265
- for i := 0; i < n; i++ {
266
- b := bg.Next()
267
- blocks = append(blocks, b)
268
- }
269
- return blocks
270
-}
271
-
272
-func NewSessionGenerator(
273
- net tn.Network, rs mock.RoutingServer) SessionGenerator {
274
- return SessionGenerator{
275
- net: net,
276
- rs: rs,
277
- seq: 0,
278
- }
279
-}
280
-
281
-type SessionGenerator struct {
282
- seq int
283
- net tn.Network
284
- rs mock.RoutingServer
285
-}
286
-
287
-func (g *SessionGenerator) Next() instance {
288
- g.seq++
289
- return session(g.net, g.rs, []byte(string(g.seq)))
290
-}
291
-
292
-func (g *SessionGenerator) Instances(n int) []instance {
293
- instances := make([]instance, 0)
294
- for j := 0; j < n; j++ {
295
- inst := g.Next()
296
- instances = append(instances, inst)
297
- }
298
- return instances
299
-}
300
-
301
-type instance struct {
302
- peer peer.Peer
303
- exchange exchange.Interface
304
- blockstore blockstore.Blockstore
305
-}
306
-
307
-// session creates a test bitswap session.
308
-//
309
-// NB: It's easy make mistakes by providing the same peer ID to two different
310
-// sessions. To safeguard, use the SessionGenerator to generate sessions. It's
311
-// just a much better idea.
312
-func session(net tn.Network, rs mock.RoutingServer, id peer.ID) instance {
313
- p := peer.WithID(id)
314
-
315
- adapter := net.Adapter(p)
316
- htc := rs.Client(p)
317
- bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
318
-
319
- const alwaysSendToPeer = true
320
- ctx := context.TODO()
321
-
322
- bs := New(ctx, p, adapter, htc, bstore, alwaysSendToPeer)
323
-
324
- return instance{
325
- peer: p,
326
- exchange: bs,
327
- blockstore: bstore,
328
- }
329
-}
exchange/bitswap/testutils.go
new
+101
@@ -0,0 +1,101 @@
1
+package bitswap
2
+
3
+import (
4
+ "code.google.com/p/go.net/context"
5
+ ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
6
+ ds_sync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
7
+ "github.com/jbenet/go-ipfs/blocks"
8
+ "github.com/jbenet/go-ipfs/blocks/blockstore"
9
+ "github.com/jbenet/go-ipfs/exchange"
10
+ tn "github.com/jbenet/go-ipfs/exchange/bitswap/testnet"
11
+ "github.com/jbenet/go-ipfs/peer"
12
+ "github.com/jbenet/go-ipfs/routing/mock"
13
+)
14
+
15
+/*
16
+TODO: This whole file needs somewhere better to live.
17
+The issue is that its very difficult to move it somewhere else
18
+without creating circular dependencies.
19
+Additional thought required.
20
+*/
21
+
22
+func NewBlockGenerator() BlockGenerator {
23
+ return BlockGenerator{}
24
+}
25
+
26
+type BlockGenerator struct {
27
+ seq int
28
+}
29
+
30
+func (bg *BlockGenerator) Next() *blocks.Block {
31
+ bg.seq++
32
+ return blocks.NewBlock([]byte(string(bg.seq)))
33
+}
34
+
35
+func (bg *BlockGenerator) Blocks(n int) []*blocks.Block {
36
+ blocks := make([]*blocks.Block, 0)
37
+ for i := 0; i < n; i++ {
38
+ b := bg.Next()
39
+ blocks = append(blocks, b)
40
+ }
41
+ return blocks
42
+}
43
+
44
+func NewSessionGenerator(
45
+ net tn.Network, rs mock.RoutingServer) SessionGenerator {
46
+ return SessionGenerator{
47
+ net: net,
48
+ rs: rs,
49
+ seq: 0,
50
+ }
51
+}
52
+
53
+type SessionGenerator struct {
54
+ seq int
55
+ net tn.Network
56
+ rs mock.RoutingServer
57
+}
58
+
59
+func (g *SessionGenerator) Next() Instance {
60
+ g.seq++
61
+ return session(g.net, g.rs, []byte(string(g.seq)))
62
+}
63
+
64
+func (g *SessionGenerator) Instances(n int) []Instance {
65
+ instances := make([]Instance, 0)
66
+ for j := 0; j < n; j++ {
67
+ inst := g.Next()
68
+ instances = append(instances, inst)
69
+ }
70
+ return instances
71
+}
72
+
73
+type Instance struct {
74
+ Peer peer.Peer
75
+ Exchange exchange.Interface
76
+ Blockstore blockstore.Blockstore
77
+}
78
+
79
+// session creates a test bitswap session.
80
+//
81
+// NB: It's easy make mistakes by providing the same peer ID to two different
82
+// sessions. To safeguard, use the SessionGenerator to generate sessions. It's
83
+// just a much better idea.
84
+func session(net tn.Network, rs mock.RoutingServer, id peer.ID) Instance {
85
+ p := peer.WithID(id)
86
+
87
+ adapter := net.Adapter(p)
88
+ htc := rs.Client(p)
89
+ bstore := blockstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
90
+
91
+ const alwaysSendToPeer = true
92
+ ctx := context.TODO()
93
+
94
+ bs := New(ctx, p, adapter, htc, bstore, alwaysSendToPeer)
95
+
96
+ return Instance{
97
+ Peer: p,
98
+ Exchange: bs,
99
+ Blockstore: bstore,
100
+ }
101
+}