mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
tests
This commit is contained in:
parent
82646e8be0
commit
f864c209ca
410
node/store/mdbx_test.go
Normal file
410
node/store/mdbx_test.go
Normal file
@ -0,0 +1,410 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/cockroachdb/pebble"
|
||||
"source.quilibrium.com/quilibrium/monorepo/node/config"
|
||||
)
|
||||
|
||||
func TestMDBXDB(t *testing.T) {
|
||||
// Create temporary directory
|
||||
tempDir, err := os.MkdirTemp("", "mdbx-test-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
// Create DB config
|
||||
dbConfig := &config.DBConfig{
|
||||
Path: tempDir,
|
||||
}
|
||||
|
||||
// Create DB instance
|
||||
db := NewMDBXDB(dbConfig)
|
||||
defer db.Close()
|
||||
|
||||
// Test basic operations
|
||||
t.Run("BasicOperations", func(t *testing.T) {
|
||||
// Test Set and Get
|
||||
key := []byte("test-key")
|
||||
value := []byte("test-value")
|
||||
|
||||
if err := db.Set(key, value); err != nil {
|
||||
t.Fatalf("Failed to set value: %v", err)
|
||||
}
|
||||
|
||||
result, closer, err := db.Get(key)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get value: %v", err)
|
||||
}
|
||||
defer closer.Close()
|
||||
|
||||
if !bytes.Equal(result, value) {
|
||||
t.Errorf("Expected %v, got %v", value, result)
|
||||
}
|
||||
|
||||
// Test Delete
|
||||
if err := db.Delete(key); err != nil {
|
||||
t.Fatalf("Failed to delete key: %v", err)
|
||||
}
|
||||
|
||||
_, _, err = db.Get(key)
|
||||
if err == nil {
|
||||
t.Errorf("Expected error for deleted key")
|
||||
}
|
||||
})
|
||||
|
||||
// Test transactions
|
||||
t.Run("Transactions", func(t *testing.T) {
|
||||
// Create a non-indexed transaction
|
||||
tx := db.NewTransaction()
|
||||
|
||||
// Set some values in the transaction
|
||||
key1 := []byte("tx-key-1")
|
||||
value1 := []byte("tx-value-1")
|
||||
key2 := []byte("tx-key-2")
|
||||
value2 := []byte("tx-value-2")
|
||||
|
||||
if err := tx.Set(key1, value1); err != nil {
|
||||
t.Fatalf("Failed to set value in transaction: %v", err)
|
||||
}
|
||||
if err := tx.Set(key2, value2); err != nil {
|
||||
t.Fatalf("Failed to set value in transaction: %v", err)
|
||||
}
|
||||
|
||||
// Values should not be visible outside the transaction yet
|
||||
_, _, err := db.Get(key1)
|
||||
if err == nil {
|
||||
t.Errorf("Key should not be visible outside transaction before commit")
|
||||
}
|
||||
|
||||
// Values should be visible inside the transaction
|
||||
result, closer, err := tx.Get(key1)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get value from transaction: %v", err)
|
||||
}
|
||||
defer closer.Close()
|
||||
if !bytes.Equal(result, value1) {
|
||||
t.Errorf("Expected %v, got %v", value1, result)
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
if err := tx.Commit(); err != nil {
|
||||
t.Fatalf("Failed to commit transaction: %v", err)
|
||||
}
|
||||
|
||||
// Values should now be visible outside the transaction
|
||||
result, closer, err = db.Get(key1)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get value after commit: %v", err)
|
||||
}
|
||||
defer closer.Close()
|
||||
if !bytes.Equal(result, value1) {
|
||||
t.Errorf("Expected %v, got %v", value1, result)
|
||||
}
|
||||
|
||||
// Test transaction abort
|
||||
tx = db.NewBatch(false)
|
||||
abortKey := []byte("abort-key")
|
||||
abortValue := []byte("abort-value")
|
||||
|
||||
if err := tx.Set(abortKey, abortValue); err != nil {
|
||||
t.Fatalf("Failed to set value in transaction: %v", err)
|
||||
}
|
||||
|
||||
if err := tx.Abort(); err != nil {
|
||||
t.Fatalf("Failed to abort transaction: %v", err)
|
||||
}
|
||||
|
||||
// Value should not be visible after abort
|
||||
_, _, err = db.Get(abortKey)
|
||||
if err == nil {
|
||||
t.Errorf("Key should not be visible after transaction abort")
|
||||
}
|
||||
|
||||
// Test transaction DeleteRange
|
||||
tx = db.NewTransaction()
|
||||
|
||||
// Set up some keys for the range delete
|
||||
for i := 1; i <= 5; i++ {
|
||||
key := []byte(filepath.Join("tx-range", "key", "prefix", "key-"+string(rune('0'+i))))
|
||||
value := []byte("tx-value-" + string(rune('0'+i)))
|
||||
if err := tx.Set(key, value); err != nil {
|
||||
t.Fatalf("Failed to set value in transaction: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete a range within the transaction
|
||||
startKey := []byte(filepath.Join("tx-range", "key", "prefix", "key-2"))
|
||||
endKey := []byte(filepath.Join("tx-range", "key", "prefix", "key-4"))
|
||||
fmt.Println("---")
|
||||
if err := tx.DeleteRange(startKey, endKey); err != nil {
|
||||
t.Fatalf("Failed to delete range in transaction: %v", err)
|
||||
}
|
||||
fmt.Println("---")
|
||||
|
||||
// Check that keys in the range are deleted within the transaction
|
||||
for i := 2; i < 4; i++ {
|
||||
key := []byte(filepath.Join("tx-range", "key", "prefix", "key-"+string(rune('0'+i))))
|
||||
_, _, err := tx.Get(key)
|
||||
if err == nil {
|
||||
t.Errorf("Key %s should be deleted in transaction", key)
|
||||
}
|
||||
}
|
||||
|
||||
// Check that keys outside the range still exist within the transaction
|
||||
txKey1 := []byte(filepath.Join("tx-range", "key", "prefix", "key-1"))
|
||||
txResult, txCloser, txErr := tx.Get(txKey1)
|
||||
if txErr != nil {
|
||||
t.Errorf("Key %s should still exist in transaction: %v", txKey1, txErr)
|
||||
} else {
|
||||
defer txCloser.Close()
|
||||
if !bytes.Equal(txResult, []byte("tx-value-1")) {
|
||||
t.Errorf("Expected %v, got %v", []byte("tx-value-1"), txResult)
|
||||
}
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
if err := tx.Commit(); err != nil {
|
||||
t.Fatalf("Failed to commit transaction: %v", err)
|
||||
}
|
||||
|
||||
// Verify the changes are visible outside the transaction
|
||||
for i := 2; i < 4; i++ {
|
||||
key := []byte(filepath.Join("tx-range", "key", "prefix", "key-"+string(rune('0'+i))))
|
||||
_, _, err := db.Get(key)
|
||||
if err == nil {
|
||||
t.Errorf("Key %s should be deleted after commit", key)
|
||||
}
|
||||
}
|
||||
|
||||
txKey5 := []byte(filepath.Join("tx-range", "key", "prefix", "key-5"))
|
||||
txResult2, txCloser2, txErr2 := db.Get(txKey5)
|
||||
if txErr2 != nil {
|
||||
t.Errorf("Key %s should still exist after commit: %v", txKey5, txErr2)
|
||||
} else {
|
||||
defer txCloser2.Close()
|
||||
if !bytes.Equal(txResult2, []byte("tx-value-5")) {
|
||||
t.Errorf("Expected %v, got %v", []byte("tx-value-5"), txResult2)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Test iterators
|
||||
t.Run("Iterators", func(t *testing.T) {
|
||||
// Insert some test data
|
||||
testData := map[string]string{
|
||||
"iter-key-1": "iter-value-1",
|
||||
"iter-key-2": "iter-value-2",
|
||||
"iter-key-3": "iter-value-3",
|
||||
"iter-key-4": "iter-value-4",
|
||||
"iter-key-5": "iter-value-5",
|
||||
}
|
||||
|
||||
for k, v := range testData {
|
||||
if err := db.Set([]byte(k), []byte(v)); err != nil {
|
||||
t.Fatalf("Failed to set value: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test full range iterator
|
||||
iter, err := db.NewIter([]byte("iter-key-1"), []byte("iter-key-6"))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create iterator: %v", err)
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
count := 0
|
||||
for iter.First(); iter.Valid(); iter.Next() {
|
||||
key := string(iter.Key())
|
||||
value := string(iter.Value())
|
||||
expectedValue, ok := testData[key]
|
||||
if !ok {
|
||||
t.Errorf("Unexpected key: %s", key)
|
||||
} else if expectedValue != value {
|
||||
t.Errorf("Expected value %s for key %s, got %s", expectedValue, key, value)
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
if count != len(testData) {
|
||||
t.Errorf("Expected %d items, got %d", len(testData), count)
|
||||
}
|
||||
|
||||
// Test partial range iterator
|
||||
iter, err = db.NewIter([]byte("iter-key-2"), []byte("iter-key-4"))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create iterator: %v", err)
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
expectedKeys := []string{"iter-key-2", "iter-key-3"}
|
||||
count = 0
|
||||
for iter.First(); iter.Valid(); iter.Next() {
|
||||
key := string(iter.Key())
|
||||
if count >= len(expectedKeys) || key != expectedKeys[count] {
|
||||
t.Errorf("Expected key %s, got %s", expectedKeys[count], key)
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
if count != len(expectedKeys) {
|
||||
t.Errorf("Expected %d items in range, got %d", len(expectedKeys), count)
|
||||
}
|
||||
|
||||
// Test Last and Prev
|
||||
iter, err = db.NewIter([]byte("iter-key-1"), []byte("iter-key-6"))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create iterator: %v", err)
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
if !iter.Last() {
|
||||
t.Errorf("Last() should return true")
|
||||
}
|
||||
|
||||
if string(iter.Key()) != "iter-key-5" {
|
||||
t.Errorf("Expected last key to be iter-key-5, got %s", string(iter.Key()))
|
||||
}
|
||||
|
||||
count = 0
|
||||
expectedReverseKeys := []string{"iter-key-5", "iter-key-4", "iter-key-3", "iter-key-2", "iter-key-1"}
|
||||
for ; iter.Valid(); iter.Prev() {
|
||||
key := string(iter.Key())
|
||||
if count >= len(expectedReverseKeys) || key != expectedReverseKeys[count] {
|
||||
t.Errorf("Expected key %s, got %s", expectedReverseKeys[count], key)
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
if count != len(expectedReverseKeys) {
|
||||
t.Errorf("Expected %d items in reverse range, got %d", len(expectedReverseKeys), count)
|
||||
}
|
||||
|
||||
// Test SeekLT
|
||||
iter, err = db.NewIter([]byte("iter-key-1"), []byte("iter-key-6"))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create iterator: %v", err)
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
if !iter.SeekLT([]byte("iter-key-4")) {
|
||||
t.Errorf("SeekLT() should return true")
|
||||
}
|
||||
|
||||
if string(iter.Key()) != "iter-key-3" {
|
||||
t.Errorf("Expected key after SeekLT to be iter-key-3, got %s", string(iter.Key()))
|
||||
}
|
||||
|
||||
// Test SeekLT with a key that doesn't exist but is in range
|
||||
if !iter.SeekLT([]byte("iter-key-3.5")) {
|
||||
t.Errorf("SeekLT() should return true")
|
||||
}
|
||||
|
||||
if string(iter.Key()) != "iter-key-3" {
|
||||
t.Errorf("Expected key after SeekLT to be iter-key-3, got %s", string(iter.Key()))
|
||||
}
|
||||
})
|
||||
|
||||
// Test DeleteRange
|
||||
t.Run("DeleteRange", func(t *testing.T) {
|
||||
// Insert some test data
|
||||
for i := 1; i <= 5; i++ {
|
||||
key := []byte(filepath.Join("range", "key", "prefix", "key-"+string(rune('0'+i))))
|
||||
value := []byte("value-" + string(rune('0'+i)))
|
||||
if err := db.Set(key, value); err != nil {
|
||||
t.Fatalf("Failed to set value: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete a range of keys
|
||||
startKey := []byte(filepath.Join("range", "key", "prefix", "key-2"))
|
||||
endKey := []byte(filepath.Join("range", "key", "prefix", "key-4"))
|
||||
if err := db.DeleteRange(startKey, endKey); err != nil {
|
||||
t.Fatalf("Failed to delete range: %v", err)
|
||||
}
|
||||
|
||||
// Check that keys in the range are deleted
|
||||
for i := 2; i < 4; i++ {
|
||||
key := []byte(filepath.Join("range", "key", "prefix", "key-"+string(rune('0'+i))))
|
||||
_, _, err := db.Get(key)
|
||||
if err == nil {
|
||||
t.Errorf("Key %s should be deleted", key)
|
||||
}
|
||||
}
|
||||
|
||||
// Check that keys outside the range still exist
|
||||
key1 := []byte(filepath.Join("range", "key", "prefix", "key-1"))
|
||||
result, closer, err := db.Get(key1)
|
||||
if err != nil {
|
||||
t.Errorf("Key %s should still exist: %v", key1, err)
|
||||
} else {
|
||||
defer closer.Close()
|
||||
if !bytes.Equal(result, []byte("value-1")) {
|
||||
t.Errorf("Expected %v, got %v", []byte("value-1"), result)
|
||||
}
|
||||
}
|
||||
|
||||
key5 := []byte(filepath.Join("range", "key", "prefix", "key-5"))
|
||||
result, closer, err = db.Get(key5)
|
||||
if err != nil {
|
||||
t.Errorf("Key %s should still exist: %v", key5, err)
|
||||
} else {
|
||||
defer closer.Close()
|
||||
if !bytes.Equal(result, []byte("value-5")) {
|
||||
t.Errorf("Expected %v, got %v", []byte("value-5"), result)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Batch", func(t *testing.T) {
|
||||
// Insert some test data
|
||||
for i := 1; i <= 5; i++ {
|
||||
key := []byte("key-" + string(rune('0'+i)))
|
||||
value := []byte("value-" + string(rune('0'+i)))
|
||||
if err := db.Set(key, value); err != nil {
|
||||
t.Fatalf("Failed to set value: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
batch := db.NewBatch(false)
|
||||
batch.Set([]byte("key-1"), []byte("potato"))
|
||||
batch.Set([]byte("key-5"), []byte("tomato"))
|
||||
batch.Delete([]byte("key-2"))
|
||||
batch.DeleteRange([]byte("key-3"), []byte("key-5"))
|
||||
if batch.Commit() != nil {
|
||||
t.Errorf("commit failed")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
for i := 1; i <= 5; i++ {
|
||||
key := []byte("key-" + string(rune('0'+i)))
|
||||
val, _, err := db.Get(key)
|
||||
if err != nil && !errors.Is(err, pebble.ErrNotFound) {
|
||||
t.Fatalf("Failed to get value: %v", err)
|
||||
t.Fail()
|
||||
}
|
||||
switch i {
|
||||
case 1:
|
||||
if !bytes.Equal(val, []byte("potato")) {
|
||||
t.Errorf("wrong key-1")
|
||||
}
|
||||
case 5:
|
||||
if !bytes.Equal(val, []byte("tomato")) {
|
||||
t.Errorf("wrong key-5")
|
||||
}
|
||||
default:
|
||||
if err != nil && errors.Is(err, ErrNotFound) {
|
||||
t.Errorf("key-%d should be deleted, but we got (%s)", i, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user