github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/base/lazy_value_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 base
     6  
     7  import (
     8  	"bytes"
     9  	"testing"
    10  	"unsafe"
    11  
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  type valueFetcherFunc func(
    16  	handle []byte, valLen int32, buf []byte) (val []byte, callerOwned bool, err error)
    17  
    18  func (v valueFetcherFunc) Fetch(
    19  	handle []byte, valLen int32, buf []byte,
    20  ) (val []byte, callerOwned bool, err error) {
    21  	return v(handle, valLen, buf)
    22  }
    23  
    24  func TestLazyValue(t *testing.T) {
    25  	// Both 40 and 48 bytes makes iteration benchmarks like
    26  	// BenchmarkIteratorScan/keys=1000,r-amp=1,key-types=points-only 75%
    27  	// slower.
    28  	require.True(t, unsafe.Sizeof(LazyValue{}) <= 32)
    29  
    30  	fooBytes1 := []byte("foo")
    31  	fooLV1 := MakeInPlaceValue(fooBytes1)
    32  	require.Equal(t, 3, fooLV1.Len())
    33  	_, hasAttr := fooLV1.TryGetShortAttribute()
    34  	require.False(t, hasAttr)
    35  	fooLV2, fooBytes2 := fooLV1.Clone(nil, &LazyFetcher{})
    36  	require.Equal(t, 3, fooLV2.Len())
    37  	_, hasAttr = fooLV2.TryGetShortAttribute()
    38  	require.False(t, hasAttr)
    39  	require.Equal(t, fooLV1.InPlaceValue(), fooLV2.InPlaceValue())
    40  	getValue := func(lv LazyValue, expectedCallerOwned bool) []byte {
    41  		v, callerOwned, err := lv.Value(nil)
    42  		require.NoError(t, err)
    43  		require.Equal(t, expectedCallerOwned, callerOwned)
    44  		return v
    45  	}
    46  	require.Equal(t, getValue(fooLV1, false), getValue(fooLV2, false))
    47  	fooBytes2[0] = 'b'
    48  	require.False(t, bytes.Equal(fooLV1.InPlaceValue(), fooLV2.InPlaceValue()))
    49  
    50  	for _, callerOwned := range []bool{false, true} {
    51  		numCalls := 0
    52  		fooLV3 := LazyValue{
    53  			ValueOrHandle: []byte("foo-handle"),
    54  			Fetcher: &LazyFetcher{
    55  				Fetcher: valueFetcherFunc(
    56  					func(handle []byte, valLen int32, buf []byte) ([]byte, bool, error) {
    57  						numCalls++
    58  						require.Equal(t, []byte("foo-handle"), handle)
    59  						require.Equal(t, int32(3), valLen)
    60  						return fooBytes1, callerOwned, nil
    61  					}),
    62  				Attribute: AttributeAndLen{ValueLen: 3, ShortAttribute: 7},
    63  			},
    64  		}
    65  		require.Equal(t, []byte("foo"), getValue(fooLV3, callerOwned))
    66  		require.Equal(t, 1, numCalls)
    67  		require.Equal(t, []byte("foo"), getValue(fooLV3, callerOwned))
    68  		require.Equal(t, 1, numCalls)
    69  		require.Equal(t, 3, fooLV3.Len())
    70  		attr, hasAttr := fooLV3.TryGetShortAttribute()
    71  		require.True(t, hasAttr)
    72  		require.Equal(t, ShortAttribute(7), attr)
    73  	}
    74  }