mirror of
https://github.com/btcsuite/btcd.git
synced 2024-11-19 01:40:07 +01:00
blockchain: Consolidate tests into package.
Putting the test code in the same package makes it easier for forks since they don't have to change the import paths as much and it also gets rid of the need for internal_test.go to bridge. While here, remove the reorganization test since it is much better handled by the full block tests and is no longer needed and do some light cleanup on a few other tests. The full block tests had to remain in the separate test package since it is a circular dependency otherwise. This did require duplicating some of the chain setup code, but given the other benefits this is acceptable.
This commit is contained in:
parent
f4fe6c373e
commit
e02fbcf5a1
@ -2,12 +2,11 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
@ -17,7 +16,7 @@ func BenchmarkIsCoinBase(b *testing.B) {
|
||||
tx, _ := btcutil.NewBlock(&Block100000).Tx(1)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
blockchain.IsCoinBase(tx)
|
||||
IsCoinBase(tx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +26,6 @@ func BenchmarkIsCoinBaseTx(b *testing.B) {
|
||||
tx := Block100000.Transactions[1]
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
blockchain.IsCoinBaseTx(tx)
|
||||
IsCoinBaseTx(tx)
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,12 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@ -49,7 +48,7 @@ func TestHaveBlock(t *testing.T) {
|
||||
chain.TstSetCoinbaseMaturity(1)
|
||||
|
||||
for i := 1; i < len(blocks); i++ {
|
||||
_, isOrphan, err := chain.ProcessBlock(blocks[i], blockchain.BFNone)
|
||||
_, isOrphan, err := chain.ProcessBlock(blocks[i], BFNone)
|
||||
if err != nil {
|
||||
t.Errorf("ProcessBlock fail on block %v: %v\n", i, err)
|
||||
return
|
||||
@ -63,7 +62,7 @@ func TestHaveBlock(t *testing.T) {
|
||||
|
||||
// Insert an orphan block.
|
||||
_, isOrphan, err := chain.ProcessBlock(btcutil.NewBlock(&Block100000),
|
||||
blockchain.BFNone)
|
||||
BFNone)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to process block: %v", err)
|
||||
return
|
||||
@ -125,12 +124,15 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
blockVersion := int32(0x20000000 | (uint32(1) << csvBit))
|
||||
|
||||
// Generate enough synthetic blocks to activate CSV.
|
||||
chain, node := blockchain.TstNewFakeChain(netParams)
|
||||
chain := newFakeChain(netParams)
|
||||
node := chain.bestNode
|
||||
blockTime := node.Header().Timestamp
|
||||
numBlocksToActivate := (netParams.MinerConfirmationWindow * 3)
|
||||
for i := uint32(0); i < numBlocksToActivate; i++ {
|
||||
blockTime = blockTime.Add(time.Second)
|
||||
node = chain.TstNewFakeNode(node, blockVersion, 0, blockTime)
|
||||
node = newFakeNode(node, blockVersion, 0, blockTime)
|
||||
chain.index.AddNode(node)
|
||||
chain.bestNode = node
|
||||
}
|
||||
|
||||
// Create a utxo view with a fake utxo for the inputs used in the
|
||||
@ -142,11 +144,9 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Value: 10,
|
||||
}},
|
||||
})
|
||||
utxoView := blockchain.NewUtxoViewpoint()
|
||||
utxoView := NewUtxoViewpoint()
|
||||
utxoView.AddTxOuts(targetTx, int32(numBlocksToActivate)-4)
|
||||
bestHeader := node.Header()
|
||||
bestHash := bestHeader.BlockHash()
|
||||
utxoView.SetBestHash(&bestHash)
|
||||
utxoView.SetBestHash(&node.hash)
|
||||
|
||||
// Create a utxo that spends the fake utxo created above for use in the
|
||||
// transactions created in the tests. It has an age of 4 blocks. Note
|
||||
@ -190,9 +190,9 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
tx *wire.MsgTx
|
||||
view *blockchain.UtxoViewpoint
|
||||
view *UtxoViewpoint
|
||||
mempool bool
|
||||
want *blockchain.SequenceLock
|
||||
want *SequenceLock
|
||||
}{
|
||||
// A transaction of version one should disable sequence locks
|
||||
// as the new sequence number semantics only apply to
|
||||
@ -202,11 +202,11 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 1,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(false, 3),
|
||||
Sequence: LockTimeToSequence(false, 3),
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: -1,
|
||||
BlockHeight: -1,
|
||||
},
|
||||
@ -223,7 +223,7 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: -1,
|
||||
BlockHeight: -1,
|
||||
},
|
||||
@ -239,11 +239,11 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 2,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(true, 2),
|
||||
Sequence: LockTimeToSequence(true, 2),
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: medianTime - 1,
|
||||
BlockHeight: -1,
|
||||
},
|
||||
@ -257,11 +257,11 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 2,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(true, 1024),
|
||||
Sequence: LockTimeToSequence(true, 1024),
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: medianTime + 1023,
|
||||
BlockHeight: -1,
|
||||
},
|
||||
@ -277,18 +277,18 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 2,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(true, 2560),
|
||||
Sequence: LockTimeToSequence(true, 2560),
|
||||
}, {
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(false, 4),
|
||||
Sequence: LockTimeToSequence(false, 4),
|
||||
}, {
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(false, 5) |
|
||||
Sequence: LockTimeToSequence(false, 5) |
|
||||
wire.SequenceLockTimeDisabled,
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: medianTime + (5 << wire.SequenceLockTimeGranularity) - 1,
|
||||
BlockHeight: prevUtxoHeight + 3,
|
||||
},
|
||||
@ -302,11 +302,11 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 2,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(false, 3),
|
||||
Sequence: LockTimeToSequence(false, 3),
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: -1,
|
||||
BlockHeight: prevUtxoHeight + 2,
|
||||
},
|
||||
@ -319,14 +319,14 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 2,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(true, 5120),
|
||||
Sequence: LockTimeToSequence(true, 5120),
|
||||
}, {
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(true, 2560),
|
||||
Sequence: LockTimeToSequence(true, 2560),
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: medianTime + (10 << wire.SequenceLockTimeGranularity) - 1,
|
||||
BlockHeight: -1,
|
||||
},
|
||||
@ -340,14 +340,14 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 2,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(false, 1),
|
||||
Sequence: LockTimeToSequence(false, 1),
|
||||
}, {
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(false, 11),
|
||||
Sequence: LockTimeToSequence(false, 11),
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: -1,
|
||||
BlockHeight: prevUtxoHeight + 10,
|
||||
},
|
||||
@ -360,20 +360,20 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 2,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(true, 2560),
|
||||
Sequence: LockTimeToSequence(true, 2560),
|
||||
}, {
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(true, 6656),
|
||||
Sequence: LockTimeToSequence(true, 6656),
|
||||
}, {
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(false, 3),
|
||||
Sequence: LockTimeToSequence(false, 3),
|
||||
}, {
|
||||
PreviousOutPoint: utxo,
|
||||
Sequence: blockchain.LockTimeToSequence(false, 9),
|
||||
Sequence: LockTimeToSequence(false, 9),
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: medianTime + (13 << wire.SequenceLockTimeGranularity) - 1,
|
||||
BlockHeight: prevUtxoHeight + 8,
|
||||
},
|
||||
@ -389,12 +389,12 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 2,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: unConfUtxo,
|
||||
Sequence: blockchain.LockTimeToSequence(false, 2),
|
||||
Sequence: LockTimeToSequence(false, 2),
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
mempool: true,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: -1,
|
||||
BlockHeight: nextBlockHeight + 1,
|
||||
},
|
||||
@ -407,12 +407,12 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
Version: 2,
|
||||
TxIn: []*wire.TxIn{{
|
||||
PreviousOutPoint: unConfUtxo,
|
||||
Sequence: blockchain.LockTimeToSequence(true, 1024),
|
||||
Sequence: LockTimeToSequence(true, 1024),
|
||||
}},
|
||||
},
|
||||
view: utxoView,
|
||||
mempool: true,
|
||||
want: &blockchain.SequenceLock{
|
||||
want: &SequenceLock{
|
||||
Seconds: nextMedianTime + 1023,
|
||||
BlockHeight: -1,
|
||||
},
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Copyright (c) 2013-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"compress/bzip2"
|
||||
@ -12,14 +12,15 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/database"
|
||||
_ "github.com/btcsuite/btcd/database/ffldb"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -56,10 +57,68 @@ func isSupportedDbType(dbType string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// loadBlocks reads files containing bitcoin block data (gzipped but otherwise
|
||||
// in the format bitcoind writes) from disk and returns them as an array of
|
||||
// btcutil.Block. This is largely borrowed from the test code in btcdb.
|
||||
func loadBlocks(filename string) (blocks []*btcutil.Block, err error) {
|
||||
filename = filepath.Join("testdata/", filename)
|
||||
|
||||
var network = wire.MainNet
|
||||
var dr io.Reader
|
||||
var fi io.ReadCloser
|
||||
|
||||
fi, err = os.Open(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasSuffix(filename, ".bz2") {
|
||||
dr = bzip2.NewReader(fi)
|
||||
} else {
|
||||
dr = fi
|
||||
}
|
||||
defer fi.Close()
|
||||
|
||||
var block *btcutil.Block
|
||||
|
||||
err = nil
|
||||
for height := int64(1); err == nil; height++ {
|
||||
var rintbuf uint32
|
||||
err = binary.Read(dr, binary.LittleEndian, &rintbuf)
|
||||
if err == io.EOF {
|
||||
// hit end of file at expected offset: no warning
|
||||
height--
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if rintbuf != uint32(network) {
|
||||
break
|
||||
}
|
||||
err = binary.Read(dr, binary.LittleEndian, &rintbuf)
|
||||
blocklen := rintbuf
|
||||
|
||||
rbytes := make([]byte, blocklen)
|
||||
|
||||
// read block
|
||||
dr.Read(rbytes)
|
||||
|
||||
block, err = btcutil.NewBlockFromBytes(rbytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
blocks = append(blocks, block)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// chainSetup is used to create a new db and chain instance with the genesis
|
||||
// block already inserted. In addition to the new chain instance, it returns
|
||||
// a teardown function the caller should invoke when done testing to clean up.
|
||||
func chainSetup(dbName string, params *chaincfg.Params) (*blockchain.BlockChain, func(), error) {
|
||||
func chainSetup(dbName string, params *chaincfg.Params) (*BlockChain, func(), error) {
|
||||
if !isSupportedDbType(testDbType) {
|
||||
return nil, nil, fmt.Errorf("unsupported db type %v", testDbType)
|
||||
}
|
||||
@ -113,11 +172,11 @@ func chainSetup(dbName string, params *chaincfg.Params) (*blockchain.BlockChain,
|
||||
paramsCopy := *params
|
||||
|
||||
// Create the main chain instance.
|
||||
chain, err := blockchain.New(&blockchain.Config{
|
||||
chain, err := New(&Config{
|
||||
DB: db,
|
||||
ChainParams: ¶msCopy,
|
||||
Checkpoints: nil,
|
||||
TimeSource: blockchain.NewMedianTime(),
|
||||
TimeSource: NewMedianTime(),
|
||||
SigCache: txscript.NewSigCache(1000),
|
||||
})
|
||||
if err != nil {
|
||||
@ -129,7 +188,7 @@ func chainSetup(dbName string, params *chaincfg.Params) (*blockchain.BlockChain,
|
||||
}
|
||||
|
||||
// loadUtxoView returns a utxo view loaded from a file.
|
||||
func loadUtxoView(filename string) (*blockchain.UtxoViewpoint, error) {
|
||||
func loadUtxoView(filename string) (*UtxoViewpoint, error) {
|
||||
// The utxostore file format is:
|
||||
// <tx hash><serialized utxo len><serialized utxo>
|
||||
//
|
||||
@ -151,7 +210,7 @@ func loadUtxoView(filename string) (*blockchain.UtxoViewpoint, error) {
|
||||
}
|
||||
defer fi.Close()
|
||||
|
||||
view := blockchain.NewUtxoViewpoint()
|
||||
view := NewUtxoViewpoint()
|
||||
for {
|
||||
// Hash of the utxo entry.
|
||||
var hash chainhash.Hash
|
||||
@ -179,7 +238,7 @@ func loadUtxoView(filename string) (*blockchain.UtxoViewpoint, error) {
|
||||
}
|
||||
|
||||
// Deserialize it and add it to the view.
|
||||
utxoEntry, err := blockchain.TstDeserializeUtxoEntry(serialized)
|
||||
utxoEntry, err := deserializeUtxoEntry(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -188,3 +247,53 @@ func loadUtxoView(filename string) (*blockchain.UtxoViewpoint, error) {
|
||||
|
||||
return view, nil
|
||||
}
|
||||
|
||||
// TstSetCoinbaseMaturity makes the ability to set the coinbase maturity
|
||||
// available when running tests.
|
||||
func (b *BlockChain) TstSetCoinbaseMaturity(maturity uint16) {
|
||||
b.chainParams.CoinbaseMaturity = maturity
|
||||
}
|
||||
|
||||
// newFakeChain returns a chain that is usable for syntetic tests. It is
|
||||
// important to note that this chain has no database associated with it, so
|
||||
// it is not usable with all functions and the tests must take care when making
|
||||
// use of it.
|
||||
func newFakeChain(params *chaincfg.Params) *BlockChain {
|
||||
// Create a genesis block node and block index index populated with it
|
||||
// for use when creating the fake chain below.
|
||||
node := newBlockNode(¶ms.GenesisBlock.Header, 0)
|
||||
node.inMainChain = true
|
||||
index := newBlockIndex(nil, params)
|
||||
index.AddNode(node)
|
||||
|
||||
targetTimespan := int64(params.TargetTimespan / time.Second)
|
||||
targetTimePerBlock := int64(params.TargetTimePerBlock / time.Second)
|
||||
adjustmentFactor := params.RetargetAdjustmentFactor
|
||||
return &BlockChain{
|
||||
chainParams: params,
|
||||
timeSource: NewMedianTime(),
|
||||
minRetargetTimespan: targetTimespan / adjustmentFactor,
|
||||
maxRetargetTimespan: targetTimespan * adjustmentFactor,
|
||||
blocksPerRetarget: int32(targetTimespan / targetTimePerBlock),
|
||||
index: index,
|
||||
warningCaches: newThresholdCaches(vbNumBits),
|
||||
deploymentCaches: newThresholdCaches(chaincfg.DefinedDeployments),
|
||||
bestNode: node,
|
||||
}
|
||||
}
|
||||
|
||||
// newFakeNode creates a block node connected to the passed parent with the
|
||||
// provided fields populated and fake values for the other fields.
|
||||
func newFakeNode(parent *blockNode, blockVersion int32, bits uint32, timestamp time.Time) *blockNode {
|
||||
// Make up a header and create a block node from it.
|
||||
header := &wire.BlockHeader{
|
||||
Version: blockVersion,
|
||||
PrevBlock: parent.hash,
|
||||
Bits: bits,
|
||||
Timestamp: timestamp,
|
||||
}
|
||||
node := newBlockNode(header, parent.height+1)
|
||||
node.parent = parent
|
||||
node.workSum.Add(parent.workSum, node.workSum)
|
||||
return node
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
)
|
||||
|
||||
// TestBigToCompact ensures BigToCompact converts big integers to the expected
|
||||
// compact representation.
|
||||
func TestBigToCompact(t *testing.T) {
|
||||
tests := []struct {
|
||||
in int64
|
||||
@ -22,7 +22,7 @@ func TestBigToCompact(t *testing.T) {
|
||||
|
||||
for x, test := range tests {
|
||||
n := big.NewInt(test.in)
|
||||
r := blockchain.BigToCompact(n)
|
||||
r := BigToCompact(n)
|
||||
if r != test.out {
|
||||
t.Errorf("TestBigToCompact test #%d failed: got %d want %d\n",
|
||||
x, r, test.out)
|
||||
@ -31,6 +31,8 @@ func TestBigToCompact(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestCompactToBig ensures CompactToBig converts numbers using the compact
|
||||
// representation to the expected big intergers.
|
||||
func TestCompactToBig(t *testing.T) {
|
||||
tests := []struct {
|
||||
in uint32
|
||||
@ -40,7 +42,7 @@ func TestCompactToBig(t *testing.T) {
|
||||
}
|
||||
|
||||
for x, test := range tests {
|
||||
n := blockchain.CompactToBig(test.in)
|
||||
n := CompactToBig(test.in)
|
||||
want := big.NewInt(test.out)
|
||||
if n.Cmp(want) != 0 {
|
||||
t.Errorf("TestCompactToBig test #%d failed: got %d want %d\n",
|
||||
@ -50,6 +52,8 @@ func TestCompactToBig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestCalcWork ensures CalcWork calculates the expected work value from values
|
||||
// in compact representation.
|
||||
func TestCalcWork(t *testing.T) {
|
||||
tests := []struct {
|
||||
in uint32
|
||||
@ -61,7 +65,7 @@ func TestCalcWork(t *testing.T) {
|
||||
for x, test := range tests {
|
||||
bits := uint32(test.in)
|
||||
|
||||
r := blockchain.CalcWork(bits)
|
||||
r := CalcWork(bits)
|
||||
if r.Int64() != test.out {
|
||||
t.Errorf("TestCalcWork test #%d failed: got %v want %d\n",
|
||||
x, r.Int64(), test.out)
|
||||
|
@ -1,59 +1,57 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
)
|
||||
|
||||
// TestErrorCodeStringer tests the stringized output for the ErrorCode type.
|
||||
func TestErrorCodeStringer(t *testing.T) {
|
||||
tests := []struct {
|
||||
in blockchain.ErrorCode
|
||||
in ErrorCode
|
||||
want string
|
||||
}{
|
||||
{blockchain.ErrDuplicateBlock, "ErrDuplicateBlock"},
|
||||
{blockchain.ErrBlockTooBig, "ErrBlockTooBig"},
|
||||
{blockchain.ErrBlockVersionTooOld, "ErrBlockVersionTooOld"},
|
||||
{blockchain.ErrInvalidTime, "ErrInvalidTime"},
|
||||
{blockchain.ErrTimeTooOld, "ErrTimeTooOld"},
|
||||
{blockchain.ErrTimeTooNew, "ErrTimeTooNew"},
|
||||
{blockchain.ErrDifficultyTooLow, "ErrDifficultyTooLow"},
|
||||
{blockchain.ErrUnexpectedDifficulty, "ErrUnexpectedDifficulty"},
|
||||
{blockchain.ErrHighHash, "ErrHighHash"},
|
||||
{blockchain.ErrBadMerkleRoot, "ErrBadMerkleRoot"},
|
||||
{blockchain.ErrBadCheckpoint, "ErrBadCheckpoint"},
|
||||
{blockchain.ErrForkTooOld, "ErrForkTooOld"},
|
||||
{blockchain.ErrCheckpointTimeTooOld, "ErrCheckpointTimeTooOld"},
|
||||
{blockchain.ErrNoTransactions, "ErrNoTransactions"},
|
||||
{blockchain.ErrTooManyTransactions, "ErrTooManyTransactions"},
|
||||
{blockchain.ErrNoTxInputs, "ErrNoTxInputs"},
|
||||
{blockchain.ErrNoTxOutputs, "ErrNoTxOutputs"},
|
||||
{blockchain.ErrTxTooBig, "ErrTxTooBig"},
|
||||
{blockchain.ErrBadTxOutValue, "ErrBadTxOutValue"},
|
||||
{blockchain.ErrDuplicateTxInputs, "ErrDuplicateTxInputs"},
|
||||
{blockchain.ErrBadTxInput, "ErrBadTxInput"},
|
||||
{blockchain.ErrBadCheckpoint, "ErrBadCheckpoint"},
|
||||
{blockchain.ErrMissingTxOut, "ErrMissingTxOut"},
|
||||
{blockchain.ErrUnfinalizedTx, "ErrUnfinalizedTx"},
|
||||
{blockchain.ErrDuplicateTx, "ErrDuplicateTx"},
|
||||
{blockchain.ErrOverwriteTx, "ErrOverwriteTx"},
|
||||
{blockchain.ErrImmatureSpend, "ErrImmatureSpend"},
|
||||
{blockchain.ErrSpendTooHigh, "ErrSpendTooHigh"},
|
||||
{blockchain.ErrBadFees, "ErrBadFees"},
|
||||
{blockchain.ErrTooManySigOps, "ErrTooManySigOps"},
|
||||
{blockchain.ErrFirstTxNotCoinbase, "ErrFirstTxNotCoinbase"},
|
||||
{blockchain.ErrMultipleCoinbases, "ErrMultipleCoinbases"},
|
||||
{blockchain.ErrBadCoinbaseScriptLen, "ErrBadCoinbaseScriptLen"},
|
||||
{blockchain.ErrBadCoinbaseValue, "ErrBadCoinbaseValue"},
|
||||
{blockchain.ErrMissingCoinbaseHeight, "ErrMissingCoinbaseHeight"},
|
||||
{blockchain.ErrBadCoinbaseHeight, "ErrBadCoinbaseHeight"},
|
||||
{blockchain.ErrScriptMalformed, "ErrScriptMalformed"},
|
||||
{blockchain.ErrScriptValidation, "ErrScriptValidation"},
|
||||
{ErrDuplicateBlock, "ErrDuplicateBlock"},
|
||||
{ErrBlockTooBig, "ErrBlockTooBig"},
|
||||
{ErrBlockVersionTooOld, "ErrBlockVersionTooOld"},
|
||||
{ErrInvalidTime, "ErrInvalidTime"},
|
||||
{ErrTimeTooOld, "ErrTimeTooOld"},
|
||||
{ErrTimeTooNew, "ErrTimeTooNew"},
|
||||
{ErrDifficultyTooLow, "ErrDifficultyTooLow"},
|
||||
{ErrUnexpectedDifficulty, "ErrUnexpectedDifficulty"},
|
||||
{ErrHighHash, "ErrHighHash"},
|
||||
{ErrBadMerkleRoot, "ErrBadMerkleRoot"},
|
||||
{ErrBadCheckpoint, "ErrBadCheckpoint"},
|
||||
{ErrForkTooOld, "ErrForkTooOld"},
|
||||
{ErrCheckpointTimeTooOld, "ErrCheckpointTimeTooOld"},
|
||||
{ErrNoTransactions, "ErrNoTransactions"},
|
||||
{ErrTooManyTransactions, "ErrTooManyTransactions"},
|
||||
{ErrNoTxInputs, "ErrNoTxInputs"},
|
||||
{ErrNoTxOutputs, "ErrNoTxOutputs"},
|
||||
{ErrTxTooBig, "ErrTxTooBig"},
|
||||
{ErrBadTxOutValue, "ErrBadTxOutValue"},
|
||||
{ErrDuplicateTxInputs, "ErrDuplicateTxInputs"},
|
||||
{ErrBadTxInput, "ErrBadTxInput"},
|
||||
{ErrBadCheckpoint, "ErrBadCheckpoint"},
|
||||
{ErrMissingTxOut, "ErrMissingTxOut"},
|
||||
{ErrUnfinalizedTx, "ErrUnfinalizedTx"},
|
||||
{ErrDuplicateTx, "ErrDuplicateTx"},
|
||||
{ErrOverwriteTx, "ErrOverwriteTx"},
|
||||
{ErrImmatureSpend, "ErrImmatureSpend"},
|
||||
{ErrSpendTooHigh, "ErrSpendTooHigh"},
|
||||
{ErrBadFees, "ErrBadFees"},
|
||||
{ErrTooManySigOps, "ErrTooManySigOps"},
|
||||
{ErrFirstTxNotCoinbase, "ErrFirstTxNotCoinbase"},
|
||||
{ErrMultipleCoinbases, "ErrMultipleCoinbases"},
|
||||
{ErrBadCoinbaseScriptLen, "ErrBadCoinbaseScriptLen"},
|
||||
{ErrBadCoinbaseValue, "ErrBadCoinbaseValue"},
|
||||
{ErrMissingCoinbaseHeight, "ErrMissingCoinbaseHeight"},
|
||||
{ErrBadCoinbaseHeight, "ErrBadCoinbaseHeight"},
|
||||
{ErrScriptMalformed, "ErrScriptMalformed"},
|
||||
{ErrScriptValidation, "ErrScriptValidation"},
|
||||
{0xffff, "Unknown ErrorCode (65535)"},
|
||||
}
|
||||
|
||||
@ -71,15 +69,15 @@ func TestErrorCodeStringer(t *testing.T) {
|
||||
// TestRuleError tests the error output for the RuleError type.
|
||||
func TestRuleError(t *testing.T) {
|
||||
tests := []struct {
|
||||
in blockchain.RuleError
|
||||
in RuleError
|
||||
want string
|
||||
}{
|
||||
{
|
||||
blockchain.RuleError{Description: "duplicate block"},
|
||||
RuleError{Description: "duplicate block"},
|
||||
"duplicate block",
|
||||
},
|
||||
{
|
||||
blockchain.RuleError{Description: "human-readable error"},
|
||||
RuleError{Description: "human-readable error"},
|
||||
"human-readable error",
|
||||
},
|
||||
}
|
||||
@ -100,19 +98,19 @@ func TestDeploymentError(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
in blockchain.DeploymentError
|
||||
in DeploymentError
|
||||
want string
|
||||
}{
|
||||
{
|
||||
blockchain.DeploymentError(0),
|
||||
DeploymentError(0),
|
||||
"deployment ID 0 does not exist",
|
||||
},
|
||||
{
|
||||
blockchain.DeploymentError(10),
|
||||
DeploymentError(10),
|
||||
"deployment ID 10 does not exist",
|
||||
},
|
||||
{
|
||||
blockchain.DeploymentError(123),
|
||||
DeploymentError(123),
|
||||
"deployment ID 123 does not exist",
|
||||
},
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2016 The Decred developers
|
||||
// Copyright (c) 2016 The btcsuite developers
|
||||
// Copyright (c) 2016-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -7,16 +7,128 @@ package blockchain_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/blockchain/fullblocktests"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/database"
|
||||
_ "github.com/btcsuite/btcd/database/ffldb"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
const (
|
||||
// testDbType is the database backend type to use for the tests.
|
||||
testDbType = "ffldb"
|
||||
|
||||
// testDbRoot is the root directory used to create all test databases.
|
||||
testDbRoot = "testdbs"
|
||||
|
||||
// blockDataNet is the expected network in the test block data.
|
||||
blockDataNet = wire.MainNet
|
||||
)
|
||||
|
||||
// filesExists returns whether or not the named file or directory exists.
|
||||
func fileExists(name string) bool {
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// isSupportedDbType returns whether or not the passed database type is
|
||||
// currently supported.
|
||||
func isSupportedDbType(dbType string) bool {
|
||||
supportedDrivers := database.SupportedDrivers()
|
||||
for _, driver := range supportedDrivers {
|
||||
if dbType == driver {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// chainSetup is used to create a new db and chain instance with the genesis
|
||||
// block already inserted. In addition to the new chain instance, it returns
|
||||
// a teardown function the caller should invoke when done testing to clean up.
|
||||
func chainSetup(dbName string, params *chaincfg.Params) (*blockchain.BlockChain, func(), error) {
|
||||
if !isSupportedDbType(testDbType) {
|
||||
return nil, nil, fmt.Errorf("unsupported db type %v", testDbType)
|
||||
}
|
||||
|
||||
// Handle memory database specially since it doesn't need the disk
|
||||
// specific handling.
|
||||
var db database.DB
|
||||
var teardown func()
|
||||
if testDbType == "memdb" {
|
||||
ndb, err := database.Create(testDbType)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating db: %v", err)
|
||||
}
|
||||
db = ndb
|
||||
|
||||
// Setup a teardown function for cleaning up. This function is
|
||||
// returned to the caller to be invoked when it is done testing.
|
||||
teardown = func() {
|
||||
db.Close()
|
||||
}
|
||||
} else {
|
||||
// Create the root directory for test databases.
|
||||
if !fileExists(testDbRoot) {
|
||||
if err := os.MkdirAll(testDbRoot, 0700); err != nil {
|
||||
err := fmt.Errorf("unable to create test db "+
|
||||
"root: %v", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new database to store the accepted blocks into.
|
||||
dbPath := filepath.Join(testDbRoot, dbName)
|
||||
_ = os.RemoveAll(dbPath)
|
||||
ndb, err := database.Create(testDbType, dbPath, blockDataNet)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating db: %v", err)
|
||||
}
|
||||
db = ndb
|
||||
|
||||
// Setup a teardown function for cleaning up. This function is
|
||||
// returned to the caller to be invoked when it is done testing.
|
||||
teardown = func() {
|
||||
db.Close()
|
||||
os.RemoveAll(dbPath)
|
||||
os.RemoveAll(testDbRoot)
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the chain params to ensure any modifications the tests do to
|
||||
// the chain parameters do not affect the global instance.
|
||||
paramsCopy := *params
|
||||
|
||||
// Create the main chain instance.
|
||||
chain, err := blockchain.New(&blockchain.Config{
|
||||
DB: db,
|
||||
ChainParams: ¶msCopy,
|
||||
Checkpoints: nil,
|
||||
TimeSource: blockchain.NewMedianTime(),
|
||||
SigCache: txscript.NewSigCache(1000),
|
||||
})
|
||||
if err != nil {
|
||||
teardown()
|
||||
err := fmt.Errorf("failed to create chain instance: %v", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
return chain, teardown, nil
|
||||
}
|
||||
|
||||
// TestFullBlocks ensures all tests generated by the fullblocktests package
|
||||
// have the expected result when processed via ProcessBlock.
|
||||
func TestFullBlocks(t *testing.T) {
|
||||
|
@ -1,99 +0,0 @@
|
||||
// Copyright (c) 2013-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
This test file is part of the blockchain package rather than than the
|
||||
blockchain_test package so it can bridge access to the internals to properly
|
||||
test cases which are either not possible or can't reliably be tested via the
|
||||
public interface. The functions are only exported while the tests are being
|
||||
run.
|
||||
*/
|
||||
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// TstSetCoinbaseMaturity makes the ability to set the coinbase maturity
|
||||
// available to the test package.
|
||||
func (b *BlockChain) TstSetCoinbaseMaturity(maturity uint16) {
|
||||
b.chainParams.CoinbaseMaturity = maturity
|
||||
}
|
||||
|
||||
// TstTimeSorter makes the internal timeSorter type available to the test
|
||||
// package.
|
||||
func TstTimeSorter(times []int64) sort.Interface {
|
||||
return timeSorter(times)
|
||||
}
|
||||
|
||||
// TstCheckSerializedHeight makes the internal checkSerializedHeight function
|
||||
// available to the test package.
|
||||
var TstCheckSerializedHeight = checkSerializedHeight
|
||||
|
||||
// TstSetMaxMedianTimeEntries makes the ability to set the maximum number of
|
||||
// median time entries available to the test package.
|
||||
func TstSetMaxMedianTimeEntries(val int) {
|
||||
maxMedianTimeEntries = val
|
||||
}
|
||||
|
||||
// TstCheckBlockScripts makes the internal checkBlockScripts function available
|
||||
// to the test package.
|
||||
var TstCheckBlockScripts = checkBlockScripts
|
||||
|
||||
// TstDeserializeUtxoEntry makes the internal deserializeUtxoEntry function
|
||||
// available to the test package.
|
||||
var TstDeserializeUtxoEntry = deserializeUtxoEntry
|
||||
|
||||
// TstNewFakeChain returns a chain that is usable for syntetic tests. It is
|
||||
// important to note that this chain has no database associated with it, so
|
||||
// it is not usable with all functions and the tests must take care when making
|
||||
// use of it.
|
||||
func TstNewFakeChain(params *chaincfg.Params) (*BlockChain, *blockNode) {
|
||||
// Create a genesis block node and block index index populated with it
|
||||
// for use when creating the fake chain below.
|
||||
node := newBlockNode(¶ms.GenesisBlock.Header, 0)
|
||||
node.inMainChain = true
|
||||
index := newBlockIndex(nil, params)
|
||||
index.AddNode(node)
|
||||
|
||||
targetTimespan := int64(params.TargetTimespan / time.Second)
|
||||
targetTimePerBlock := int64(params.TargetTimePerBlock / time.Second)
|
||||
adjustmentFactor := params.RetargetAdjustmentFactor
|
||||
return &BlockChain{
|
||||
chainParams: params,
|
||||
timeSource: NewMedianTime(),
|
||||
minRetargetTimespan: targetTimespan / adjustmentFactor,
|
||||
maxRetargetTimespan: targetTimespan * adjustmentFactor,
|
||||
blocksPerRetarget: int32(targetTimespan / targetTimePerBlock),
|
||||
index: index,
|
||||
warningCaches: newThresholdCaches(vbNumBits),
|
||||
deploymentCaches: newThresholdCaches(chaincfg.DefinedDeployments),
|
||||
bestNode: node,
|
||||
}, node
|
||||
}
|
||||
|
||||
// TstNewFakeNode creates a block node connected to the passed parent with the
|
||||
// provided fields populated and fake values for the other fields and adds it
|
||||
// to the blockchain's index as well as makes it the best node.
|
||||
func (b *BlockChain) TstNewFakeNode(parent *blockNode, blockVersion int32, bits uint32, timestamp time.Time) *blockNode {
|
||||
// Make up a header and create a block node from it.
|
||||
header := &wire.BlockHeader{
|
||||
Version: blockVersion,
|
||||
PrevBlock: parent.hash,
|
||||
Bits: bits,
|
||||
Timestamp: timestamp,
|
||||
}
|
||||
node := newBlockNode(header, parent.height+1)
|
||||
node.parent = parent
|
||||
node.workSum.Add(parent.workSum, node.workSum)
|
||||
|
||||
b.index.AddNode(node)
|
||||
b.bestNode = node
|
||||
return node
|
||||
}
|
@ -1,15 +1,13 @@
|
||||
// Copyright (c) 2013-2014 The btcsuite developers
|
||||
// Copyright (c) 2013-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
)
|
||||
|
||||
// TestMedianTime tests the medianTime implementation.
|
||||
@ -55,11 +53,11 @@ func TestMedianTime(t *testing.T) {
|
||||
}
|
||||
|
||||
// Modify the max number of allowed median time entries for these tests.
|
||||
blockchain.TstSetMaxMedianTimeEntries(10)
|
||||
defer blockchain.TstSetMaxMedianTimeEntries(200)
|
||||
maxMedianTimeEntries = 10
|
||||
defer func() { maxMedianTimeEntries = 200 }()
|
||||
|
||||
for i, test := range tests {
|
||||
filter := blockchain.NewMedianTime()
|
||||
filter := NewMedianTime()
|
||||
for j, offset := range test.in {
|
||||
id := strconv.Itoa(j)
|
||||
now := time.Unix(time.Now().Unix(), 0)
|
||||
|
@ -1,20 +1,19 @@
|
||||
// Copyright (c) 2013-2014 The btcsuite developers
|
||||
// Copyright (c) 2013-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// TestMerkle tests the BuildMerkleTreeStore API.
|
||||
func TestMerkle(t *testing.T) {
|
||||
block := btcutil.NewBlock(&Block100000)
|
||||
merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false)
|
||||
merkles := BuildMerkleTreeStore(block.Transactions(), false)
|
||||
calculatedMerkleRoot := merkles[len(merkles)-1]
|
||||
wantMerkle := &Block100000.Header.MerkleRoot
|
||||
if !wantMerkle.IsEqual(calculatedMerkleRoot) {
|
||||
|
@ -2,12 +2,11 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
)
|
||||
|
||||
@ -27,8 +26,8 @@ func TestNotifications(t *testing.T) {
|
||||
defer teardownFunc()
|
||||
|
||||
notificationCount := 0
|
||||
callback := func(notification *blockchain.Notification) {
|
||||
if notification.Type == blockchain.NTBlockAccepted {
|
||||
callback := func(notification *Notification) {
|
||||
if notification.Type == NTBlockAccepted {
|
||||
notificationCount++
|
||||
}
|
||||
}
|
||||
@ -40,7 +39,7 @@ func TestNotifications(t *testing.T) {
|
||||
chain.Subscribe(callback)
|
||||
}
|
||||
|
||||
_, _, err = chain.ProcessBlock(blocks[1], blockchain.BFNone)
|
||||
_, _, err = chain.ProcessBlock(blocks[1], BFNone)
|
||||
if err != nil {
|
||||
t.Fatalf("ProcessBlock fail on block 1: %v\n", err)
|
||||
}
|
||||
|
@ -1,129 +0,0 @@
|
||||
// Copyright (c) 2013-2014 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
|
||||
import (
|
||||
"compress/bzip2"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// TestReorganization loads a set of test blocks which force a chain
|
||||
// reorganization to test the block chain handling code.
|
||||
// The test blocks were originally from a post on the bitcoin talk forums:
|
||||
// https://bitcointalk.org/index.php?topic=46370.msg577556#msg577556
|
||||
func TestReorganization(t *testing.T) {
|
||||
// Intentionally load the side chain blocks out of order to ensure
|
||||
// orphans are handled properly along with chain reorganization.
|
||||
testFiles := []string{
|
||||
"blk_0_to_4.dat.bz2",
|
||||
"blk_4A.dat.bz2",
|
||||
"blk_5A.dat.bz2",
|
||||
"blk_3A.dat.bz2",
|
||||
}
|
||||
|
||||
var blocks []*btcutil.Block
|
||||
for _, file := range testFiles {
|
||||
blockTmp, err := loadBlocks(file)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading file: %v\n", err)
|
||||
}
|
||||
blocks = append(blocks, blockTmp...)
|
||||
}
|
||||
|
||||
t.Logf("Number of blocks: %v\n", len(blocks))
|
||||
|
||||
// Create a new database and chain instance to run tests against.
|
||||
chain, teardownFunc, err := chainSetup("reorg", &chaincfg.MainNetParams)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to setup chain instance: %v", err)
|
||||
return
|
||||
}
|
||||
defer teardownFunc()
|
||||
|
||||
// Since we're not dealing with the real block chain set the coinbase
|
||||
// maturity to 1.
|
||||
chain.TstSetCoinbaseMaturity(1)
|
||||
|
||||
expectedOrphans := map[int]struct{}{5: {}, 6: {}}
|
||||
for i := 1; i < len(blocks); i++ {
|
||||
_, isOrphan, err := chain.ProcessBlock(blocks[i], blockchain.BFNone)
|
||||
if err != nil {
|
||||
t.Errorf("ProcessBlock fail on block %v: %v\n", i, err)
|
||||
return
|
||||
}
|
||||
if _, ok := expectedOrphans[i]; !ok && isOrphan {
|
||||
t.Errorf("ProcessBlock incorrectly returned block %v "+
|
||||
"is an orphan\n", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loadBlocks reads files containing bitcoin block data (gzipped but otherwise
|
||||
// in the format bitcoind writes) from disk and returns them as an array of
|
||||
// btcutil.Block. This is largely borrowed from the test code in btcdb.
|
||||
func loadBlocks(filename string) (blocks []*btcutil.Block, err error) {
|
||||
filename = filepath.Join("testdata/", filename)
|
||||
|
||||
var network = wire.MainNet
|
||||
var dr io.Reader
|
||||
var fi io.ReadCloser
|
||||
|
||||
fi, err = os.Open(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasSuffix(filename, ".bz2") {
|
||||
dr = bzip2.NewReader(fi)
|
||||
} else {
|
||||
dr = fi
|
||||
}
|
||||
defer fi.Close()
|
||||
|
||||
var block *btcutil.Block
|
||||
|
||||
err = nil
|
||||
for height := int64(1); err == nil; height++ {
|
||||
var rintbuf uint32
|
||||
err = binary.Read(dr, binary.LittleEndian, &rintbuf)
|
||||
if err == io.EOF {
|
||||
// hit end of file at expected offset: no warning
|
||||
height--
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if rintbuf != uint32(network) {
|
||||
break
|
||||
}
|
||||
err = binary.Read(dr, binary.LittleEndian, &rintbuf)
|
||||
blocklen := rintbuf
|
||||
|
||||
rbytes := make([]byte, blocklen)
|
||||
|
||||
// read block
|
||||
dr.Read(rbytes)
|
||||
|
||||
block, err = btcutil.NewBlockFromBytes(rbytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
blocks = append(blocks, block)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -1,15 +1,14 @@
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Copyright (c) 2013-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
)
|
||||
|
||||
@ -42,8 +41,7 @@ func TestCheckBlockScripts(t *testing.T) {
|
||||
}
|
||||
|
||||
scriptFlags := txscript.ScriptBip16
|
||||
err = blockchain.TstCheckBlockScripts(blocks[0], view, scriptFlags,
|
||||
nil, nil)
|
||||
err = checkBlockScripts(blocks[0], view, scriptFlags, nil, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Transaction script validation failed: %v\n", err)
|
||||
return
|
||||
|
@ -2,14 +2,12 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
)
|
||||
|
||||
// TestTimeSorter tests the timeSorter implementation.
|
||||
@ -39,7 +37,7 @@ func TestTimeSorter(t *testing.T) {
|
||||
for i, test := range tests {
|
||||
result := make([]int64, len(test.in))
|
||||
copy(result, test.in)
|
||||
sort.Sort(blockchain.TstTimeSorter(result))
|
||||
sort.Sort(timeSorter(result))
|
||||
if !reflect.DeepEqual(result, test.want) {
|
||||
t.Errorf("timeSorter #%d got %v want %v", i, result,
|
||||
test.want)
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Copyright (c) 2013-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain_test
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"math"
|
||||
@ -10,7 +10,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@ -20,15 +19,15 @@ import (
|
||||
// TestSequenceLocksActive tests the SequenceLockActive function to ensure it
|
||||
// works as expected in all possible combinations/scenarios.
|
||||
func TestSequenceLocksActive(t *testing.T) {
|
||||
seqLock := func(h int32, s int64) *blockchain.SequenceLock {
|
||||
return &blockchain.SequenceLock{
|
||||
seqLock := func(h int32, s int64) *SequenceLock {
|
||||
return &SequenceLock{
|
||||
Seconds: s,
|
||||
BlockHeight: h,
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
seqLock *blockchain.SequenceLock
|
||||
seqLock *SequenceLock
|
||||
blockHeight int32
|
||||
mtp time.Time
|
||||
|
||||
@ -55,7 +54,7 @@ func TestSequenceLocksActive(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d sequence locks tests", len(tests))
|
||||
for i, test := range tests {
|
||||
got := blockchain.SequenceLockActive(test.seqLock,
|
||||
got := SequenceLockActive(test.seqLock,
|
||||
test.blockHeight, test.mtp)
|
||||
if got != test.want {
|
||||
t.Fatalf("SequenceLockActive #%d got %v want %v", i,
|
||||
@ -89,8 +88,8 @@ func TestCheckConnectBlock(t *testing.T) {
|
||||
func TestCheckBlockSanity(t *testing.T) {
|
||||
powLimit := chaincfg.MainNetParams.PowLimit
|
||||
block := btcutil.NewBlock(&Block100000)
|
||||
timeSource := blockchain.NewMedianTime()
|
||||
err := blockchain.CheckBlockSanity(block, powLimit, timeSource)
|
||||
timeSource := NewMedianTime()
|
||||
err := CheckBlockSanity(block, powLimit, timeSource)
|
||||
if err != nil {
|
||||
t.Errorf("CheckBlockSanity: %v", err)
|
||||
}
|
||||
@ -99,7 +98,7 @@ func TestCheckBlockSanity(t *testing.T) {
|
||||
// second fails.
|
||||
timestamp := block.MsgBlock().Header.Timestamp
|
||||
block.MsgBlock().Header.Timestamp = timestamp.Add(time.Nanosecond)
|
||||
err = blockchain.CheckBlockSanity(block, powLimit, timeSource)
|
||||
err = CheckBlockSanity(block, powLimit, timeSource)
|
||||
if err == nil {
|
||||
t.Errorf("CheckBlockSanity: error is nil when it shouldn't be")
|
||||
}
|
||||
@ -115,11 +114,11 @@ func TestCheckSerializedHeight(t *testing.T) {
|
||||
coinbaseTx.AddTxIn(wire.NewTxIn(coinbaseOutpoint, nil, nil))
|
||||
|
||||
// Expected rule errors.
|
||||
missingHeightError := blockchain.RuleError{
|
||||
ErrorCode: blockchain.ErrMissingCoinbaseHeight,
|
||||
missingHeightError := RuleError{
|
||||
ErrorCode: ErrMissingCoinbaseHeight,
|
||||
}
|
||||
badHeightError := blockchain.RuleError{
|
||||
ErrorCode: blockchain.ErrBadCoinbaseHeight,
|
||||
badHeightError := RuleError{
|
||||
ErrorCode: ErrBadCoinbaseHeight,
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@ -151,15 +150,15 @@ func TestCheckSerializedHeight(t *testing.T) {
|
||||
msgTx.TxIn[0].SignatureScript = test.sigScript
|
||||
tx := btcutil.NewTx(msgTx)
|
||||
|
||||
err := blockchain.TstCheckSerializedHeight(tx, test.wantHeight)
|
||||
err := checkSerializedHeight(tx, test.wantHeight)
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
t.Errorf("checkSerializedHeight #%d wrong error type "+
|
||||
"got: %v <%T>, want: %T", i, err, err, test.err)
|
||||
continue
|
||||
}
|
||||
|
||||
if rerr, ok := err.(blockchain.RuleError); ok {
|
||||
trerr := test.err.(blockchain.RuleError)
|
||||
if rerr, ok := err.(RuleError); ok {
|
||||
trerr := test.err.(RuleError)
|
||||
if rerr.ErrorCode != trerr.ErrorCode {
|
||||
t.Errorf("checkSerializedHeight #%d wrong "+
|
||||
"error code got: %v, want: %v", i,
|
||||
|
Loading…
Reference in New Issue
Block a user