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  }