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:
Dave Collins 2017-08-19 19:21:36 -05:00
parent f4fe6c373e
commit e02fbcf5a1
No known key found for this signature in database
GPG key ID: B8904D9D9C93D1F2
14 changed files with 366 additions and 381 deletions

View file

@ -2,12 +2,11 @@
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"testing" "testing"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
) )
@ -17,7 +16,7 @@ func BenchmarkIsCoinBase(b *testing.B) {
tx, _ := btcutil.NewBlock(&Block100000).Tx(1) tx, _ := btcutil.NewBlock(&Block100000).Tx(1)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { 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] tx := Block100000.Transactions[1]
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
blockchain.IsCoinBaseTx(tx) IsCoinBaseTx(tx)
} }
} }

View file

@ -2,13 +2,12 @@
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"testing" "testing"
"time" "time"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
@ -49,7 +48,7 @@ func TestHaveBlock(t *testing.T) {
chain.TstSetCoinbaseMaturity(1) chain.TstSetCoinbaseMaturity(1)
for i := 1; i < len(blocks); i++ { 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 { if err != nil {
t.Errorf("ProcessBlock fail on block %v: %v\n", i, err) t.Errorf("ProcessBlock fail on block %v: %v\n", i, err)
return return
@ -63,7 +62,7 @@ func TestHaveBlock(t *testing.T) {
// Insert an orphan block. // Insert an orphan block.
_, isOrphan, err := chain.ProcessBlock(btcutil.NewBlock(&Block100000), _, isOrphan, err := chain.ProcessBlock(btcutil.NewBlock(&Block100000),
blockchain.BFNone) BFNone)
if err != nil { if err != nil {
t.Errorf("Unable to process block: %v", err) t.Errorf("Unable to process block: %v", err)
return return
@ -125,12 +124,15 @@ func TestCalcSequenceLock(t *testing.T) {
blockVersion := int32(0x20000000 | (uint32(1) << csvBit)) blockVersion := int32(0x20000000 | (uint32(1) << csvBit))
// Generate enough synthetic blocks to activate CSV. // Generate enough synthetic blocks to activate CSV.
chain, node := blockchain.TstNewFakeChain(netParams) chain := newFakeChain(netParams)
node := chain.bestNode
blockTime := node.Header().Timestamp blockTime := node.Header().Timestamp
numBlocksToActivate := (netParams.MinerConfirmationWindow * 3) numBlocksToActivate := (netParams.MinerConfirmationWindow * 3)
for i := uint32(0); i < numBlocksToActivate; i++ { for i := uint32(0); i < numBlocksToActivate; i++ {
blockTime = blockTime.Add(time.Second) 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 // 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, Value: 10,
}}, }},
}) })
utxoView := blockchain.NewUtxoViewpoint() utxoView := NewUtxoViewpoint()
utxoView.AddTxOuts(targetTx, int32(numBlocksToActivate)-4) utxoView.AddTxOuts(targetTx, int32(numBlocksToActivate)-4)
bestHeader := node.Header() utxoView.SetBestHash(&node.hash)
bestHash := bestHeader.BlockHash()
utxoView.SetBestHash(&bestHash)
// Create a utxo that spends the fake utxo created above for use in the // 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 // transactions created in the tests. It has an age of 4 blocks. Note
@ -190,9 +190,9 @@ func TestCalcSequenceLock(t *testing.T) {
tests := []struct { tests := []struct {
tx *wire.MsgTx tx *wire.MsgTx
view *blockchain.UtxoViewpoint view *UtxoViewpoint
mempool bool mempool bool
want *blockchain.SequenceLock want *SequenceLock
}{ }{
// A transaction of version one should disable sequence locks // A transaction of version one should disable sequence locks
// as the new sequence number semantics only apply to // as the new sequence number semantics only apply to
@ -202,11 +202,11 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 1, Version: 1,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(false, 3), Sequence: LockTimeToSequence(false, 3),
}}, }},
}, },
view: utxoView, view: utxoView,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: -1, Seconds: -1,
BlockHeight: -1, BlockHeight: -1,
}, },
@ -223,7 +223,7 @@ func TestCalcSequenceLock(t *testing.T) {
}}, }},
}, },
view: utxoView, view: utxoView,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: -1, Seconds: -1,
BlockHeight: -1, BlockHeight: -1,
}, },
@ -239,11 +239,11 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 2, Version: 2,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(true, 2), Sequence: LockTimeToSequence(true, 2),
}}, }},
}, },
view: utxoView, view: utxoView,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: medianTime - 1, Seconds: medianTime - 1,
BlockHeight: -1, BlockHeight: -1,
}, },
@ -257,11 +257,11 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 2, Version: 2,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(true, 1024), Sequence: LockTimeToSequence(true, 1024),
}}, }},
}, },
view: utxoView, view: utxoView,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: medianTime + 1023, Seconds: medianTime + 1023,
BlockHeight: -1, BlockHeight: -1,
}, },
@ -277,18 +277,18 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 2, Version: 2,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(true, 2560), Sequence: LockTimeToSequence(true, 2560),
}, { }, {
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(false, 4), Sequence: LockTimeToSequence(false, 4),
}, { }, {
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(false, 5) | Sequence: LockTimeToSequence(false, 5) |
wire.SequenceLockTimeDisabled, wire.SequenceLockTimeDisabled,
}}, }},
}, },
view: utxoView, view: utxoView,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: medianTime + (5 << wire.SequenceLockTimeGranularity) - 1, Seconds: medianTime + (5 << wire.SequenceLockTimeGranularity) - 1,
BlockHeight: prevUtxoHeight + 3, BlockHeight: prevUtxoHeight + 3,
}, },
@ -302,11 +302,11 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 2, Version: 2,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(false, 3), Sequence: LockTimeToSequence(false, 3),
}}, }},
}, },
view: utxoView, view: utxoView,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: -1, Seconds: -1,
BlockHeight: prevUtxoHeight + 2, BlockHeight: prevUtxoHeight + 2,
}, },
@ -319,14 +319,14 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 2, Version: 2,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(true, 5120), Sequence: LockTimeToSequence(true, 5120),
}, { }, {
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(true, 2560), Sequence: LockTimeToSequence(true, 2560),
}}, }},
}, },
view: utxoView, view: utxoView,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: medianTime + (10 << wire.SequenceLockTimeGranularity) - 1, Seconds: medianTime + (10 << wire.SequenceLockTimeGranularity) - 1,
BlockHeight: -1, BlockHeight: -1,
}, },
@ -340,14 +340,14 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 2, Version: 2,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(false, 1), Sequence: LockTimeToSequence(false, 1),
}, { }, {
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(false, 11), Sequence: LockTimeToSequence(false, 11),
}}, }},
}, },
view: utxoView, view: utxoView,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: -1, Seconds: -1,
BlockHeight: prevUtxoHeight + 10, BlockHeight: prevUtxoHeight + 10,
}, },
@ -360,20 +360,20 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 2, Version: 2,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(true, 2560), Sequence: LockTimeToSequence(true, 2560),
}, { }, {
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(true, 6656), Sequence: LockTimeToSequence(true, 6656),
}, { }, {
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(false, 3), Sequence: LockTimeToSequence(false, 3),
}, { }, {
PreviousOutPoint: utxo, PreviousOutPoint: utxo,
Sequence: blockchain.LockTimeToSequence(false, 9), Sequence: LockTimeToSequence(false, 9),
}}, }},
}, },
view: utxoView, view: utxoView,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: medianTime + (13 << wire.SequenceLockTimeGranularity) - 1, Seconds: medianTime + (13 << wire.SequenceLockTimeGranularity) - 1,
BlockHeight: prevUtxoHeight + 8, BlockHeight: prevUtxoHeight + 8,
}, },
@ -389,12 +389,12 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 2, Version: 2,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: unConfUtxo, PreviousOutPoint: unConfUtxo,
Sequence: blockchain.LockTimeToSequence(false, 2), Sequence: LockTimeToSequence(false, 2),
}}, }},
}, },
view: utxoView, view: utxoView,
mempool: true, mempool: true,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: -1, Seconds: -1,
BlockHeight: nextBlockHeight + 1, BlockHeight: nextBlockHeight + 1,
}, },
@ -407,12 +407,12 @@ func TestCalcSequenceLock(t *testing.T) {
Version: 2, Version: 2,
TxIn: []*wire.TxIn{{ TxIn: []*wire.TxIn{{
PreviousOutPoint: unConfUtxo, PreviousOutPoint: unConfUtxo,
Sequence: blockchain.LockTimeToSequence(true, 1024), Sequence: LockTimeToSequence(true, 1024),
}}, }},
}, },
view: utxoView, view: utxoView,
mempool: true, mempool: true,
want: &blockchain.SequenceLock{ want: &SequenceLock{
Seconds: nextMedianTime + 1023, Seconds: nextMedianTime + 1023,
BlockHeight: -1, BlockHeight: -1,
}, },

