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