OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / database / ffldb / driver_test.go
1 // Copyright (c) 2015-2016 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4
5 package ffldb_test
6
7 import (
8         "fmt"
9         "os"
10         "path/filepath"
11         "reflect"
12         "runtime"
13         "testing"
14
15         "github.com/btcsuite/btcd/chaincfg"
16         "github.com/btcsuite/btcd/database"
17         "github.com/btcsuite/btcd/database/ffldb"
18         "github.com/btcsuite/btcutil"
19 )
20
21 // dbType is the database type name for this driver.
22 const dbType = "ffldb"
23
24 // TestCreateOpenFail ensures that errors related to creating and opening a
25 // database are handled properly.
26 func TestCreateOpenFail(t *testing.T) {
27         t.Parallel()
28
29         // Ensure that attempting to open a database that doesn't exist returns
30         // the expected error.
31         wantErrCode := database.ErrDbDoesNotExist
32         _, err := database.Open(dbType, "noexist", blockDataNet)
33         if !checkDbError(t, "Open", err, wantErrCode) {
34                 return
35         }
36
37         // Ensure that attempting to open a database with the wrong number of
38         // parameters returns the expected error.
39         wantErr := fmt.Errorf("invalid arguments to %s.Open -- expected "+
40                 "database path and block network", dbType)
41         _, err = database.Open(dbType, 1, 2, 3)
42         if err.Error() != wantErr.Error() {
43                 t.Errorf("Open: did not receive expected error - got %v, "+
44                         "want %v", err, wantErr)
45                 return
46         }
47
48         // Ensure that attempting to open a database with an invalid type for
49         // the first parameter returns the expected error.
50         wantErr = fmt.Errorf("first argument to %s.Open is invalid -- "+
51                 "expected database path string", dbType)
52         _, err = database.Open(dbType, 1, blockDataNet)
53         if err.Error() != wantErr.Error() {
54                 t.Errorf("Open: did not receive expected error - got %v, "+
55                         "want %v", err, wantErr)
56                 return
57         }
58
59         // Ensure that attempting to open a database with an invalid type for
60         // the second parameter returns the expected error.
61         wantErr = fmt.Errorf("second argument to %s.Open is invalid -- "+
62                 "expected block network", dbType)
63         _, err = database.Open(dbType, "noexist", "invalid")
64         if err.Error() != wantErr.Error() {
65                 t.Errorf("Open: did not receive expected error - got %v, "+
66                         "want %v", err, wantErr)
67                 return
68         }
69
70         // Ensure that attempting to create a database with the wrong number of
71         // parameters returns the expected error.
72         wantErr = fmt.Errorf("invalid arguments to %s.Create -- expected "+
73                 "database path and block network", dbType)
74         _, err = database.Create(dbType, 1, 2, 3)
75         if err.Error() != wantErr.Error() {
76                 t.Errorf("Create: did not receive expected error - got %v, "+
77                         "want %v", err, wantErr)
78                 return
79         }
80
81         // Ensure that attempting to create a database with an invalid type for
82         // the first parameter returns the expected error.
83         wantErr = fmt.Errorf("first argument to %s.Create is invalid -- "+
84                 "expected database path string", dbType)
85         _, err = database.Create(dbType, 1, blockDataNet)
86         if err.Error() != wantErr.Error() {
87                 t.Errorf("Create: did not receive expected error - got %v, "+
88                         "want %v", err, wantErr)
89                 return
90         }
91
92         // Ensure that attempting to create a database with an invalid type for
93         // the second parameter returns the expected error.
94         wantErr = fmt.Errorf("second argument to %s.Create is invalid -- "+
95                 "expected block network", dbType)
96         _, err = database.Create(dbType, "noexist", "invalid")
97         if err.Error() != wantErr.Error() {
98                 t.Errorf("Create: did not receive expected error - got %v, "+
99                         "want %v", err, wantErr)
100                 return
101         }
102
103         // Ensure operations against a closed database return the expected
104         // error.
105         dbPath := filepath.Join(os.TempDir(), "ffldb-createfail")
106         _ = os.RemoveAll(dbPath)
107         db, err := database.Create(dbType, dbPath, blockDataNet)
108         if err != nil {
109                 t.Errorf("Create: unexpected error: %v", err)
110                 return
111         }
112         defer os.RemoveAll(dbPath)
113         db.Close()
114
115         wantErrCode = database.ErrDbNotOpen
116         err = db.View(func(tx database.Tx) error {
117                 return nil
118         })
119         if !checkDbError(t, "View", err, wantErrCode) {
120                 return
121         }
122
123         wantErrCode = database.ErrDbNotOpen
124         err = db.Update(func(tx database.Tx) error {
125                 return nil
126         })
127         if !checkDbError(t, "Update", err, wantErrCode) {
128                 return
129         }
130
131         wantErrCode = database.ErrDbNotOpen
132         _, err = db.Begin(false)
133         if !checkDbError(t, "Begin(false)", err, wantErrCode) {
134                 return
135         }
136
137         wantErrCode = database.ErrDbNotOpen
138         _, err = db.Begin(true)
139         if !checkDbError(t, "Begin(true)", err, wantErrCode) {
140                 return
141         }
142
143         wantErrCode = database.ErrDbNotOpen
144         err = db.Close()
145         if !checkDbError(t, "Close", err, wantErrCode) {
146                 return
147         }
148 }
149
150 // TestPersistence ensures that values stored are still valid after closing and
151 // reopening the database.
152 func TestPersistence(t *testing.T) {
153         t.Parallel()
154
155         // Create a new database to run tests against.
156         dbPath := filepath.Join(os.TempDir(), "ffldb-persistencetest")
157         _ = os.RemoveAll(dbPath)
158         db, err := database.Create(dbType, dbPath, blockDataNet)
159         if err != nil {
160                 t.Errorf("Failed to create test database (%s) %v", dbType, err)
161                 return
162         }
163         defer os.RemoveAll(dbPath)
164         defer db.Close()
165
166         // Create a bucket, put some values into it, and store a block so they
167         // can be tested for existence on re-open.
168         bucket1Key := []byte("bucket1")
169         storeValues := map[string]string{
170                 "b1key1": "foo1",
171                 "b1key2": "foo2",
172                 "b1key3": "foo3",
173         }
174         genesisBlock := btcutil.NewBlock(chaincfg.MainNetParams.GenesisBlock)
175         genesisHash := chaincfg.MainNetParams.GenesisHash
176         err = db.Update(func(tx database.Tx) error {
177                 metadataBucket := tx.Metadata()
178                 if metadataBucket == nil {
179                         return fmt.Errorf("Metadata: unexpected nil bucket")
180                 }
181
182                 bucket1, err := metadataBucket.CreateBucket(bucket1Key)
183                 if err != nil {
184                         return fmt.Errorf("CreateBucket: unexpected error: %v",
185                                 err)
186                 }
187
188                 for k, v := range storeValues {
189                         err := bucket1.Put([]byte(k), []byte(v))
190                         if err != nil {
191                                 return fmt.Errorf("Put: unexpected error: %v",
192                                         err)
193                         }
194                 }
195
196                 if err := tx.StoreBlock(genesisBlock); err != nil {
197                         return fmt.Errorf("StoreBlock: unexpected error: %v",
198                                 err)
199                 }
200
201                 return nil
202         })
203         if err != nil {
204                 t.Errorf("Update: unexpected error: %v", err)
205                 return
206         }
207
208         // Close and reopen the database to ensure the values persist.
209         db.Close()
210         db, err = database.Open(dbType, dbPath, blockDataNet)
211         if err != nil {
212                 t.Errorf("Failed to open test database (%s) %v", dbType, err)
213                 return
214         }
215         defer db.Close()
216
217         // Ensure the values previously stored in the 3rd namespace still exist
218         // and are correct.
219         err = db.View(func(tx database.Tx) error {
220                 metadataBucket := tx.Metadata()
221                 if metadataBucket == nil {
222                         return fmt.Errorf("Metadata: unexpected nil bucket")
223                 }
224
225                 bucket1 := metadataBucket.Bucket(bucket1Key)
226                 if bucket1 == nil {
227                         return fmt.Errorf("Bucket1: unexpected nil bucket")
228                 }
229
230                 for k, v := range storeValues {
231                         gotVal := bucket1.Get([]byte(k))
232                         if !reflect.DeepEqual(gotVal, []byte(v)) {
233                                 return fmt.Errorf("Get: key '%s' does not "+
234                                         "match expected value - got %s, want %s",
235                                         k, gotVal, v)
236                         }
237                 }
238
239                 genesisBlockBytes, _ := genesisBlock.Bytes()
240                 gotBytes, err := tx.FetchBlock(genesisHash)
241                 if err != nil {
242                         return fmt.Errorf("FetchBlock: unexpected error: %v",
243                                 err)
244                 }
245                 if !reflect.DeepEqual(gotBytes, genesisBlockBytes) {
246                         return fmt.Errorf("FetchBlock: stored block mismatch")
247                 }
248
249                 return nil
250         })
251         if err != nil {
252                 t.Errorf("View: unexpected error: %v", err)
253                 return
254         }
255 }
256
257 // TestInterface performs all interfaces tests for this database driver.
258 func TestInterface(t *testing.T) {
259         t.Parallel()
260
261         // Create a new database to run tests against.
262         dbPath := filepath.Join(os.TempDir(), "ffldb-interfacetest")
263         _ = os.RemoveAll(dbPath)
264         db, err := database.Create(dbType, dbPath, blockDataNet)
265         if err != nil {
266                 t.Errorf("Failed to create test database (%s) %v", dbType, err)
267                 return
268         }
269         defer os.RemoveAll(dbPath)
270         defer db.Close()
271
272         // Ensure the driver type is the expected value.
273         gotDbType := db.Type()
274         if gotDbType != dbType {
275                 t.Errorf("Type: unepxected driver type - got %v, want %v",
276                         gotDbType, dbType)
277                 return
278         }
279
280         // Run all of the interface tests against the database.
281         runtime.GOMAXPROCS(runtime.NumCPU())
282
283         // Change the maximum file size to a small value to force multiple flat
284         // files with the test data set.
285         ffldb.TstRunWithMaxBlockFileSize(db, 2048, func() {
286                 testInterface(t, db)
287         })
288 }