github.com/evdatsion/aphelion-dpos-bft@v0.32.1/libs/db/common_test.go (about) 1 package db 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "io/ioutil" 8 "sync" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 cmn "github.com/evdatsion/aphelion-dpos-bft/libs/common" 14 ) 15 16 //---------------------------------------- 17 // Helper functions. 18 19 func checkValue(t *testing.T, db DB, key []byte, valueWanted []byte) { 20 valueGot := db.Get(key) 21 assert.Equal(t, valueWanted, valueGot) 22 } 23 24 func checkValid(t *testing.T, itr Iterator, expected bool) { 25 valid := itr.Valid() 26 require.Equal(t, expected, valid) 27 } 28 29 func checkNext(t *testing.T, itr Iterator, expected bool) { 30 itr.Next() 31 valid := itr.Valid() 32 require.Equal(t, expected, valid) 33 } 34 35 func checkNextPanics(t *testing.T, itr Iterator) { 36 assert.Panics(t, func() { itr.Next() }, "checkNextPanics expected panic but didn't") 37 } 38 39 func checkDomain(t *testing.T, itr Iterator, start, end []byte) { 40 ds, de := itr.Domain() 41 assert.Equal(t, start, ds, "checkDomain domain start incorrect") 42 assert.Equal(t, end, de, "checkDomain domain end incorrect") 43 } 44 45 func checkItem(t *testing.T, itr Iterator, key []byte, value []byte) { 46 k, v := itr.Key(), itr.Value() 47 assert.Exactly(t, key, k) 48 assert.Exactly(t, value, v) 49 } 50 51 func checkInvalid(t *testing.T, itr Iterator) { 52 checkValid(t, itr, false) 53 checkKeyPanics(t, itr) 54 checkValuePanics(t, itr) 55 checkNextPanics(t, itr) 56 } 57 58 func checkKeyPanics(t *testing.T, itr Iterator) { 59 assert.Panics(t, func() { itr.Key() }, "checkKeyPanics expected panic but didn't") 60 } 61 62 func checkValuePanics(t *testing.T, itr Iterator) { 63 assert.Panics(t, func() { itr.Value() }, "checkValuePanics expected panic but didn't") 64 } 65 66 func newTempDB(t *testing.T, backend DBBackendType) (db DB, dbDir string) { 67 dirname, err := ioutil.TempDir("", "db_common_test") 68 require.Nil(t, err) 69 return NewDB("testdb", backend, dirname), dirname 70 } 71 72 //---------------------------------------- 73 // mockDB 74 75 // NOTE: not actually goroutine safe. 76 // If you want something goroutine safe, maybe you just want a MemDB. 77 type mockDB struct { 78 mtx sync.Mutex 79 calls map[string]int 80 } 81 82 func newMockDB() *mockDB { 83 return &mockDB{ 84 calls: make(map[string]int), 85 } 86 } 87 88 func (mdb *mockDB) Mutex() *sync.Mutex { 89 return &(mdb.mtx) 90 } 91 92 func (mdb *mockDB) Get([]byte) []byte { 93 mdb.calls["Get"]++ 94 return nil 95 } 96 97 func (mdb *mockDB) Has([]byte) bool { 98 mdb.calls["Has"]++ 99 return false 100 } 101 102 func (mdb *mockDB) Set([]byte, []byte) { 103 mdb.calls["Set"]++ 104 } 105 106 func (mdb *mockDB) SetSync([]byte, []byte) { 107 mdb.calls["SetSync"]++ 108 } 109 110 func (mdb *mockDB) SetNoLock([]byte, []byte) { 111 mdb.calls["SetNoLock"]++ 112 } 113 114 func (mdb *mockDB) SetNoLockSync([]byte, []byte) { 115 mdb.calls["SetNoLockSync"]++ 116 } 117 118 func (mdb *mockDB) Delete([]byte) { 119 mdb.calls["Delete"]++ 120 } 121 122 func (mdb *mockDB) DeleteSync([]byte) { 123 mdb.calls["DeleteSync"]++ 124 } 125 126 func (mdb *mockDB) DeleteNoLock([]byte) { 127 mdb.calls["DeleteNoLock"]++ 128 } 129 130 func (mdb *mockDB) DeleteNoLockSync([]byte) { 131 mdb.calls["DeleteNoLockSync"]++ 132 } 133 134 func (mdb *mockDB) Iterator(start, end []byte) Iterator { 135 mdb.calls["Iterator"]++ 136 return &mockIterator{} 137 } 138 139 func (mdb *mockDB) ReverseIterator(start, end []byte) Iterator { 140 mdb.calls["ReverseIterator"]++ 141 return &mockIterator{} 142 } 143 144 func (mdb *mockDB) Close() { 145 mdb.calls["Close"]++ 146 } 147 148 func (mdb *mockDB) NewBatch() Batch { 149 mdb.calls["NewBatch"]++ 150 return &memBatch{db: mdb} 151 } 152 153 func (mdb *mockDB) Print() { 154 mdb.calls["Print"]++ 155 fmt.Printf("mockDB{%v}", mdb.Stats()) 156 } 157 158 func (mdb *mockDB) Stats() map[string]string { 159 mdb.calls["Stats"]++ 160 161 res := make(map[string]string) 162 for key, count := range mdb.calls { 163 res[key] = fmt.Sprintf("%d", count) 164 } 165 return res 166 } 167 168 //---------------------------------------- 169 // mockIterator 170 171 type mockIterator struct{} 172 173 func (mockIterator) Domain() (start []byte, end []byte) { 174 return nil, nil 175 } 176 177 func (mockIterator) Valid() bool { 178 return false 179 } 180 181 func (mockIterator) Next() { 182 } 183 184 func (mockIterator) Key() []byte { 185 return nil 186 } 187 188 func (mockIterator) Value() []byte { 189 return nil 190 } 191 192 func (mockIterator) Close() { 193 } 194 195 func benchmarkRandomReadsWrites(b *testing.B, db DB) { 196 b.StopTimer() 197 198 // create dummy data 199 const numItems = int64(1000000) 200 internal := map[int64]int64{} 201 for i := 0; i < int(numItems); i++ { 202 internal[int64(i)] = int64(0) 203 } 204 205 // fmt.Println("ok, starting") 206 b.StartTimer() 207 208 for i := 0; i < b.N; i++ { 209 // Write something 210 { 211 idx := int64(cmn.RandInt()) % numItems 212 internal[idx]++ 213 val := internal[idx] 214 idxBytes := int642Bytes(int64(idx)) 215 valBytes := int642Bytes(int64(val)) 216 //fmt.Printf("Set %X -> %X\n", idxBytes, valBytes) 217 db.Set(idxBytes, valBytes) 218 } 219 220 // Read something 221 { 222 idx := int64(cmn.RandInt()) % numItems 223 valExp := internal[idx] 224 idxBytes := int642Bytes(int64(idx)) 225 valBytes := db.Get(idxBytes) 226 //fmt.Printf("Get %X -> %X\n", idxBytes, valBytes) 227 if valExp == 0 { 228 if !bytes.Equal(valBytes, nil) { 229 b.Errorf("Expected %v for %v, got %X", nil, idx, valBytes) 230 break 231 } 232 } else { 233 if len(valBytes) != 8 { 234 b.Errorf("Expected length 8 for %v, got %X", idx, valBytes) 235 break 236 } 237 valGot := bytes2Int64(valBytes) 238 if valExp != valGot { 239 b.Errorf("Expected %v for %v, got %v", valExp, idx, valGot) 240 break 241 } 242 } 243 } 244 245 } 246 } 247 248 func int642Bytes(i int64) []byte { 249 buf := make([]byte, 8) 250 binary.BigEndian.PutUint64(buf, uint64(i)) 251 return buf 252 } 253 254 func bytes2Int64(buf []byte) int64 { 255 return int64(binary.BigEndian.Uint64(buf)) 256 }