Skip to content

Commit

Permalink
Validate softforking mechanism with the fullblock tester.
Browse files Browse the repository at this point in the history
All corner cases are thoroughly documented in the Generate function in
file blockchain/stakeversiontests/generate.go.

Fixes btcsuite#525
  • Loading branch information
marcopeereboom authored and davecgh committed Dec 23, 2016
1 parent e3eb40b commit 88e4de2
Show file tree
Hide file tree
Showing 4 changed files with 2,498 additions and 2 deletions.
116 changes: 116 additions & 0 deletions blockchain/fullblocksstakeversion_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright (c) 2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package blockchain_test

import (
"testing"

"github.com/decred/dcrd/blockchain"
"github.com/decred/dcrd/blockchain/stakeversiontests"
"github.com/decred/dcrd/chaincfg"
"github.com/decred/dcrutil"
)

// TestFullBlocksStakeVersion ensures all tests generated by the
// stakeversiontests package have the expected result when processed via
// ProcessBlock.
func TestFullBlocksStakeVersion(t *testing.T) {
// Skip tests when running with -short
if testing.Short() {
t.Skip("Skipping stake/voter full block tests in short mode")
}

tests, err := stakeversiontests.Generate()
if err != nil {
t.Fatalf("failed to generate tests: %v", err)
}

// Create a new database and chain instance to run tests against.
chain, teardownFunc, err := chainSetup("stakeversiontest",
&chaincfg.SimNetParams)
if err != nil {
t.Fatalf("Failed to setup chain instance: %v", err)
}
defer teardownFunc()

// testAcceptedBlock attempts to process the block in the provided test
// instance and ensures that it was accepted according to the flags
// specified in the test.
testAcceptedBlock := func(item stakeversiontests.AcceptedBlock) {
blockHeight := item.Block.Header.Height
block := dcrutil.NewBlock(item.Block)
t.Logf("Testing block %s (hash %s, height %d)",
item.Name, block.Hash(), blockHeight)

isMainChain, isOrphan, err := chain.ProcessBlock(block,
blockchain.BFNone)
if err != nil {
t.Fatalf("block %q (hash %s, height %d) should "+
"have been accepted: %v", item.Name,
block.Hash(), blockHeight, err)
}

// Ensure the main chain and orphan flags match the values
// specified in the test.
if isMainChain != item.IsMainChain {
t.Fatalf("block %q (hash %s, height %d) unexpected main "+
"chain flag -- got %v, want %v", item.Name,
block.Hash(), blockHeight, isMainChain,
item.IsMainChain)
}
if isOrphan != item.IsOrphan {
t.Fatalf("block %q (hash %s, height %d) unexpected "+
"orphan flag -- got %v, want %v", item.Name,
block.Hash(), blockHeight, isOrphan,
item.IsOrphan)
}
}

// testRejectedBlock attempts to process the block in the provided test
// instance and ensures that it was rejected with the reject code
// specified in the test.
testRejectedBlock := func(item stakeversiontests.RejectedBlock) {
blockHeight := item.Block.Header.Height
block := dcrutil.NewBlock(item.Block)
t.Logf("Testing block %s (hash %s, height %d)",
item.Name, block.Hash(), blockHeight)

_, _, err := chain.ProcessBlock(block, blockchain.BFNone)
if err == nil {
t.Fatalf("block %q (hash %s, height %d) should not "+
"have been accepted", item.Name, block.Hash(),
blockHeight)
}

// Ensure the error code is of the expected type and the reject
// code matches the value specified in the test instance.
rerr, ok := err.(blockchain.RuleError)
if !ok {
t.Fatalf("block %q (hash %s, height %d) returned "+
"unexpected error type -- got %T, want "+
"blockchain.RuleError", item.Name, block.Hash(),
blockHeight, err)
}
if rerr.ErrorCode != item.RejectCode {
t.Fatalf("block %q (hash %s, height %d) does not have "+
"expected reject code -- got %v, want %v",
item.Name, block.Hash(), blockHeight,
rerr.ErrorCode, item.RejectCode)
}
}

for testNum, item := range tests {
switch item := item.(type) {
case stakeversiontests.AcceptedBlock:
testAcceptedBlock(item)
case stakeversiontests.RejectedBlock:
testRejectedBlock(item)
default:
t.Fatalf("test #%d, is not one of the supported test "+
"instance types -- got type: %T", testNum,
testNum, item)
}
}
}
Loading

0 comments on commit 88e4de2

Please sign in to comment.