Move db interfaces to top level

This commit is contained in:
Ethan Frey 2017-10-23 21:49:36 +02:00
parent 2a3c072cc5
commit 555db84977
13 changed files with 170 additions and 153 deletions

46
db.go Normal file
View File

@ -0,0 +1,46 @@
package sdk
import (
"github.com/tendermint/go-wire/data"
)
// KVStore is a simple interface to get/set data
type KVStore interface {
Set(key, value []byte)
Get(key []byte) (value []byte)
}
//----------------------------------------
// Model grabs together key and value to allow easier return values
type Model struct {
Key data.Bytes
Value data.Bytes
}
// SimpleDB allows us to do some basic range queries on a db
type SimpleDB interface {
KVStore
Has(key []byte) (has bool)
Remove(key []byte) (value []byte) // returns old value if there was one
// Start is inclusive, End is exclusive...
// Thus List ([]byte{12, 13}, []byte{12, 14}) will return anything with
// the prefix []byte{12, 13}
List(start, end []byte, limit int) []Model
First(start, end []byte) Model
Last(start, end []byte) Model
// Checkpoint returns the same state, but where writes
// are buffered and don't affect the parent
Checkpoint() SimpleDB
// Commit will take all changes from the checkpoint and write
// them to the parent.
// Returns an error if this is not a child of this one
Commit(SimpleDB) error
// Discard will remove reference to this
Discard()
}

View File

