github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/base/comparer_test.go (about)

     1  // Copyright 2011 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 base
     6  
     7  import (
     8  	"fmt"
     9  	"sort"
    10  	"testing"
    11  	"time"
    12  
    13  	"golang.org/x/exp/rand"
    14  )
    15  
    16  func TestDefAppendSeparator(t *testing.T) {
    17  	testCases := []struct {
    18  		a, b, want string
    19  	}{
    20  		// Examples from the doc comments.
    21  		{"black", "blue", "blb"},
    22  		{"green", "", "green"},
    23  		// Non-empty b values. The C++ Level-DB code calls these separators.
    24  		{"", "2", ""},
    25  		{"1", "2", "1"},
    26  		{"1", "29", "2"},
    27  		{"13", "19", "14"},
    28  		{"13", "99", "2"},
    29  		{"135", "19", "14"},
    30  		{"1357", "19", "14"},
    31  		{"1357", "2", "14"},
    32  		{"13\xff", "14", "13\xff"},
    33  		{"13\xff", "19", "14"},
    34  		{"1\xff\xff", "19", "1\xff\xff"},
    35  		{"1\xff\xff", "2", "1\xff\xff"},
    36  		{"1\xff\xff", "9", "2"},
    37  		// Empty b values. The C++ Level-DB code calls these successors.
    38  		{"", "", ""},
    39  		{"1", "", "1"},
    40  		{"11", "", "11"},
    41  		{"11\xff", "", "11\xff"},
    42  		{"1\xff", "", "1\xff"},
    43  		{"1\xff\xff", "", "1\xff\xff"},
    44  		{"\xff", "", "\xff"},
    45  		{"\xff\xff", "", "\xff\xff"},
    46  		{"\xff\xff\xff", "", "\xff\xff\xff"},
    47  	}
    48  	for _, tc := range testCases {
    49  		t.Run("", func(t *testing.T) {
    50  			got := string(DefaultComparer.Separator(nil, []byte(tc.a), []byte(tc.b)))
    51  			if got != tc.want {
    52  				t.Errorf("a, b = %q, %q: got %q, want %q", tc.a, tc.b, got, tc.want)
    53  			}
    54  		})
    55  	}
    56  }
    57  
    58  func TestAbbreviatedKey(t *testing.T) {
    59  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
    60  	randBytes := func(size int) []byte {
    61  		data := make([]byte, size)
    62  		for i := range data {
    63  			data[i] = byte(rng.Int() & 0xff)
    64  		}
    65  		return data
    66  	}
    67  
    68  	keys := make([][]byte, 10000)
    69  	for i := range keys {
    70  		keys[i] = randBytes(rng.Intn(16))
    71  	}
    72  	sort.Slice(keys, func(i, j int) bool {
    73  		return DefaultComparer.Compare(keys[i], keys[j]) < 0
    74  	})
    75  
    76  	for i := 1; i < len(keys); i++ {
    77  		last := DefaultComparer.AbbreviatedKey(keys[i-1])
    78  		cur := DefaultComparer.AbbreviatedKey(keys[i])
    79  		cmp := DefaultComparer.Compare(keys[i-1], keys[i])
    80  		if cmp == 0 {
    81  			if last != cur {
    82  				t.Fatalf("expected equal abbreviated keys: %x[%x] != %x[%x]",
    83  					last, keys[i-1], cur, keys[i])
    84  			}
    85  		} else {
    86  			if last > cur {
    87  				t.Fatalf("unexpected abbreviated key ordering: %x[%x] > %x[%x]",
    88  					last, keys[i-1], cur, keys[i])
    89  			}
    90  		}
    91  	}
    92  }
    93  
    94  func BenchmarkAbbreviatedKey(b *testing.B) {
    95  	rng := rand.New(rand.NewSource(1449168817))
    96  	randBytes := func(size int) []byte {
    97  		data := make([]byte, size)
    98  		for i := range data {
    99  			data[i] = byte(rng.Int() & 0xff)
   100  		}
   101  		return data
   102  	}
   103  	keys := make([][]byte, 10000)
   104  	for i := range keys {
   105  		keys[i] = randBytes(8)
   106  	}
   107  
   108  	b.ResetTimer()
   109  	var sum uint64
   110  	for i := 0; i < b.N; i++ {
   111  		j := i % len(keys)
   112  		sum += DefaultComparer.AbbreviatedKey(keys[j])
   113  	}
   114  
   115  	if testing.Verbose() {
   116  		// Ensure the compiler doesn't optimize away our benchmark.
   117  		fmt.Println(sum)
   118  	}
   119  }