mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-26 15:22:15 +00:00
Remove Prev from Iterator
This commit is contained in:
parent
0d03cd9e31
commit
7f650cea86
@ -202,13 +202,6 @@ func (c cLevelDBIterator) Next() {
|
|||||||
c.itr.Next()
|
c.itr.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c cLevelDBIterator) Prev() {
|
|
||||||
if !c.itr.Valid() {
|
|
||||||
panic("cLevelDBIterator Prev() called when invalid")
|
|
||||||
}
|
|
||||||
c.itr.Prev()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c cLevelDBIterator) Release() {
|
func (c cLevelDBIterator) Release() {
|
||||||
c.itr.Close()
|
c.itr.Close()
|
||||||
}
|
}
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
package db
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func bz(s string) []byte { return []byte(s) }
|
|
||||||
|
|
||||||
func TestCacheDB(t *testing.T) {
|
|
||||||
mem := NewMemDB()
|
|
||||||
cdb := mem.CacheDB()
|
|
||||||
|
|
||||||
require.Empty(t, cdb.Get(bz("key1")), "Expected `key1` to be empty")
|
|
||||||
|
|
||||||
mem.Set(bz("key1"), bz("value1"))
|
|
||||||
cdb.Set(bz("key1"), bz("value1"))
|
|
||||||
require.Equal(t, bz("value1"), cdb.Get(bz("key1")))
|
|
||||||
|
|
||||||
cdb.Set(bz("key1"), bz("value2"))
|
|
||||||
require.Equal(t, bz("value2"), cdb.Get(bz("key1")))
|
|
||||||
require.Equal(t, bz("value1"), mem.Get(bz("key1")))
|
|
||||||
|
|
||||||
cdb.Write()
|
|
||||||
require.Equal(t, bz("value2"), mem.Get(bz("key1")))
|
|
||||||
|
|
||||||
require.Panics(t, func() { cdb.Write() }, "Expected second cdb.Write() to fail")
|
|
||||||
|
|
||||||
cdb = mem.CacheDB()
|
|
||||||
cdb.Delete(bz("key1"))
|
|
||||||
require.Empty(t, cdb.Get(bz("key1")))
|
|
||||||
require.Equal(t, mem.Get(bz("key1")), bz("value2"))
|
|
||||||
|
|
||||||
cdb.Write()
|
|
||||||
require.Empty(t, cdb.Get(bz("key1")), "Expected `key1` to be empty")
|
|
||||||
require.Empty(t, mem.Get(bz("key1")), "Expected `key1` to be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCacheDBWriteLock(t *testing.T) {
|
|
||||||
mem := NewMemDB()
|
|
||||||
cdb := mem.CacheDB()
|
|
||||||
require.NotPanics(t, func() { cdb.Write() })
|
|
||||||
require.Panics(t, func() { cdb.Write() })
|
|
||||||
cdb = mem.CacheDB()
|
|
||||||
require.NotPanics(t, func() { cdb.Write() })
|
|
||||||
require.Panics(t, func() { cdb.Write() })
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCacheDBWriteLockNested(t *testing.T) {
|
|
||||||
mem := NewMemDB()
|
|
||||||
cdb := mem.CacheDB()
|
|
||||||
cdb2 := cdb.CacheDB()
|
|
||||||
require.NotPanics(t, func() { cdb2.Write() })
|
|
||||||
require.Panics(t, func() { cdb2.Write() })
|
|
||||||
cdb2 = cdb.CacheDB()
|
|
||||||
require.NotPanics(t, func() { cdb2.Write() })
|
|
||||||
require.Panics(t, func() { cdb2.Write() })
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCacheDBNested(t *testing.T) {
|
|
||||||
mem := NewMemDB()
|
|
||||||
cdb := mem.CacheDB()
|
|
||||||
cdb.Set(bz("key1"), bz("value1"))
|
|
||||||
|
|
||||||
require.Empty(t, mem.Get(bz("key1")))
|
|
||||||
require.Equal(t, bz("value1"), cdb.Get(bz("key1")))
|
|
||||||
cdb2 := cdb.CacheDB()
|
|
||||||
require.Equal(t, bz("value1"), cdb2.Get(bz("key1")))
|
|
||||||
|
|
||||||
cdb2.Set(bz("key1"), bz("VALUE2"))
|
|
||||||
require.Equal(t, []byte(nil), mem.Get(bz("key1")))
|
|
||||||
require.Equal(t, bz("value1"), cdb.Get(bz("key1")))
|
|
||||||
require.Equal(t, bz("VALUE2"), cdb2.Get(bz("key1")))
|
|
||||||
|
|
||||||
cdb2.Write()
|
|
||||||
require.Equal(t, []byte(nil), mem.Get(bz("key1")))
|
|
||||||
require.Equal(t, bz("VALUE2"), cdb.Get(bz("key1")))
|
|
||||||
|
|
||||||
cdb.Write()
|
|
||||||
require.Equal(t, bz("VALUE2"), mem.Get(bz("key1")))
|
|
||||||
|
|
||||||
}
|
|
@ -23,16 +23,6 @@ func checkNextPanics(t *testing.T, itr Iterator) {
|
|||||||
assert.Panics(t, func() { itr.Next() }, "checkNextPanics expected panic but didn't")
|
assert.Panics(t, func() { itr.Next() }, "checkNextPanics expected panic but didn't")
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPrevPanics(t *testing.T, itr Iterator) {
|
|
||||||
assert.Panics(t, func() { itr.Prev() }, "checkPrevPanics expected panic but didn't")
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkPrev(t *testing.T, itr Iterator, expected bool) {
|
|
||||||
itr.Prev()
|
|
||||||
valid := itr.Valid()
|
|
||||||
assert.Equal(t, expected, valid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkItem(t *testing.T, itr Iterator, key []byte, value []byte) {
|
func checkItem(t *testing.T, itr Iterator, key []byte, value []byte) {
|
||||||
k, v := itr.Key(), itr.Value()
|
k, v := itr.Key(), itr.Value()
|
||||||
assert.Exactly(t, key, k)
|
assert.Exactly(t, key, k)
|
||||||
@ -44,7 +34,6 @@ func checkInvalid(t *testing.T, itr Iterator) {
|
|||||||
checkKeyPanics(t, itr)
|
checkKeyPanics(t, itr)
|
||||||
checkValuePanics(t, itr)
|
checkValuePanics(t, itr)
|
||||||
checkNextPanics(t, itr)
|
checkNextPanics(t, itr)
|
||||||
checkPrevPanics(t, itr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkKeyPanics(t *testing.T, itr Iterator) {
|
func checkKeyPanics(t *testing.T, itr Iterator) {
|
||||||
@ -67,7 +56,7 @@ func TestDBIteratorSingleKey(t *testing.T) {
|
|||||||
t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) {
|
t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) {
|
||||||
db := newTempDB(t, backend)
|
db := newTempDB(t, backend)
|
||||||
db.SetSync(bz("1"), bz("value_1"))
|
db.SetSync(bz("1"), bz("value_1"))
|
||||||
itr := db.Iterator()
|
itr := db.Iterator(BeginningKey(), EndingKey())
|
||||||
|
|
||||||
checkValid(t, itr, true)
|
checkValid(t, itr, true)
|
||||||
checkNext(t, itr, false)
|
checkNext(t, itr, false)
|
||||||
@ -88,15 +77,12 @@ func TestDBIteratorTwoKeys(t *testing.T) {
|
|||||||
db.SetSync(bz("2"), bz("value_1"))
|
db.SetSync(bz("2"), bz("value_1"))
|
||||||
|
|
||||||
{ // Fail by calling Next too much
|
{ // Fail by calling Next too much
|
||||||
itr := db.Iterator()
|
itr := db.Iterator(BeginningKey(), EndingKey())
|
||||||
checkValid(t, itr, true)
|
checkValid(t, itr, true)
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
checkNext(t, itr, true)
|
checkNext(t, itr, true)
|
||||||
checkValid(t, itr, true)
|
checkValid(t, itr, true)
|
||||||
|
|
||||||
checkPrev(t, itr, true)
|
|
||||||
checkValid(t, itr, true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNext(t, itr, true)
|
checkNext(t, itr, true)
|
||||||
@ -110,27 +96,6 @@ func TestDBIteratorTwoKeys(t *testing.T) {
|
|||||||
// Once invalid...
|
// Once invalid...
|
||||||
checkInvalid(t, itr)
|
checkInvalid(t, itr)
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Fail by calling Prev too much
|
|
||||||
itr := db.Iterator()
|
|
||||||
checkValid(t, itr, true)
|
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
checkNext(t, itr, true)
|
|
||||||
checkValid(t, itr, true)
|
|
||||||
|
|
||||||
checkPrev(t, itr, true)
|
|
||||||
checkValid(t, itr, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
checkPrev(t, itr, false)
|
|
||||||
checkValid(t, itr, false)
|
|
||||||
|
|
||||||
checkPrevPanics(t, itr)
|
|
||||||
|
|
||||||
// Once invalid...
|
|
||||||
checkInvalid(t, itr)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,32 +104,30 @@ func TestDBIteratorEmpty(t *testing.T) {
|
|||||||
for backend, _ := range backends {
|
for backend, _ := range backends {
|
||||||
t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) {
|
t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) {
|
||||||
db := newTempDB(t, backend)
|
db := newTempDB(t, backend)
|
||||||
itr := db.Iterator()
|
itr := db.Iterator(BeginningKey(), EndingKey())
|
||||||
|
|
||||||
checkInvalid(t, itr)
|
checkInvalid(t, itr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDBIteratorEmptySeek(t *testing.T) {
|
func TestDBIteratorEmptyBeginAfter(t *testing.T) {
|
||||||
for backend, _ := range backends {
|
for backend, _ := range backends {
|
||||||
t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) {
|
t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) {
|
||||||
db := newTempDB(t, backend)
|
db := newTempDB(t, backend)
|
||||||
itr := db.Iterator()
|
itr := db.Iterator(bz("1"), EndingKey())
|
||||||
itr.Seek(bz("1"))
|
|
||||||
|
|
||||||
checkInvalid(t, itr)
|
checkInvalid(t, itr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDBIteratorBadSeek(t *testing.T) {
|
func TestDBIteratorNonemptyBeginAfter(t *testing.T) {
|
||||||
for backend, _ := range backends {
|
for backend, _ := range backends {
|
||||||
t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) {
|
t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) {
|
||||||
db := newTempDB(t, backend)
|
db := newTempDB(t, backend)
|
||||||
db.SetSync(bz("1"), bz("value_1"))
|
db.SetSync(bz("1"), bz("value_1"))
|
||||||
itr := db.Iterator()
|
itr := db.Iterator(bz("2"), EndingKey())
|
||||||
itr.Seek(bz("2"))
|
|
||||||
|
|
||||||
checkInvalid(t, itr)
|
checkInvalid(t, itr)
|
||||||
})
|
})
|
||||||
|
@ -19,7 +19,7 @@ func TestMemDbIterator(t *testing.T) {
|
|||||||
db.Set(k, value)
|
db.Set(k, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
iter := db.Iterator()
|
iter := db.Iterator(BeginningKey(), EndingKey())
|
||||||
i := 0
|
i := 0
|
||||||
for ; iter.Valid(); iter.Next() {
|
for ; iter.Valid(); iter.Next() {
|
||||||
assert.Equal(t, db.Get(iter.Key()), iter.Value(), "values dont match for key")
|
assert.Equal(t, db.Get(iter.Key()), iter.Value(), "values dont match for key")
|
||||||
|
13
db/types.go
13
db/types.go
@ -90,17 +90,11 @@ type Iterator interface {
|
|||||||
Valid() bool
|
Valid() bool
|
||||||
|
|
||||||
// Next moves the iterator to the next sequential key in the database, as
|
// Next moves the iterator to the next sequential key in the database, as
|
||||||
// defined by the Comparator in the ReadOptions used to create this Iterator.
|
// defined by order of iteration.
|
||||||
//
|
//
|
||||||
// If Valid returns false, this method will panic.
|
// If Valid returns false, this method will panic.
|
||||||
Next()
|
Next()
|
||||||
|
|
||||||
// Prev moves the iterator to the previous sequential key in the database, as
|
|
||||||
// defined by the Comparator in the ReadOptions used to create this Iterator.
|
|
||||||
//
|
|
||||||
// If Valid returns false, this method will panic.
|
|
||||||
Prev()
|
|
||||||
|
|
||||||
// Key returns the key of the cursor.
|
// Key returns the key of the cursor.
|
||||||
//
|
//
|
||||||
// If Valid returns false, this method will panic.
|
// If Valid returns false, this method will panic.
|
||||||
@ -120,3 +114,8 @@ type Iterator interface {
|
|||||||
// Release deallocates the given Iterator.
|
// Release deallocates the given Iterator.
|
||||||
Release()
|
Release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For testing convenience.
|
||||||
|
func bz(s string) []byte {
|
||||||
|
return []byte(s)
|
||||||
|
}
|
||||||
|
@ -66,7 +66,6 @@ func TestPrefixIteratorMatches1N(t *testing.T) {
|
|||||||
db.SetSync(bz("a/1"), bz("value_1"))
|
db.SetSync(bz("a/1"), bz("value_1"))
|
||||||
db.SetSync(bz("a/3"), bz("value_3"))
|
db.SetSync(bz("a/3"), bz("value_3"))
|
||||||
itr := IteratePrefix(db, []byte("a/"))
|
itr := IteratePrefix(db, []byte("a/"))
|
||||||
itr.Seek(bz("a/1"))
|
|
||||||
|
|
||||||
checkValid(t, itr, true)
|
checkValid(t, itr, true)
|
||||||
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
||||||
@ -82,32 +81,6 @@ func TestPrefixIteratorMatches1N(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for a/1, fail by too much Prev()
|
|
||||||
func TestPrefixIteratorMatches1P(t *testing.T) {
|
|
||||||
for backend, _ := range backends {
|
|
||||||
t.Run(fmt.Sprintf("Prefix w/ backend %s", backend), func(t *testing.T) {
|
|
||||||
db := newTempDB(t, backend)
|
|
||||||
db.SetSync(bz("a/1"), bz("value_1"))
|
|
||||||
db.SetSync(bz("a/3"), bz("value_3"))
|
|
||||||
itr := IteratePrefix(db, []byte("a/"))
|
|
||||||
itr.Seek(bz("a/1"))
|
|
||||||
|
|
||||||
checkValid(t, itr, true)
|
|
||||||
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
|
||||||
checkNext(t, itr, true)
|
|
||||||
checkItem(t, itr, bz("a/3"), bz("value_3"))
|
|
||||||
checkPrev(t, itr, true)
|
|
||||||
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
|
||||||
|
|
||||||
// Bad!
|
|
||||||
checkPrev(t, itr, false)
|
|
||||||
|
|
||||||
// Once invalid...
|
|
||||||
checkInvalid(t, itr)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for a/2, fail by too much Next()
|
// Search for a/2, fail by too much Next()
|
||||||
func TestPrefixIteratorMatches2N(t *testing.T) {
|
func TestPrefixIteratorMatches2N(t *testing.T) {
|
||||||
for backend, _ := range backends {
|
for backend, _ := range backends {
|
||||||
@ -116,13 +89,11 @@ func TestPrefixIteratorMatches2N(t *testing.T) {
|
|||||||
db.SetSync(bz("a/1"), bz("value_1"))
|
db.SetSync(bz("a/1"), bz("value_1"))
|
||||||
db.SetSync(bz("a/3"), bz("value_3"))
|
db.SetSync(bz("a/3"), bz("value_3"))
|
||||||
itr := IteratePrefix(db, []byte("a/"))
|
itr := IteratePrefix(db, []byte("a/"))
|
||||||
itr.Seek(bz("a/2"))
|
|
||||||
|
|
||||||
checkValid(t, itr, true)
|
checkValid(t, itr, true)
|
||||||
checkItem(t, itr, bz("a/3"), bz("value_3"))
|
|
||||||
checkPrev(t, itr, true)
|
|
||||||
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
||||||
checkNext(t, itr, true)
|
checkNext(t, itr, true)
|
||||||
|
checkValid(t, itr, true)
|
||||||
checkItem(t, itr, bz("a/3"), bz("value_3"))
|
checkItem(t, itr, bz("a/3"), bz("value_3"))
|
||||||
|
|
||||||
// Bad!
|
// Bad!
|
||||||
@ -134,30 +105,6 @@ func TestPrefixIteratorMatches2N(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for a/2, fail by too much Prev()
|
|
||||||
func TestPrefixIteratorMatches2P(t *testing.T) {
|
|
||||||
for backend, _ := range backends {
|
|
||||||
t.Run(fmt.Sprintf("Prefix w/ backend %s", backend), func(t *testing.T) {
|
|
||||||
db := newTempDB(t, backend)
|
|
||||||
db.SetSync(bz("a/1"), bz("value_1"))
|
|
||||||
db.SetSync(bz("a/3"), bz("value_3"))
|
|
||||||
itr := IteratePrefix(db, []byte("a/"))
|
|
||||||
itr.Seek(bz("a/2"))
|
|
||||||
|
|
||||||
checkValid(t, itr, true)
|
|
||||||
checkItem(t, itr, bz("a/3"), bz("value_3"))
|
|
||||||
checkPrev(t, itr, true)
|
|
||||||
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
|
||||||
|
|
||||||
// Bad!
|
|
||||||
checkPrev(t, itr, false)
|
|
||||||
|
|
||||||
// Once invalid...
|
|
||||||
checkInvalid(t, itr)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for a/3, fail by too much Next()
|
// Search for a/3, fail by too much Next()
|
||||||
func TestPrefixIteratorMatches3N(t *testing.T) {
|
func TestPrefixIteratorMatches3N(t *testing.T) {
|
||||||
for backend, _ := range backends {
|
for backend, _ := range backends {
|
||||||
@ -166,11 +113,8 @@ func TestPrefixIteratorMatches3N(t *testing.T) {
|
|||||||
db.SetSync(bz("a/1"), bz("value_1"))
|
db.SetSync(bz("a/1"), bz("value_1"))
|
||||||
db.SetSync(bz("a/3"), bz("value_3"))
|
db.SetSync(bz("a/3"), bz("value_3"))
|
||||||
itr := IteratePrefix(db, []byte("a/"))
|
itr := IteratePrefix(db, []byte("a/"))
|
||||||
itr.Seek(bz("a/3"))
|
|
||||||
|
|
||||||
checkValid(t, itr, true)
|
checkValid(t, itr, true)
|
||||||
checkItem(t, itr, bz("a/3"), bz("value_3"))
|
|
||||||
checkPrev(t, itr, true)
|
|
||||||
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
||||||
checkNext(t, itr, true)
|
checkNext(t, itr, true)
|
||||||
checkItem(t, itr, bz("a/3"), bz("value_3"))
|
checkItem(t, itr, bz("a/3"), bz("value_3"))
|
||||||
@ -183,27 +127,3 @@ func TestPrefixIteratorMatches3N(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for a/3, fail by too much Prev()
|
|
||||||
func TestPrefixIteratorMatches3P(t *testing.T) {
|
|
||||||
for backend, _ := range backends {
|
|
||||||
t.Run(fmt.Sprintf("Prefix w/ backend %s", backend), func(t *testing.T) {
|
|
||||||
db := newTempDB(t, backend)
|
|
||||||
db.SetSync(bz("a/1"), bz("value_1"))
|
|
||||||
db.SetSync(bz("a/3"), bz("value_3"))
|
|
||||||
itr := IteratePrefix(db, []byte("a/"))
|
|
||||||
itr.Seek(bz("a/3"))
|
|
||||||
|
|
||||||
checkValid(t, itr, true)
|
|
||||||
checkItem(t, itr, bz("a/3"), bz("value_3"))
|
|
||||||
checkPrev(t, itr, true)
|
|
||||||
checkItem(t, itr, bz("a/1"), bz("value_1"))
|
|
||||||
|
|
||||||
// Bad!
|
|
||||||
checkPrev(t, itr, false)
|
|
||||||
|
|
||||||
// Once invalid...
|
|
||||||
checkInvalid(t, itr)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user