Skip to content

Commit

Permalink
Improve database/ tests with require (ava-labs#1506)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhrubabasu committed Jun 15, 2023
1 parent 94b9ce6 commit df6228b
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 379 deletions.
116 changes: 40 additions & 76 deletions database/benchmark_database.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"math/rand"
"testing"

"github.com/stretchr/testify/require"

"github.com/ava-labs/avalanchego/utils/units"
)

Expand Down Expand Up @@ -35,6 +37,8 @@ var (

// Writes size data into the db in order to setup reads in subsequent tests.
func SetupBenchmark(b *testing.B, count int, keySize, valueSize int) ([][]byte, [][]byte) {
require := require.New(b)

b.Helper()

keys := make([][]byte, count)
Expand All @@ -43,217 +47,177 @@ func SetupBenchmark(b *testing.B, count int, keySize, valueSize int) ([][]byte,
keyBytes := make([]byte, keySize)
valueBytes := make([]byte, valueSize)
_, err := rand.Read(keyBytes) // #nosec G404
if err != nil {
b.Fatal(err)
}
require.NoError(err)
_, err = rand.Read(valueBytes) // #nosec G404
if err != nil {
b.Fatal(err)
}
require.NoError(err)
keys[i], values[i] = keyBytes, valueBytes
}
return keys, values
}

// BenchmarkGet measures the time it takes to get an operation from a database.
func BenchmarkGet(b *testing.B, db Database, name string, keys, values [][]byte) {
require.NotEmpty(b, keys)
count := len(keys)
if count == 0 {
b.Fatal("no keys")
}

b.Run(fmt.Sprintf("%s_%d_pairs_%d_keys_%d_values_db.get", name, count, len(keys[0]), len(values[0])), func(b *testing.B) {
require := require.New(b)

for i, key := range keys {
value := values[i]
if err := db.Put(key, value); err != nil {
b.Fatalf("Unexpected error in Put %s", err)
}
require.NoError(db.Put(key, value))
}

b.ResetTimer()

// Reads b.N values from the db
for i := 0; i < b.N; i++ {
if _, err := db.Get(keys[i%count]); err != nil {
b.Fatalf("Unexpected error in Get %s", err)
}
_, err := db.Get(keys[i%count])
require.NoError(err)
}
})
}

// BenchmarkPut measures the time it takes to write an operation to a database.
func BenchmarkPut(b *testing.B, db Database, name string, keys, values [][]byte) {
require.NotEmpty(b, keys)
count := len(keys)
if count == 0 {
b.Fatal("no keys")
}

b.Run(fmt.Sprintf("%s_%d_pairs_%d_keys_%d_values_db.put", name, count, len(keys[0]), len(values[0])), func(b *testing.B) {
// Writes b.N values to the db
for i := 0; i < b.N; i++ {
if err := db.Put(keys[i%count], values[i%count]); err != nil {
b.Fatalf("Unexpected error in Put %s", err)
}
require.NoError(b, db.Put(keys[i%count], values[i%count]))
}
})
}

// BenchmarkDelete measures the time it takes to delete a (k, v) from a database.
func BenchmarkDelete(b *testing.B, db Database, name string, keys, values [][]byte) {
require.NotEmpty(b, keys)
count := len(keys)
if count == 0 {
b.Fatal("no keys")
}

b.Run(fmt.Sprintf("%s_%d_pairs_%d_keys_%d_values_db.delete", name, count, len(keys[0]), len(values[0])), func(b *testing.B) {
require := require.New(b)

// Writes random values of size _size_ to the database
for i, key := range keys {
value := values[i]
if err := db.Put(key, value); err != nil {
b.Fatalf("Unexpected error in Put %s", err)
}
require.NoError(db.Put(key, value))
}

b.ResetTimer()

// Deletes b.N values from the db
for i := 0; i < b.N; i++ {
if err := db.Delete(keys[i%count]); err != nil {
b.Fatalf("Unexpected error in Delete %s", err)
}
require.NoError(db.Delete(keys[i%count]))
}
})
}

// BenchmarkBatchPut measures the time it takes to batch put.
func BenchmarkBatchPut(b *testing.B, db Database, name string, keys, values [][]byte) {
require.NotEmpty(b, keys)
count := len(keys)
if count == 0 {
b.Fatal("no keys")
}

b.Run(fmt.Sprintf("%s_%d_pairs_%d_keys_%d_values_batch.put", name, count, len(keys[0]), len(values[0])), func(b *testing.B) {
batch := db.NewBatch()
for i := 0; i < b.N; i++ {
if err := batch.Put(keys[i%count], values[i%count]); err != nil {
b.Fatalf("Unexpected error in batch.Put: %s", err)
}
require.NoError(b, batch.Put(keys[i%count], values[i%count]))
}
})
}

// BenchmarkBatchDelete measures the time it takes to batch delete.
func BenchmarkBatchDelete(b *testing.B, db Database, name string, keys, values [][]byte) {
require.NotEmpty(b, keys)
count := len(keys)
if count == 0 {
b.Fatal("no keys")
}

b.Run(fmt.Sprintf("%s_%d_pairs_%d_keys_%d_values_batch.delete", name, count, len(keys[0]), len(values[0])), func(b *testing.B) {
batch := db.NewBatch()
for i := 0; i < b.N; i++ {
if err := batch.Delete(keys[i%count]); err != nil {
b.Fatalf("Unexpected error in batch.Delete: %s", err)
}
require.NoError(b, batch.Delete(keys[i%count]))
}
})
}

// BenchmarkBatchWrite measures the time it takes to batch write.
func BenchmarkBatchWrite(b *testing.B, db Database, name string, keys, values [][]byte) {
require.NotEmpty(b, keys)
count := len(keys)
if count == 0 {
b.Fatal("no keys")
}

b.Run(fmt.Sprintf("%s_%d_pairs_%d_keys_%d_values_batch.write", name, count, len(keys[0]), len(values[0])), func(b *testing.B) {
require := require.New(b)

batch := db.NewBatch()
for i, key := range keys {
value := values[i]

if err := batch.Put(key, value); err != nil {
b.Fatalf("Unexpected error in batch.Put: %s", err)
}
require.NoError(batch.Put(key, value))
}

b.ResetTimer()

for i := 0; i < b.N; i++ {
if err := batch.Write(); err != nil {
b.Fatalf("Unexpected error in batch.Write: %s", err)
}
require.NoError(batch.Write())
}
})
}

// BenchmarkParallelGet measures the time it takes to read in parallel.
func BenchmarkParallelGet(b *testing.B, db Database, name string, keys, values [][]byte) {
require.NotEmpty(b, keys)
count := len(keys)
if count == 0 {
b.Fatal("no keys")
}

b.Run(fmt.Sprintf("%s_%d_pairs_%d_keys_%d_values_db.get_parallel", name, count, len(keys[0]), len(values[0])), func(b *testing.B) {
require := require.New(b)

for i, key := range keys {
value := values[i]
if err := db.Put(key, value); err != nil {
b.Fatalf("Unexpected error in Put %s", err)
}
require.NoError(db.Put(key, value))
}

b.ResetTimer()

b.RunParallel(func(pb *testing.PB) {
for i := 0; pb.Next(); i++ {
if _, err := db.Get(keys[i%count]); err != nil {
b.Fatalf("Unexpected error in Get %s", err)
}
_, err := db.Get(keys[i%count])
require.NoError(err)
}
})
})
}

// BenchmarkParallelPut measures the time it takes to write to the db in parallel.
func BenchmarkParallelPut(b *testing.B, db Database, name string, keys, values [][]byte) {
require.NotEmpty(b, keys)
count := len(keys)
if count == 0 {
b.Fatal("no keys")
}

b.Run(fmt.Sprintf("%s_%d_pairs_%d_keys_%d_values_db.put_parallel", name, count, len(keys[0]), len(values[0])), func(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
// Write N values to the db
for i := 0; pb.Next(); i++ {
if err := db.Put(keys[i%count], values[i%count]); err != nil {
b.Fatalf("Unexpected error in Put %s", err)
}
require.NoError(b, db.Put(keys[i%count], values[i%count]))
}
})
})
}

