github.com/ledgerwatch/erigon-lib@v1.0.0/recsplit/recsplit_test.go (about) 1 /* 2 Copyright 2021 Erigon contributors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package recsplit 18 19 import ( 20 "context" 21 "fmt" 22 "path/filepath" 23 "testing" 24 25 "github.com/ledgerwatch/log/v3" 26 ) 27 28 func TestRecSplit2(t *testing.T) { 29 logger := log.New() 30 tmpDir := t.TempDir() 31 rs, err := NewRecSplit(RecSplitArgs{ 32 KeyCount: 2, 33 BucketSize: 10, 34 Salt: 0, 35 TmpDir: tmpDir, 36 IndexFile: filepath.Join(tmpDir, "index"), 37 LeafSize: 8, 38 }, logger) 39 if err != nil { 40 t.Fatal(err) 41 } 42 if err = rs.AddKey([]byte("first_key"), 0); err != nil { 43 t.Error(err) 44 } 45 if err = rs.Build(context.Background()); err == nil { 46 t.Errorf("test is expected to fail, too few keys added") 47 } 48 if err = rs.AddKey([]byte("second_key"), 0); err != nil { 49 t.Error(err) 50 } 51 if err = rs.Build(context.Background()); err != nil { 52 t.Error(err) 53 } 54 if err = rs.Build(context.Background()); err == nil { 55 t.Errorf("test is expected to fail, hash gunction was built already") 56 } 57 if err = rs.AddKey([]byte("key_to_fail"), 0); err == nil { 58 t.Errorf("test is expected to fail, hash function was built") 59 } 60 } 61 62 func TestRecSplitDuplicate(t *testing.T) { 63 logger := log.New() 64 tmpDir := t.TempDir() 65 rs, err := NewRecSplit(RecSplitArgs{ 66 KeyCount: 2, 67 BucketSize: 10, 68 Salt: 0, 69 TmpDir: tmpDir, 70 IndexFile: filepath.Join(tmpDir, "index"), 71 LeafSize: 8, 72 }, logger) 73 if err != nil { 74 t.Fatal(err) 75 } 76 if err := rs.AddKey([]byte("first_key"), 0); err != nil { 77 t.Error(err) 78 } 79 if err := rs.AddKey([]byte("first_key"), 0); err != nil { 80 t.Error(err) 81 } 82 if err := rs.Build(context.Background()); err == nil { 83 t.Errorf("test is expected to fail, duplicate key") 84 } 85 } 86 87 func TestRecSplitLeafSizeTooLarge(t *testing.T) { 88 logger := log.New() 89 tmpDir := t.TempDir() 90 _, err := NewRecSplit(RecSplitArgs{ 91 KeyCount: 2, 92 BucketSize: 10, 93 Salt: 0, 94 TmpDir: tmpDir, 95 IndexFile: filepath.Join(tmpDir, "index"), 96 LeafSize: 64, 97 }, logger) 98 if err == nil { 99 t.Errorf("test is expected to fail, leaf size too large") 100 } 101 } 102 103 func TestIndexLookup(t *testing.T) { 104 logger := log.New() 105 tmpDir := t.TempDir() 106 indexFile := filepath.Join(tmpDir, "index") 107 rs, err := NewRecSplit(RecSplitArgs{ 108 KeyCount: 100, 109 BucketSize: 10, 110 Salt: 0, 111 TmpDir: tmpDir, 112 IndexFile: indexFile, 113 LeafSize: 8, 114 }, logger) 115 if err != nil { 116 t.Fatal(err) 117 } 118 for i := 0; i < 100; i++ { 119 if err = rs.AddKey([]byte(fmt.Sprintf("key %d", i)), uint64(i*17)); err != nil { 120 t.Fatal(err) 121 } 122 } 123 if err := rs.Build(context.Background()); err != nil { 124 t.Fatal(err) 125 } 126 idx := MustOpen(indexFile) 127 defer idx.Close() 128 for i := 0; i < 100; i++ { 129 reader := NewIndexReader(idx) 130 offset := reader.Lookup([]byte(fmt.Sprintf("key %d", i))) 131 if offset != uint64(i*17) { 132 t.Errorf("expected offset: %d, looked up: %d", i*17, offset) 133 } 134 } 135 } 136 137 func TestTwoLayerIndex(t *testing.T) { 138 logger := log.New() 139 tmpDir := t.TempDir() 140 indexFile := filepath.Join(tmpDir, "index") 141 rs, err := NewRecSplit(RecSplitArgs{ 142 KeyCount: 100, 143 BucketSize: 10, 144 Salt: 0, 145 TmpDir: tmpDir, 146 IndexFile: indexFile, 147 LeafSize: 8, 148 Enums: true, 149 }, logger) 150 if err != nil { 151 t.Fatal(err) 152 } 153 for i := 0; i < 100; i++ { 154 if err = rs.AddKey([]byte(fmt.Sprintf("key %d", i)), uint64(i*17)); err != nil { 155 t.Fatal(err) 156 } 157 } 158 if err := rs.Build(context.Background()); err != nil { 159 t.Fatal(err) 160 } 161 162 idx := MustOpen(indexFile) 163 defer idx.Close() 164 for i := 0; i < 100; i++ { 165 reader := NewIndexReader(idx) 166 e := reader.Lookup([]byte(fmt.Sprintf("key %d", i))) 167 if e != uint64(i) { 168 t.Errorf("expected enumeration: %d, lookup up: %d", i, e) 169 } 170 offset := idx.OrdinalLookup(e) 171 if offset != uint64(i*17) { 172 t.Errorf("expected offset: %d, looked up: %d", i*17, offset) 173 } 174 } 175 }