kubo/blocks/blockstore/arc_cache_test.go
Steven Allen dfe7ef4fcf gx: update go-multihash
License: MIT
Signed-off-by: Steven Allen <steven@stebalien.com>
2017-12-14 13:09:51 -08:00

202 lines
4.2 KiB
Go

package blockstore
import (
"context"
"testing"
"gx/ipfs/QmYsEQydGrsxNZfAiskvQ76N2xE9hDQtSAkRSynwMiUK3c/go-block-format"
ds "gx/ipfs/QmdHG8MAuARdGHxx4rPQASLcvhz24fzjSQq7AJRAQEorq5/go-datastore"
syncds "gx/ipfs/QmdHG8MAuARdGHxx4rPQASLcvhz24fzjSQq7AJRAQEorq5/go-datastore/sync"
cid "gx/ipfs/QmeSrf6pzut73u6zLQkRFQ3ygt3k6XFT2kjdYP8Tnkwwyg/go-cid"
)
var exampleBlock = blocks.NewBlock([]byte("foo"))
func testArcCached(ctx context.Context, bs Blockstore) (*arccache, error) {
if ctx == nil {
ctx = context.TODO()
}
opts := DefaultCacheOpts()
opts.HasBloomFilterSize = 0
opts.HasBloomFilterHashes = 0
bbs, err := CachedBlockstore(ctx, bs, opts)
if err == nil {
return bbs.(*arccache), nil
}
return nil, err
}
func createStores(t *testing.T) (*arccache, Blockstore, *callbackDatastore) {
cd := &callbackDatastore{f: func() {}, ds: ds.NewMapDatastore()}
bs := NewBlockstore(syncds.MutexWrap(cd))
arc, err := testArcCached(context.TODO(), bs)
if err != nil {
t.Fatal(err)
}
return arc, bs, cd
}
func trap(message string, cd *callbackDatastore, t *testing.T) {
cd.SetFunc(func() {
t.Fatal(message)
})
}
func untrap(cd *callbackDatastore) {
cd.SetFunc(func() {})
}
func TestRemoveCacheEntryOnDelete(t *testing.T) {
arc, _, cd := createStores(t)
arc.Put(exampleBlock)
cd.Lock()
writeHitTheDatastore := false
cd.Unlock()
cd.SetFunc(func() {
writeHitTheDatastore = true
})
arc.DeleteBlock(exampleBlock.Cid())
arc.Put(exampleBlock)
if !writeHitTheDatastore {
t.Fail()
}
}
func TestElideDuplicateWrite(t *testing.T) {
arc, _, cd := createStores(t)
arc.Put(exampleBlock)
trap("write hit datastore", cd, t)
arc.Put(exampleBlock)
}
func TestHasRequestTriggersCache(t *testing.T) {
arc, _, cd := createStores(t)
arc.Has(exampleBlock.Cid())
trap("has hit datastore", cd, t)
if has, err := arc.Has(exampleBlock.Cid()); has || err != nil {
t.Fatal("has was true but there is no such block")
}
untrap(cd)
err := arc.Put(exampleBlock)
if err != nil {
t.Fatal(err)
}
trap("has hit datastore", cd, t)
if has, err := arc.Has(exampleBlock.Cid()); !has || err != nil {
t.Fatal("has returned invalid result")
}
}
func TestGetFillsCache(t *testing.T) {
arc, _, cd := createStores(t)
if bl, err := arc.Get(exampleBlock.Cid()); bl != nil || err == nil {
t.Fatal("block was found or there was no error")
}
trap("has hit datastore", cd, t)
if has, err := arc.Has(exampleBlock.Cid()); has || err != nil {
t.Fatal("has was true but there is no such block")
}
untrap(cd)
if err := arc.Put(exampleBlock); err != nil {
t.Fatal(err)
}
trap("has hit datastore", cd, t)
if has, err := arc.Has(exampleBlock.Cid()); !has || err != nil {
t.Fatal("has returned invalid result")
}
}
func TestGetAndDeleteFalseShortCircuit(t *testing.T) {
arc, _, cd := createStores(t)
arc.Has(exampleBlock.Cid())
trap("get hit datastore", cd, t)
if bl, err := arc.Get(exampleBlock.Cid()); bl != nil || err != ErrNotFound {
t.Fatal("get returned invalid result")
}
if arc.DeleteBlock(exampleBlock.Cid()) != ErrNotFound {
t.Fatal("expected ErrNotFound error")
}
}
func TestArcCreationFailure(t *testing.T) {
if arc, err := newARCCachedBS(context.TODO(), nil, -1); arc != nil || err == nil {
t.Fatal("expected error and no cache")
}
}
func TestInvalidKey(t *testing.T) {
arc, _, _ := createStores(t)
bl, err := arc.Get(nil)
if bl != nil {
t.Fatal("blocks should be nil")
}
if err == nil {
t.Fatal("expected error")
}
}
func TestHasAfterSucessfulGetIsCached(t *testing.T) {
arc, bs, cd := createStores(t)
bs.Put(exampleBlock)
arc.Get(exampleBlock.Cid())
trap("has hit datastore", cd, t)
arc.Has(exampleBlock.Cid())
}
func TestDifferentKeyObjectsWork(t *testing.T) {
arc, bs, cd := createStores(t)
bs.Put(exampleBlock)
arc.Get(exampleBlock.Cid())
trap("has hit datastore", cd, t)
cidstr := exampleBlock.Cid().String()
ncid, err := cid.Decode(cidstr)
if err != nil {
t.Fatal(err)
}
arc.Has(ncid)
}
func TestPutManyCaches(t *testing.T) {
arc, _, cd := createStores(t)
arc.PutMany([]blocks.Block{exampleBlock})
trap("has hit datastore", cd, t)
arc.Has(exampleBlock.Cid())
untrap(cd)
arc.DeleteBlock(exampleBlock.Cid())
arc.Put(exampleBlock)
trap("PunMany has hit datastore", cd, t)
arc.PutMany([]blocks.Block{exampleBlock})
}