// BenchmarkParallelDelete measures the time it takes to delete a (k, v) from the db.
func BenchmarkParallelDelete(b *testing.B, db Database, name string, keys, values [][]byte) {
require.NotEmpty(b, keys)
count := len(keys)
if count == 0 {
b.Fatal("no keys")
}

b.Run(fmt.Sprintf("%s_%d_pairs_%d_keys_%d_values_db.delete_parallel", name, count, len(keys[0]), len(values[0])), func(b *testing.B) {
require := require.New(b)
for i, key := range keys {
value := values[i]
if err := db.Put(key, value); err != nil {
b.Fatalf("Unexpected error in Put %s", err)
}
require.NoError(db.Put(key, value))
}
b.ResetTimer()

b.RunParallel(func(pb *testing.PB) {
// Deletes b.N values from the db
for i := 0; pb.Next(); i++ {
if err := db.Delete(keys[i%count]); err != nil {
b.Fatalf("Unexpected error in Delete %s", err)
}
require.NoError(db.Delete(keys[i%count]))
}
})
})
Expand Down
2 changes: 1 addition & 1 deletion database/corruptabledb/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestCorruption(t *testing.T) {
for name, testFn := range tests {
t.Run(name, func(tt *testing.T) {
err := testFn(corruptableDB)
require.ErrorIsf(tt, err, errTest, "not received the corruption error")
require.ErrorIs(tt, err, errTest)
})
}
}
8 changes: 2 additions & 6 deletions database/encdb/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ func TestInterface(t *testing.T) {
for _, test := range database.Tests {
unencryptedDB := memdb.New()
db, err := New([]byte(testPassword), unencryptedDB)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)

test(t, db)
}
Expand All @@ -43,9 +41,7 @@ func BenchmarkInterface(b *testing.B) {
for _, bench := range database.Benchmarks {
unencryptedDB := memdb.New()
db, err := New([]byte(testPassword), unencryptedDB)
if err != nil {
b.Fatal(err)
}
require.NoError(b, err)
bench(b, db, "encdb", keys, values)
}
}
Expand Down
8 changes: 2 additions & 6 deletions database/leveldb/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ func TestInterface(t *testing.T) {
for _, test := range database.Tests {
folder := t.TempDir()
db, err := New(folder, nil, logging.NoLog{}, "", prometheus.NewRegistry())
if err != nil {
t.Fatalf("leveldb.New(%q, logging.NoLog{}) errored with %s", folder, err)
}
require.NoError(t, err)

defer db.Close()

Expand Down Expand Up @@ -57,9 +55,7 @@ func BenchmarkInterface(b *testing.B) {
folder := b.TempDir()

db, err := New(folder, nil, logging.NoLog{}, "", prometheus.NewRegistry())
if err != nil {
b.Fatal(err)
}
require.NoError(b, err)

bench(b, db, "leveldb", keys, values)

Expand Down
16 changes: 7 additions & 9 deletions database/linkeddb/linkeddb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ func TestLinkedDB(t *testing.T) {

has, err := ldb.Has(key)
require.NoError(err)
require.False(has, "db unexpectedly had key %s", key)
require.False(has)

_, err = ldb.Get(key)
require.Equal(database.ErrNotFound, err, "Expected db.Get to return a Not Found error.")
require.Equal(database.ErrNotFound, err)

require.NoError(ldb.Delete(key))

require.NoError(ldb.Put(key, value))

has, err = ldb.Has(key)
require.NoError(err)
require.True(has, "db should have had key %s", key)
require.True(has)

v, err := ldb.Get(key)
require.NoError(err)
Expand All @@ -44,14 +44,13 @@ func TestLinkedDB(t *testing.T) {

has, err = ldb.Has(key)
require.NoError(err)
require.False(has, "db unexpectedly had key %s", key)
require.False(has)

_, err = ldb.Get(key)
require.Equal(database.ErrNotFound, err, "Expected db.Get to return a Not Found error.")
require.Equal(database.ErrNotFound, err)

iterator := db.NewIterator()
next := iterator.Next()
require.False(next, "database should be empty")
require.False(iterator.Next())
iterator.Release()
}

Expand All @@ -76,8 +75,7 @@ func TestLinkedDBDuplicatedPut(t *testing.T) {
require.NoError(ldb.Delete(key))

iterator := db.NewIterator()
next := iterator.Next()
require.False(next, "database should be empty")
require.False(iterator.Next())
iterator.Release()
}

Expand Down

0 comments on commit df6228b

Please sign in to comment.