mirror of
https://github.com/ipfs/kubo.git
synced 2026-03-05 00:08:06 +08:00
This change adds the /ipfs/bitswap/1.1.0 protocol. The new protocol adds a 'payload' field to the protobuf message and deprecates the existing 'blocks' field. The 'payload' field is an array of pairs of cid prefixes and block data. The cid prefixes are used to ensure the correct codecs and hash functions are used to handle the block on the receiving end. License: MIT Signed-off-by: Jeromy <why@ipfs.io>
203 lines
4.2 KiB
Go
203 lines
4.2 KiB
Go
package blockstore
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/ipfs/go-ipfs/blocks"
|
|
|
|
cid "gx/ipfs/QmXUuRadqDq5BuFWzVU6VuKaSjTcNm1gNCtLvvP1TJCW4z/go-cid"
|
|
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
|
|
syncds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
|
|
)
|
|
|
|
var exampleBlock = blocks.NewBlock([]byte("foo"))
|
|
|
|
func testArcCached(bs GCBlockstore, ctx context.Context) (*arccache, error) {
|
|
if ctx == nil {
|
|
ctx = context.TODO()
|
|
}
|
|
opts := DefaultCacheOpts()
|
|
opts.HasBloomFilterSize = 0
|
|
opts.HasBloomFilterHashes = 0
|
|
bbs, err := CachedBlockstore(bs, ctx, opts)
|
|
if err == nil {
|
|
return bbs.(*arccache), nil
|
|
} else {
|
|
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(bs, nil)
|
|
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})
|
|
}
|