// Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use // of this source code is governed by a BSD-style license that can be found in // the LICENSE file. package sstable import ( "math/rand" "os" "path/filepath" "reflect" "strings" "testing" "testing/quick" "time" "github.com/kr/pretty" "github.com/stretchr/testify/require" ) func TestPropertiesLoad(t *testing.T) { expected := Properties{ CommonProperties: CommonProperties{ NumEntries: 1727, NumDeletions: 17, NumRangeDeletions: 17, RawKeySize: 23938, RawValueSize: 1912, }, ComparerName: "leveldb.BytewiseComparator", CompressionName: "Snappy", CompressionOptions: "window_bits=-14; level=32767; strategy=0; max_dict_bytes=0; zstd_max_train_bytes=0; enabled=0; ", DataSize: 13913, ExternalFormatVersion: 2, IndexSize: 325, MergerName: "nullptr", NumDataBlocks: 14, PrefixExtractorName: "nullptr", PropertyCollectorNames: "[KeyCountPropertyCollector]", UserProperties: map[string]string{ "test.key-count": "1727", }, WholeKeyFiltering: false, } { // Check that we can read properties from a table. f, err := os.Open(filepath.FromSlash("testdata/h.sst")) require.NoError(t, err) r, err := newReader(f, ReaderOptions{}) require.NoError(t, err) defer r.Close() r.Properties.Loaded = nil if diff := pretty.Diff(expected, r.Properties); diff != nil { t.Fatalf("%s", strings.Join(diff, "\n")) } } } var testProps = Properties{ CommonProperties: CommonProperties{ NumDeletions: 15, NumEntries: 16, NumRangeDeletions: 18, NumRangeKeyDels: 19, NumRangeKeySets: 20, RawKeySize: 25, RawValueSize: 26, }, ComparerName: "comparator name", CompressionName: "compression name", CompressionOptions: "compression option", DataSize: 3, ExternalFormatVersion: 4, FilterPolicyName: "filter policy name", FilterSize: 5, GlobalSeqNum: 8, IndexPartitions: 10, IndexSize: 11, IndexType: 12, IsStrictObsolete: true, MergerName: "merge operator name", NumDataBlocks: 14, NumMergeOperands: 17, NumRangeKeyUnsets: 21, NumValueBlocks: 22, NumValuesInValueBlocks: 23, PrefixExtractorName: "prefix extractor name", PrefixFiltering: true, PropertyCollectorNames: "prefix collector names", TopLevelIndexSize: 27, WholeKeyFiltering: true, UserProperties: map[string]string{ "user-prop-a": "1", "user-prop-b": "2", }, } func TestPropertiesSave(t *testing.T) { expected := &Properties{} *expected = testProps check1 := func(expected *Properties) { // Check that we can save properties and read them back. var w rawBlockWriter w.restartInterval = propertiesBlockRestartInterval expected.save(TableFormatPebblev2, &w) var props Properties require.NoError(t, props.load(w.finish(), 0, make(map[string]struct{}))) props.Loaded = nil if diff := pretty.Diff(*expected, props); diff != nil { t.Fatalf("%s", strings.Join(diff, "\n")) } } check1(expected) rng := rand.New(rand.NewSource(time.Now().UnixNano())) for i := 0; i < 1000; i++ { v, _ := quick.Value(reflect.TypeOf(Properties{}), rng) props := v.Interface().(Properties) if props.IndexPartitions == 0 { props.TopLevelIndexSize = 0 } check1(&props) } } func BenchmarkPropertiesLoad(b *testing.B) { var w rawBlockWriter w.restartInterval = propertiesBlockRestartInterval testProps.save(TableFormatPebblev2, &w) block := w.finish() b.ResetTimer() p := &Properties{} for i := 0; i < b.N; i++ { *p = Properties{} require.NoError(b, p.load(block, 0, nil)) } }