@ -1,9 +1,5 @@
package sdk
import (
"github.com/cosmos/cosmos-sdk/state"
)
// Decorator is anything that wraps another handler
// to enhance functionality.
//
@ -15,12 +11,12 @@ type Decorator interface {
}
type DecorateChecker interface {
CheckTx(ctx Context, store state.SimpleDB,
CheckTx(ctx Context, store SimpleDB,
tx interface{}, next Checker) (CheckResult, error)
}
type DecorateDeliverer interface {
DeliverTx(ctx Context, store state.SimpleDB, tx interface{},
DeliverTx(ctx Context, store SimpleDB, tx interface{},
next Deliverer) (DeliverResult, error)
}
@ -74,14 +70,14 @@ type decorator struct {
var _ Handler = &decorator{}
// CheckTx fulfils Handler interface
func (m *decorator) CheckTx(ctx Context, store state.SimpleDB,
func (m *decorator) CheckTx(ctx Context, store SimpleDB,
tx interface{}) (CheckResult, error) {
return m.decorator.CheckTx(ctx, store, tx, m.next)
}
// DeliverTx fulfils Handler interface
func (m *decorator) DeliverTx(ctx Context, store state.SimpleDB,
func (m *decorator) DeliverTx(ctx Context, store SimpleDB,
tx interface{}) (res DeliverResult, err error) {
return m.decorator.DeliverTx(ctx, store, tx, m.next)

View File

@ -3,8 +3,6 @@ package sdk
import (
abci "github.com/tendermint/abci/types"
"github.com/tendermint/tmlibs/log"
"github.com/cosmos/cosmos-sdk/state"
)
const (
@ -25,25 +23,25 @@ type Handler interface {
// Checker verifies there are valid fees and estimates work
type Checker interface {
CheckTx(ctx Context, store state.SimpleDB, tx interface{}) (CheckResult, error)
CheckTx(ctx Context, store SimpleDB, tx interface{}) (CheckResult, error)
}
// CheckerFunc (like http.HandlerFunc) is a shortcut for making wrappers
type CheckerFunc func(Context, state.SimpleDB, interface{}) (CheckResult, error)
type CheckerFunc func(Context, SimpleDB, interface{}) (CheckResult, error)
func (c CheckerFunc) CheckTx(ctx Context, store state.SimpleDB, tx interface{}) (CheckResult, error) {
func (c CheckerFunc) CheckTx(ctx Context, store SimpleDB, tx interface{}) (CheckResult, error) {
return c(ctx, store, tx)
}
// Deliverer performs the tx once it makes it in the block
type Deliverer interface {
DeliverTx(ctx Context, store state.SimpleDB, tx interface{}) (DeliverResult, error)
DeliverTx(ctx Context, store SimpleDB, tx interface{}) (DeliverResult, error)
}
// DelivererFunc (like http.HandlerFunc) is a shortcut for making wrappers
type DelivererFunc func(Context, state.SimpleDB, interface{}) (DeliverResult, error)
type DelivererFunc func(Context, SimpleDB, interface{}) (DeliverResult, error)
func (c DelivererFunc) DeliverTx(ctx Context, store state.SimpleDB, tx interface{}) (DeliverResult, error) {
func (c DelivererFunc) DeliverTx(ctx Context, store SimpleDB, tx interface{}) (DeliverResult, error) {
return c(ctx, store, tx)
}
@ -53,20 +51,20 @@ func (c DelivererFunc) DeliverTx(ctx Context, store state.SimpleDB, tx interface
// Ticker can be executed every block.
// Called from BeginBlock
type Ticker interface {
Tick(Context, state.SimpleDB) ([]*abci.Validator, error)
Tick(Context, SimpleDB) ([]*abci.Validator, error)
}
// TickerFunc allows a function to implement the interface
type TickerFunc func(Context, state.SimpleDB) ([]*abci.Validator, error)
type TickerFunc func(Context, SimpleDB) ([]*abci.Validator, error)
func (t TickerFunc) Tick(ctx Context, store state.SimpleDB) ([]*abci.Validator, error) {
func (t TickerFunc) Tick(ctx Context, store SimpleDB) ([]*abci.Validator, error) {
return t(ctx, store)
}
// InitValidator sets the initial validator set.
// Called from InitChain
type InitValidator interface {
InitValidators(logger log.Logger, store state.SimpleDB,
InitValidators(logger log.Logger, store SimpleDB,
vals []*abci.Validator)
}
@ -74,7 +72,7 @@ type InitValidator interface {
//
// TODO: Think if this belongs here, in genesis, or somewhere else
type InitStater interface {
InitState(logger log.Logger, store state.SimpleDB,
InitState(logger log.Logger, store SimpleDB,
module, key, value string) (string, error)
}

View File

@ -3,6 +3,7 @@ package state
import (
"math/rand"
sdk "github.com/cosmos/cosmos-sdk"
"github.com/tendermint/iavl"
)
@ -19,7 +20,7 @@ func (b *Bonsai) String() string {
return "Bonsai{" + b.Tree.String() + "}"
}
var _ SimpleDB = &Bonsai{}
var _ sdk.SimpleDB = &Bonsai{}
// NewBonsai wraps a merkle tree and tags it to track children
func NewBonsai(tree *iavl.VersionedTree) *Bonsai {
@ -58,10 +59,10 @@ func (b *Bonsai) GetVersionedWithProof(key []byte, version uint64) ([]byte, iavl
return b.Tree.GetVersionedWithProof(key, version)
}
func (b *Bonsai) List(start, end []byte, limit int) []Model {
res := []Model{}
func (b *Bonsai) List(start, end []byte, limit int) []sdk.Model {
res := []sdk.Model{}
stopAtCount := func(key []byte, value []byte) (stop bool) {
m := Model{key, value}
m := sdk.Model{key, value}
res = append(res, m)
return limit > 0 && len(res) >= limit
}
@ -69,31 +70,31 @@ func (b *Bonsai) List(start, end []byte, limit int) []Model {
return res
}
func (b *Bonsai) First(start, end []byte) Model {
var m Model
func (b *Bonsai) First(start, end []byte) sdk.Model {
var m sdk.Model
stopAtFirst := func(key []byte, value []byte) (stop bool) {
m = Model{key, value}
m = sdk.Model{key, value}
return true
}
b.Tree.IterateRange(start, end, true, stopAtFirst)
return m
}
func (b *Bonsai) Last(start, end []byte) Model {
var m Model
func (b *Bonsai) Last(start, end []byte) sdk.Model {
var m sdk.Model
stopAtFirst := func(key []byte, value []byte) (stop bool) {
m = Model{key, value}
m = sdk.Model{key, value}
return true
}
b.Tree.IterateRange(start, end, false, stopAtFirst)
return m
}
func (b *Bonsai) Checkpoint() SimpleDB {
func (b *Bonsai) Checkpoint() sdk.SimpleDB {
return NewMemKVCache(b)
}
func (b *Bonsai) Commit(sub SimpleDB) error {
func (b *Bonsai) Commit(sub sdk.SimpleDB) error {
cache, ok := sub.(*MemKVCache)
if !ok {
return ErrNotASubTransaction()
@ -115,7 +116,7 @@ func (b *Bonsai) Commit(sub SimpleDB) error {
//
// FIXME: use this code when iavltree is improved
// func (b *Bonsai) Checkpoint() SimpleDB {
// func (b *Bonsai) Checkpoint() sdk.SimpleDB {
// return &Bonsai{
// id: b.id,
// Tree: b.Tree.Copy(),
@ -125,7 +126,7 @@ func (b *Bonsai) Commit(sub SimpleDB) error {
// // Commit will take all changes from the checkpoint and write
// // them to the parent.
// // Returns an error if this is not a child of this one
// func (b *Bonsai) Commit(sub SimpleDB) error {
// func (b *Bonsai) Commit(sub sdk.SimpleDB) error {
// bb, ok := sub.(*Bonsai)
// if !ok || (b.id != bb.id) {
// return ErrNotASubTransaction()

View File

@ -1,5 +1,7 @@
package state
import sdk "github.com/cosmos/cosmos-sdk"
// ChainState maintains general information for the chain
type ChainState struct {
chainID string
@ -13,13 +15,13 @@ func NewChainState() *ChainState {
var baseChainIDKey = []byte("base/chain_id")
// SetChainID stores the chain id in the store
func (s *ChainState) SetChainID(store KVStore, chainID string) {
func (s *ChainState) SetChainID(store sdk.KVStore, chainID string) {
s.chainID = chainID
store.Set(baseChainIDKey, []byte(chainID))
}
// GetChainID gets the chain id from the cache or the store
func (s *ChainState) GetChainID(store KVStore) string {
func (s *ChainState) GetChainID(store sdk.KVStore) string {
if s.chainID != "" {
return s.chainID
}

View File

@ -1,18 +1,20 @@
package state
import sdk "github.com/cosmos/cosmos-sdk"
// MemKVCache is designed to wrap MemKVStore as a cache
type MemKVCache struct {
store SimpleDB
store sdk.SimpleDB
cache *MemKVStore
}
var _ SimpleDB = (*MemKVCache)(nil)
var _ sdk.SimpleDB = (*MemKVCache)(nil)
// NewMemKVCache wraps a cache around MemKVStore
//
// You probably don't want to use directly, but rather
// via MemKVCache.Checkpoint()
func NewMemKVCache(store SimpleDB) *MemKVCache {
func NewMemKVCache(store sdk.SimpleDB) *MemKVCache {
if store == nil {
panic("wtf")
}
@ -53,7 +55,7 @@ func (c *MemKVCache) Remove(key []byte) (value []byte) {
}
// List is also inefficiently implemented...
func (c *MemKVCache) List(start, end []byte, limit int) []Model {
func (c *MemKVCache) List(start, end []byte, limit int) []sdk.Model {
orig := c.store.List(start, end, 0)
cached := c.cache.List(start, end, 0)
keys := c.combineLists(orig, cached)
@ -69,7 +71,7 @@ func (c *MemKVCache) List(start, end []byte, limit int) []Model {
return keys
}
func (c *MemKVCache) combineLists(orig, cache []Model) []Model {
func (c *MemKVCache) combineLists(orig, cache []sdk.Model) []sdk.Model {
store := NewMemKVStore()
for _, m := range orig {
store.Set(m.Key, m.Value)
@ -86,33 +88,33 @@ func (c *MemKVCache) combineLists(orig, cache []Model) []Model {
}
// First is done with List, but could be much more efficient
func (c *MemKVCache) First(start, end []byte) Model {
func (c *MemKVCache) First(start, end []byte) sdk.Model {
data := c.List(start, end, 0)
if len(data) == 0 {
return Model{}
return sdk.Model{}
}
return data[0]
}
// Last is done with List, but could be much more efficient
func (c *MemKVCache) Last(start, end []byte) Model {
func (c *MemKVCache) Last(start, end []byte) sdk.Model {
data := c.List(start, end, 0)
if len(data) == 0 {
return Model{}
return sdk.Model{}
}
return data[len(data)-1]
}
// Checkpoint returns the same state, but where writes
// are buffered and don't affect the parent
func (c *MemKVCache) Checkpoint() SimpleDB {
func (c *MemKVCache) Checkpoint() sdk.SimpleDB {
return NewMemKVCache(c)
}
// Commit will take all changes from the checkpoint and write
// them to the parent.
// Returns an error if this is not a child of this one
func (c *MemKVCache) Commit(sub SimpleDB) error {
func (c *MemKVCache) Commit(sub sdk.SimpleDB) error {
cache, ok := sub.(*MemKVCache)
if !ok {
return ErrNotASubTransaction()

View File

@ -4,6 +4,7 @@ import (
"fmt"
"testing"
sdk "github.com/cosmos/cosmos-sdk"
"github.com/stretchr/testify/assert"
)
@ -11,47 +12,47 @@ func TestCache(t *testing.T) {
assert := assert.New(t)
cases := []struct {
init []Model
toGet []Model
init []sdk.Model
toGet []sdk.Model
toList []listQuery
setCache []Model
removeCache []Model
getCache []Model
setCache []sdk.Model
removeCache []sdk.Model
getCache []sdk.Model
listCache []listQuery
}{
// simple add
{
init: []Model{m("a", "1"), m("c", "2")},
toGet: []Model{m("a", "1"), m("c", "2"), m("d", "")},
init: []sdk.Model{m("a", "1"), m("c", "2")},
toGet: []sdk.Model{m("a", "1"), m("c", "2"), m("d", "")},
toList: []listQuery{{
"a", "e", 0,
[]Model{m("a", "1"), m("c", "2")},
[]sdk.Model{m("a", "1"), m("c", "2")},
m("c", "2"),
}},
setCache: []Model{m("d", "3")},
removeCache: []Model{m("a", "1")},
getCache: []Model{m("a", ""), m("c", "2"), m("d", "3")},
setCache: []sdk.Model{m("d", "3")},
removeCache: []sdk.Model{m("a", "1")},
getCache: []sdk.Model{m("a", ""), m("c", "2"), m("d", "3")},
listCache: []listQuery{{
"a", "e", 0,
[]Model{m("c", "2"), m("d", "3")},
[]sdk.Model{m("c", "2"), m("d", "3")},
m("d", "3"),
}},
},
}
checkGet := func(db SimpleDB, m Model, msg string) {
checkGet := func(db sdk.SimpleDB, m sdk.Model, msg string) {
val := db.Get(m.Key)
assert.EqualValues(m.Value, val, msg)
has := db.Has(m.Key)
assert.Equal(len(m.Value) != 0, has, msg)
}
checkList := func(db SimpleDB, lq listQuery, msg string) {
checkList := func(db sdk.SimpleDB, lq listQuery, msg string) {
start, end := []byte(lq.start), []byte(lq.end)
list := db.List(start, end, lq.limit)
if assert.EqualValues(lq.expected, list, msg) {
var first Model
var first sdk.Model
if len(lq.expected) > 0 {
first = lq.expected[0]
}

View File

@ -3,60 +3,19 @@ package state
import (
"sort"
"github.com/tendermint/go-wire/data"
sdk "github.com/cosmos/cosmos-sdk"
)
// KVStore is a simple interface to get/set data
type KVStore interface {
Set(key, value []byte)
Get(key []byte) (value []byte)
}
//----------------------------------------
// Model grabs together key and value to allow easier return values
type Model struct {
Key data.Bytes
Value data.Bytes
}
// SimpleDB allows us to do some basic range queries on a db
type SimpleDB interface {
KVStore
Has(key []byte) (has bool)
Remove(key []byte) (value []byte) // returns old value if there was one
// Start is inclusive, End is exclusive...
// Thus List ([]byte{12, 13}, []byte{12, 14}) will return anything with
// the prefix []byte{12, 13}
List(start, end []byte, limit int) []Model
First(start, end []byte) Model
Last(start, end []byte) Model
// Checkpoint returns the same state, but where writes
// are buffered and don't affect the parent
Checkpoint() SimpleDB
// Commit will take all changes from the checkpoint and write
// them to the parent.
// Returns an error if this is not a child of this one
Commit(SimpleDB) error
// Discard will remove reference to this
Discard()
}
//----------------------------------------
// MemKVStore is a simple implementation of SimpleDB.
// MemKVStore is a simple implementation of sdk.SimpleDB.
// It is only intended for quick testing, not to be used
// in production or with large data stores.
type MemKVStore struct {
m map[string][]byte
}
var _ SimpleDB = NewMemKVStore()
var _ sdk.SimpleDB = NewMemKVStore()
// NewMemKVStore initializes a MemKVStore
func NewMemKVStore() *MemKVStore {
@ -84,7 +43,7 @@ func (m *MemKVStore) Remove(key []byte) (value []byte) {
return val
}
func (m *MemKVStore) List(start, end []byte, limit int) []Model {
func (m *MemKVStore) List(start, end []byte, limit int) []sdk.Model {
keys := m.keysInRange(start, end)
if limit > 0 && len(keys) > 0 {
if limit > len(keys) {
@ -93,9 +52,9 @@ func (m *MemKVStore) List(start, end []byte, limit int) []Model {
keys = keys[:limit]
}
res := make([]Model, len(keys))
res := make([]sdk.Model, len(keys))
for i, k := range keys {
res[i] = Model{
res[i] = sdk.Model{
Key: []byte(k),
Value: m.m[k],
}
@ -104,7 +63,7 @@ func (m *MemKVStore) List(start, end []byte, limit int) []Model {
}
// First iterates through all keys to find the one that matches
func (m *MemKVStore) First(start, end []byte) Model {
func (m *MemKVStore) First(start, end []byte) sdk.Model {
key := ""
for _, k := range m.keysInRange(start, end) {
if key == "" || k < key {
@ -112,15 +71,15 @@ func (m *MemKVStore) First(start, end []byte) Model {
}
}
if key == "" {
return Model{}
return sdk.Model{}
}
return Model{
return sdk.Model{
Key: []byte(key),
Value: m.m[key],
}
}
func (m *MemKVStore) Last(start, end []byte) Model {
func (m *MemKVStore) Last(start, end []byte) sdk.Model {
key := ""
for _, k := range m.keysInRange(start, end) {
if key == "" || k > key {
@ -128,9 +87,9 @@ func (m *MemKVStore) Last(start, end []byte) Model {
}
}
if key == "" {
return Model{}
return sdk.Model{}
}
return Model{
return sdk.Model{
Key: []byte(key),
Value: m.m[key],
}
@ -140,11 +99,11 @@ func (m *MemKVStore) Discard() {
m.m = make(map[string][]byte, 0)
}
func (m *MemKVStore) Checkpoint() SimpleDB {
func (m *MemKVStore) Checkpoint() sdk.SimpleDB {
return NewMemKVCache(m)
}
func (m *MemKVStore) Commit(sub SimpleDB) error {
func (m *MemKVStore) Commit(sub sdk.SimpleDB) error {
cache, ok := sub.(*MemKVCache)
if !ok {
return ErrNotASubTransaction()

View File

@ -1,13 +1,16 @@
package state
import "github.com/tendermint/iavl"
import (
sdk "github.com/cosmos/cosmos-sdk"
"github.com/tendermint/iavl"
)
// State represents the app states, separating the commited state (for queries)
// from the working state (for CheckTx and AppendTx)
type State struct {
committed *Bonsai
deliverTx SimpleDB
checkTx SimpleDB
deliverTx sdk.SimpleDB
checkTx sdk.SimpleDB
historySize uint64
}
@ -42,13 +45,13 @@ func (s State) Committed() *Bonsai {
// Append gives us read-write access to the current working
// state (to be committed at EndBlock)
func (s State) Append() SimpleDB {
func (s State) Append() sdk.SimpleDB {
return s.deliverTx
}
// Append gives us read-write access to the current scratch
// state (to be reset at EndBlock)
func (s State) Check() SimpleDB {
func (s State) Check() sdk.SimpleDB {
return s.checkTx
}

View File

@ -1,6 +1,10 @@
package state
import "encoding/binary"
import (
"encoding/binary"
sdk "github.com/cosmos/cosmos-sdk"
)
var (
headKey = []byte("h")
@ -25,7 +29,7 @@ func QueueItemKey(i uint64) []byte {
// Queue allows us to fill up a range of the db, and grab from either end
type Queue struct {
store KVStore
store sdk.KVStore
head uint64 // if Size() > 0, the first element is here
tail uint64 // this is the first empty slot to Push() to
}
@ -33,7 +37,7 @@ type Queue struct {
// NewQueue will load or initialize a queue in this state-space
//
// Generally, you will want to stack.PrefixStore() the space first
func NewQueue(store KVStore) *Queue {
func NewQueue(store sdk.KVStore) *Queue {
q := &Queue{store: store}
q.head = q.getCount(headKey)
q.tail = q.getCount(tailKey)

View File

@ -4,6 +4,7 @@ import (
"bytes"
"sort"
sdk "github.com/cosmos/cosmos-sdk"
wire "github.com/tendermint/go-wire"
)
@ -18,14 +19,14 @@ func SetKey() []byte {
// If we had full access to the IAVL tree, this would be completely
// trivial and redundant
type Set struct {
store KVStore
store sdk.KVStore
keys KeyList
}
var _ KVStore = &Set{}
var _ sdk.KVStore = &Set{}
// NewSet loads or initializes a span of keys
func NewSet(store KVStore) *Set {
func NewSet(store sdk.KVStore) *Set {
s := &Set{store: store}
s.loadKeys()
return s

View File

@ -1,6 +1,9 @@
package state
import wire "github.com/tendermint/go-wire"
import (
sdk "github.com/cosmos/cosmos-sdk"
wire "github.com/tendermint/go-wire"
)
var (
keys = []byte("keys")
@ -16,13 +19,13 @@ var (
//
// TODO: doesn't handle deleting....
type Span struct {
store KVStore
store sdk.KVStore
// keys is sorted ascending and cannot contain duplicates
keys []uint64
}
// NewSpan loads or initializes a span of keys
func NewSpan(store KVStore) *Span {
func NewSpan(store sdk.KVStore) *Span {
s := &Span{store: store}
s.loadKeys()
return s

View File

@ -4,13 +4,14 @@ import (
"io/ioutil"
"testing"
sdk "github.com/cosmos/cosmos-sdk"
"github.com/stretchr/testify/assert"
"github.com/tendermint/iavl"
dbm "github.com/tendermint/tmlibs/db"
)
func GetDBs() []SimpleDB {
func GetDBs() []sdk.SimpleDB {
// tree with persistence....
tmpDir, err := ioutil.TempDir("", "state-tests")
if err != nil {
@ -19,7 +20,7 @@ func GetDBs() []SimpleDB {
db := dbm.NewDB("test-get-dbs", dbm.LevelDBBackendStr, tmpDir)
persist := iavl.NewVersionedTree(500, db)
return []SimpleDB{
return []sdk.SimpleDB{
NewMemKVStore(),
NewBonsai(iavl.NewVersionedTree(0, dbm.NewMemDB())),
NewBonsai(persist),
@ -33,8 +34,8 @@ func b(k string) []byte {
return []byte(k)
}
func m(k, v string) Model {
return Model{
func m(k, v string) sdk.Model {
return sdk.Model{
Key: b(k),
Value: b(v),
}
@ -45,9 +46,9 @@ type listQuery struct {
start, end string
limit int
// expected result from List, first element also expected for First
expected []Model
expected []sdk.Model
// expected result from Last
last Model
last sdk.Model
}
// TestKVStore makes sure that get/set/remove operations work,
@ -56,39 +57,39 @@ func TestKVStore(t *testing.T) {
assert := assert.New(t)
cases := []struct {
toSet []Model
toRemove []Model
toGet []Model
toSet []sdk.Model
toRemove []sdk.Model
toGet []sdk.Model
toList []listQuery
}{
// simple add
{
toSet: []Model{m("a", "b"), m("c", "d")},
toSet: []sdk.Model{m("a", "b"), m("c", "d")},
toRemove: nil,
toGet: []Model{m("a", "b")},
toGet: []sdk.Model{m("a", "b")},
toList: []listQuery{
{
"a", "d", 0,
[]Model{m("a", "b"), m("c", "d")},
[]sdk.Model{m("a", "b"), m("c", "d")},
m("c", "d"),
},
{
"a", "c", 10,
[]Model{m("a", "b")},
[]sdk.Model{m("a", "b")},
m("a", "b"),
},
},
},
// over-write data, remove
{
toSet: []Model{
toSet: []sdk.Model{
m("a", "1"),
m("b", "2"),
m("c", "3"),
m("b", "4"),
},
toRemove: []Model{m("c", "3")},
toGet: []Model{
toRemove: []sdk.Model{m("c", "3")},
toGet: []sdk.Model{
m("a", "1"),
m("b", "4"),
m("c", ""),
@ -96,17 +97,17 @@ func TestKVStore(t *testing.T) {
toList: []listQuery{
{
"0d", "h", 1,
[]Model{m("a", "1")},
[]sdk.Model{m("a", "1")},
m("b", "4"),
},
{
"ad", "ak", 10,
[]Model{},
Model{},
[]sdk.Model{},
sdk.Model{},
},
{
"ad", "k", 0,
[]Model{m("b", "4")},
[]sdk.Model{m("b", "4")},
m("b", "4"),
},
},
@ -132,7 +133,7 @@ func TestKVStore(t *testing.T) {
start, end := []byte(lq.start), []byte(lq.end)
list := db.List(start, end, lq.limit)
if assert.EqualValues(lq.expected, list, "%d/%d/%d", i, j, k) {
var first Model
var first sdk.Model
if len(lq.expected) > 0 {
first = lq.expected[0]
}