driver_test.go raw

   1  package bdb_test
   2  
   3  import (
   4  	"fmt"
   5  	"os"
   6  	"reflect"
   7  	"testing"
   8  	
   9  	"github.com/p9c/p9/pkg/walletdb"
  10  	"github.com/p9c/p9/pkg/walletdb/bdb"
  11  	_ "github.com/p9c/p9/pkg/walletdb/bdb"
  12  )
  13  
  14  // dbType is the database type name for this driver.
  15  const dbType = "bdb"
  16  
  17  // TestCreateOpenFail ensures that errors related to creating and opening a database are handled properly.
  18  func TestCreateOpenFail(t *testing.T) {
  19  	var e error
  20  	// Ensure that attempting to open a database that doesn't exist returns the expected error.
  21  	wantErr := walletdb.ErrDbDoesNotExist
  22  	if _, e = walletdb.Open(dbType, "noexist.db"); e != wantErr {
  23  		t.Errorf("Open: did not receive expected error - got %v, "+
  24  			"want %v", e, wantErr,
  25  		)
  26  		return
  27  	}
  28  	// Ensure that attempting to open a database with the wrong number of parameters returns the expected error.
  29  	wantErr = fmt.Errorf("invalid arguments to %s.Open -- expected "+
  30  		"database path", dbType,
  31  	)
  32  	if _, e = walletdb.Open(dbType, 1, 2, 3); e != nil && e.Error() != wantErr.Error() {
  33  		t.Errorf("Open: did not receive expected error - got %v, "+
  34  			"want %v", e, wantErr,
  35  		)
  36  		return
  37  	}
  38  	// Ensure that attempting to open a database with an invalid type for the first parameter returns the expected
  39  	// error.
  40  	wantErr = fmt.Errorf("first argument to %s.Open is invalid -- "+
  41  		"expected database path string", dbType,
  42  	)
  43  	if _, e = walletdb.Open(dbType, 1); e != nil && e.Error() != wantErr.Error() {
  44  		t.Errorf("Open: did not receive expected error - got %v, "+
  45  			"want %v", e, wantErr,
  46  		)
  47  		return
  48  	}
  49  	// Ensure that attempting to create a database with the wrong number of parameters returns the expected error.
  50  	wantErr = fmt.Errorf("invalid arguments to %s.Create -- expected "+
  51  		"database path", dbType,
  52  	)
  53  	if _, e = walletdb.Create(dbType, 1, 2, 3); e != nil && e.Error() != wantErr.Error() {
  54  		t.Errorf("Create: did not receive expected error - got %v, "+
  55  			"want %v", e, wantErr,
  56  		)
  57  		return
  58  	}
  59  	// Ensure that attempting to open a database with an invalid type for the first parameter returns the expected
  60  	// error.
  61  	wantErr = fmt.Errorf("first argument to %s.Create is invalid -- "+
  62  		"expected database path string", dbType,
  63  	)
  64  	if _, e = walletdb.Create(dbType, 1); e != nil && e.Error() != wantErr.Error() {
  65  		t.Errorf("Create: did not receive expected error - got %v, "+
  66  			"want %v", e, wantErr,
  67  		)
  68  		return
  69  	}
  70  	// Ensure operations against a closed database return the expected error.
  71  	dbPath := "createfail.db"
  72  	db, e := walletdb.Create(dbType, dbPath)
  73  	if e != nil {
  74  		t.Errorf("Create: unexpected error: %v", e)
  75  		return
  76  	}
  77  	defer func() {
  78  		if e = os.Remove(dbPath); bdb.E.Chk(e) {
  79  		}
  80  	}()
  81  	if e = db.Close(); bdb.E.Chk(e) {
  82  	}
  83  	wantErr = walletdb.ErrDbNotOpen
  84  	if _, e = db.BeginReadTx(); e != wantErr {
  85  		t.Errorf("Namespace: did not receive expected error - got %v, "+
  86  			"want %v", e, wantErr,
  87  		)
  88  		return
  89  	}
  90  }
  91  
  92  // TestPersistence ensures that values stored are still valid after closing and reopening the database.
  93  func TestPersistence(t *testing.T) {
  94  	// Create a new database to run tests against.
  95  	dbPath := "persistencetest.db"
  96  	db, e := walletdb.Create(dbType, dbPath)
  97  	if e != nil {
  98  		t.Errorf("Failed to create test database (%s) %v", dbType, e)
  99  		return
 100  	}
 101  	defer func() {
 102  		if e = os.Remove(dbPath); bdb.E.Chk(e) {
 103  		}
 104  	}()
 105  	defer func() {
 106  		if e = db.Close(); bdb.E.Chk(e) {
 107  		}
 108  	}()
 109  	// Create a namespace and put some values into it so they can be tested for existence on re-open.
 110  	storeValues := map[string]string{
 111  		"ns1key1": "foo1",
 112  		"ns1key2": "foo2",
 113  		"ns1key3": "foo3",
 114  	}
 115  	ns1Key := []byte("ns1")
 116  	e = walletdb.Update(db, func(tx walletdb.ReadWriteTx) (e error) {
 117  		ns1, e := tx.CreateTopLevelBucket(ns1Key)
 118  		if e != nil {
 119  			return e
 120  		}
 121  		for k, v := range storeValues {
 122  			if e := ns1.Put([]byte(k), []byte(v)); E.Chk(e) {
 123  				return fmt.Errorf("put: unexpected error: %v", e)
 124  			}
 125  		}
 126  		return nil
 127  	},
 128  	)
 129  	if e != nil {
 130  		t.Errorf("ns1 Update: unexpected error: %v", e)
 131  		return
 132  	}
 133  	// Close and reopen the database to ensure the values persist.
 134  	if e = db.Close(); bdb.E.Chk(e) {
 135  	}
 136  	db, e = walletdb.Open(dbType, dbPath)
 137  	if e != nil {
 138  		t.Errorf("failed to open test database (%s) %v", dbType, e)
 139  		return
 140  	}
 141  	defer func() {
 142  		if e = db.Close(); bdb.E.Chk(e) {
 143  		}
 144  	}()
 145  	// Ensure the values previously stored in the 3rd namespace still exist and are correct.
 146  	e = walletdb.View(db, func(tx walletdb.ReadTx) (e error) {
 147  		ns1 := tx.ReadBucket(ns1Key)
 148  		if ns1 == nil {
 149  			return fmt.Errorf("ReadTx.ReadBucket: unexpected nil root bucket")
 150  		}
 151  		for k, v := range storeValues {
 152  			gotVal := ns1.Get([]byte(k))
 153  			if !reflect.DeepEqual(gotVal, []byte(v)) {
 154  				return fmt.Errorf("get: key '%s' does not match expected value - got %s, want %s",
 155  					k, gotVal, v,
 156  				)
 157  			}
 158  		}
 159  		return nil
 160  	},
 161  	)
 162  	if e != nil {
 163  		t.Errorf("ns1 View: unexpected error: %v", e)
 164  		return
 165  	}
 166  }
 167