github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/internal/testkeys/testkeys_test.go (about)

     1  // Copyright 2021 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 testkeys
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/require"
    13  	"github.com/zuoyebang/bitalostable/internal/datadriven"
    14  )
    15  
    16  func TestGenerateAlphabetKey(t *testing.T) {
    17  	testCases := []struct {
    18  		alphabet string
    19  		i        int
    20  		depth    int
    21  		want     string
    22  	}{
    23  		{"abc", 0, 1, "a"},
    24  		{"abc", 0, 2, "a"},
    25  		{"abc", 0, 3, "a"},
    26  
    27  		{"abc", 1, 1, "b"},
    28  		{"abc", 2, 1, "c"},
    29  
    30  		{"abc", 0, 2, "a"},
    31  		{"abc", 1, 2, "aa"},
    32  		{"abc", 2, 2, "ab"},
    33  		{"abc", 3, 2, "ac"},
    34  		{"abc", 4, 2, "b"},
    35  		{"abc", 5, 2, "ba"},
    36  		{"abc", 6, 2, "bb"},
    37  		{"abc", 7, 2, "bc"},
    38  		{"abc", 8, 2, "c"},
    39  		{"abc", 9, 2, "ca"},
    40  		{"abc", 10, 2, "cb"},
    41  		{"abc", 11, 2, "cc"},
    42  	}
    43  
    44  	buf := make([]byte, 10)
    45  	for _, tc := range testCases {
    46  		kc := keyCount(len(tc.alphabet), tc.depth)
    47  		n := generateAlphabetKey(buf, []byte(tc.alphabet), tc.i, kc)
    48  		got := string(buf[:n])
    49  		if got != tc.want {
    50  			t.Errorf("generateAlphabetKey(%q, %d, %d) = %q, want %q", tc.alphabet, tc.i, kc, got, tc.want)
    51  		}
    52  	}
    53  }
    54  
    55  func TestKeyCount(t *testing.T) {
    56  	type params struct {
    57  		n, l int
    58  	}
    59  	testCases := map[params]int{
    60  		{26, 1}: 26,
    61  		{52, 1}: 52,
    62  		{2, 2}:  6,
    63  		{2, 3}:  14,
    64  		{2, 4}:  30,
    65  		{3, 2}:  12,
    66  	}
    67  	for p, want := range testCases {
    68  		got := keyCount(p.n, p.l)
    69  		if got != want {
    70  			t.Errorf("keyCount(%d, %d) = %d, want %d", p.n, p.l, got, want)
    71  		}
    72  	}
    73  }
    74  
    75  func TestFullKeyspaces(t *testing.T) {
    76  	testCases := []struct {
    77  		ks   Keyspace
    78  		want string
    79  	}{
    80  		{
    81  			Alpha(1),
    82  			"a b c d e f g h i j k l m n o p q r s t u v w x y z",
    83  		},
    84  		{
    85  			alphabet{[]byte("abc"), 2, 0, 0, 1},
    86  			"a aa ab ac b ba bb bc c ca cb cc",
    87  		},
    88  		{
    89  			alphabet{[]byte("abc"), 2, 0, 0, 2},
    90  			"a ab b bb c cb",
    91  		},
    92  		{
    93  			alphabet{[]byte("abc"), 3, 0, 0, 1},
    94  			"a aa aaa aab aac ab aba abb abc ac aca acb acc b ba baa bab bac bb bba bbb bbc bc bca bcb bcc c ca caa cab cac cb cba cbb cbc cc cca ccb ccc",
    95  		},
    96  		{
    97  			alphabet{[]byte("abc"), 3, 7, 10, 1},
    98  			"abb abc ac aca acb acc b ba baa bab bac bb bba bbb bbc bc bca bcb bcc c ca caa",
    99  		},
   100  	}
   101  	for _, tc := range testCases {
   102  		require.Equal(t, tc.want, keyspaceToString(tc.ks))
   103  	}
   104  }
   105  
   106  func TestSlice(t *testing.T) {
   107  	testCases := []struct {
   108  		orig Keyspace
   109  		i, j int
   110  		want string
   111  	}{
   112  		{Alpha(1), 1, 25, "b c d e f g h i j k l m n o p q r s t u v w x y"},
   113  		{Alpha(1).Slice(1, 25), 1, 23, "c d e f g h i j k l m n o p q r s t u v w x"},
   114  		{Alpha(1).Slice(1, 25).Slice(1, 23), 10, 22, "m n o p q r s t u v w x"},
   115  	}
   116  	for _, tc := range testCases {
   117  		got := keyspaceToString(tc.orig.Slice(tc.i, tc.j))
   118  		if got != tc.want {
   119  			t.Errorf("(%q).Slice(%d, %d) = %q, want %q",
   120  				keyspaceToString(tc.orig), tc.i, tc.j, got, tc.want)
   121  		}
   122  	}
   123  }
   124  
   125  func TestSuffix(t *testing.T) {
   126  	ks := Alpha(3)
   127  	require.Equal(t, "a@1", string(KeyAt(ks, 0, 1)))
   128  	require.Equal(t, "a@10", string(KeyAt(ks, 0, 10)))
   129  	require.Equal(t, "aab@5", string(KeyAt(ks, 3, 5)))
   130  
   131  	assertCmp := func(want int, a, b []byte) {
   132  		got := Comparer.Compare(a, b)
   133  		if got != want {
   134  			t.Helper()
   135  			t.Errorf("Compare(%q, %q) = %d, want %d", a, b, got, want)
   136  		}
   137  	}
   138  
   139  	for i := 1; i < ks.Count(); i++ {
   140  		assertCmp(-1, KeyAt(ks, i-1, 1), KeyAt(ks, i, 1))
   141  		assertCmp(-1, Key(ks, i-1), Key(ks, i))
   142  		assertCmp(0, Key(ks, i), Key(ks, i))
   143  		for ts := 2; ts < 11; ts++ {
   144  			assertCmp(+1, KeyAt(ks, i, ts-1), KeyAt(ks, i, ts))
   145  			assertCmp(-1, KeyAt(ks, i-1, ts-1), KeyAt(ks, i, ts))
   146  		}
   147  	}
   148  
   149  	// Suffixes should be comparable on their own too.
   150  	a, b := make([]byte, MaxSuffixLen), make([]byte, MaxSuffixLen)
   151  	for ts := 2; ts < 150; ts++ {
   152  		an := WriteSuffix(a, ts-1)
   153  		bn := WriteSuffix(b, ts)
   154  		assertCmp(+1, a[:an], b[:bn])
   155  	}
   156  }
   157  
   158  func TestSuffixLen(t *testing.T) {
   159  	testCases := map[int]int{
   160  		0:    2,
   161  		1:    2,
   162  		5:    2,
   163  		9:    2,
   164  		10:   3,
   165  		17:   3,
   166  		20:   3,
   167  		99:   3,
   168  		100:  4,
   169  		101:  4,
   170  		999:  4,
   171  		1000: 5,
   172  	}
   173  	for ts, want := range testCases {
   174  		if got := SuffixLen(ts); got != want {
   175  			t.Errorf("SuffixLen(%d) = %d, want %d", ts, got, want)
   176  		}
   177  	}
   178  }
   179  
   180  func TestDivvy(t *testing.T) {
   181  	var buf bytes.Buffer
   182  	datadriven.RunTest(t, "testdata/divvy", func(d *datadriven.TestData) string {
   183  		buf.Reset()
   184  		switch d.Cmd {
   185  		case "divvy":
   186  			var alphaLen, portions int
   187  			d.ScanArgs(t, "alpha", &alphaLen)
   188  			d.ScanArgs(t, "portions", &portions)
   189  
   190  			input := Alpha(alphaLen)
   191  			for _, ks := range Divvy(input, portions) {
   192  				fmt.Fprintln(&buf, keyspaceToString(ks))
   193  			}
   194  			return buf.String()
   195  		default:
   196  			return fmt.Sprintf("unrecognized command %q", d.Cmd)
   197  		}
   198  	})
   199  }
   200  
   201  func keyspaceToString(ks Keyspace) string {
   202  	var buf bytes.Buffer
   203  	b := make([]byte, ks.MaxLen())
   204  	for i := 0; i < ks.Count(); i++ {
   205  		n := ks.key(b, i)
   206  		if i > 0 {
   207  			buf.WriteRune(' ')
   208  		}
   209  		buf.Write(b[:n])
   210  	}
   211  	return buf.String()
   212  }