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 }