aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/README.md44
-rw-r--r--src/test/data/script_tests.json7
-rw-r--r--src/test/denialofservice_tests.cpp12
-rw-r--r--src/test/merkle_tests.cpp100
-rw-r--r--src/test/pow_tests.cpp54
-rw-r--r--src/test/serialize_tests.cpp8
-rw-r--r--src/test/streams_tests.cpp244
-rw-r--r--src/test/txvalidationcache_tests.cpp20
-rw-r--r--src/test/util_tests.cpp2
9 files changed, 455 insertions, 36 deletions
diff --git a/src/test/README.md b/src/test/README.md
index 0017e3de26..96dcb072bc 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -1,3 +1,15 @@
+# Unit tests
+
+The sources in this directory are unit test cases. Boost includes a
+unit testing framework, and since Bitcoin Core already uses Boost, it makes
+sense to simply use this framework rather than require developers to
+configure some other framework (we want as few impediments to creating
+unit tests as possible).
+
+The build system is set up to compile an executable called `test_bitcoin`
+that runs all of the unit tests. The main source file is called
+`setup_common.cpp`.
+
### Compiling/running unit tests
Unit tests will be automatically compiled if dependencies were met in `./configure`
@@ -12,7 +24,7 @@ to run the bitcoind tests.
To add more bitcoind tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
.cpp files in the `test/` directory or add new .cpp files that
-implement new BOOST_AUTO_TEST_SUITE sections.
+implement new `BOOST_AUTO_TEST_SUITE` sections.
To run the bitcoin-qt tests manually, launch `src/qt/test/test_bitcoin-qt`
@@ -32,24 +44,24 @@ example, to run just the getarg_tests verbosely:
Run `test_bitcoin --help` for the full list.
-### Note on adding test cases
+### Adding test cases
-The sources in this directory are unit test cases. Boost includes a
-unit testing framework, and since bitcoin already uses boost, it makes
-sense to simply use this framework rather than require developers to
-configure some other framework (we want as few impediments to creating
-unit tests as possible).
-
-The build system is setup to compile an executable called `test_bitcoin`
-that runs all of the unit tests. The main source file is called
-setup_common.cpp. To add a new unit test file to our test suite you need
+To add a new unit test file to our test suite you need
to add the file to `src/Makefile.test.include`. The pattern is to create
one test file for each class or source file for which you want to create
-unit tests. The file naming convention is `<source_filename>_tests.cpp`
+unit tests. The file naming convention is `<source_filename>_tests.cpp`
and such files should wrap their tests in a test suite
called `<source_filename>_tests`. For an example of this pattern,
-examine `uint256_tests.cpp`.
+see `uint256_tests.cpp`.
+
+### Logging and debugging in unit tests
+
+To write to logs from unit tests you need to use specific message methods
+provided by Boost. The simplest is `BOOST_TEST_MESSAGE`.
+
+For debugging you can launch the test_bitcoin executable with `gdb`or `lldb` and
+start debugging, just like you would with bitcoind:
-For further reading, I found the following website to be helpful in
-explaining how the boost unit test framework works:
-[http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/](http://archive.is/dRBGf).
+```bash
+gdb src/test/test_bitcoin
+```
diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json
index 9b320b6943..3241f32f56 100644
--- a/src/test/data/script_tests.json
+++ b/src/test/data/script_tests.json
@@ -829,15 +829,16 @@
["NOP", "2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["TEST DISABLED OP CODES (CVE-2010-5137)"],
["'a' 'b'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"],
["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"],
["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"],
["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"],
["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "LEFT disabled"],
["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "RIGHT disabled"],
-
-["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
-
["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"],
["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "AND disabled"],
["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "OR disabled"],
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index a50d6854f8..b0a613372f 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -151,17 +151,17 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false);
const Consensus::Params& consensusParams = Params().GetConsensus();
- constexpr int nMaxOutbound = 8;
+ constexpr int max_outbound_full_relay = 8;
CConnman::Options options;
options.nMaxConnections = 125;
- options.nMaxOutbound = nMaxOutbound;
+ options.m_max_outbound_full_relay = max_outbound_full_relay;
options.nMaxFeeler = 1;
connman->Init(options);
std::vector<CNode *> vNodes;
// Mock some outbound peers
- for (int i=0; i<nMaxOutbound; ++i) {
+ for (int i=0; i<max_outbound_full_relay; ++i) {
AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
}
@@ -190,7 +190,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
- for (int i=0; i<nMaxOutbound; ++i) {
+ for (int i=0; i<max_outbound_full_relay; ++i) {
BOOST_CHECK(vNodes[i]->fDisconnect == false);
}
// Last added node should get marked for eviction
@@ -203,10 +203,10 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
UpdateLastBlockAnnounceTime(vNodes.back()->GetId(), GetTime());
peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
- for (int i=0; i<nMaxOutbound-1; ++i) {
+ for (int i=0; i<max_outbound_full_relay-1; ++i) {
BOOST_CHECK(vNodes[i]->fDisconnect == false);
}
- BOOST_CHECK(vNodes[nMaxOutbound-1]->fDisconnect == true);
+ BOOST_CHECK(vNodes[max_outbound_full_relay-1]->fDisconnect == true);
BOOST_CHECK(vNodes.back()->fDisconnect == false);
bool dummy;
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index 1684258c9f..dc38a1a818 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -249,4 +249,104 @@ BOOST_AUTO_TEST_CASE(merkle_test)
}
}
+
+BOOST_AUTO_TEST_CASE(merkle_test_empty_block)
+{
+ bool mutated = false;
+ CBlock block;
+ uint256 root = BlockMerkleRoot(block, &mutated);
+
+ BOOST_CHECK_EQUAL(root.IsNull(), true);
+ BOOST_CHECK_EQUAL(mutated, false);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_test_oneTx_block)
+{
+ bool mutated = false;
+ CBlock block;
+
+ block.vtx.resize(1);
+ CMutableTransaction mtx;
+ mtx.nLockTime = 0;
+ block.vtx[0] = MakeTransactionRef(std::move(mtx));
+ uint256 root = BlockMerkleRoot(block, &mutated);
+ BOOST_CHECK_EQUAL(root, block.vtx[0]->GetHash());
+ BOOST_CHECK_EQUAL(mutated, false);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_test_OddTxWithRepeatedLastTx_block)
+{
+ bool mutated;
+ CBlock block, blockWithRepeatedLastTx;
+
+ block.vtx.resize(3);
+
+ for (std::size_t pos = 0; pos < block.vtx.size(); pos++) {
+ CMutableTransaction mtx;
+ mtx.nLockTime = pos;
+ block.vtx[pos] = MakeTransactionRef(std::move(mtx));
+ }
+
+ blockWithRepeatedLastTx = block;
+ blockWithRepeatedLastTx.vtx.push_back(blockWithRepeatedLastTx.vtx.back());
+
+ uint256 rootofBlock = BlockMerkleRoot(block, &mutated);
+ BOOST_CHECK_EQUAL(mutated, false);
+
+ uint256 rootofBlockWithRepeatedLastTx = BlockMerkleRoot(blockWithRepeatedLastTx, &mutated);
+ BOOST_CHECK_EQUAL(rootofBlock, rootofBlockWithRepeatedLastTx);
+ BOOST_CHECK_EQUAL(mutated, true);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_test_LeftSubtreeRightSubtree)
+{
+ CBlock block, leftSubtreeBlock, rightSubtreeBlock;
+
+ block.vtx.resize(4);
+ std::size_t pos;
+ for (pos = 0; pos < block.vtx.size(); pos++) {
+ CMutableTransaction mtx;
+ mtx.nLockTime = pos;
+ block.vtx[pos] = MakeTransactionRef(std::move(mtx));
+ }
+
+ for (pos = 0; pos < block.vtx.size() / 2; pos++)
+ leftSubtreeBlock.vtx.push_back(block.vtx[pos]);
+
+ for (pos = block.vtx.size() / 2; pos < block.vtx.size(); pos++)
+ rightSubtreeBlock.vtx.push_back(block.vtx[pos]);
+
+ uint256 root = BlockMerkleRoot(block);
+ uint256 rootOfLeftSubtree = BlockMerkleRoot(leftSubtreeBlock);
+ uint256 rootOfRightSubtree = BlockMerkleRoot(rightSubtreeBlock);
+ std::vector<uint256> leftRight;
+ leftRight.push_back(rootOfLeftSubtree);
+ leftRight.push_back(rootOfRightSubtree);
+ uint256 rootOfLR = ComputeMerkleRoot(leftRight);
+
+ BOOST_CHECK_EQUAL(root, rootOfLR);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_test_BlockWitness)
+{
+ CBlock block;
+
+ block.vtx.resize(2);
+ for (std::size_t pos = 0; pos < block.vtx.size(); pos++) {
+ CMutableTransaction mtx;
+ mtx.nLockTime = pos;
+ block.vtx[pos] = MakeTransactionRef(std::move(mtx));
+ }
+
+ uint256 blockWitness = BlockWitnessMerkleRoot(block);
+
+ std::vector<uint256> hashes;
+ hashes.resize(block.vtx.size());
+ hashes[0].SetNull();
+ hashes[1] = block.vtx[1]->GetHash();
+
+ uint256 merkelRootofHashes = ComputeMerkleRoot(hashes);
+
+ BOOST_CHECK_EQUAL(merkelRootofHashes, blockWitness);
+}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 1123d4202c..deac349867 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -60,6 +60,60 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00e1fdU);
}
+BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_negative_target)
+{
+ const auto consensus = CreateChainParams(CBaseChainParams::MAIN)->GetConsensus();
+ uint256 hash;
+ unsigned int nBits;
+ nBits = UintToArith256(consensus.powLimit).GetCompact(true);
+ hash.SetHex("0x1");
+ BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
+}
+
+BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_overflow_target)
+{
+ const auto consensus = CreateChainParams(CBaseChainParams::MAIN)->GetConsensus();
+ uint256 hash;
+ unsigned int nBits = ~0x00800000;
+ hash.SetHex("0x1");
+ BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
+}
+
+BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_too_easy_target)
+{
+ const auto consensus = CreateChainParams(CBaseChainParams::MAIN)->GetConsensus();
+ uint256 hash;
+ unsigned int nBits;
+ arith_uint256 nBits_arith = UintToArith256(consensus.powLimit);
+ nBits_arith *= 2;
+ nBits = nBits_arith.GetCompact();
+ hash.SetHex("0x1");
+ BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
+}
+
+BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_biger_hash_than_target)
+{
+ const auto consensus = CreateChainParams(CBaseChainParams::MAIN)->GetConsensus();
+ uint256 hash;
+ unsigned int nBits;
+ arith_uint256 hash_arith = UintToArith256(consensus.powLimit);
+ nBits = hash_arith.GetCompact();
+ hash_arith *= 2; // hash > nBits
+ hash = ArithToUint256(hash_arith);
+ BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
+}
+
+BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_zero_target)
+{
+ const auto consensus = CreateChainParams(CBaseChainParams::MAIN)->GetConsensus();
+ uint256 hash;
+ unsigned int nBits;
+ arith_uint256 hash_arith{0};
+ nBits = hash_arith.GetCompact();
+ hash = ArithToUint256(hash_arith);
+ BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
+}
+
BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
{
const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 8a8620938e..b90be15fba 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -258,6 +258,14 @@ static bool isCanonicalException(const std::ios_base::failure& ex)
return strcmp(expectedException.what(), ex.what()) == 0;
}
+BOOST_AUTO_TEST_CASE(vector_bool)
+{
+ std::vector<uint8_t> vec1{1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1};
+ std::vector<bool> vec2{1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1};
+
+ BOOST_CHECK(vec1 == std::vector<uint8_t>(vec2.begin(), vec2.end()));
+ BOOST_CHECK(SerializeHash(vec1) == SerializeHash(vec2));
+}
BOOST_AUTO_TEST_CASE(noncanonical)
{
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index b812cef801..638819d564 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <random.h>
#include <streams.h>
#include <test/setup_common.h>
@@ -202,4 +203,247 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
std::string(ds.begin(), ds.end()));
}
+BOOST_AUTO_TEST_CASE(streams_buffered_file)
+{
+ FILE* file = fsbridge::fopen("streams_test_tmp", "w+b");
+ // The value at each offset is the offset.
+ for (uint8_t j = 0; j < 40; ++j) {
+ fwrite(&j, 1, 1, file);
+ }
+ rewind(file);
+
+ // The buffer size (second arg) must be greater than the rewind
+ // amount (third arg).
+ try {
+ CBufferedFile bfbad(file, 25, 25, 222, 333);
+ BOOST_CHECK(false);
+ } catch (const std::exception& e) {
+ BOOST_CHECK(strstr(e.what(),
+ "Rewind limit must be less than buffer size") != nullptr);
+ }
+
+ // The buffer is 25 bytes, allow rewinding 10 bytes.
+ CBufferedFile bf(file, 25, 10, 222, 333);
+ BOOST_CHECK(!bf.eof());
+
+ // These two members have no functional effect.
+ BOOST_CHECK_EQUAL(bf.GetType(), 222);
+ BOOST_CHECK_EQUAL(bf.GetVersion(), 333);
+
+ uint8_t i;
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, 0);
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, 1);
+
+ // After reading bytes 0 and 1, we're positioned at 2.
+ BOOST_CHECK_EQUAL(bf.GetPos(), 2);
+
+ // Rewind to offset 0, ok (within the 10 byte window).
+ BOOST_CHECK(bf.SetPos(0));
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, 0);
+
+ // We can go forward to where we've been, but beyond may fail.
+ BOOST_CHECK(bf.SetPos(2));
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, 2);
+
+ // If you know the maximum number of bytes that should be
+ // read to deserialize the variable, you can limit the read
+ // extent. The current file offset is 3, so the following
+ // SetLimit() allows zero bytes to be read.
+ BOOST_CHECK(bf.SetLimit(3));
+ try {
+ bf >> i;
+ BOOST_CHECK(false);
+ } catch (const std::exception& e) {
+ BOOST_CHECK(strstr(e.what(),
+ "Read attempted past buffer limit") != nullptr);
+ }
+ // The default argument removes the limit completely.
+ BOOST_CHECK(bf.SetLimit());
+ // The read position should still be at 3 (no change).
+ BOOST_CHECK_EQUAL(bf.GetPos(), 3);
+
+ // Read from current offset, 3, forward until position 10.
+ for (uint8_t j = 3; j < 10; ++j) {
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, j);
+ }
+ BOOST_CHECK_EQUAL(bf.GetPos(), 10);
+
+ // We're guaranteed (just barely) to be able to rewind to zero.
+ BOOST_CHECK(bf.SetPos(0));
+ BOOST_CHECK_EQUAL(bf.GetPos(), 0);
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, 0);
+
+ // We can set the position forward again up to the farthest
+ // into the stream we've been, but no farther. (Attempting
+ // to go farther may succeed, but it's not guaranteed.)
+ BOOST_CHECK(bf.SetPos(10));
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, 10);
+ BOOST_CHECK_EQUAL(bf.GetPos(), 11);
+
+ // Now it's only guaranteed that we can rewind to offset 1
+ // (current read position, 11, minus rewind amount, 10).
+ BOOST_CHECK(bf.SetPos(1));
+ BOOST_CHECK_EQUAL(bf.GetPos(), 1);
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, 1);
+
+ // We can stream into large variables, even larger than
+ // the buffer size.
+ BOOST_CHECK(bf.SetPos(11));
+ {
+ uint8_t a[40 - 11];
+ bf >> a;
+ for (uint8_t j = 0; j < sizeof(a); ++j) {
+ BOOST_CHECK_EQUAL(a[j], 11 + j);
+ }
+ }
+ BOOST_CHECK_EQUAL(bf.GetPos(), 40);
+
+ // We've read the entire file, the next read should throw.
+ try {
+ bf >> i;
+ BOOST_CHECK(false);
+ } catch (const std::exception& e) {
+ BOOST_CHECK(strstr(e.what(),
+ "CBufferedFile::Fill: end of file") != nullptr);
+ }
+ // Attempting to read beyond the end sets the EOF indicator.
+ BOOST_CHECK(bf.eof());
+
+ // Still at offset 40, we can go back 10, to 30.
+ BOOST_CHECK_EQUAL(bf.GetPos(), 40);
+ BOOST_CHECK(bf.SetPos(30));
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, 30);
+ BOOST_CHECK_EQUAL(bf.GetPos(), 31);
+
+ // We're too far to rewind to position zero.
+ BOOST_CHECK(!bf.SetPos(0));
+ // But we should now be positioned at least as far back as allowed
+ // by the rewind window (relative to our farthest read position, 40).
+ BOOST_CHECK(bf.GetPos() <= 30);
+
+ // We can explicitly close the file, or the destructor will do it.
+ bf.fclose();
+
+ fs::remove("streams_test_tmp");
+}
+
+BOOST_AUTO_TEST_CASE(streams_buffered_file_rand)
+{
+ // Make this test deterministic.
+ SeedInsecureRand(true);
+
+ for (int rep = 0; rep < 50; ++rep) {
+ FILE* file = fsbridge::fopen("streams_test_tmp", "w+b");
+ size_t fileSize = InsecureRandRange(256);
+ for (uint8_t i = 0; i < fileSize; ++i) {
+ fwrite(&i, 1, 1, file);
+ }
+ rewind(file);
+
+ size_t bufSize = InsecureRandRange(300) + 1;
+ size_t rewindSize = InsecureRandRange(bufSize);
+ CBufferedFile bf(file, bufSize, rewindSize, 222, 333);
+ size_t currentPos = 0;
+ size_t maxPos = 0;
+ for (int step = 0; step < 100; ++step) {
+ if (currentPos >= fileSize)
+ break;
+
+ // We haven't read to the end of the file yet.
+ BOOST_CHECK(!bf.eof());
+ BOOST_CHECK_EQUAL(bf.GetPos(), currentPos);
+
+ // Pretend the file consists of a series of objects of varying
+ // sizes; the boundaries of the objects can interact arbitrarily
+ // with the CBufferFile's internal buffer. These first three
+ // cases simulate objects of various sizes (1, 2, 5 bytes).
+ switch (InsecureRandRange(5)) {
+ case 0: {
+ uint8_t a[1];
+ if (currentPos + 1 > fileSize)
+ continue;
+ bf.SetLimit(currentPos + 1);
+ bf >> a;
+ for (uint8_t i = 0; i < 1; ++i) {
+ BOOST_CHECK_EQUAL(a[i], currentPos);
+ currentPos++;
+ }
+ break;
+ }
+ case 1: {
+ uint8_t a[2];
+ if (currentPos + 2 > fileSize)
+ continue;
+ bf.SetLimit(currentPos + 2);
+ bf >> a;
+ for (uint8_t i = 0; i < 2; ++i) {
+ BOOST_CHECK_EQUAL(a[i], currentPos);
+ currentPos++;
+ }
+ break;
+ }
+ case 2: {
+ uint8_t a[5];
+ if (currentPos + 5 > fileSize)
+ continue;
+ bf.SetLimit(currentPos + 5);
+ bf >> a;
+ for (uint8_t i = 0; i < 5; ++i) {
+ BOOST_CHECK_EQUAL(a[i], currentPos);
+ currentPos++;
+ }
+ break;
+ }
+ case 3: {
+ // Find a byte value (that is at or ahead of the current position).
+ size_t find = currentPos + InsecureRandRange(8);
+ if (find >= fileSize)
+ find = fileSize - 1;
+ bf.FindByte(static_cast<char>(find));
+ // The value at each offset is the offset.
+ BOOST_CHECK_EQUAL(bf.GetPos(), find);
+ currentPos = find;
+
+ bf.SetLimit(currentPos + 1);
+ uint8_t i;
+ bf >> i;
+ BOOST_CHECK_EQUAL(i, currentPos);
+ currentPos++;
+ break;
+ }
+ case 4: {
+ size_t requestPos = InsecureRandRange(maxPos + 4);
+ bool okay = bf.SetPos(requestPos);
+ // The new position may differ from the requested position
+ // because we may not be able to rewind beyond the rewind
+ // window, and we may not be able to move forward beyond the
+ // farthest position we've reached so far.
+ currentPos = bf.GetPos();
+ BOOST_CHECK_EQUAL(okay, currentPos == requestPos);
+ // Check that we can position within the rewind window.
+ if (requestPos <= maxPos &&
+ maxPos > rewindSize &&
+ requestPos >= maxPos - rewindSize) {
+ // We requested a position within the rewind window.
+ BOOST_CHECK(okay);
+ }
+ break;
+ }
+ }
+ if (maxPos < currentPos)
+ maxPos = currentPos;
+ }
+ }
+ fs::remove("streams_test_tmp");
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index e69ebcc2c3..193858cca9 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -13,7 +13,7 @@
#include <boost/test/unit_test.hpp>
-bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks);
+bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks);
BOOST_AUTO_TEST_SUITE(tx_validationcache_tests)
@@ -125,7 +125,7 @@ static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t fail
// WITNESS requires P2SH
test_flags |= SCRIPT_VERIFY_P2SH;
}
- bool ret = CheckInputs(tx, state, &::ChainstateActive().CoinsTip(), true, test_flags, true, add_to_cache, txdata, nullptr);
+ bool ret = CheckInputs(tx, state, &::ChainstateActive().CoinsTip(), test_flags, true, add_to_cache, txdata, nullptr);
// CheckInputs should succeed iff test_flags doesn't intersect with
// failing_flags
bool expected_return_value = !(test_flags & failing_flags);
@@ -135,13 +135,13 @@ static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t fail
if (ret && add_to_cache) {
// Check that we get a cache hit if the tx was valid
std::vector<CScriptCheck> scriptchecks;
- BOOST_CHECK(CheckInputs(tx, state, &::ChainstateActive().CoinsTip(), true, test_flags, true, add_to_cache, txdata, &scriptchecks));
+ BOOST_CHECK(CheckInputs(tx, state, &::ChainstateActive().CoinsTip(), test_flags, true, add_to_cache, txdata, &scriptchecks));
BOOST_CHECK(scriptchecks.empty());
} else {
// Check that we get script executions to check, if the transaction
// was invalid, or we didn't add to cache.
std::vector<CScriptCheck> scriptchecks;
- BOOST_CHECK(CheckInputs(tx, state, &::ChainstateActive().CoinsTip(), true, test_flags, true, add_to_cache, txdata, &scriptchecks));
+ BOOST_CHECK(CheckInputs(tx, state, &::ChainstateActive().CoinsTip(), test_flags, true, add_to_cache, txdata, &scriptchecks));
BOOST_CHECK_EQUAL(scriptchecks.size(), tx.vin.size());
}
}
@@ -204,13 +204,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
CValidationState state;
PrecomputedTransactionData ptd_spend_tx(spend_tx);
- BOOST_CHECK(!CheckInputs(CTransaction(spend_tx), state, &::ChainstateActive().CoinsTip(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
+ BOOST_CHECK(!CheckInputs(CTransaction(spend_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
// If we call again asking for scriptchecks (as happens in
// ConnectBlock), we should add a script check object for this -- we're
// not caching invalidity (if that changes, delete this test case).
std::vector<CScriptCheck> scriptchecks;
- BOOST_CHECK(CheckInputs(CTransaction(spend_tx), state, &::ChainstateActive().CoinsTip(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks));
+ BOOST_CHECK(CheckInputs(CTransaction(spend_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks));
BOOST_CHECK_EQUAL(scriptchecks.size(), 1U);
// Test that CheckInputs returns true iff DERSIG-enforcing flags are
@@ -272,7 +272,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
CValidationState state;
PrecomputedTransactionData txdata(invalid_with_cltv_tx);
- BOOST_CHECK(CheckInputs(CTransaction(invalid_with_cltv_tx), state, ::ChainstateActive().CoinsTip(), true, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
+ BOOST_CHECK(CheckInputs(CTransaction(invalid_with_cltv_tx), state, ::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
}
// TEST CHECKSEQUENCEVERIFY
@@ -300,7 +300,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
CValidationState state;
PrecomputedTransactionData txdata(invalid_with_csv_tx);
- BOOST_CHECK(CheckInputs(CTransaction(invalid_with_csv_tx), state, &::ChainstateActive().CoinsTip(), true, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
+ BOOST_CHECK(CheckInputs(CTransaction(invalid_with_csv_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
}
// TODO: add tests for remaining script flags
@@ -362,12 +362,12 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
CValidationState state;
PrecomputedTransactionData txdata(tx);
// This transaction is now invalid under segwit, because of the second input.
- BOOST_CHECK(!CheckInputs(CTransaction(tx), state, &::ChainstateActive().CoinsTip(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
+ BOOST_CHECK(!CheckInputs(CTransaction(tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
std::vector<CScriptCheck> scriptchecks;
// Make sure this transaction was not cached (ie because the first
// input was valid)
- BOOST_CHECK(CheckInputs(CTransaction(tx), state, &::ChainstateActive().CoinsTip(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks));
+ BOOST_CHECK(CheckInputs(CTransaction(tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks));
// Should get 2 script checks back -- caching is on a whole-transaction basis.
BOOST_CHECK_EQUAL(scriptchecks.size(), 2U);
}
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 65cb956fbe..d0cd4b0a03 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -913,7 +913,7 @@ BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup)
// Results file is formatted like:
//
// <input> || <output>
- BOOST_CHECK_EQUAL(out_sha_hex, "b284f4b4a15dd6bf8c06213a69a004b1960388e1d9917173927db52ac220927f");
+ BOOST_CHECK_EQUAL(out_sha_hex, "94b4ad55c8ac639a56b93e36f7e32e4c611fd7d7dd7b2be6a71707b1eadcaec7");
}
BOOST_AUTO_TEST_CASE(util_FormatMoney)