Skip to content

Commit

Permalink
[Tests] check specific validation error in miner tests
Browse files Browse the repository at this point in the history
BOOST_CHECK_THROW merely checks that some std::runtime_error is
thrown, but not which one.

One example of how this could lead to a test passing when a developer
introduces a consensus bug: the test for the sigops limit assumes
that CreateNewBlock fails with bad-blk-sigops. However it can
also fail with bad-txns-vout-negative, e.g. if a naive developer lowers
BLOCKSUBSIDY to 1*COIN in the test.

BOOST_CHECK_EXCEPTION allows an additional predicate function. This
commit uses this for all exceptions that are checked for in
miner_tets.cpp:
* bad-blk-sigops
* bad-cb-multiple
* bad-txns-inputs-missingorspent
* block-validation-failed

An instance of the CheckRejectInvalid class (for a given validation string)
is passed to BOOST_CHECK_EXCEPTION.
  • Loading branch information
Sjors committed Nov 9, 2017
1 parent f7388e9 commit 12781db
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions src/test/miner_tests.cpp
Expand Up @@ -26,6 +26,17 @@

BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup)

// BOOST_CHECK_EXCEPTION predicates to check the specific validation error
class HasReason {
public:
HasReason(const std::string& reason) : m_reason(reason) {}
bool operator() (const std::runtime_error& e) const {
return std::string(e.what()).find(m_reason) != std::string::npos;
};
private:
const std::string m_reason;
};

static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);

static BlockAssembler AssemblerForTest(const CChainParams& params) {
Expand Down Expand Up @@ -264,7 +275,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
tx.vin[0].prevout.hash = hash;
}
BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);

BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops"));
mempool.clear();

tx.vin[0].prevout.hash = txFirst[0]->GetHash();
Expand Down Expand Up @@ -304,7 +316,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// orphan in mempool, template creation fails
hash = tx.GetHash();
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx));
BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
mempool.clear();

// child with higher feerate than parent
Expand Down Expand Up @@ -332,7 +344,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
hash = tx.GetHash();
// give it a fee so it'll get mined
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
// Should throw bad-cb-multiple
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple"));
mempool.clear();

// double spend txn pair in mempool, template creation fails
Expand All @@ -345,7 +358,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].scriptPubKey = CScript() << OP_2;
hash = tx.GetHash();
mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
mempool.clear();

// subsidy changing
Expand Down Expand Up @@ -389,7 +402,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue -= LOWFEE;
hash = tx.GetHash();
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
// Should throw block-validation-failed
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
mempool.clear();

// Delete the dummy blocks again.
Expand Down

0 comments on commit 12781db

Please sign in to comment.