github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/sstable/properties_test.go (about)

     1  // Copyright 2018 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  	"math/rand"
     9  	"os"
    10  	"path/filepath"
    11  	"reflect"
    12  	"strings"
    13  	"testing"
    14  	"testing/quick"
    15  	"time"
    16  
    17  	"github.com/kr/pretty"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  func TestPropertiesLoad(t *testing.T) {
    22  	expected := Properties{
    23  		CommonProperties: CommonProperties{
    24  			NumEntries:        1727,
    25  			NumDeletions:      17,
    26  			NumRangeDeletions: 17,
    27  			RawKeySize:        23938,
    28  			RawValueSize:      1912,
    29  		},
    30  		ComparerName:           "leveldb.BytewiseComparator",
    31  		CompressionName:        "Snappy",
    32  		CompressionOptions:     "window_bits=-14; level=32767; strategy=0; max_dict_bytes=0; zstd_max_train_bytes=0; enabled=0; ",
    33  		DataSize:               13913,
    34  		ExternalFormatVersion:  2,
    35  		IndexSize:              325,
    36  		MergerName:             "nullptr",
    37  		NumDataBlocks:          14,
    38  		PrefixExtractorName:    "nullptr",
    39  		PropertyCollectorNames: "[KeyCountPropertyCollector]",
    40  		UserProperties: map[string]string{
    41  			"test.key-count": "1727",
    42  		},
    43  		WholeKeyFiltering: false,
    44  	}
    45  
    46  	{
    47  		// Check that we can read properties from a table.
    48  		f, err := os.Open(filepath.FromSlash("testdata/h.sst"))
    49  		require.NoError(t, err)
    50  
    51  		r, err := newReader(f, ReaderOptions{})
    52  
    53  		require.NoError(t, err)
    54  		defer r.Close()
    55  
    56  		r.Properties.Loaded = nil
    57  
    58  		if diff := pretty.Diff(expected, r.Properties); diff != nil {
    59  			t.Fatalf("%s", strings.Join(diff, "\n"))
    60  		}
    61  	}
    62  }
    63  
    64  var testProps = Properties{
    65  	CommonProperties: CommonProperties{
    66  		NumDeletions:      15,
    67  		NumEntries:        16,
    68  		NumRangeDeletions: 18,
    69  		NumRangeKeyDels:   19,
    70  		NumRangeKeySets:   20,
    71  		RawKeySize:        25,
    72  		RawValueSize:      26,
    73  	},
    74  	ComparerName:           "comparator name",
    75  	CompressionName:        "compression name",
    76  	CompressionOptions:     "compression option",
    77  	DataSize:               3,
    78  	ExternalFormatVersion:  4,
    79  	FilterPolicyName:       "filter policy name",
    80  	FilterSize:             5,
    81  	GlobalSeqNum:           8,
    82  	IndexPartitions:        10,
    83  	IndexSize:              11,
    84  	IndexType:              12,
    85  	IsStrictObsolete:       true,
    86  	MergerName:             "merge operator name",
    87  	NumDataBlocks:          14,
    88  	NumMergeOperands:       17,
    89  	NumRangeKeyUnsets:      21,
    90  	NumValueBlocks:         22,
    91  	NumValuesInValueBlocks: 23,
    92  	PrefixExtractorName:    "prefix extractor name",
    93  	PrefixFiltering:        true,
    94  	PropertyCollectorNames: "prefix collector names",
    95  	TopLevelIndexSize:      27,
    96  	WholeKeyFiltering:      true,
    97  	UserProperties: map[string]string{
    98  		"user-prop-a": "1",
    99  		"user-prop-b": "2",
   100  	},
   101  }
   102  
   103  func TestPropertiesSave(t *testing.T) {
   104  	expected := &Properties{}
   105  	*expected = testProps
   106  
   107  	check1 := func(expected *Properties) {
   108  		// Check that we can save properties and read them back.
   109  		var w rawBlockWriter
   110  		w.restartInterval = propertiesBlockRestartInterval
   111  		expected.save(TableFormatPebblev2, &w)
   112  		var props Properties
   113  
   114  		require.NoError(t, props.load(w.finish(), 0, make(map[string]struct{})))
   115  		props.Loaded = nil
   116  		if diff := pretty.Diff(*expected, props); diff != nil {
   117  			t.Fatalf("%s", strings.Join(diff, "\n"))
   118  		}
   119  	}
   120  
   121  	check1(expected)
   122  
   123  	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
   124  	for i := 0; i < 1000; i++ {
   125  		v, _ := quick.Value(reflect.TypeOf(Properties{}), rng)
   126  		props := v.Interface().(Properties)
   127  		if props.IndexPartitions == 0 {
   128  			props.TopLevelIndexSize = 0
   129  		}
   130  		check1(&props)
   131  	}
   132  }
   133  
   134  func BenchmarkPropertiesLoad(b *testing.B) {
   135  	var w rawBlockWriter
   136  	w.restartInterval = propertiesBlockRestartInterval
   137  	testProps.save(TableFormatPebblev2, &w)
   138  	block := w.finish()
   139  
   140  	b.ResetTimer()
   141  	p := &Properties{}
   142  	for i := 0; i < b.N; i++ {
   143  		*p = Properties{}
   144  		require.NoError(b, p.load(block, 0, nil))
   145  	}
   146  }