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