@cryptotaxi247 / kubo / commits / 233a622ed

test: 81% coverage on blockstore

Coverage report available at: https://ipfs.io/ipfs/QmTuMtwGCfHrbYyZdQ1RaGNwS2MGsmAkjA8AaB69N7Ya1g/coverage.html#file0 Part of #3053 License: MIT Signed-off-by: Jakub Sztandera <kubuxu@ipfs.io>

Jakub Sztandera committed Aug 11, 2016 at 22:18 UTC 233a622ed0dbf1b58ce1b9fda26d78578b56723c
4 files changed +191 -16
blocks/blockstore/arc_cache_test.go
+125 -15
@@ -2,6 +2,7 @@ package blockstore
2
3 import (
4 "github.com/ipfs/go-ipfs/blocks"
5 + "github.com/ipfs/go-ipfs/blocks/key"
6 "testing"
7
8 ds "gx/ipfs/QmTxLSvdhwg68WJimdS6icLPhZi28aTp6b7uihC2Yb47Xk/go-datastore"
@@ -9,6 +10,8 @@ import (
10 context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
11 )
12
13 +var exampleBlock = blocks.NewBlock([]byte("foo"))
14 +
15 func testArcCached(bs GCBlockstore, ctx context.Context) (*arccache, error) {
16 if ctx == nil {
17 ctx = context.TODO()
@@ -24,15 +27,29 @@ func testArcCached(bs GCBlockstore, ctx context.Context) (*arccache, error) {
27 }
28 }
29
27 -func TestRemoveCacheEntryOnDelete(t *testing.T) {
28 - b := blocks.NewBlock([]byte("foo"))
30 +func createStores(t *testing.T) (*arccache, *blockstore, *callbackDatastore) {
31 cd := &callbackDatastore{f: func() {}, ds: ds.NewMapDatastore()}
32 bs := NewBlockstore(syncds.MutexWrap(cd))
31 - cachedbs, err := testArcCached(bs, nil)
33 + arc, err := testArcCached(bs, nil)
34 if err != nil {
35 t.Fatal(err)
36 }
35 - cachedbs.Put(b)
37 + return arc, bs, cd
38 +}
39 +
40 +func trap(message string, cd *callbackDatastore, t *testing.T) {
41 + cd.SetFunc(func() {
42 + t.Fatal(message)
43 + })
44 +}
45 +func untrap(cd *callbackDatastore) {
46 + cd.SetFunc(func() {})
47 +}
48 +
49 +func TestRemoveCacheEntryOnDelete(t *testing.T) {
50 + arc, _, cd := createStores(t)
51 +
52 + arc.Put(exampleBlock)
53
54 cd.Lock()
55 writeHitTheDatastore := false
@@ -42,26 +59,119 @@ func TestRemoveCacheEntryOnDelete(t *testing.T) {
59 writeHitTheDatastore = true
60 })
61
45 - cachedbs.DeleteBlock(b.Key())
46 - cachedbs.Put(b)
62 + arc.DeleteBlock(exampleBlock.Key())
63 + arc.Put(exampleBlock)
64 if !writeHitTheDatastore {
65 t.Fail()
66 }
67 }
68
69 func TestElideDuplicateWrite(t *testing.T) {
53 - cd := &callbackDatastore{f: func() {}, ds: ds.NewMapDatastore()}
54 - bs := NewBlockstore(syncds.MutexWrap(cd))
55 - cachedbs, err := testArcCached(bs, nil)
70 + arc, _, cd := createStores(t)
71 +
72 + arc.Put(exampleBlock)
73 + trap("write hit datastore", cd, t)
74 + arc.Put(exampleBlock)
75 +}
76 +
77 +func TestHasRequestTriggersCache(t *testing.T) {
78 + arc, _, cd := createStores(t)
79 +
80 + arc.Has(exampleBlock.Key())
81 + trap("has hit datastore", cd, t)
82 + if has, err := arc.Has(exampleBlock.Key()); has || err != nil {
83 + t.Fatal("has was true but there is no such block")
84 + }
85 +
86 + untrap(cd)
87 + err := arc.Put(exampleBlock)
88 if err != nil {
89 t.Fatal(err)
90 }
91
60 - b1 := blocks.NewBlock([]byte("foo"))
92 + trap("has hit datastore", cd, t)
93
62 - cachedbs.Put(b1)
63 - cd.SetFunc(func() {
64 - t.Fatal("write hit the datastore")
65 - })
66 - cachedbs.Put(b1)
94 + if has, err := arc.Has(exampleBlock.Key()); !has || err != nil {
95 + t.Fatal("has returned invalid result")
96 + }
97 +}
98 +
99 +func TestGetFillsCache(t *testing.T) {
100 + arc, _, cd := createStores(t)
101 +
102 + if bl, err := arc.Get(exampleBlock.Key()); bl != nil || err == nil {
103 + t.Fatal("block was found or there was no error")
104 + }
105 +
106 + trap("has hit datastore", cd, t)
107 +
108 + if has, err := arc.Has(exampleBlock.Key()); has || err != nil {
109 + t.Fatal("has was true but there is no such block")
110 + }
111 +
112 + untrap(cd)
113 +
114 + if err := arc.Put(exampleBlock); err != nil {
115 + t.Fatal(err)
116 + }
117 +
118 + trap("has hit datastore", cd, t)
119 +
120 + if has, err := arc.Has(exampleBlock.Key()); !has || err != nil {
121 + t.Fatal("has returned invalid result")
122 + }
123 +}
124 +
125 +func TestGetAndDeleteFalseShortCirciot(t *testing.T) {
126 + arc, _, cd := createStores(t)
127 +
128 + arc.Has(exampleBlock.Key())
129 +
130 + trap("get hit datastore", cd, t)
131 +
132 + if bl, err := arc.Get(exampleBlock.Key()); bl != nil || err != ErrNotFound {
133 + t.Fatal("get returned invalid result")
134 + }
135 +
136 + if arc.DeleteBlock(exampleBlock.Key()) != ErrNotFound {
137 + t.Fatal("expected ErrNotFound error")
138 + }
139 +}
140 +
141 +func TestArcCreationFailure(t *testing.T) {
142 + if arc, err := arcCached(nil, -1); arc != nil || err == nil {
143 + t.Fatal("expected error and no cache")
144 + }
145 +}
146 +
147 +func TestInvalidKey(t *testing.T) {
148 + arc, _, _ := createStores(t)
149 +
150 + bl, err := arc.Get(key.Key(""))
151 +
152 + if bl != nil {
153 + t.Fatal("blocks should be nil")
154 + }
155 + if err == nil {
156 + t.Fatal("expected error")
157 + }
158 +}
159 +
160 +func TestHasAfterSucessfulGetIsCached(t *testing.T) {
161 + arc, bs, cd := createStores(t)
162 +
163 + bs.Put(exampleBlock)
164 +
165 + arc.Get(exampleBlock.Key())
166 +
167 + trap("has hit datastore", cd, t)
168 + arc.Has(exampleBlock.Key())
169 +}
170 +
171 +func TestPutManyCaches(t *testing.T) {
172 + arc, _, cd := createStores(t)
173 + arc.PutMany([]blocks.Block{exampleBlock})
174 +
175 + trap("has hit datastore", cd, t)
176 + arc.Has(exampleBlock.Key())
177 }
blocks/blockstore/blockstore_test.go
+6 -1
@@ -57,16 +57,21 @@ func TestRuntimeHashing(t *testing.T) {
57 bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
58 bl := blocks.NewBlock([]byte("some data"))
59 blBad, err := blocks.NewBlockWithHash([]byte("some other data"), bl.Key().ToMultihash())
60 + bl2 := blocks.NewBlock([]byte("some other data"))
61 if err != nil {
62 t.Fatal("Debug is enabled")
63 }
63 -
64 bs.Put(blBad)
65 + bs.Put(bl2)
66 bs.RuntimeHashing(true)
67
68 if _, err := bs.Get(bl.Key()); err != ErrHashMismatch {
69 t.Fatalf("Expected '%v' got '%v'\n", ErrHashMismatch, err)
70 }
71 +
72 + if b, err := bs.Get(bl2.Key()); err != nil || b.String() != bl2.String() {
73 + t.Fatal("got wrong blocks")
74 + }
75 }
76
77 func newBlockStoreWithKeys(t *testing.T, d ds.Datastore, N int) (Blockstore, []key.Key) {
blocks/blockstore/bloom_cache_test.go
+25
@@ -66,6 +66,31 @@ func TestHasIsBloomCached(t *testing.T) {
66 if float64(cacheFails)/float64(1000) > float64(0.05) {
67 t.Fatal("Bloom filter has cache miss rate of more than 5%")
68 }
69 +
70 + cacheFails = 0
71 + block := blocks.NewBlock([]byte("newBlock"))
72 +
73 + cachedbs.PutMany([]blocks.Block{block})
74 + if cacheFails != 2 {
75 + t.Fatalf("expected two datastore hits: %d", cacheFails)
76 + }
77 + cachedbs.Put(block)
78 + if cacheFails != 3 {
79 + t.Fatalf("expected datastore hit: %d", cacheFails)
80 + }
81 +
82 + if has, err := cachedbs.Has(block.Key()); !has || err != nil {
83 + t.Fatal("has gave wrong response")
84 + }
85 +
86 + bl, err := cachedbs.Get(block.Key())
87 + if bl.String() != block.String() {
88 + t.Fatal("block data doesn't match")
89 + }
90 +
91 + if err != nil {
92 + t.Fatal("there should't be an error")
93 + }
94 }
95
96 type callbackDatastore struct {
blocks/blockstore/caching_test.go new
+35
@@ -0,0 +1,35 @@
1 +package blockstore
2 +
3 +import "testing"
4 +
5 +func TestCachingOptsLessThanZero(t *testing.T) {
6 + opts := DefaultCacheOpts()
7 + opts.HasARCCacheSize = -1
8 +
9 + if _, err := CachedBlockstore(nil, nil, opts); err == nil {
10 + t.Fatal()
11 + }
12 +
13 + opts = DefaultCacheOpts()
14 + opts.HasBloomFilterSize = -1
15 +
16 + if _, err := CachedBlockstore(nil, nil, opts); err == nil {
17 + t.Fatal()
18 + }
19 +
20 + opts = DefaultCacheOpts()
21 + opts.HasBloomFilterHashes = -1
22 +
23 + if _, err := CachedBlockstore(nil, nil, opts); err == nil {
24 + t.Fatal()
25 + }
26 +}
27 +
28 +func TestBloomHashesAtZero(t *testing.T) {
29 + opts := DefaultCacheOpts()
30 + opts.HasBloomFilterHashes = 0
31 +
32 + if _, err := CachedBlockstore(nil, nil, opts); err == nil {
33 + t.Fatal()
34 + }
35 +}