Skip to content

Commit 1a4361e

Browse files
Merge pull request #3074 from ipfs/feat/test-cover-blockstore
test: 81% coverage on blockstore
2 parents 411f9d6 + 4ed8c3e commit 1a4361e

File tree

4 files changed

+208
-26
lines changed

4 files changed

+208
-26
lines changed

blocks/blockstore/arc_cache_test.go

+127-16
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package blockstore
22

33
import (
4-
"github.com/ipfs/go-ipfs/blocks"
54
"testing"
65

6+
"github.com/ipfs/go-ipfs/blocks"
7+
"github.com/ipfs/go-ipfs/blocks/key"
8+
79
ds "gx/ipfs/QmTxLSvdhwg68WJimdS6icLPhZi28aTp6b7uihC2Yb47Xk/go-datastore"
810
syncds "gx/ipfs/QmTxLSvdhwg68WJimdS6icLPhZi28aTp6b7uihC2Yb47Xk/go-datastore/sync"
911
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
1012
)
1113

14+
var exampleBlock = blocks.NewBlock([]byte("foo"))
15+
1216
func testArcCached(bs GCBlockstore, ctx context.Context) (*arccache, error) {
1317
if ctx == nil {
1418
ctx = context.TODO()
@@ -24,15 +28,29 @@ func testArcCached(bs GCBlockstore, ctx context.Context) (*arccache, error) {
2428
}
2529
}
2630

27-
func TestRemoveCacheEntryOnDelete(t *testing.T) {
28-
b := blocks.NewBlock([]byte("foo"))
31+
func createStores(t *testing.T) (*arccache, *blockstore, *callbackDatastore) {
2932
cd := &callbackDatastore{f: func() {}, ds: ds.NewMapDatastore()}
3033
bs := NewBlockstore(syncds.MutexWrap(cd))
31-
cachedbs, err := testArcCached(bs, nil)
34+
arc, err := testArcCached(bs, nil)
3235
if err != nil {
3336
t.Fatal(err)
3437
}
35-
cachedbs.Put(b)
38+
return arc, bs, cd
39+
}
40+
41+
func trap(message string, cd *callbackDatastore, t *testing.T) {
42+
cd.SetFunc(func() {
43+
t.Fatal(message)
44+
})
45+
}
46+
func untrap(cd *callbackDatastore) {
47+
cd.SetFunc(func() {})
48+
}
49+
50+
func TestRemoveCacheEntryOnDelete(t *testing.T) {
51+
arc, _, cd := createStores(t)
52+
53+
arc.Put(exampleBlock)
3654

3755
cd.Lock()
3856
writeHitTheDatastore := false
@@ -42,26 +60,119 @@ func TestRemoveCacheEntryOnDelete(t *testing.T) {
4260
writeHitTheDatastore = true
4361
})
4462

45-
cachedbs.DeleteBlock(b.Key())
46-
cachedbs.Put(b)
63+
arc.DeleteBlock(exampleBlock.Key())
64+
arc.Put(exampleBlock)
4765
if !writeHitTheDatastore {
4866
t.Fail()
4967
}
5068
}
5169

5270
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)
71+
arc, _, cd := createStores(t)
72+
73+
arc.Put(exampleBlock)
74+
trap("write hit datastore", cd, t)
75+
arc.Put(exampleBlock)
76+
}
77+
78+
func TestHasRequestTriggersCache(t *testing.T) {
79+
arc, _, cd := createStores(t)
80+
81+
arc.Has(exampleBlock.Key())
82+
trap("has hit datastore", cd, t)
83+
if has, err := arc.Has(exampleBlock.Key()); has || err != nil {
84+
t.Fatal("has was true but there is no such block")
85+
}
86+
87+
untrap(cd)
88+
err := arc.Put(exampleBlock)
5689
if err != nil {
5790
t.Fatal(err)
5891
}
5992

60-
b1 := blocks.NewBlock([]byte("foo"))
93+
trap("has hit datastore", cd, t)
6194

62-
cachedbs.Put(b1)
63-
cd.SetFunc(func() {
64-
t.Fatal("write hit the datastore")
65-
})
66-
cachedbs.Put(b1)
95+
if has, err := arc.Has(exampleBlock.Key()); !has || err != nil {
96+
t.Fatal("has returned invalid result")
97+
}
98+
}
99+
100+
func TestGetFillsCache(t *testing.T) {
101+
arc, _, cd := createStores(t)
102+
103+
if bl, err := arc.Get(exampleBlock.Key()); bl != nil || err == nil {
104+
t.Fatal("block was found or there was no error")
105+
}
106+
107+
trap("has hit datastore", cd, t)
108+
109+
if has, err := arc.Has(exampleBlock.Key()); has || err != nil {
110+
t.Fatal("has was true but there is no such block")
111+
}
112+
113+
untrap(cd)
114+
115+
if err := arc.Put(exampleBlock); err != nil {
116+
t.Fatal(err)
117+
}
118+
119+
trap("has hit datastore", cd, t)
120+
121+
if has, err := arc.Has(exampleBlock.Key()); !has || err != nil {
122+
t.Fatal("has returned invalid result")
123+
}
124+
}
125+
126+
func TestGetAndDeleteFalseShortCircuit(t *testing.T) {
127+
arc, _, cd := createStores(t)
128+
129+
arc.Has(exampleBlock.Key())
130+
131+
trap("get hit datastore", cd, t)
132+
133+
if bl, err := arc.Get(exampleBlock.Key()); bl != nil || err != ErrNotFound {
134+
t.Fatal("get returned invalid result")
135+
}
136+
137+
if arc.DeleteBlock(exampleBlock.Key()) != ErrNotFound {
138+
t.Fatal("expected ErrNotFound error")
139+
}
140+
}
141+
142+
func TestArcCreationFailure(t *testing.T) {
143+
if arc, err := arcCached(nil, -1); arc != nil || err == nil {
144+
t.Fatal("expected error and no cache")
145+
}
146+
}
147+
148+
func TestInvalidKey(t *testing.T) {
149+
arc, _, _ := createStores(t)
150+
151+
bl, err := arc.Get(key.Key(""))
152+
153+
if bl != nil {
154+
t.Fatal("blocks should be nil")
155+
}
156+
if err == nil {
157+
t.Fatal("expected error")
158+
}
159+
}
160+
161+
func TestHasAfterSucessfulGetIsCached(t *testing.T) {
162+
arc, bs, cd := createStores(t)
163+
164+
bs.Put(exampleBlock)
165+
166+
arc.Get(exampleBlock.Key())
167+
168+
trap("has hit datastore", cd, t)
169+
arc.Has(exampleBlock.Key())
170+
}
171+
172+
func TestPutManyCaches(t *testing.T) {
173+
arc, _, cd := createStores(t)
174+
arc.PutMany([]blocks.Block{exampleBlock})
175+
176+
trap("has hit datastore", cd, t)
177+
arc.Has(exampleBlock.Key())
67178
}

