github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/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 func TestPropertiesSave(t *testing.T) { 65 expected := &Properties{ 66 CommonProperties: CommonProperties{ 67 NumDeletions: 15, 68 NumEntries: 16, 69 NumRangeDeletions: 18, 70 NumRangeKeyDels: 19, 71 NumRangeKeySets: 20, 72 RawKeySize: 25, 73 RawValueSize: 26, 74 }, 75 ComparerName: "comparator name", 76 CompressionName: "compression name", 77 CompressionOptions: "compression option", 78 DataSize: 3, 79 ExternalFormatVersion: 4, 80 FilterPolicyName: "filter policy name", 81 FilterSize: 5, 82 GlobalSeqNum: 8, 83 IndexPartitions: 10, 84 IndexSize: 11, 85 IndexType: 12, 86 IsStrictObsolete: true, 87 MergerName: "merge operator name", 88 NumDataBlocks: 14, 89 NumMergeOperands: 17, 90 NumRangeKeyUnsets: 21, 91 NumValueBlocks: 22, 92 NumValuesInValueBlocks: 23, 93 PrefixExtractorName: "prefix extractor name", 94 PrefixFiltering: true, 95 PropertyCollectorNames: "prefix collector names", 96 TopLevelIndexSize: 27, 97 WholeKeyFiltering: true, 98 UserProperties: map[string]string{ 99 "user-prop-a": "1", 100 "user-prop-b": "2", 101 }, 102 } 103 104 check1 := func(expected *Properties) { 105 // Check that we can save properties and read them back. 106 var w rawBlockWriter 107 w.restartInterval = propertiesBlockRestartInterval 108 expected.save(TableFormatPebblev2, &w) 109 var props Properties 110 111 require.NoError(t, props.load(w.finish(), 0, make(map[string]struct{}))) 112 props.Loaded = nil 113 if diff := pretty.Diff(*expected, props); diff != nil { 114 t.Fatalf("%s", strings.Join(diff, "\n")) 115 } 116 } 117 118 check1(expected) 119 120 rng := rand.New(rand.NewSource(time.Now().UnixNano())) 121 for i := 0; i < 1000; i++ { 122 v, _ := quick.Value(reflect.TypeOf(Properties{}), rng) 123 props := v.Interface().(Properties) 124 if props.IndexPartitions == 0 { 125 props.TopLevelIndexSize = 0 126 } 127 check1(&props) 128 } 129 }