You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
5.8 KiB
188 lines
5.8 KiB
// Copyright (c) 2013-2015 The btcsuite developers |
|
// Use of this source code is governed by an ISC |
|
// license that can be found in the LICENSE file. |
|
|
|
package database_test |
|
|
|
import ( |
|
"fmt" |
|
"testing" |
|
|
|
"github.com/btcsuite/btcd/database" |
|
) |
|
|
|
var ( |
|
// ignoreDbTypes are types which should be ignored when running tests |
|
// that iterate all supported DB types. This allows some tests to add |
|
// bogus drivers for testing purposes while still allowing other tests |
|
// to easily iterate all supported drivers. |
|
ignoreDbTypes = map[string]bool{"createopenfail": true} |
|
) |
|
|
|
// testNewestShaEmpty ensures that NewestSha returns the values expected by |
|
// the interface contract. |
|
func testNewestShaEmpty(t *testing.T, db database.Db) { |
|
sha, height, err := db.NewestSha() |
|
if err != nil { |
|
t.Errorf("NewestSha error %v", err) |
|
} |
|
if !sha.IsEqual(&zeroHash) { |
|
t.Errorf("NewestSha wrong hash got: %s, want %s", sha, &zeroHash) |
|
|
|
} |
|
if height != -1 { |
|
t.Errorf("NewestSha wrong height got: %d, want %d", height, -1) |
|
} |
|
} |
|
|
|
// TestEmptyDB tests that empty databases are handled properly. |
|
func TestEmptyDB(t *testing.T) { |
|
for _, dbType := range database.SupportedDBs() { |
|
// Ensure NewestSha returns expected values for a newly created |
|
// db. |
|
db, teardown, err := createDB(dbType, "emptydb", false) |
|
if err != nil { |
|
t.Errorf("Failed to create test database %v", err) |
|
return |
|
} |
|
testNewestShaEmpty(t, db) |
|
|
|
// Ensure NewestSha still returns expected values for an empty |
|
// database after reopen. |
|
db.Close() |
|
db, err = openDB(dbType, "emptydb") |
|
if err != nil { |
|
t.Errorf("Failed to open test database %v", err) |
|
return |
|
} |
|
testNewestShaEmpty(t, db) |
|
db.Close() |
|
|
|
// Clean up the old db. |
|
teardown() |
|
} |
|
} |
|
|
|
// TestAddDuplicateDriver ensures that adding a duplicate driver does not |
|
// overwrite an existing one. |
|
func TestAddDuplicateDriver(t *testing.T) { |
|
supportedDBs := database.SupportedDBs() |
|
if len(supportedDBs) == 0 { |
|
t.Errorf("TestAddDuplicateDriver: No backends to test") |
|
return |
|
} |
|
dbType := supportedDBs[0] |
|
|
|
// bogusCreateDB is a function which acts as a bogus create and open |
|
// driver function and intentionally returns a failure that can be |
|
// detected if the interface allows a duplicate driver to overwrite an |
|
// existing one. |
|
bogusCreateDB := func(args ...interface{}) (database.Db, error) { |
|
return nil, fmt.Errorf("duplicate driver allowed for database "+ |
|
"type [%v]", dbType) |
|
} |
|
|
|
// Create a driver that tries to replace an existing one. Set its |
|
// create and open functions to a function that causes a test failure if |
|
// they are invoked. |
|
driver := database.DriverDB{ |
|
DbType: dbType, |
|
CreateDB: bogusCreateDB, |
|
OpenDB: bogusCreateDB, |
|
} |
|
database.AddDBDriver(driver) |
|
|
|
// Ensure creating a database of the type that we tried to replace |
|
// doesn't fail (if it does, it indicates the driver was erroneously |
|
// replaced). |
|
_, teardown, err := createDB(dbType, "dupdrivertest", true) |
|
if err != nil { |
|
t.Errorf("TestAddDuplicateDriver: %v", err) |
|
return |
|
} |
|
teardown() |
|
} |
|
|
|
// TestCreateOpenFail ensures that errors which occur while opening or closing |
|
// a database are handled properly. |
|
func TestCreateOpenFail(t *testing.T) { |
|
// bogusCreateDB is a function which acts as a bogus create and open |
|
// driver function that intentionally returns a failure which can be |
|
// detected. |
|
dbType := "createopenfail" |
|
openError := fmt.Errorf("failed to create or open database for "+ |
|
"database type [%v]", dbType) |
|
bogusCreateDB := func(args ...interface{}) (database.Db, error) { |
|
return nil, openError |
|
} |
|
|
|
// Create and add driver that intentionally fails when created or opened |
|
// to ensure errors on database open and create are handled properly. |
|
driver := database.DriverDB{ |
|
DbType: dbType, |
|
CreateDB: bogusCreateDB, |
|
OpenDB: bogusCreateDB, |
|
} |
|
database.AddDBDriver(driver) |
|
|
|
// Ensure creating a database with the new type fails with the expected |
|
// error. |
|
_, err := database.CreateDB(dbType, "createfailtest") |
|
if err != openError { |
|
t.Errorf("TestCreateOpenFail: expected error not received - "+ |
|
"got: %v, want %v", err, openError) |
|
return |
|
} |
|
|
|
// Ensure opening a database with the new type fails with the expected |
|
// error. |
|
_, err = database.OpenDB(dbType, "openfailtest") |
|
if err != openError { |
|
t.Errorf("TestCreateOpenFail: expected error not received - "+ |
|
"got: %v, want %v", err, openError) |
|
return |
|
} |
|
} |
|
|
|
// TestCreateOpenUnsupported ensures that attempting to create or open an |
|
// unsupported database type is handled properly. |
|
func TestCreateOpenUnsupported(t *testing.T) { |
|
// Ensure creating a database with an unsupported type fails with the |
|
// expected error. |
|
dbType := "unsupported" |
|
_, err := database.CreateDB(dbType, "unsupportedcreatetest") |
|
if err != database.ErrDbUnknownType { |
|
t.Errorf("TestCreateOpenUnsupported: expected error not "+ |
|
"received - got: %v, want %v", err, database.ErrDbUnknownType) |
|
return |
|
} |
|
|
|
// Ensure opening a database with the new type fails with the expected |
|
// error. |
|
_, err = database.OpenDB(dbType, "unsupportedopentest") |
|
if err != database.ErrDbUnknownType { |
|
t.Errorf("TestCreateOpenUnsupported: expected error not "+ |
|
"received - got: %v, want %v", err, database.ErrDbUnknownType) |
|
return |
|
} |
|
} |
|
|
|
// TestInterface performs tests for the various interfaces of the database |
|
// package which require state in the database for each supported database |
|
// type (those loaded in common_test.go that is). |
|
func TestInterface(t *testing.T) { |
|
for _, dbType := range database.SupportedDBs() { |
|
if _, exists := ignoreDbTypes[dbType]; !exists { |
|
testInterface(t, dbType) |
|
} |
|
} |
|
} |
|
|
|
// TestReorganization performs reorganization tests for each supported DB type |
|
func TestReorganization(t *testing.T) { |
|
for _, dbType := range database.SupportedDBs() { |
|
if _, exists := ignoreDbTypes[dbType]; !exists { |
|
testReorganization(t, dbType) |
|
} |
|
} |
|
}
|
|
|