add test case for seeing prefix iterators outside of range
similar to #256 except for prefix iterators includes fix for boltdb and gtreap which had incorrect behavior
This commit is contained in:
parent
0ba164322b
commit
f0d282f5f8
|
@ -39,9 +39,17 @@ func (i *Iterator) updateValid() {
|
|||
}
|
||||
|
||||
func (i *Iterator) Seek(k []byte) {
|
||||
if bytes.Compare(k, i.start) < 0 {
|
||||
if i.start != nil && bytes.Compare(k, i.start) < 0 {
|
||||
k = i.start
|
||||
}
|
||||
if i.prefix != nil && !bytes.HasPrefix(k, i.prefix) {
|
||||
if bytes.Compare(k, i.prefix) < 0 {
|
||||
k = i.prefix
|
||||
} else {
|
||||
i.valid = false
|
||||
return
|
||||
}
|
||||
}
|
||||
i.key, i.val = i.cursor.Seek(k)
|
||||
i.updateValid()
|
||||
}
|
||||
|
|
|
@ -66,6 +66,12 @@ func TestBoltDBPrefixIterator(t *testing.T) {
|
|||
test.CommonTestPrefixIterator(t, s)
|
||||
}
|
||||
|
||||
func TestBoltDBPrefixIteratorSeek(t *testing.T) {
|
||||
s := open(t, nil)
|
||||
defer cleanup(t, s)
|
||||
test.CommonTestPrefixIteratorSeek(t, s)
|
||||
}
|
||||
|
||||
func TestBoltDBRangeIterator(t *testing.T) {
|
||||
s := open(t, nil)
|
||||
defer cleanup(t, s)
|
||||
|
|
|
@ -69,6 +69,12 @@ func TestGoLevelDBPrefixIterator(t *testing.T) {
|
|||
test.CommonTestPrefixIterator(t, s)
|
||||
}
|
||||
|
||||
func TestGoLevelDBPrefixIteratorSeek(t *testing.T) {
|
||||
s := open(t, nil)
|
||||
defer cleanup(t, s)
|
||||
test.CommonTestPrefixIteratorSeek(t, s)
|
||||
}
|
||||
|
||||
func TestGoLevelDBRangeIterator(t *testing.T) {
|
||||
s := open(t, nil)
|
||||
defer cleanup(t, s)
|
||||
|
|
|
@ -36,9 +36,26 @@ type Iterator struct {
|
|||
}
|
||||
|
||||
func (w *Iterator) Seek(k []byte) {
|
||||
if bytes.Compare(k, w.start) < 0 {
|
||||
if w.start != nil && bytes.Compare(k, w.start) < 0 {
|
||||
k = w.start
|
||||
}
|
||||
if w.prefix != nil && !bytes.HasPrefix(k, w.prefix) {
|
||||
if bytes.Compare(k, w.prefix) < 0 {
|
||||
k = w.prefix
|
||||
} else {
|
||||
var end []byte
|
||||
for i := len(w.prefix) - 1; i >= 0; i-- {
|
||||
c := w.prefix[i]
|
||||
if c < 0xff {
|
||||
end = make([]byte, i+1)
|
||||
copy(end, w.prefix)
|
||||
end[i] = c + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
k = end
|
||||
}
|
||||
}
|
||||
w.restart(&Item{k: k})
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,12 @@ func TestGTreapPrefixIterator(t *testing.T) {
|
|||
test.CommonTestPrefixIterator(t, s)
|
||||
}
|
||||
|
||||
func TestGTreapPrefixIteratorSeek(t *testing.T) {
|
||||
s := open(t, nil)
|
||||
defer cleanup(t, s)
|
||||
test.CommonTestPrefixIteratorSeek(t, s)
|
||||
}
|
||||
|
||||
func TestGTreapRangeIterator(t *testing.T) {
|
||||
s := open(t, nil)
|
||||
defer cleanup(t, s)
|
||||
|
|
|
@ -53,6 +53,12 @@ func TestMetricsPrefixIterator(t *testing.T) {
|
|||
test.CommonTestPrefixIterator(t, s)
|
||||
}
|
||||
|
||||
func TestMetricsPrefixIteratorSeek(t *testing.T) {
|
||||
s := open(t, nil)
|
||||
defer cleanup(t, s)
|
||||
test.CommonTestPrefixIteratorSeek(t, s)
|
||||
}
|
||||
|
||||
func TestMetricsRangeIterator(t *testing.T) {
|
||||
s := open(t, nil)
|
||||
defer cleanup(t, s)
|
||||
|
|
|
@ -131,6 +131,74 @@ func CommonTestPrefixIterator(t *testing.T, s store.KVStore) {
|
|||
}
|
||||
}
|
||||
|
||||
func CommonTestPrefixIteratorSeek(t *testing.T, s store.KVStore) {
|
||||
|
||||
data := []testRow{
|
||||
{[]byte("a"), []byte("val")},
|
||||
{[]byte("b1"), []byte("val")},
|
||||
{[]byte("b2"), []byte("val")},
|
||||
{[]byte("b3"), []byte("val")},
|
||||
{[]byte("c"), []byte("val")},
|
||||
}
|
||||
|
||||
err := batchWriteRows(s, data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// open a reader
|
||||
reader, err := s.Reader()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// get an iterator on a central subset of the data
|
||||
iter := reader.PrefixIterator([]byte("b"))
|
||||
|
||||
// check that all keys have prefix
|
||||
found := []string{}
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
found = append(found, string(iter.Key()))
|
||||
}
|
||||
for _, f := range found {
|
||||
if !strings.HasPrefix(f, "b") {
|
||||
t.Errorf("got key '%s' that doesn't have correct prefix")
|
||||
}
|
||||
}
|
||||
if len(found) != 3 {
|
||||
t.Errorf("expected 3 keys with prefix, got %d", len(found))
|
||||
}
|
||||
|
||||
// now try to seek before the prefix and repeat
|
||||
found = []string{}
|
||||
for iter.Seek([]byte("a")); iter.Valid(); iter.Next() {
|
||||
found = append(found, string(iter.Key()))
|
||||
}
|
||||
for _, f := range found {
|
||||
if !strings.HasPrefix(f, "b") {
|
||||
t.Errorf("got key '%s' that doesn't have correct prefix")
|
||||
}
|
||||
}
|
||||
if len(found) != 3 {
|
||||
t.Errorf("expected 3 keys with prefix, got %d", len(found))
|
||||
}
|
||||
|
||||
// now try to seek after the prefix and repeat
|
||||
found = []string{}
|
||||
for iter.Seek([]byte("c")); iter.Valid(); iter.Next() {
|
||||
found = append(found, string(iter.Key()))
|
||||
}
|
||||
for _, f := range found {
|
||||
if !strings.HasPrefix(f, "b") {
|
||||
t.Errorf("got key '%s' that doesn't have correct prefix")
|
||||
}
|
||||
}
|
||||
if len(found) != 0 {
|
||||
t.Errorf("expected 0 keys with prefix, got %d", len(found))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func CommonTestRangeIterator(t *testing.T, s store.KVStore) {
|
||||
|
||||
data := []testRow{
|
||||
|
|
Loading…
Reference in New Issue
Block a user