decred.org/dcrwallet/v3@v3.1.0/wallet/internal/bdb/driver_test.go (about)

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