View file

@ -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 // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"compress/bzip2" "compress/bzip2"
@ -12,14 +12,15 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/database"
_ "github.com/btcsuite/btcd/database/ffldb" _ "github.com/btcsuite/btcd/database/ffldb"
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
) )
const ( const (
@ -56,10 +57,68 @@ func isSupportedDbType(dbType string) bool {
return false 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 // 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 // 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. // 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) { if !isSupportedDbType(testDbType) {
return nil, nil, fmt.Errorf("unsupported db type %v", 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 paramsCopy := *params
// Create the main chain instance. // Create the main chain instance.
chain, err := blockchain.New(&blockchain.Config{ chain, err := New(&Config{
DB: db, DB: db,
ChainParams: &paramsCopy, ChainParams: &paramsCopy,
Checkpoints: nil, Checkpoints: nil,
TimeSource: blockchain.NewMedianTime(), TimeSource: NewMedianTime(),
SigCache: txscript.NewSigCache(1000), SigCache: txscript.NewSigCache(1000),
}) })
if err != nil { 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. // 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: // The utxostore file format is:
// <tx hash><serialized utxo len><serialized utxo> // <tx hash><serialized utxo len><serialized utxo>
// //
@ -151,7 +210,7 @@ func loadUtxoView(filename string) (*blockchain.UtxoViewpoint, error) {
} }
defer fi.Close() defer fi.Close()
view := blockchain.NewUtxoViewpoint() view := NewUtxoViewpoint()
for { for {
// Hash of the utxo entry. // Hash of the utxo entry.
var hash chainhash.Hash var hash chainhash.Hash
@ -179,7 +238,7 @@ func loadUtxoView(filename string) (*blockchain.UtxoViewpoint, error) {
} }
// Deserialize it and add it to the view. // Deserialize it and add it to the view.
utxoEntry, err := blockchain.TstDeserializeUtxoEntry(serialized) utxoEntry, err := deserializeUtxoEntry(serialized)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -188,3 +247,53 @@ func loadUtxoView(filename string) (*blockchain.UtxoViewpoint, error) {
return view, nil 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(&params.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
}

View file

@ -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 // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"math/big" "math/big"
"testing" "testing"
"github.com/btcsuite/btcd/blockchain"
) )
// TestBigToCompact ensures BigToCompact converts big integers to the expected
// compact representation.
func TestBigToCompact(t *testing.T) { func TestBigToCompact(t *testing.T) {
tests := []struct { tests := []struct {
in int64 in int64
@ -22,7 +22,7 @@ func TestBigToCompact(t *testing.T) {
for x, test := range tests { for x, test := range tests {
n := big.NewInt(test.in) n := big.NewInt(test.in)
r := blockchain.BigToCompact(n) r := BigToCompact(n)
if r != test.out { if r != test.out {
t.Errorf("TestBigToCompact test #%d failed: got %d want %d\n", t.Errorf("TestBigToCompact test #%d failed: got %d want %d\n",
x, r, test.out) 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) { func TestCompactToBig(t *testing.T) {
tests := []struct { tests := []struct {
in uint32 in uint32
@ -40,7 +42,7 @@ func TestCompactToBig(t *testing.T) {
} }
for x, test := range tests { for x, test := range tests {
n := blockchain.CompactToBig(test.in) n := CompactToBig(test.in)
want := big.NewInt(test.out) want := big.NewInt(test.out)
if n.Cmp(want) != 0 { if n.Cmp(want) != 0 {
t.Errorf("TestCompactToBig test #%d failed: got %d want %d\n", 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) { func TestCalcWork(t *testing.T) {
tests := []struct { tests := []struct {
in uint32 in uint32
@ -61,7 +65,7 @@ func TestCalcWork(t *testing.T) {
for x, test := range tests { for x, test := range tests {
bits := uint32(test.in) bits := uint32(test.in)
r := blockchain.CalcWork(bits) r := CalcWork(bits)
if r.Int64() != test.out { if r.Int64() != test.out {
t.Errorf("TestCalcWork test #%d failed: got %v want %d\n", t.Errorf("TestCalcWork test #%d failed: got %v want %d\n",
x, r.Int64(), test.out) x, r.Int64(), test.out)

View file

@ -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 // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"testing" "testing"
"github.com/btcsuite/btcd/blockchain"
) )
// TestErrorCodeStringer tests the stringized output for the ErrorCode type. // TestErrorCodeStringer tests the stringized output for the ErrorCode type.
func TestErrorCodeStringer(t *testing.T) { func TestErrorCodeStringer(t *testing.T) {
tests := []struct { tests := []struct {
in blockchain.ErrorCode in ErrorCode
want string want string
}{ }{
{blockchain.ErrDuplicateBlock, "ErrDuplicateBlock"}, {ErrDuplicateBlock, "ErrDuplicateBlock"},
{blockchain.ErrBlockTooBig, "ErrBlockTooBig"}, {ErrBlockTooBig, "ErrBlockTooBig"},
{blockchain.ErrBlockVersionTooOld, "ErrBlockVersionTooOld"}, {ErrBlockVersionTooOld, "ErrBlockVersionTooOld"},
{blockchain.ErrInvalidTime, "ErrInvalidTime"}, {ErrInvalidTime, "ErrInvalidTime"},
{blockchain.ErrTimeTooOld, "ErrTimeTooOld"}, {ErrTimeTooOld, "ErrTimeTooOld"},
{blockchain.ErrTimeTooNew, "ErrTimeTooNew"}, {ErrTimeTooNew, "ErrTimeTooNew"},
{blockchain.ErrDifficultyTooLow, "ErrDifficultyTooLow"}, {ErrDifficultyTooLow, "ErrDifficultyTooLow"},
{blockchain.ErrUnexpectedDifficulty, "ErrUnexpectedDifficulty"}, {ErrUnexpectedDifficulty, "ErrUnexpectedDifficulty"},
{blockchain.ErrHighHash, "ErrHighHash"}, {ErrHighHash, "ErrHighHash"},
{blockchain.ErrBadMerkleRoot, "ErrBadMerkleRoot"}, {ErrBadMerkleRoot, "ErrBadMerkleRoot"},
{blockchain.ErrBadCheckpoint, "ErrBadCheckpoint"}, {ErrBadCheckpoint, "ErrBadCheckpoint"},
{blockchain.ErrForkTooOld, "ErrForkTooOld"}, {ErrForkTooOld, "ErrForkTooOld"},
{blockchain.ErrCheckpointTimeTooOld, "ErrCheckpointTimeTooOld"}, {ErrCheckpointTimeTooOld, "ErrCheckpointTimeTooOld"},
{blockchain.ErrNoTransactions, "ErrNoTransactions"}, {ErrNoTransactions, "ErrNoTransactions"},
{blockchain.ErrTooManyTransactions, "ErrTooManyTransactions"}, {ErrTooManyTransactions, "ErrTooManyTransactions"},
{blockchain.ErrNoTxInputs, "ErrNoTxInputs"}, {ErrNoTxInputs, "ErrNoTxInputs"},
{blockchain.ErrNoTxOutputs, "ErrNoTxOutputs"}, {ErrNoTxOutputs, "ErrNoTxOutputs"},
{blockchain.ErrTxTooBig, "ErrTxTooBig"}, {ErrTxTooBig, "ErrTxTooBig"},
{blockchain.ErrBadTxOutValue, "ErrBadTxOutValue"}, {ErrBadTxOutValue, "ErrBadTxOutValue"},
{blockchain.ErrDuplicateTxInputs, "ErrDuplicateTxInputs"}, {ErrDuplicateTxInputs, "ErrDuplicateTxInputs"},
{blockchain.ErrBadTxInput, "ErrBadTxInput"}, {ErrBadTxInput, "ErrBadTxInput"},
{blockchain.ErrBadCheckpoint, "ErrBadCheckpoint"}, {ErrBadCheckpoint, "ErrBadCheckpoint"},
{blockchain.ErrMissingTxOut, "ErrMissingTxOut"}, {ErrMissingTxOut, "ErrMissingTxOut"},
{blockchain.ErrUnfinalizedTx, "ErrUnfinalizedTx"}, {ErrUnfinalizedTx, "ErrUnfinalizedTx"},
{blockchain.ErrDuplicateTx, "ErrDuplicateTx"}, {ErrDuplicateTx, "ErrDuplicateTx"},
{blockchain.ErrOverwriteTx, "ErrOverwriteTx"}, {ErrOverwriteTx, "ErrOverwriteTx"},
{blockchain.ErrImmatureSpend, "ErrImmatureSpend"}, {ErrImmatureSpend, "ErrImmatureSpend"},
{blockchain.ErrSpendTooHigh, "ErrSpendTooHigh"}, {ErrSpendTooHigh, "ErrSpendTooHigh"},
{blockchain.ErrBadFees, "ErrBadFees"}, {ErrBadFees, "ErrBadFees"},
{blockchain.ErrTooManySigOps, "ErrTooManySigOps"}, {ErrTooManySigOps, "ErrTooManySigOps"},
{blockchain.ErrFirstTxNotCoinbase, "ErrFirstTxNotCoinbase"}, {ErrFirstTxNotCoinbase, "ErrFirstTxNotCoinbase"},
{blockchain.ErrMultipleCoinbases, "ErrMultipleCoinbases"}, {ErrMultipleCoinbases, "ErrMultipleCoinbases"},
{blockchain.ErrBadCoinbaseScriptLen, "ErrBadCoinbaseScriptLen"}, {ErrBadCoinbaseScriptLen, "ErrBadCoinbaseScriptLen"},
{blockchain.ErrBadCoinbaseValue, "ErrBadCoinbaseValue"}, {ErrBadCoinbaseValue, "ErrBadCoinbaseValue"},
{blockchain.ErrMissingCoinbaseHeight, "ErrMissingCoinbaseHeight"}, {ErrMissingCoinbaseHeight, "ErrMissingCoinbaseHeight"},
{blockchain.ErrBadCoinbaseHeight, "ErrBadCoinbaseHeight"}, {ErrBadCoinbaseHeight, "ErrBadCoinbaseHeight"},
{blockchain.ErrScriptMalformed, "ErrScriptMalformed"}, {ErrScriptMalformed, "ErrScriptMalformed"},
{blockchain.ErrScriptValidation, "ErrScriptValidation"}, {ErrScriptValidation, "ErrScriptValidation"},
{0xffff, "Unknown ErrorCode (65535)"}, {0xffff, "Unknown ErrorCode (65535)"},
} }
@ -71,15 +69,15 @@ func TestErrorCodeStringer(t *testing.T) {
// TestRuleError tests the error output for the RuleError type. // TestRuleError tests the error output for the RuleError type.
func TestRuleError(t *testing.T) { func TestRuleError(t *testing.T) {
tests := []struct { tests := []struct {
in blockchain.RuleError in RuleError
want string want string
}{ }{
{ {
blockchain.RuleError{Description: "duplicate block"}, RuleError{Description: "duplicate block"},
"duplicate block", "duplicate block",
}, },
{ {
blockchain.RuleError{Description: "human-readable error"}, RuleError{Description: "human-readable error"},
"human-readable error", "human-readable error",
}, },
} }
@ -100,19 +98,19 @@ func TestDeploymentError(t *testing.T) {
t.Parallel() t.Parallel()
tests := []struct { tests := []struct {
in blockchain.DeploymentError in DeploymentError
want string want string
}{ }{
{ {
blockchain.DeploymentError(0), DeploymentError(0),
"deployment ID 0 does not exist", "deployment ID 0 does not exist",
}, },
{ {
blockchain.DeploymentError(10), DeploymentError(10),
"deployment ID 10 does not exist", "deployment ID 10 does not exist",
}, },
{ {
blockchain.DeploymentError(123), DeploymentError(123),
"deployment ID 123 does not exist", "deployment ID 123 does not exist",
}, },
} }

View file

@ -1,5 +1,5 @@
// Copyright (c) 2016 The Decred developers // 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 // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -7,16 +7,128 @@ package blockchain_test
import ( import (
"bytes" "bytes"
"fmt"
"os"
"path/filepath"
"testing" "testing"
"github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/blockchain/fullblocktests" "github.com/btcsuite/btcd/blockchain/fullblocktests"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash" "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/btcd/wire"
"github.com/btcsuite/btcutil" "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: &paramsCopy,
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 // TestFullBlocks ensures all tests generated by the fullblocktests package
// have the expected result when processed via ProcessBlock. // have the expected result when processed via ProcessBlock.
func TestFullBlocks(t *testing.T) { func TestFullBlocks(t *testing.T) {

View file

@ -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(&params.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
}

View file

@ -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 // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"strconv" "strconv"
"testing" "testing"
"time" "time"
"github.com/btcsuite/btcd/blockchain"
) )
// TestMedianTime tests the medianTime implementation. // 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. // Modify the max number of allowed median time entries for these tests.
blockchain.TstSetMaxMedianTimeEntries(10) maxMedianTimeEntries = 10
defer blockchain.TstSetMaxMedianTimeEntries(200) defer func() { maxMedianTimeEntries = 200 }()
for i, test := range tests { for i, test := range tests {
filter := blockchain.NewMedianTime() filter := NewMedianTime()
for j, offset := range test.in { for j, offset := range test.in {
id := strconv.Itoa(j) id := strconv.Itoa(j)
now := time.Unix(time.Now().Unix(), 0) now := time.Unix(time.Now().Unix(), 0)

View file

@ -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 // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"testing" "testing"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
) )
// TestMerkle tests the BuildMerkleTreeStore API. // TestMerkle tests the BuildMerkleTreeStore API.
func TestMerkle(t *testing.T) { func TestMerkle(t *testing.T) {
block := btcutil.NewBlock(&Block100000) block := btcutil.NewBlock(&Block100000)
merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false) merkles := BuildMerkleTreeStore(block.Transactions(), false)
calculatedMerkleRoot := merkles[len(merkles)-1] calculatedMerkleRoot := merkles[len(merkles)-1]
wantMerkle := &Block100000.Header.MerkleRoot wantMerkle := &Block100000.Header.MerkleRoot
if !wantMerkle.IsEqual(calculatedMerkleRoot) { if !wantMerkle.IsEqual(calculatedMerkleRoot) {

View file

@ -2,12 +2,11 @@
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"testing" "testing"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
) )
@ -27,8 +26,8 @@ func TestNotifications(t *testing.T) {
defer teardownFunc() defer teardownFunc()
notificationCount := 0 notificationCount := 0
callback := func(notification *blockchain.Notification) { callback := func(notification *Notification) {
if notification.Type == blockchain.NTBlockAccepted { if notification.Type == NTBlockAccepted {
notificationCount++ notificationCount++
} }
} }
@ -40,7 +39,7 @@ func TestNotifications(t *testing.T) {
chain.Subscribe(callback) chain.Subscribe(callback)
} }
_, _, err = chain.ProcessBlock(blocks[1], blockchain.BFNone) _, _, err = chain.ProcessBlock(blocks[1], BFNone)
if err != nil { if err != nil {
t.Fatalf("ProcessBlock fail on block 1: %v\n", err) t.Fatalf("ProcessBlock fail on block 1: %v\n", err)
} }

View file

@ -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
}

View file

@ -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 // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"fmt" "fmt"
"runtime" "runtime"
"testing" "testing"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
) )
@ -42,8 +41,7 @@ func TestCheckBlockScripts(t *testing.T) {
} }
scriptFlags := txscript.ScriptBip16 scriptFlags := txscript.ScriptBip16
err = blockchain.TstCheckBlockScripts(blocks[0], view, scriptFlags, err = checkBlockScripts(blocks[0], view, scriptFlags, nil, nil)
nil, nil)
if err != nil { if err != nil {
t.Errorf("Transaction script validation failed: %v\n", err) t.Errorf("Transaction script validation failed: %v\n", err)
return return

View file

@ -2,14 +2,12 @@
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"reflect" "reflect"
"sort" "sort"
"testing" "testing"
"github.com/btcsuite/btcd/blockchain"
) )
// TestTimeSorter tests the timeSorter implementation. // TestTimeSorter tests the timeSorter implementation.
@ -39,7 +37,7 @@ func TestTimeSorter(t *testing.T) {
for i, test := range tests { for i, test := range tests {
result := make([]int64, len(test.in)) result := make([]int64, len(test.in))
copy(result, test.in) copy(result, test.in)
sort.Sort(blockchain.TstTimeSorter(result)) sort.Sort(timeSorter(result))
if !reflect.DeepEqual(result, test.want) { if !reflect.DeepEqual(result, test.want) {
t.Errorf("timeSorter #%d got %v want %v", i, result, t.Errorf("timeSorter #%d got %v want %v", i, result,
test.want) test.want)

View file

@ -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 // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package blockchain_test package blockchain
import ( import (
"math" "math"
@ -10,7 +10,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
@ -20,15 +19,15 @@ import (
// TestSequenceLocksActive tests the SequenceLockActive function to ensure it // TestSequenceLocksActive tests the SequenceLockActive function to ensure it
// works as expected in all possible combinations/scenarios. // works as expected in all possible combinations/scenarios.
func TestSequenceLocksActive(t *testing.T) { func TestSequenceLocksActive(t *testing.T) {
seqLock := func(h int32, s int64) *blockchain.SequenceLock { seqLock := func(h int32, s int64) *SequenceLock {
return &blockchain.SequenceLock{ return &SequenceLock{
Seconds: s, Seconds: s,
BlockHeight: h, BlockHeight: h,
} }
} }
tests := []struct { tests := []struct {
seqLock *blockchain.SequenceLock seqLock *SequenceLock
blockHeight int32 blockHeight int32
mtp time.Time mtp time.Time
@ -55,7 +54,7 @@ func TestSequenceLocksActive(t *testing.T) {
t.Logf("Running %d sequence locks tests", len(tests)) t.Logf("Running %d sequence locks tests", len(tests))
for i, test := range tests { for i, test := range tests {
got := blockchain.SequenceLockActive(test.seqLock, got := SequenceLockActive(test.seqLock,
test.blockHeight, test.mtp) test.blockHeight, test.mtp)
if got != test.want { if got != test.want {
t.Fatalf("SequenceLockActive #%d got %v want %v", i, t.Fatalf("SequenceLockActive #%d got %v want %v", i,
@ -89,8 +88,8 @@ func TestCheckConnectBlock(t *testing.T) {
func TestCheckBlockSanity(t *testing.T) { func TestCheckBlockSanity(t *testing.T) {
powLimit := chaincfg.MainNetParams.PowLimit powLimit := chaincfg.MainNetParams.PowLimit
block := btcutil.NewBlock(&Block100000) block := btcutil.NewBlock(&Block100000)
timeSource := blockchain.NewMedianTime() timeSource := NewMedianTime()
err := blockchain.CheckBlockSanity(block, powLimit, timeSource) err := CheckBlockSanity(block, powLimit, timeSource)
if err != nil { if err != nil {
t.Errorf("CheckBlockSanity: %v", err) t.Errorf("CheckBlockSanity: %v", err)
} }
@ -99,7 +98,7 @@ func TestCheckBlockSanity(t *testing.T) {
// second fails. // second fails.
timestamp := block.MsgBlock().Header.Timestamp timestamp := block.MsgBlock().Header.Timestamp
block.MsgBlock().Header.Timestamp = timestamp.Add(time.Nanosecond) block.MsgBlock().Header.Timestamp = timestamp.Add(time.Nanosecond)
err = blockchain.CheckBlockSanity(block, powLimit, timeSource) err = CheckBlockSanity(block, powLimit, timeSource)
if err == nil { if err == nil {
t.Errorf("CheckBlockSanity: error is nil when it shouldn't be") 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)) coinbaseTx.AddTxIn(wire.NewTxIn(coinbaseOutpoint, nil, nil))
// Expected rule errors. // Expected rule errors.
missingHeightError := blockchain.RuleError{ missingHeightError := RuleError{
ErrorCode: blockchain.ErrMissingCoinbaseHeight, ErrorCode: ErrMissingCoinbaseHeight,
} }
badHeightError := blockchain.RuleError{ badHeightError := RuleError{
ErrorCode: blockchain.ErrBadCoinbaseHeight, ErrorCode: ErrBadCoinbaseHeight,
} }
tests := []struct { tests := []struct {
@ -151,15 +150,15 @@ func TestCheckSerializedHeight(t *testing.T) {
msgTx.TxIn[0].SignatureScript = test.sigScript msgTx.TxIn[0].SignatureScript = test.sigScript
tx := btcutil.NewTx(msgTx) tx := btcutil.NewTx(msgTx)
err := blockchain.TstCheckSerializedHeight(tx, test.wantHeight) err := checkSerializedHeight(tx, test.wantHeight)
if reflect.TypeOf(err) != reflect.TypeOf(test.err) { if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
t.Errorf("checkSerializedHeight #%d wrong error type "+ t.Errorf("checkSerializedHeight #%d wrong error type "+
"got: %v <%T>, want: %T", i, err, err, test.err) "got: %v <%T>, want: %T", i, err, err, test.err)
continue continue
} }
if rerr, ok := err.(blockchain.RuleError); ok { if rerr, ok := err.(RuleError); ok {
trerr := test.err.(blockchain.RuleError) trerr := test.err.(RuleError)
if rerr.ErrorCode != trerr.ErrorCode { if rerr.ErrorCode != trerr.ErrorCode {
t.Errorf("checkSerializedHeight #%d wrong "+ t.Errorf("checkSerializedHeight #%d wrong "+
"error code got: %v, want: %v", i, "error code got: %v, want: %v", i,