github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/sstable/value_block_test.go (about)

     1  // Copyright 2022 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 sstable
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"math/rand"
    11  	"testing"
    12  
    13  	"github.com/cockroachdb/pebble/internal/base"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestValueHandleEncodeDecode(t *testing.T) {
    18  	testCases := []valueHandle{
    19  		{valueLen: 23, blockNum: 100003, offsetInBlock: 2300},
    20  		{valueLen: math.MaxUint32 - 1, blockNum: math.MaxUint32 / 2, offsetInBlock: math.MaxUint32 - 2},
    21  	}
    22  	var buf [valueHandleMaxLen]byte
    23  	for _, tc := range testCases {
    24  		t.Run(fmt.Sprintf("%+v", tc), func(t *testing.T) {
    25  			n := encodeValueHandle(buf[:], tc)
    26  			vh := decodeValueHandle(buf[:n])
    27  			require.Equal(t, tc, vh)
    28  		})
    29  	}
    30  }
    31  
    32  func TestValuePrefix(t *testing.T) {
    33  	testCases := []struct {
    34  		isHandle         bool
    35  		setHasSamePrefix bool
    36  		attr             base.ShortAttribute
    37  	}{
    38  		{
    39  			isHandle:         false,
    40  			setHasSamePrefix: false,
    41  		},
    42  		{
    43  			isHandle:         false,
    44  			setHasSamePrefix: true,
    45  		},
    46  		{
    47  			isHandle:         true,
    48  			setHasSamePrefix: false,
    49  			attr:             5,
    50  		},
    51  		{
    52  			isHandle:         true,
    53  			setHasSamePrefix: true,
    54  			attr:             2,
    55  		},
    56  	}
    57  	for _, tc := range testCases {
    58  		t.Run(fmt.Sprintf("%+v", tc), func(t *testing.T) {
    59  			var prefix valuePrefix
    60  			if tc.isHandle {
    61  				prefix = makePrefixForValueHandle(tc.setHasSamePrefix, tc.attr)
    62  			} else {
    63  				prefix = makePrefixForInPlaceValue(tc.setHasSamePrefix)
    64  			}
    65  			require.Equal(t, tc.isHandle, isValueHandle(prefix))
    66  			require.Equal(t, tc.setHasSamePrefix, setHasSamePrefix(prefix))
    67  			if tc.isHandle {
    68  				require.Equal(t, tc.attr, getShortAttribute(prefix))
    69  			}
    70  		})
    71  	}
    72  }
    73  
    74  func TestValueBlocksIndexHandleEncodeDecode(t *testing.T) {
    75  	testCases := []valueBlocksIndexHandle{
    76  		{
    77  			h: BlockHandle{
    78  				Offset: math.MaxUint64 / 2,
    79  				Length: math.MaxUint64 / 4,
    80  			},
    81  			blockNumByteLength:    53,
    82  			blockOffsetByteLength: math.MaxUint8,
    83  			blockLengthByteLength: math.MaxUint8 / 2,
    84  		},
    85  	}
    86  	var buf [valueBlocksIndexHandleMaxLen]byte
    87  	for _, tc := range testCases {
    88  		t.Run(fmt.Sprintf("%+v", tc), func(t *testing.T) {
    89  			n := encodeValueBlocksIndexHandle(buf[:], tc)
    90  			vbih, n2, err := decodeValueBlocksIndexHandle(buf[:n])
    91  			require.NoError(t, err)
    92  			require.Equal(t, n, n2)
    93  			require.Equal(t, tc, vbih)
    94  		})
    95  	}
    96  }
    97  
    98  func TestLittleEndianGetPut(t *testing.T) {
    99  	testCases := []uint64{
   100  		0, (1 << 10) - 1, (1 << 25) + 1, math.MaxUint32, math.MaxUint64, uint64(rand.Int63())}
   101  	var buf [8]byte
   102  	for _, tc := range testCases {
   103  		t.Run(fmt.Sprintf("%d", tc), func(t *testing.T) {
   104  			length := lenLittleEndian(tc)
   105  			b := buf[:length:length]
   106  			littleEndianPut(tc, b, length)
   107  			v := littleEndianGet(b, length)
   108  			require.Equal(t, tc, v)
   109  		})
   110  	}
   111  }