github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/util/leveldbhelper/leveldb_provider_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package leveldbhelper 8 9 import ( 10 "fmt" 11 "os" 12 "testing" 13 14 "github.com/hechain20/hechain/common/ledger/dataformat" 15 16 "github.com/hechain20/hechain/common/flogging" 17 "github.com/stretchr/testify/require" 18 ) 19 20 func TestMain(m *testing.M) { 21 flogging.ActivateSpec("leveldbhelper=debug") 22 os.Exit(m.Run()) 23 } 24 25 func TestDBBasicWriteAndReads(t *testing.T) { 26 testDBBasicWriteAndReads(t, "db1", "db2", "") 27 } 28 29 func TestIterator(t *testing.T) { 30 env := newTestProviderEnv(t, testDBPath) 31 defer env.cleanup() 32 p := env.provider 33 34 db1 := p.GetDBHandle("db1") 35 db2 := p.GetDBHandle("db2") 36 db3 := p.GetDBHandle("db3") 37 for i := 0; i < 20; i++ { 38 db1.Put([]byte(createTestKey(i)), []byte(createTestValue("db1", i)), false) 39 db2.Put([]byte(createTestKey(i)), []byte(createTestValue("db2", i)), false) 40 db3.Put([]byte(createTestKey(i)), []byte(createTestValue("db3", i)), false) 41 } 42 43 rangeTestCases := []struct { 44 startKey []byte 45 endKey []byte 46 expectedKeys []string 47 expectedValues []string 48 }{ 49 { 50 startKey: []byte(createTestKey(2)), 51 endKey: []byte(createTestKey(4)), 52 expectedKeys: createTestKeys(2, 3), 53 expectedValues: createTestValues("db2", 2, 3), 54 }, 55 { 56 startKey: []byte(createTestKey(2)), 57 endKey: nil, 58 expectedKeys: createTestKeys(2, 19), 59 expectedValues: createTestValues("db2", 2, 19), 60 }, 61 { 62 startKey: nil, 63 endKey: nil, 64 expectedKeys: createTestKeys(0, 19), 65 expectedValues: createTestValues("db2", 0, 19), 66 }, 67 } 68 69 for i, testCase := range rangeTestCases { 70 t.Run( 71 fmt.Sprintf("range testCase %d", i), 72 func(t *testing.T) { 73 itr, err := db2.GetIterator(testCase.startKey, testCase.endKey) 74 require.NoError(t, err) 75 defer itr.Release() 76 checkItrResults(t, itr, testCase.expectedKeys, testCase.expectedValues) 77 }, 78 ) 79 } 80 81 rangeWithSeekTestCases := []struct { 82 startKey []byte 83 endKey []byte 84 seekToKey []byte 85 itrAtKeyAfterSeek []byte 86 expectedKeys []string 87 expectedValues []string 88 }{ 89 { 90 startKey: nil, 91 endKey: nil, 92 seekToKey: []byte(createTestKey(10)), 93 itrAtKeyAfterSeek: []byte(createTestKey(10)), 94 expectedKeys: createTestKeys(11, 19), 95 expectedValues: createTestValues("db1", 11, 19), 96 }, 97 { 98 startKey: []byte(createTestKey(11)), 99 endKey: nil, 100 seekToKey: []byte(createTestKey(5)), 101 itrAtKeyAfterSeek: []byte(createTestKey(11)), 102 expectedKeys: createTestKeys(12, 19), 103 expectedValues: createTestValues("db1", 12, 19), 104 }, 105 { 106 startKey: nil, 107 endKey: nil, 108 seekToKey: []byte(createTestKey(19)), 109 itrAtKeyAfterSeek: []byte(createTestKey(19)), 110 expectedKeys: nil, 111 expectedValues: nil, 112 }, 113 } 114 115 for i, testCase := range rangeWithSeekTestCases { 116 t.Run( 117 fmt.Sprintf("range with seek testCase %d", i), 118 func(t *testing.T) { 119 itr, err := db1.GetIterator(testCase.startKey, testCase.endKey) 120 require.NoError(t, err) 121 defer itr.Release() 122 require.True(t, itr.Seek(testCase.seekToKey)) 123 require.Equal(t, testCase.itrAtKeyAfterSeek, itr.Key()) 124 checkItrResults(t, itr, testCase.expectedKeys, testCase.expectedValues) 125 }, 126 ) 127 } 128 129 t.Run("test-first-prev", func(t *testing.T) { 130 itr, err := db1.GetIterator(nil, nil) 131 require.NoError(t, err) 132 defer itr.Release() 133 require.True(t, itr.Seek([]byte(createTestKey(10)))) 134 require.Equal(t, []byte(createTestKey(10)), itr.Key()) 135 checkItrResults(t, itr, createTestKeys(11, 19), createTestValues("db1", 11, 19)) 136 137 require.True(t, itr.First()) 138 require.True(t, itr.Seek([]byte(createTestKey(10)))) 139 require.Equal(t, []byte(createTestKey(10)), itr.Key()) 140 require.True(t, itr.Prev()) 141 checkItrResults(t, itr, createTestKeys(10, 19), createTestValues("db1", 10, 19)) 142 143 require.True(t, itr.First()) 144 require.False(t, itr.Seek([]byte(createTestKey(20)))) 145 require.True(t, itr.First()) 146 checkItrResults(t, itr, createTestKeys(1, 19), createTestValues("db1", 1, 19)) 147 148 require.True(t, itr.First()) 149 require.False(t, itr.Prev()) 150 checkItrResults(t, itr, createTestKeys(0, 19), createTestValues("db1", 0, 19)) 151 152 require.True(t, itr.First()) 153 require.True(t, itr.Last()) 154 checkItrResults(t, itr, nil, nil) 155 }) 156 157 t.Run("test-error-path", func(t *testing.T) { 158 env.provider.Close() 159 itr, err := db1.GetIterator(nil, nil) 160 require.EqualError(t, err, "internal leveldb error while obtaining db iterator: leveldb: closed") 161 require.Nil(t, itr) 162 }) 163 } 164 165 func TestBatchedUpdates(t *testing.T) { 166 env := newTestProviderEnv(t, testDBPath) 167 defer env.cleanup() 168 p := env.provider 169 170 db1 := p.GetDBHandle("db1") 171 db2 := p.GetDBHandle("db2") 172 173 dbs := []*DBHandle{db1, db2} 174 for _, db := range dbs { 175 batch := db.NewUpdateBatch() 176 batch.Put([]byte("key1"), []byte("value1")) 177 batch.Put([]byte("key2"), []byte("value2")) 178 batch.Put([]byte("key3"), []byte("value3")) 179 db.WriteBatch(batch, true) 180 } 181 182 for _, db := range dbs { 183 batch := db.NewUpdateBatch() 184 batch.Delete([]byte("key2")) 185 db.WriteBatch(batch, true) 186 } 187 188 for _, db := range dbs { 189 val1, _ := db.Get([]byte("key1")) 190 require.Equal(t, "value1", string(val1)) 191 192 val2, err2 := db.Get([]byte("key2")) 193 require.NoError(t, err2, "") 194 require.Nil(t, val2) 195 196 val3, _ := db.Get([]byte("key3")) 197 require.Equal(t, "value3", string(val3)) 198 } 199 } 200 201 func TestDrop(t *testing.T) { 202 env := newTestProviderEnv(t, testDBPath) 203 defer env.cleanup() 204 p := env.provider 205 206 db1 := p.GetDBHandle("db1") 207 db2 := p.GetDBHandle("db2") 208 db3 := p.GetDBHandle("db3") 209 210 require.Contains(t, p.dbHandles, "db1") 211 require.Contains(t, p.dbHandles, "db2") 212 require.Contains(t, p.dbHandles, "db3") 213 214 for i := 0; i < 20; i++ { 215 db1.Put([]byte(createTestKey(i)), []byte(createTestValue("db1", i)), false) 216 db2.Put([]byte(createTestKey(i)), []byte(createTestValue("db2", i)), false) 217 } 218 // db3 is used to test remove when multiple batches are needed (each long key has 125 bytes) 219 for i := 0; i < 10000; i++ { 220 db3.Put([]byte(createTestLongKey(i)), []byte(createTestValue("db3", i)), false) 221 } 222 223 expectedSetup := []struct { 224 db *DBHandle 225 expectedKeys []string 226 expectedValues []string 227 }{ 228 { 229 db: db1, 230 expectedKeys: createTestKeys(0, 19), 231 expectedValues: createTestValues("db1", 0, 19), 232 }, 233 { 234 db: db2, 235 expectedKeys: createTestKeys(0, 19), 236 expectedValues: createTestValues("db2", 0, 19), 237 }, 238 { 239 db: db3, 240 expectedKeys: createTestLongKeys(0, 9999), 241 expectedValues: createTestValues("db3", 0, 9999), 242 }, 243 } 244 245 for _, dbSetup := range expectedSetup { 246 itr, err := dbSetup.db.GetIterator(nil, nil) 247 require.NoError(t, err) 248 checkItrResults(t, itr, dbSetup.expectedKeys, dbSetup.expectedValues) 249 itr.Release() 250 } 251 252 require.NoError(t, p.Drop("db1")) 253 require.NoError(t, p.Drop("db3")) 254 255 require.NotContains(t, p.dbHandles, "db1") 256 require.NotContains(t, p.dbHandles, "db3") 257 require.Contains(t, p.dbHandles, "db2") 258 259 expectedResults := []struct { 260 db *DBHandle 261 expectedKeys []string 262 expectedValues []string 263 }{ 264 { 265 db: db1, 266 expectedKeys: nil, 267 expectedValues: nil, 268 }, 269 { 270 db: db2, 271 expectedKeys: createTestKeys(0, 19), 272 expectedValues: createTestValues("db2", 0, 19), 273 }, 274 { 275 db: db3, 276 expectedKeys: nil, 277 expectedValues: nil, 278 }, 279 } 280 281 for _, result := range expectedResults { 282 itr, err := result.db.GetIterator(nil, nil) 283 require.NoError(t, err) 284 checkItrResults(t, itr, result.expectedKeys, result.expectedValues) 285 itr.Release() 286 } 287 288 // negative test 289 p.Close() 290 require.EqualError(t, db2.deleteAll(), "internal leveldb error while obtaining db iterator: leveldb: closed") 291 } 292 293 func TestFormatCheck(t *testing.T) { 294 testCases := []struct { 295 dataFormat string 296 dataExists bool 297 expectedFormat string 298 expectedErr *dataformat.ErrFormatMismatch 299 }{ 300 { 301 dataFormat: "", 302 dataExists: true, 303 expectedFormat: "", 304 expectedErr: nil, 305 }, 306 { 307 dataFormat: "", 308 dataExists: false, 309 expectedFormat: "", 310 expectedErr: nil, 311 }, 312 { 313 dataFormat: "", 314 dataExists: false, 315 expectedFormat: "2.0", 316 expectedErr: nil, 317 }, 318 { 319 dataFormat: "", 320 dataExists: true, 321 expectedFormat: "2.0", 322 expectedErr: &dataformat.ErrFormatMismatch{Format: "", ExpectedFormat: "2.0"}, 323 }, 324 { 325 dataFormat: "2.0", 326 dataExists: true, 327 expectedFormat: "2.0", 328 expectedErr: nil, 329 }, 330 { 331 dataFormat: "2.0", 332 dataExists: true, 333 expectedFormat: "3.0", 334 expectedErr: &dataformat.ErrFormatMismatch{Format: "2.0", ExpectedFormat: "3.0"}, 335 }, 336 } 337 338 for i, testCase := range testCases { 339 t.Run( 340 fmt.Sprintf("testCase %d", i), 341 func(t *testing.T) { 342 testFormatCheck(t, testCase.dataFormat, testCase.expectedFormat, testCase.dataExists, testCase.expectedErr) 343 }) 344 } 345 } 346 347 func TestClose(t *testing.T) { 348 env := newTestProviderEnv(t, testDBPath) 349 defer env.cleanup() 350 p := env.provider 351 352 db1 := p.GetDBHandle("db1") 353 db2 := p.GetDBHandle("db2") 354 355 expectedDBHandles := map[string]*DBHandle{ 356 "db1": db1, 357 "db2": db2, 358 } 359 require.Equal(t, expectedDBHandles, p.dbHandles) 360 361 db1.Close() 362 expectedDBHandles = map[string]*DBHandle{ 363 "db2": db2, 364 } 365 require.Equal(t, expectedDBHandles, p.dbHandles) 366 367 db2.Close() 368 require.Equal(t, map[string]*DBHandle{}, p.dbHandles) 369 } 370 371 func TestIsEmpty(t *testing.T) { 372 var env *testDBProviderEnv 373 var db1, db2 *DBHandle 374 375 setup := func() { 376 env = newTestProviderEnv(t, testDBPath) 377 p := env.provider 378 db1 = p.GetDBHandle("db1") 379 db2 = p.GetDBHandle("db2") 380 } 381 382 cleanup := func() { 383 env.cleanup() 384 } 385 386 t.Run("both the dbs are empty", func(t *testing.T) { 387 setup() 388 defer cleanup() 389 390 empty, err := db1.IsEmpty() 391 require.NoError(t, err) 392 require.True(t, empty) 393 394 empty, err = db2.IsEmpty() 395 require.NoError(t, err) 396 require.True(t, empty) 397 }) 398 399 t.Run("only one db is empty", func(t *testing.T) { 400 setup() 401 defer cleanup() 402 403 db1.Put([]byte("key"), []byte("value"), false) 404 empty, err := db1.IsEmpty() 405 require.NoError(t, err) 406 require.False(t, empty) 407 408 empty, err = db2.IsEmpty() 409 require.NoError(t, err) 410 require.True(t, empty) 411 }) 412 413 t.Run("both the dbs contain data", func(t *testing.T) { 414 setup() 415 defer cleanup() 416 417 db1.Put([]byte("key"), []byte("value"), false) 418 db2.Put([]byte("key"), []byte("value"), false) 419 420 empty, err := db1.IsEmpty() 421 require.NoError(t, err) 422 require.False(t, empty) 423 424 empty, err = db2.IsEmpty() 425 require.NoError(t, err) 426 require.False(t, empty) 427 }) 428 429 t.Run("iter error", func(t *testing.T) { 430 setup() 431 defer cleanup() 432 433 env.provider.Close() 434 empty, err := db1.IsEmpty() 435 require.EqualError(t, err, "internal leveldb error while obtaining db iterator: leveldb: closed") 436 require.False(t, empty) 437 438 empty, err = db2.IsEmpty() 439 require.EqualError(t, err, "internal leveldb error while obtaining db iterator: leveldb: closed") 440 require.False(t, empty) 441 }) 442 } 443 444 func testFormatCheck(t *testing.T, dataFormat, expectedFormat string, dataExists bool, expectedErr *dataformat.ErrFormatMismatch) { 445 require.NoError(t, os.RemoveAll(testDBPath)) 446 defer func() { 447 require.NoError(t, os.RemoveAll(testDBPath)) 448 }() 449 450 // setup test pre-conditions (create a db with dbformat) 451 p, err := NewProvider(&Conf{DBPath: testDBPath, ExpectedFormat: dataFormat}) 452 require.NoError(t, err) 453 f, err := p.GetDataFormat() 454 require.NoError(t, err) 455 require.Equal(t, dataFormat, f) 456 if dataExists { 457 require.NoError(t, p.GetDBHandle("testdb").Put([]byte("key"), []byte("value"), true)) 458 } 459 460 // close and reopen with new conf 461 p.Close() 462 p, err = NewProvider(&Conf{DBPath: testDBPath, ExpectedFormat: expectedFormat}) 463 if expectedErr != nil { 464 expectedErr.DBInfo = fmt.Sprintf("leveldb at [%s]", testDBPath) 465 require.Equal(t, err, expectedErr) 466 return 467 } 468 require.NoError(t, err) 469 f, err = p.GetDataFormat() 470 require.NoError(t, err) 471 require.Equal(t, expectedFormat, f) 472 } 473 474 func testDBBasicWriteAndReads(t *testing.T, dbNames ...string) { 475 env := newTestProviderEnv(t, testDBPath) 476 defer env.cleanup() 477 p := env.provider 478 479 for _, dbName := range dbNames { 480 db := p.GetDBHandle(dbName) 481 db.Put([]byte("key1"), []byte("value1_"+dbName), false) 482 db.Put([]byte("key2"), []byte("value2_"+dbName), false) 483 db.Put([]byte("key3"), []byte("value3_"+dbName), false) 484 } 485 486 for _, dbName := range dbNames { 487 db := p.GetDBHandle(dbName) 488 val, err := db.Get([]byte("key1")) 489 require.NoError(t, err, "") 490 require.Equal(t, []byte("value1_"+dbName), val) 491 492 val, err = db.Get([]byte("key2")) 493 require.NoError(t, err, "") 494 require.Equal(t, []byte("value2_"+dbName), val) 495 496 val, err = db.Get([]byte("key3")) 497 require.NoError(t, err, "") 498 require.Equal(t, []byte("value3_"+dbName), val) 499 } 500 501 for _, dbName := range dbNames { 502 db := p.GetDBHandle(dbName) 503 require.NoError(t, db.Delete([]byte("key1"), false), "") 504 val, err := db.Get([]byte("key1")) 505 require.NoError(t, err, "") 506 require.Nil(t, val) 507 508 require.NoError(t, db.Delete([]byte("key2"), false), "") 509 val, err = db.Get([]byte("key2")) 510 require.NoError(t, err, "") 511 require.Nil(t, val) 512 513 require.NoError(t, db.Delete([]byte("key3"), false), "") 514 val, err = db.Get([]byte("key3")) 515 require.NoError(t, err, "") 516 require.Nil(t, val) 517 } 518 } 519 520 func checkItrResults(t *testing.T, itr *Iterator, expectedKeys []string, expectedValues []string) { 521 var actualKeys []string 522 var actualValues []string 523 for itr.Next(); itr.Valid(); itr.Next() { 524 actualKeys = append(actualKeys, string(itr.Key())) 525 actualValues = append(actualValues, string(itr.Value())) 526 } 527 require.Equal(t, expectedKeys, actualKeys) 528 require.Equal(t, expectedValues, actualValues) 529 require.Equal(t, false, itr.Next()) 530 } 531 532 func createTestKey(i int) string { 533 return fmt.Sprintf("key_%06d", i) 534 } 535 536 const padding100 = "_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_" 537 538 func createTestLongKey(i int) string { 539 return fmt.Sprintf("key_%s_%10d", padding100, i) 540 } 541 542 func createTestValue(dbname string, i int) string { 543 return fmt.Sprintf("value_%s_%06d", dbname, i) 544 } 545 546 func createTestKeys(start int, end int) []string { 547 var keys []string 548 for i := start; i <= end; i++ { 549 keys = append(keys, createTestKey(i)) 550 } 551 return keys 552 } 553 554 func createTestLongKeys(start int, end int) []string { 555 var keys []string 556 for i := start; i <= end; i++ { 557 keys = append(keys, createTestLongKey(i)) 558 } 559 return keys 560 } 561 562 func createTestValues(dbname string, start int, end int) []string { 563 var values []string 564 for i := start; i <= end; i++ { 565 values = append(values, createTestValue(dbname, i)) 566 } 567 return values 568 }