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  }