github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/blockchain/common_test.go (about) 1 // Copyright (c) 2013-2016 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package blockchain_test 7 8 import ( 9 "compress/bzip2" 10 "encoding/binary" 11 "fmt" 12 "io" 13 "os" 14 "path/filepath" 15 "strings" 16 17 "github.com/BlockABC/godash/blockchain" 18 "github.com/BlockABC/godash/chaincfg" 19 "github.com/BlockABC/godash/database" 20 _ "github.com/BlockABC/godash/database/ffldb" 21 "github.com/BlockABC/godash/wire" 22 ) 23 24 const ( 25 // testDbType is the database backend type to use for the tests. 26 testDbType = "ffldb" 27 28 // testDbRoot is the root directory used to create all test databases. 29 testDbRoot = "testdbs" 30 31 // blockDataNet is the expected network in the test block data. 32 blockDataNet = wire.MainNet 33 ) 34 35 // filesExists returns whether or not the named file or directory exists. 36 func fileExists(name string) bool { 37 if _, err := os.Stat(name); err != nil { 38 if os.IsNotExist(err) { 39 return false 40 } 41 } 42 return true 43 } 44 45 // isSupportedDbType returns whether or not the passed database type is 46 // currently supported. 47 func isSupportedDbType(dbType string) bool { 48 supportedDrivers := database.SupportedDrivers() 49 for _, driver := range supportedDrivers { 50 if dbType == driver { 51 return true 52 } 53 } 54 55 return false 56 } 57 58 // chainSetup is used to create a new db and chain instance with the genesis 59 // block already inserted. In addition to the new chain instnce, it returns 60 // a teardown function the caller should invoke when done testing to clean up. 61 func chainSetup(dbName string) (*blockchain.BlockChain, func(), error) { 62 if !isSupportedDbType(testDbType) { 63 return nil, nil, fmt.Errorf("unsupported db type %v", testDbType) 64 } 65 66 // Handle memory database specially since it doesn't need the disk 67 // specific handling. 68 var db database.DB 69 var teardown func() 70 if testDbType == "memdb" { 71 ndb, err := database.Create(testDbType) 72 if err != nil { 73 return nil, nil, fmt.Errorf("error creating db: %v", err) 74 } 75 db = ndb 76 77 // Setup a teardown function for cleaning up. This function is 78 // returned to the caller to be invoked when it is done testing. 79 teardown = func() { 80 db.Close() 81 } 82 } else { 83 // Create the root directory for test databases. 84 if !fileExists(testDbRoot) { 85 if err := os.MkdirAll(testDbRoot, 0700); err != nil { 86 err := fmt.Errorf("unable to create test db "+ 87 "root: %v", err) 88 return nil, nil, err 89 } 90 } 91 92 // Create a new database to store the accepted blocks into. 93 dbPath := filepath.Join(testDbRoot, dbName) 94 _ = os.RemoveAll(dbPath) 95 ndb, err := database.Create(testDbType, dbPath, blockDataNet) 96 if err != nil { 97 return nil, nil, fmt.Errorf("error creating db: %v", err) 98 } 99 db = ndb 100 101 // Setup a teardown function for cleaning up. This function is 102 // returned to the caller to be invoked when it is done testing. 103 teardown = func() { 104 db.Close() 105 os.RemoveAll(dbPath) 106 os.RemoveAll(testDbRoot) 107 } 108 } 109 110 // Create the main chain instance. 111 chain, err := blockchain.New(&blockchain.Config{ 112 DB: db, 113 ChainParams: &chaincfg.MainNetParams, 114 TimeSource: blockchain.NewMedianTime(), 115 }) 116 if err != nil { 117 teardown() 118 err := fmt.Errorf("failed to create chain instance: %v", err) 119 return nil, nil, err 120 } 121 return chain, teardown, nil 122 } 123 124 // loadUtxoView returns a utxo view loaded from a file. 125 func loadUtxoView(filename string) (*blockchain.UtxoViewpoint, error) { 126 // The utxostore file format is: 127 // <tx hash><serialized utxo len><serialized utxo> 128 // 129 // The serialized utxo len is a little endian uint32 and the serialized 130 // utxo uses the format described in chainio.go. 131 132 filename = filepath.Join("testdata", filename) 133 fi, err := os.Open(filename) 134 if err != nil { 135 return nil, err 136 } 137 138 // Choose read based on whether the file is compressed or not. 139 var r io.Reader 140 if strings.HasSuffix(filename, ".bz2") { 141 r = bzip2.NewReader(fi) 142 } else { 143 r = fi 144 } 145 defer fi.Close() 146 147 view := blockchain.NewUtxoViewpoint() 148 for { 149 // Hash of the utxo entry. 150 var hash wire.ShaHash 151 _, err := io.ReadAtLeast(r, hash[:], len(hash[:])) 152 if err != nil { 153 // Expected EOF at the right offset. 154 if err == io.EOF { 155 break 156 } 157 return nil, err 158 } 159 160 // Num of serialize utxo entry bytes. 161 var numBytes uint32 162 err = binary.Read(r, binary.LittleEndian, &numBytes) 163 if err != nil { 164 return nil, err 165 } 166 167 // Serialized utxo entry. 168 serialized := make([]byte, numBytes) 169 _, err = io.ReadAtLeast(r, serialized, int(numBytes)) 170 if err != nil { 171 return nil, err 172 } 173 174 // Deserialize it and add it to the view. 175 utxoEntry, err := blockchain.TstDeserializeUtxoEntry(serialized) 176 if err != nil { 177 return nil, err 178 } 179 view.Entries()[hash] = utxoEntry 180 } 181 182 return view, nil 183 }