github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/internal/rangedel/seek_test.go (about) 1 // Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package rangedel 6 7 import ( 8 "bytes" 9 "fmt" 10 "reflect" 11 "strconv" 12 "strings" 13 "testing" 14 15 "github.com/petermattis/pebble/internal/base" 16 "github.com/petermattis/pebble/internal/datadriven" 17 ) 18 19 type iterAdapter struct { 20 *Iter 21 } 22 23 func (i *iterAdapter) verify(key *base.InternalKey, val []byte) (*base.InternalKey, []byte) { 24 valid := key != nil 25 if valid != i.Valid() { 26 panic(fmt.Sprintf("inconsistent valid: %t != %t", valid, i.Valid())) 27 } 28 if valid { 29 if base.InternalCompare(bytes.Compare, *key, *i.Key()) != 0 { 30 panic(fmt.Sprintf("inconsistent key: %s != %s", *key, i.Key())) 31 } 32 if !bytes.Equal(val, i.Value()) { 33 panic(fmt.Sprintf("inconsistent value: [% x] != [% x]", val, i.Value())) 34 } 35 } 36 return key, val 37 } 38 39 func (i *iterAdapter) SeekGE(key []byte) (*base.InternalKey, []byte) { 40 return i.verify(i.Iter.SeekGE(key)) 41 } 42 43 func (i *iterAdapter) SeekLT(key []byte) (*base.InternalKey, []byte) { 44 return i.verify(i.Iter.SeekLT(key)) 45 } 46 47 func (i *iterAdapter) First() (*base.InternalKey, []byte) { 48 return i.verify(i.Iter.First()) 49 } 50 51 func (i *iterAdapter) Last() (*base.InternalKey, []byte) { 52 return i.verify(i.Iter.Last()) 53 } 54 55 func (i *iterAdapter) Next() (*base.InternalKey, []byte) { 56 return i.verify(i.Iter.Next()) 57 } 58 59 func (i *iterAdapter) Prev() (*base.InternalKey, []byte) { 60 return i.verify(i.Iter.Prev()) 61 } 62 63 func TestSeek(t *testing.T) { 64 cmp := base.DefaultComparer.Compare 65 iter := &iterAdapter{} 66 67 datadriven.RunTest(t, "testdata/seek", func(d *datadriven.TestData) string { 68 switch d.Cmd { 69 case "build": 70 tombstones := buildTombstones(t, cmp, d.Input) 71 iter.Iter = NewIter(cmp, tombstones) 72 return formatTombstones(tombstones) 73 74 case "seek-ge", "seek-le": 75 seek := SeekGE 76 if d.Cmd == "seek-le" { 77 seek = SeekLE 78 } 79 80 var buf bytes.Buffer 81 for _, line := range strings.Split(d.Input, "\n") { 82 parts := strings.Fields(line) 83 if len(parts) != 2 { 84 return fmt.Sprintf("malformed input: %s", line) 85 } 86 seq, err := strconv.ParseUint(parts[1], 10, 64) 87 if err != nil { 88 return err.Error() 89 } 90 tombstone := seek(cmp, iter, []byte(parts[0]), seq) 91 fmt.Fprintf(&buf, "%s", 92 strings.TrimSpace(formatTombstones([]Tombstone{tombstone}))) 93 // Check that the returned tombstone and the tombstone the iterator is 94 // pointed at are identical. 95 var iTombstone Tombstone 96 if iter.Valid() { 97 iTombstone = Tombstone{ 98 Start: *iter.Key(), 99 End: iter.Value(), 100 } 101 } 102 if !reflect.DeepEqual(tombstone, iTombstone) { 103 fmt.Fprintf(&buf, " [%s]", 104 strings.TrimSpace(formatTombstones([]Tombstone{tombstone}))) 105 } 106 fmt.Fprintf(&buf, "\n") 107 } 108 return buf.String() 109 110 default: 111 return fmt.Sprintf("unknown command: %s", d.Cmd) 112 } 113 }) 114 }