@cryptotaxi247 / kubo / commits / 07bb901ed

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