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) {
|
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
|
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.key, i.val = i.cursor.Seek(k)
|
||||||
i.updateValid()
|
i.updateValid()
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,12 @@ func TestBoltDBPrefixIterator(t *testing.T) {
|
||||||
test.CommonTestPrefixIterator(t, s)
|
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) {
|
func TestBoltDBRangeIterator(t *testing.T) {
|
||||||
s := open(t, nil)
|
s := open(t, nil)
|
||||||
defer cleanup(t, s)
|
defer cleanup(t, s)
|
||||||
|
|
|
@ -69,6 +69,12 @@ func TestGoLevelDBPrefixIterator(t *testing.T) {
|
||||||
test.CommonTestPrefixIterator(t, s)
|
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) {
|
func TestGoLevelDBRangeIterator(t *testing.T) {
|
||||||
s := open(t, nil)
|
s := open(t, nil)
|
||||||
defer cleanup(t, s)
|
defer cleanup(t, s)
|
||||||
|
|
|
@ -36,9 +36,26 @@ type Iterator struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Iterator) Seek(k []byte) {
|
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
|
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})
|
w.restart(&Item{k: k})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,12 @@ func TestGTreapPrefixIterator(t *testing.T) {
|
||||||
test.CommonTestPrefixIterator(t, s)
|
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) {
|
func TestGTreapRangeIterator(t *testing.T) {
|
||||||
s := open(t, nil)
|
s := open(t, nil)
|
||||||
defer cleanup(t, s)
|
defer cleanup(t, s)
|
||||||
|
|
|
@ -53,6 +53,12 @@ func TestMetricsPrefixIterator(t *testing.T) {
|
||||||
test.CommonTestPrefixIterator(t, s)
|
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) {
|
func TestMetricsRangeIterator(t *testing.T) {
|
||||||
s := open(t, nil)
|
s := open(t, nil)
|
||||||
defer cleanup(t, s)
|
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) {
|
func CommonTestRangeIterator(t *testing.T, s store.KVStore) {
|
||||||
|
|
||||||
data := []testRow{
|
data := []testRow{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user