github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/manifest/level_metadata_test.go (about) 1 // Copyright 2020 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 manifest 6 7 import ( 8 "bytes" 9 "fmt" 10 "strings" 11 "testing" 12 13 "github.com/cockroachdb/datadriven" 14 "github.com/cockroachdb/pebble/internal/base" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestLevelIterator(t *testing.T) { 19 var level LevelSlice 20 datadriven.RunTest(t, "testdata/level_iterator", 21 func(t *testing.T, d *datadriven.TestData) string { 22 switch d.Cmd { 23 case "define": 24 var files []*FileMetadata 25 var startReslice int 26 var endReslice int 27 for _, metaStr := range strings.Split(d.Input, " ") { 28 switch metaStr { 29 case "[": 30 startReslice = len(files) 31 continue 32 case "]": 33 endReslice = len(files) 34 continue 35 case " ", "": 36 continue 37 default: 38 parts := strings.Split(metaStr, "-") 39 if len(parts) != 2 { 40 t.Fatalf("malformed table spec: %q", metaStr) 41 } 42 m := &FileMetadata{FileNum: base.FileNum(len(files) + 1)} 43 m.ExtendPointKeyBounds( 44 base.DefaultComparer.Compare, 45 base.ParseInternalKey(strings.TrimSpace(parts[0])), 46 base.ParseInternalKey(strings.TrimSpace(parts[1])), 47 ) 48 m.SmallestSeqNum = m.Smallest.SeqNum() 49 m.LargestSeqNum = m.Largest.SeqNum() 50 m.InitPhysicalBacking() 51 files = append(files, m) 52 } 53 } 54 level = NewLevelSliceKeySorted(base.DefaultComparer.Compare, files) 55 level = level.Reslice(func(start, end *LevelIterator) { 56 for i := 0; i < startReslice; i++ { 57 start.Next() 58 } 59 for i := len(files); i > endReslice; i-- { 60 end.Prev() 61 } 62 }) 63 return "" 64 65 case "iter": 66 return runIterCmd(t, d, level.Iter(), false /* verbose */) 67 68 default: 69 return fmt.Sprintf("unknown command %q", d.Cmd) 70 } 71 }) 72 } 73 74 func TestLevelIteratorFiltered(t *testing.T) { 75 var level LevelSlice 76 datadriven.RunTest(t, "testdata/level_iterator_filtered", 77 func(t *testing.T, d *datadriven.TestData) string { 78 switch d.Cmd { 79 case "define": 80 var files []*FileMetadata 81 for _, metaStr := range strings.Split(d.Input, "\n") { 82 m, err := ParseFileMetadataDebug(metaStr) 83 require.NoError(t, err) 84 files = append(files, m) 85 } 86 level = NewLevelSliceKeySorted(base.DefaultComparer.Compare, files) 87 return "" 88 89 case "iter": 90 var keyType string 91 d.ScanArgs(t, "key-type", &keyType) 92 iter := level.Iter() 93 switch keyType { 94 case "both": 95 // noop 96 case "points": 97 iter = iter.Filter(KeyTypePoint) 98 case "ranges": 99 iter = iter.Filter(KeyTypeRange) 100 } 101 return runIterCmd(t, d, iter, true /* verbose */) 102 103 default: 104 return fmt.Sprintf("unknown command %q", d.Cmd) 105 } 106 }) 107 } 108 109 func runIterCmd(t *testing.T, d *datadriven.TestData, iter LevelIterator, verbose bool) string { 110 var buf bytes.Buffer 111 for _, line := range strings.Split(d.Input, "\n") { 112 parts := strings.Fields(line) 113 if len(parts) == 0 { 114 continue 115 } 116 var m *FileMetadata 117 switch parts[0] { 118 case "first": 119 m = iter.First() 120 case "last": 121 m = iter.Last() 122 case "next": 123 m = iter.Next() 124 case "prev": 125 m = iter.Prev() 126 case "seek-ge": 127 m = iter.SeekGE(base.DefaultComparer.Compare, []byte(parts[1])) 128 case "seek-lt": 129 m = iter.SeekLT(base.DefaultComparer.Compare, []byte(parts[1])) 130 default: 131 return fmt.Sprintf("unknown command %q", parts[0]) 132 } 133 if m == nil { 134 fmt.Fprintln(&buf, ".") 135 } else { 136 if verbose { 137 fmt.Fprintln(&buf, m.DebugString(base.DefaultComparer.FormatKey, verbose)) 138 } else { 139 fmt.Fprintln(&buf, m) 140 } 141 } 142 } 143 return buf.String() 144 }