blocks/blockstore/blockstore_test.go

+21-10
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@ import (
88
ds "gx/ipfs/QmTxLSvdhwg68WJimdS6icLPhZi28aTp6b7uihC2Yb47Xk/go-datastore"
99
dsq "gx/ipfs/QmTxLSvdhwg68WJimdS6icLPhZi28aTp6b7uihC2Yb47Xk/go-datastore/query"
1010
ds_sync "gx/ipfs/QmTxLSvdhwg68WJimdS6icLPhZi28aTp6b7uihC2Yb47Xk/go-datastore/sync"
11+
u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
1112
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
1213

1314
blocks "github.com/ipfs/go-ipfs/blocks"
1415
key "github.com/ipfs/go-ipfs/blocks/key"
1516
)
1617

17-
// TODO(brian): TestGetReturnsNil
18-
1918
func TestGetWhenKeyNotPresent(t *testing.T) {
2019
bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
21-
_, err := bs.Get(key.Key("not present"))
20+
bl, err := bs.Get(key.Key("not present"))
2221

23-
if err != nil {
24-
t.Log("As expected, block is not present")
25-
return
22+
if bl != nil {
23+
t.Error("nil block expected")
24+
}
25+
if err == nil {
26+
t.Error("error expected, got nil")
2627
}
27-
t.Fail()
2828
}
2929

3030
func TestGetWhenKeyIsEmptyString(t *testing.T) {
@@ -54,18 +54,29 @@ func TestPutThenGetBlock(t *testing.T) {
5454
}
5555

5656
func TestRuntimeHashing(t *testing.T) {
57+
orginalDebug := u.Debug
58+
defer (func() {
59+
u.Debug = orginalDebug
60+
})()
61+
u.Debug = false
62+
5763
bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
5864
bl := blocks.NewBlock([]byte("some data"))
5965
blBad, err := blocks.NewBlockWithHash([]byte("some other data"), bl.Key().ToMultihash())
6066
if err != nil {
61-
t.Fatal("Debug is enabled")
67+
t.Fatal("debug is off, still got an error")
6268
}
63-
69+
bl2 := blocks.NewBlock([]byte("some other data"))
6470
bs.Put(blBad)
71+
bs.Put(bl2)
6572
bs.RuntimeHashing(true)
6673

6774
if _, err := bs.Get(bl.Key()); err != ErrHashMismatch {
68-
t.Fatalf("Expected '%v' got '%v'\n", ErrHashMismatch, err)
75+
t.Fatalf("expected '%v' got '%v'\n", ErrHashMismatch, err)
76+
}
77+
78+
if b, err := bs.Get(bl2.Key()); err != nil || b.String() != bl2.String() {
79+
t.Fatal("got wrong blocks")
6980
}
7081
}
7182

blocks/blockstore/bloom_cache_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,31 @@ func TestHasIsBloomCached(t *testing.T) {
6666
if float64(cacheFails)/float64(1000) > float64(0.05) {
6767
t.Fatal("Bloom filter has cache miss rate of more than 5%")
6868
}
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+
}
6994
}
7095

7196
type callbackDatastore struct {

blocks/blockstore/caching_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -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.Error("wrong ARC setting was not detected")
11+
}
12+
13+
opts = DefaultCacheOpts()
14+
opts.HasBloomFilterSize = -1
15+
16+
if _, err := CachedBlockstore(nil, nil, opts); err == nil {
17+
t.Error("negative bloom size was not detected")
18+
}
19+
20+
opts = DefaultCacheOpts()
21+
opts.HasBloomFilterHashes = -1
22+
23+
if _, err := CachedBlockstore(nil, nil, opts); err == nil {
24+
t.Error("negative hashes setting was not detected")
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.Error("zero hashes setting with positive size was not detected")
34+
}
35+
}

0 commit comments

Comments
 (0)