driver_test.go raw

   1  package database_test
   2  
   3  import (
   4  	"fmt"
   5  	"testing"
   6  	
   7  	"github.com/p9c/p9/pkg/database"
   8  	_ "github.com/p9c/p9/pkg/database/ffldb"
   9  )
  10  
  11  var (
  12  	// ignoreDbTypes are types which should be ignored when running tests that iterate all supported DB types. This allows
  13  	// some tests to add bogus drivers for testing purposes while still allowing other tests to easily iterate all
  14  	// supported drivers.
  15  	ignoreDbTypes = map[string]bool{"createopenfail": true}
  16  )
  17  
  18  // checkDbError ensures the passed error is a database.DBError with an error code that matches the passed  error code.
  19  func checkDbError(t *testing.T, testName string, gotErr error, wantErrCode database.ErrorCode) bool {
  20  	dbErr, ok := gotErr.(database.DBError)
  21  	if !ok {
  22  		t.Errorf("%s: unexpected error type - got %T, want %T",
  23  			testName, gotErr, database.DBError{},
  24  		)
  25  		return false
  26  	}
  27  	if dbErr.ErrorCode != wantErrCode {
  28  		t.Errorf("%s: unexpected error code - got %s (%s), want %s",
  29  			testName, dbErr.ErrorCode, dbErr.Description,
  30  			wantErrCode,
  31  		)
  32  		return false
  33  	}
  34  	return true
  35  }
  36  
  37  // TestAddDuplicateDriver ensures that adding a duplicate driver does not overwrite an existing one.
  38  func TestAddDuplicateDriver(t *testing.T) {
  39  	supportedDrivers := database.SupportedDrivers()
  40  	if len(supportedDrivers) == 0 {
  41  		t.Errorf("no backends to test")
  42  		return
  43  	}
  44  	dbType := supportedDrivers[0]
  45  	// bogusCreateDB is a function which acts as a bogus create and open driver function and intentionally returns a
  46  	// failure that can be detected if the interface allows a duplicate driver to overwrite an existing one.
  47  	bogusCreateDB := func(args ...interface{}) (database.DB, error) {
  48  		return nil, fmt.Errorf("duplicate driver allowed for database "+
  49  			"type [%v]", dbType,
  50  		)
  51  	}
  52  	// Create a driver that tries to replace an existing one. Set its create and open functions to a function that
  53  	// causes a test failure if they are invoked.
  54  	driver := database.Driver{
  55  		DbType: dbType,
  56  		Create: bogusCreateDB,
  57  		Open:   bogusCreateDB,
  58  	}
  59  	testName := "duplicate driver registration"
  60  	e := database.RegisterDriver(driver)
  61  	if !checkDbError(t, testName, e, database.ErrDbTypeRegistered) {
  62  		return
  63  	}
  64  }
  65  
  66  // TestCreateOpenFail ensures that errors which occur while opening or closing a database are handled properly.
  67  func TestCreateOpenFail(t *testing.T) {
  68  	// bogusCreateDB is a function which acts as a bogus create and open driver function that intentionally returns a
  69  	// failure which can be detected.
  70  	dbType := "createopenfail"
  71  	openError := fmt.Errorf("failed to create or open database for "+
  72  		"database type [%v]", dbType,
  73  	)
  74  	bogusCreateDB := func(args ...interface{}) (database.DB, error) {
  75  		return nil, openError
  76  	}
  77  	// Create and add driver that intentionally fails when created or opened to ensure errors on database open and
  78  	// create are handled properly.
  79  	driver := database.Driver{
  80  		DbType: dbType,
  81  		Create: bogusCreateDB,
  82  		Open:   bogusCreateDB,
  83  	}
  84  	e := database.RegisterDriver(driver)
  85  	if e != nil {
  86  		t.Log(e)
  87  	}
  88  	// Ensure creating a database with the new type fails with the expected error.
  89  	_, e = database.Create(dbType)
  90  	if e != openError {
  91  		t.Errorf("expected error not received - got: %v, want %v", e,
  92  			openError,
  93  		)
  94  		return
  95  	}
  96  	// Ensure opening a database with the new type fails with the expected error.
  97  	_, e = database.Open(dbType)
  98  	if e != openError {
  99  		t.Errorf("expected error not received - got: %v, want %v", e,
 100  			openError,
 101  		)
 102  		return
 103  	}
 104  }
 105  
 106  // TestCreateOpenUnsupported ensures that attempting to create or open an unsupported database type is handled properly.
 107  func TestCreateOpenUnsupported(t *testing.T) {
 108  	// Ensure creating a database with an unsupported type fails with the expected error.
 109  	testName := "create with unsupported database type"
 110  	dbType := "unsupported"
 111  	_, e := database.Create(dbType)
 112  	if !checkDbError(t, testName, e, database.ErrDbUnknownType) {
 113  		return
 114  	}
 115  	// Ensure opening a database with the an unsupported type fails with the expected error.
 116  	testName = "open with unsupported database type"
 117  	_, e = database.Open(dbType)
 118  	if !checkDbError(t, testName, e, database.ErrDbUnknownType) {
 119  		return
 120  	}
 121  }
 122