aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/Checkpoints_tests.cpp2
-rw-r--r--src/test/README.md2
-rw-r--r--src/test/addrman_tests.cpp180
-rw-r--r--src/test/base58_tests.cpp2
-rw-r--r--src/test/data/tx_invalid.json8
-rw-r--r--src/test/data/tx_valid.json6
-rw-r--r--src/test/leveldbwrapper_tests.cpp207
-rw-r--r--src/test/limitedmap_tests.cpp101
-rw-r--r--src/test/mempool_tests.cpp334
-rw-r--r--src/test/miner_tests.cpp2
-rw-r--r--src/test/netbase_tests.cpp99
-rw-r--r--src/test/pmt_tests.cpp2
-rw-r--r--src/test/reverselock_tests.cpp64
-rw-r--r--src/test/rpc_tests.cpp31
-rw-r--r--src/test/rpc_wallet_tests.cpp2
-rw-r--r--src/test/script_tests.cpp34
-rw-r--r--src/test/sighash_tests.cpp2
-rw-r--r--src/test/streams_tests.cpp67
-rw-r--r--src/test/test_bitcoin.cpp6
-rw-r--r--src/test/test_bitcoin.h4
-rw-r--r--src/test/transaction_tests.cpp25
-rw-r--r--src/test/txvalidationcache_tests.cpp2
-rw-r--r--src/test/univalue_tests.cpp17
-rw-r--r--src/test/util_tests.cpp4
24 files changed, 1154 insertions, 49 deletions
diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp
index 703cf307d..0a23c430e 100644
--- a/src/test/Checkpoints_tests.cpp
+++ b/src/test/Checkpoints_tests.cpp
@@ -20,7 +20,7 @@ BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(sanity)
{
- const Checkpoints::CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints();
+ const CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints();
BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444);
}
diff --git a/src/test/README.md b/src/test/README.md
index e36112bd4..b2d6be14f 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -16,6 +16,8 @@ their tests in a test suite called "<source_filename>_tests". For an
examples of this pattern, examine uint160_tests.cpp and
uint256_tests.cpp.
+Add the source files to /src/Makefile.test.include to add them to the build.
+
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://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/).
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
new file mode 100644
index 000000000..cfcdd9abb
--- /dev/null
+++ b/src/test/addrman_tests.cpp
@@ -0,0 +1,180 @@
+// Copyright (c) 2012-2013 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "addrman.h"
+#include "test/test_bitcoin.h"
+#include <string>
+#include <boost/test/unit_test.hpp>
+
+#include "random.h"
+
+using namespace std;
+
+class CAddrManTest : public CAddrMan{};
+
+BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(addrman_simple)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ // Test 1: Does Addrman respond correctly when empty.
+ BOOST_CHECK(addrman.size() == 0);
+ CAddrInfo addr_null = addrman.Select();
+ BOOST_CHECK(addr_null.ToString() == "[::]:0");
+
+ // Test 2: Does Addrman::Add work as expected.
+ CService addr1 = CService("250.1.1.1:8333");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 1);
+ CAddrInfo addr_ret1 = addrman.Select();
+ BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
+
+ // Test 3: Does IP address deduplication work correctly.
+ // Expected dup IP should not be added.
+ CService addr1_dup = CService("250.1.1.1:8333");
+ addrman.Add(CAddress(addr1_dup), source);
+ BOOST_CHECK(addrman.size() == 1);
+
+
+ // Test 5: New table has one addr and we add a diff addr we should
+ // have two addrs.
+ CService addr2 = CService("250.1.1.2:8333");
+ addrman.Add(CAddress(addr2), source);
+ BOOST_CHECK(addrman.size() == 2);
+
+ // Test 6: AddrMan::Clear() should empty the new table.
+ addrman.Clear();
+ BOOST_CHECK(addrman.size() == 0);
+ CAddrInfo addr_null2 = addrman.Select();
+ BOOST_CHECK(addr_null2.ToString() == "[::]:0");
+}
+
+BOOST_AUTO_TEST_CASE(addrman_ports)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ BOOST_CHECK(addrman.size() == 0);
+
+ // Test 7; Addr with same IP but diff port does not replace existing addr.
+ CService addr1 = CService("250.1.1.1:8333");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 1);
+
+ CService addr1_port = CService("250.1.1.1:8334");
+ addrman.Add(CAddress(addr1_port), source);
+ BOOST_CHECK(addrman.size() == 1);
+ CAddrInfo addr_ret2 = addrman.Select();
+ BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333");
+
+ // Test 8: Add same IP but diff port to tried table, it doesn't get added.
+ // Perhaps this is not ideal behavior but it is the current behavior.
+ addrman.Good(CAddress(addr1_port));
+ BOOST_CHECK(addrman.size() == 1);
+ bool newOnly = true;
+ CAddrInfo addr_ret3 = addrman.Select(newOnly);
+ BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
+}
+
+
+BOOST_AUTO_TEST_CASE(addrman_select)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ // Test 9: Select from new with 1 addr in new.
+ CService addr1 = CService("250.1.1.1:8333");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 1);
+
+ bool newOnly = true;
+ CAddrInfo addr_ret1 = addrman.Select(newOnly);
+ BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
+
+
+ // Test 10: move addr to tried, select from new expected nothing returned.
+ addrman.Good(CAddress(addr1));
+ BOOST_CHECK(addrman.size() == 1);
+ CAddrInfo addr_ret2 = addrman.Select(newOnly);
+ BOOST_CHECK(addr_ret2.ToString() == "[::]:0");
+
+ CAddrInfo addr_ret3 = addrman.Select();
+ BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
+}
+
+BOOST_AUTO_TEST_CASE(addrman_new_collisions)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ BOOST_CHECK(addrman.size() == 0);
+
+ for (unsigned int i = 1; i < 4; i++){
+ CService addr = CService("250.1.1."+boost::to_string(i));
+ addrman.Add(CAddress(addr), source);
+
+ //Test 11: No collision in new table yet.
+ BOOST_CHECK(addrman.size() == i);
+ }
+
+ //Test 12: new table collision!
+ CService addr1 = CService("250.1.1.4");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 3);
+
+ CService addr2 = CService("250.1.1.5");
+ addrman.Add(CAddress(addr2), source);
+ BOOST_CHECK(addrman.size() == 4);
+}
+
+BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ BOOST_CHECK(addrman.size() == 0);
+
+ for (unsigned int i = 1; i < 75; i++){
+ CService addr = CService("250.1.1."+boost::to_string(i));
+ addrman.Add(CAddress(addr), source);
+ addrman.Good(CAddress(addr));
+
+ //Test 13: No collision in tried table yet.
+ BOOST_TEST_MESSAGE(addrman.size());
+ BOOST_CHECK(addrman.size() == i);
+ }
+
+ //Test 14: tried table collision!
+ CService addr1 = CService("250.1.1.76");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 74);
+
+ CService addr2 = CService("250.1.1.77");
+ addrman.Add(CAddress(addr2), source);
+ BOOST_CHECK(addrman.size() == 75);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index 9e74f5f42..9845df697 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -18,7 +18,7 @@
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
-#include "univalue/univalue.h"
+#include <univalue.h>
extern UniValue read_json(const std::string& jsondata);
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index 20bdbd08a..d3c859434 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -128,7 +128,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000fe64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
-["By-time locks, with argument just beyond tx nLockTime (but within numerical boundries)"],
+["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000001 NOP2 1"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]],
@@ -181,7 +181,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP2 1"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffff7f", "P2SH,CHECKLOCKTIMEVERIFY"],
-["6 byte non-minimally-encoded arguments are invalid even in their contents are valid"],
+["6 byte non-minimally-encoded arguments are invalid even if their contents are valid"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 NOP2 1"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
@@ -193,5 +193,9 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+["A transaction with a non-standard DER signature."],
+[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
+"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH,DERSIG"],
+
["Make diffs cleaner by leaving a comment here without comma at the end"]
]
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 24fff575c..0dfef73ae 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -197,7 +197,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
-["By-time locks, with argument just beyond tx nLockTime (but within numerical boundries)"],
+["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]],
@@ -229,5 +229,9 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+["A transaction with a non-standard DER signature."],
+[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
+"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"],
+
["Make diffs cleaner by leaving a comment here without comma at the end"]
]
diff --git a/src/test/leveldbwrapper_tests.cpp b/src/test/leveldbwrapper_tests.cpp
new file mode 100644
index 000000000..606313b00
--- /dev/null
+++ b/src/test/leveldbwrapper_tests.cpp
@@ -0,0 +1,207 @@
+// Copyright (c) 2012-2013 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "leveldbwrapper.h"
+#include "uint256.h"
+#include "random.h"
+#include "test/test_bitcoin.h"
+
+#include <boost/assign/std/vector.hpp> // for 'operator+=()'
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+using namespace boost::assign; // bring 'operator+=()' into scope
+using namespace boost::filesystem;
+
+// Test if a string consists entirely of null characters
+bool is_null_key(const vector<unsigned char>& key) {
+ bool isnull = true;
+
+ for (unsigned int i = 0; i < key.size(); i++)
+ isnull &= (key[i] == '\x00');
+
+ return isnull;
+}
+
+BOOST_FIXTURE_TEST_SUITE(leveldbwrapper_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(leveldbwrapper)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (int i = 0; i < 2; i++) {
+ bool obfuscate = (bool)i;
+ path ph = temp_directory_path() / unique_path();
+ CLevelDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
+ char key = 'k';
+ uint256 in = GetRandHash();
+ uint256 res;
+
+ // Ensure that we're doing real obfuscation when obfuscate=true
+ BOOST_CHECK(obfuscate != is_null_key(dbw.GetObfuscateKey()));
+
+ BOOST_CHECK(dbw.Write(key, in));
+ BOOST_CHECK(dbw.Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+ }
+}
+
+// Test batch operations
+BOOST_AUTO_TEST_CASE(leveldbwrapper_batch)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (int i = 0; i < 2; i++) {
+ bool obfuscate = (bool)i;
+ path ph = temp_directory_path() / unique_path();
+ CLevelDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
+
+ char key = 'i';
+ uint256 in = GetRandHash();
+ char key2 = 'j';
+ uint256 in2 = GetRandHash();
+ char key3 = 'k';
+ uint256 in3 = GetRandHash();
+
+ uint256 res;
+ CLevelDBBatch batch(&dbw.GetObfuscateKey());
+
+ batch.Write(key, in);
+ batch.Write(key2, in2);
+ batch.Write(key3, in3);
+
+ // Remove key3 before it's even been written
+ batch.Erase(key3);
+
+ dbw.WriteBatch(batch);
+
+ BOOST_CHECK(dbw.Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+ BOOST_CHECK(dbw.Read(key2, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in2.ToString());
+
+ // key3 never should've been written
+ BOOST_CHECK(dbw.Read(key3, res) == false);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(leveldbwrapper_iterator)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (int i = 0; i < 2; i++) {
+ bool obfuscate = (bool)i;
+ path ph = temp_directory_path() / unique_path();
+ CLevelDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
+
+ // The two keys are intentionally chosen for ordering
+ char key = 'j';
+ uint256 in = GetRandHash();
+ BOOST_CHECK(dbw.Write(key, in));
+ char key2 = 'k';
+ uint256 in2 = GetRandHash();
+ BOOST_CHECK(dbw.Write(key2, in2));
+
+ boost::scoped_ptr<CLevelDBIterator> it(const_cast<CLevelDBWrapper*>(&dbw)->NewIterator());
+
+ // Be sure to seek past the obfuscation key (if it exists)
+ it->Seek(key);
+
+ char key_res;
+ uint256 val_res;
+
+ it->GetKey(key_res);
+ it->GetValue(val_res);
+ BOOST_CHECK_EQUAL(key_res, key);
+ BOOST_CHECK_EQUAL(val_res.ToString(), in.ToString());
+
+ it->Next();
+
+ it->GetKey(key_res);
+ it->GetValue(val_res);
+ BOOST_CHECK_EQUAL(key_res, key2);
+ BOOST_CHECK_EQUAL(val_res.ToString(), in2.ToString());
+
+ it->Next();
+ BOOST_CHECK_EQUAL(it->Valid(), false);
+ }
+}
+
+// Test that we do not obfuscation if there is existing data.
+BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
+{
+ // We're going to share this path between two wrappers
+ path ph = temp_directory_path() / unique_path();
+ create_directories(ph);
+
+ // Set up a non-obfuscated wrapper to write some initial data.
+ CLevelDBWrapper* dbw = new CLevelDBWrapper(ph, (1 << 10), false, false, false);
+ char key = 'k';
+ uint256 in = GetRandHash();
+ uint256 res;
+
+ BOOST_CHECK(dbw->Write(key, in));
+ BOOST_CHECK(dbw->Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+
+ // Call the destructor to free leveldb LOCK
+ delete dbw;
+
+ // Now, set up another wrapper that wants to obfuscate the same directory
+ CLevelDBWrapper odbw(ph, (1 << 10), false, false, true);
+
+ // Check that the key/val we wrote with unobfuscated wrapper exists and
+ // is readable.
+ uint256 res2;
+ BOOST_CHECK(odbw.Read(key, res2));
+ BOOST_CHECK_EQUAL(res2.ToString(), in.ToString());
+
+ BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data
+ BOOST_CHECK(is_null_key(odbw.GetObfuscateKey())); // The key should be an empty string
+
+ uint256 in2 = GetRandHash();
+ uint256 res3;
+
+ // Check that we can write successfully
+ BOOST_CHECK(odbw.Write(key, in2));
+ BOOST_CHECK(odbw.Read(key, res3));
+ BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
+}
+
+// Ensure that we start obfuscating during a reindex.
+BOOST_AUTO_TEST_CASE(existing_data_reindex)
+{
+ // We're going to share this path between two wrappers
+ path ph = temp_directory_path() / unique_path();
+ create_directories(ph);
+
+ // Set up a non-obfuscated wrapper to write some initial data.
+ CLevelDBWrapper* dbw = new CLevelDBWrapper(ph, (1 << 10), false, false, false);
+ char key = 'k';
+ uint256 in = GetRandHash();
+ uint256 res;
+
+ BOOST_CHECK(dbw->Write(key, in));
+ BOOST_CHECK(dbw->Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+
+ // Call the destructor to free leveldb LOCK
+ delete dbw;
+
+ // Simulate a -reindex by wiping the existing data store
+ CLevelDBWrapper odbw(ph, (1 << 10), false, true, true);
+
+ // Check that the key/val we wrote with unobfuscated wrapper doesn't exist
+ uint256 res2;
+ BOOST_CHECK(!odbw.Read(key, res2));
+ BOOST_CHECK(!is_null_key(odbw.GetObfuscateKey()));
+
+ uint256 in2 = GetRandHash();
+ uint256 res3;
+
+ // Check that we can write successfully
+ BOOST_CHECK(odbw.Write(key, in2));
+ BOOST_CHECK(odbw.Read(key, res3));
+ BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp
new file mode 100644
index 000000000..faaddffad
--- /dev/null
+++ b/src/test/limitedmap_tests.cpp
@@ -0,0 +1,101 @@
+// Copyright (c) 2012-2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "limitedmap.h"
+
+#include "test/test_bitcoin.h"
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(limitedmap_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(limitedmap_test)
+{
+ // create a limitedmap capped at 10 items
+ limitedmap<int, int> map(10);
+
+ // check that the max size is 10
+ BOOST_CHECK(map.max_size() == 10);
+
+ // check that it's empty
+ BOOST_CHECK(map.size() == 0);
+
+ // insert (-1, -1)
+ map.insert(std::pair<int, int>(-1, -1));
+
+ // make sure that the size is updated
+ BOOST_CHECK(map.size() == 1);
+
+ // make sure that the new items is in the map
+ BOOST_CHECK(map.count(-1) == 1);
+
+ // insert 10 new items
+ for (int i = 0; i < 10; i++) {
+ map.insert(std::pair<int, int>(i, i + 1));
+ }
+
+ // make sure that the map now contains 10 items...
+ BOOST_CHECK(map.size() == 10);
+
+ // ...and that the first item has been discarded
+ BOOST_CHECK(map.count(-1) == 0);
+
+ // iterate over the map, both with an index and an iterator
+ limitedmap<int, int>::const_iterator it = map.begin();
+ for (int i = 0; i < 10; i++) {
+ // make sure the item is present
+ BOOST_CHECK(map.count(i) == 1);
+
+ // use the iterator to check for the expected key adn value
+ BOOST_CHECK(it->first == i);
+ BOOST_CHECK(it->second == i + 1);
+
+ // use find to check for the value
+ BOOST_CHECK(map.find(i)->second == i + 1);
+
+ // update and recheck
+ map.update(it, i + 2);
+ BOOST_CHECK(map.find(i)->second == i + 2);
+
+ it++;
+ }
+
+ // check that we've exhausted the iterator
+ BOOST_CHECK(it == map.end());
+
+ // resize the map to 5 items
+ map.max_size(5);
+
+ // check that the max size and size are now 5
+ BOOST_CHECK(map.max_size() == 5);
+ BOOST_CHECK(map.size() == 5);
+
+ // check that items less than 5 have been discarded
+ // and items greater than 5 are retained
+ for (int i = 0; i < 10; i++) {
+ if (i < 5) {
+ BOOST_CHECK(map.count(i) == 0);
+ } else {
+ BOOST_CHECK(map.count(i) == 1);
+ }
+ }
+
+ // erase some items not in the map
+ for (int i = 100; i < 1000; i += 100) {
+ map.erase(i);
+ }
+
+ // check that the size is unaffected
+ BOOST_CHECK(map.size() == 5);
+
+ // erase the remaining elements
+ for (int i = 5; i < 10; i++) {
+ map.erase(i);
+ }
+
+ // check that the map is now empty
+ BOOST_CHECK(map.empty());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index 2439689d7..0cf906a25 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -9,6 +9,7 @@
#include <boost/test/unit_test.hpp>
#include <list>
+#include <vector>
BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup)
@@ -100,4 +101,337 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
removed.clear();
}
+void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder)
+{
+ BOOST_CHECK_EQUAL(pool.size(), sortedOrder.size());
+ CTxMemPool::indexed_transaction_set::nth_index<1>::type::iterator it = pool.mapTx.get<1>().begin();
+ int count=0;
+ for (; it != pool.mapTx.get<1>().end(); ++it, ++count) {
+ BOOST_CHECK_EQUAL(it->GetTx().GetHash().ToString(), sortedOrder[count]);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
+{
+ CTxMemPool pool(CFeeRate(0));
+
+ /* 3rd highest fee */
+ CMutableTransaction tx1 = CMutableTransaction();
+ tx1.vout.resize(1);
+ tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx1.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx1.GetHash(), CTxMemPoolEntry(tx1, 10000LL, 0, 10.0, 1, true));
+
+ /* highest fee */
+ CMutableTransaction tx2 = CMutableTransaction();
+ tx2.vout.resize(1);
+ tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx2.vout[0].nValue = 2 * COIN;
+ pool.addUnchecked(tx2.GetHash(), CTxMemPoolEntry(tx2, 20000LL, 0, 9.0, 1, true));
+
+ /* lowest fee */
+ CMutableTransaction tx3 = CMutableTransaction();
+ tx3.vout.resize(1);
+ tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx3.vout[0].nValue = 5 * COIN;
+ pool.addUnchecked(tx3.GetHash(), CTxMemPoolEntry(tx3, 0LL, 0, 100.0, 1, true));
+
+ /* 2nd highest fee */
+ CMutableTransaction tx4 = CMutableTransaction();
+ tx4.vout.resize(1);
+ tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx4.vout[0].nValue = 6 * COIN;
+ pool.addUnchecked(tx4.GetHash(), CTxMemPoolEntry(tx4, 15000LL, 0, 1.0, 1, true));
+
+ /* equal fee rate to tx1, but newer */
+ CMutableTransaction tx5 = CMutableTransaction();
+ tx5.vout.resize(1);
+ tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx5.vout[0].nValue = 11 * COIN;
+ pool.addUnchecked(tx5.GetHash(), CTxMemPoolEntry(tx5, 10000LL, 1, 10.0, 1, true));
+ BOOST_CHECK_EQUAL(pool.size(), 5);
+
+ std::vector<std::string> sortedOrder;
+ sortedOrder.resize(5);
+ sortedOrder[0] = tx3.GetHash().ToString(); // 0
+ sortedOrder[1] = tx5.GetHash().ToString(); // 10000
+ sortedOrder[2] = tx1.GetHash().ToString(); // 10000
+ sortedOrder[3] = tx4.GetHash().ToString(); // 15000
+ sortedOrder[4] = tx2.GetHash().ToString(); // 20000
+ CheckSort(pool, sortedOrder);
+
+ /* low fee but with high fee child */
+ /* tx6 -> tx7 -> tx8, tx9 -> tx10 */
+ CMutableTransaction tx6 = CMutableTransaction();
+ tx6.vout.resize(1);
+ tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx6.vout[0].nValue = 20 * COIN;
+ pool.addUnchecked(tx6.GetHash(), CTxMemPoolEntry(tx6, 0LL, 1, 10.0, 1, true));
+ BOOST_CHECK_EQUAL(pool.size(), 6);
+ // Check that at this point, tx6 is sorted low
+ sortedOrder.insert(sortedOrder.begin(), tx6.GetHash().ToString());
+ CheckSort(pool, sortedOrder);
+
+ CTxMemPool::setEntries setAncestors;
+ setAncestors.insert(pool.mapTx.find(tx6.GetHash()));
+ CMutableTransaction tx7 = CMutableTransaction();
+ tx7.vin.resize(1);
+ tx7.vin[0].prevout = COutPoint(tx6.GetHash(), 0);
+ tx7.vin[0].scriptSig = CScript() << OP_11;
+ tx7.vout.resize(2);
+ tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx7.vout[0].nValue = 10 * COIN;
+ tx7.vout[1].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx7.vout[1].nValue = 1 * COIN;
+
+ CTxMemPool::setEntries setAncestorsCalculated;
+ std::string dummy;
+ CTxMemPoolEntry entry7(tx7, 2000000LL, 1, 10.0, 1, true);
+ BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry7, setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
+ BOOST_CHECK(setAncestorsCalculated == setAncestors);
+
+ pool.addUnchecked(tx7.GetHash(), CTxMemPoolEntry(tx7, 2000000LL, 1, 10.0, 1, true), setAncestors);
+ BOOST_CHECK_EQUAL(pool.size(), 7);
+
+ // Now tx6 should be sorted higher (high fee child): tx7, tx6, tx2, ...
+ sortedOrder.erase(sortedOrder.begin());
+ sortedOrder.push_back(tx6.GetHash().ToString());
+ sortedOrder.push_back(tx7.GetHash().ToString());
+ CheckSort(pool, sortedOrder);
+
+ /* low fee child of tx7 */
+ CMutableTransaction tx8 = CMutableTransaction();
+ tx8.vin.resize(1);
+ tx8.vin[0].prevout = COutPoint(tx7.GetHash(), 0);
+ tx8.vin[0].scriptSig = CScript() << OP_11;
+ tx8.vout.resize(1);
+ tx8.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx8.vout[0].nValue = 10 * COIN;
+ setAncestors.insert(pool.mapTx.find(tx7.GetHash()));
+ pool.addUnchecked(tx8.GetHash(), CTxMemPoolEntry(tx8, 0LL, 2, 10.0, 1, true), setAncestors);
+
+ // Now tx8 should be sorted low, but tx6/tx both high
+ sortedOrder.insert(sortedOrder.begin(), tx8.GetHash().ToString());
+ CheckSort(pool, sortedOrder);
+
+ /* low fee child of tx7 */
+ CMutableTransaction tx9 = CMutableTransaction();
+ tx9.vin.resize(1);
+ tx9.vin[0].prevout = COutPoint(tx7.GetHash(), 1);
+ tx9.vin[0].scriptSig = CScript() << OP_11;
+ tx9.vout.resize(1);
+ tx9.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx9.vout[0].nValue = 1 * COIN;
+ pool.addUnchecked(tx9.GetHash(), CTxMemPoolEntry(tx9, 0LL, 3, 10.0, 1, true), setAncestors);
+
+ // tx9 should be sorted low
+ BOOST_CHECK_EQUAL(pool.size(), 9);
+ sortedOrder.insert(sortedOrder.begin(), tx9.GetHash().ToString());
+ CheckSort(pool, sortedOrder);
+
+ std::vector<std::string> snapshotOrder = sortedOrder;
+
+ setAncestors.insert(pool.mapTx.find(tx8.GetHash()));
+ setAncestors.insert(pool.mapTx.find(tx9.GetHash()));
+ /* tx10 depends on tx8 and tx9 and has a high fee*/
+ CMutableTransaction tx10 = CMutableTransaction();
+ tx10.vin.resize(2);
+ tx10.vin[0].prevout = COutPoint(tx8.GetHash(), 0);
+ tx10.vin[0].scriptSig = CScript() << OP_11;
+ tx10.vin[1].prevout = COutPoint(tx9.GetHash(), 0);
+ tx10.vin[1].scriptSig = CScript() << OP_11;
+ tx10.vout.resize(1);
+ tx10.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx10.vout[0].nValue = 10 * COIN;
+
+ setAncestorsCalculated.clear();
+ CTxMemPoolEntry entry10(tx10, 200000LL, 4, 10.0, 1, true);
+ BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry10, setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
+ BOOST_CHECK(setAncestorsCalculated == setAncestors);
+
+ pool.addUnchecked(tx10.GetHash(), CTxMemPoolEntry(tx10, 200000LL, 4, 10.0, 1, true), setAncestors);
+
+ /**
+ * tx8 and tx9 should both now be sorted higher
+ * Final order after tx10 is added:
+ *
+ * tx3 = 0 (1)
+ * tx5 = 10000 (1)
+ * tx1 = 10000 (1)
+ * tx4 = 15000 (1)
+ * tx2 = 20000 (1)
+ * tx9 = 200k (2 txs)
+ * tx8 = 200k (2 txs)
+ * tx10 = 200k (1 tx)
+ * tx6 = 2.2M (5 txs)
+ * tx7 = 2.2M (4 txs)
+ */
+ sortedOrder.erase(sortedOrder.begin(), sortedOrder.begin()+2); // take out tx9, tx8 from the beginning
+ sortedOrder.insert(sortedOrder.begin()+5, tx9.GetHash().ToString());
+ sortedOrder.insert(sortedOrder.begin()+6, tx8.GetHash().ToString());
+ sortedOrder.insert(sortedOrder.begin()+7, tx10.GetHash().ToString()); // tx10 is just before tx6
+ CheckSort(pool, sortedOrder);
+
+ // there should be 10 transactions in the mempool
+ BOOST_CHECK_EQUAL(pool.size(), 10);
+
+ // Now try removing tx10 and verify the sort order returns to normal
+ std::list<CTransaction> removed;
+ pool.remove(pool.mapTx.find(tx10.GetHash())->GetTx(), removed, true);
+ CheckSort(pool, snapshotOrder);
+}
+
+BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
+{
+ CTxMemPool pool(CFeeRate(1000));
+
+ CMutableTransaction tx1 = CMutableTransaction();
+ tx1.vin.resize(1);
+ tx1.vin[0].scriptSig = CScript() << OP_1;
+ tx1.vout.resize(1);
+ tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
+ tx1.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx1.GetHash(), CTxMemPoolEntry(tx1, 10000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx1)));
+
+ CMutableTransaction tx2 = CMutableTransaction();
+ tx2.vin.resize(1);
+ tx2.vin[0].scriptSig = CScript() << OP_2;
+ tx2.vout.resize(1);
+ tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
+ tx2.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx2.GetHash(), CTxMemPoolEntry(tx2, 5000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx2)));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing
+ BOOST_CHECK(pool.exists(tx1.GetHash()));
+ BOOST_CHECK(pool.exists(tx2.GetHash()));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // should remove the lower-feerate transaction
+ BOOST_CHECK(pool.exists(tx1.GetHash()));
+ BOOST_CHECK(!pool.exists(tx2.GetHash()));
+
+ pool.addUnchecked(tx2.GetHash(), CTxMemPoolEntry(tx2, 5000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx2)));
+ CMutableTransaction tx3 = CMutableTransaction();
+ tx3.vin.resize(1);
+ tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0);
+ tx3.vin[0].scriptSig = CScript() << OP_2;
+ tx3.vout.resize(1);
+ tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
+ tx3.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx3.GetHash(), CTxMemPoolEntry(tx3, 20000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx3)));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP)
+ BOOST_CHECK(!pool.exists(tx1.GetHash()));
+ BOOST_CHECK(pool.exists(tx2.GetHash()));
+ BOOST_CHECK(pool.exists(tx3.GetHash()));
+
+ pool.TrimToSize(::GetSerializeSize(CTransaction(tx1), SER_NETWORK, PROTOCOL_VERSION)); // mempool is limited to tx1's size in memory usage, so nothing fits
+ BOOST_CHECK(!pool.exists(tx1.GetHash()));
+ BOOST_CHECK(!pool.exists(tx2.GetHash()));
+ BOOST_CHECK(!pool.exists(tx3.GetHash()));
+
+ CFeeRate maxFeeRateRemoved(25000, ::GetSerializeSize(CTransaction(tx3), SER_NETWORK, PROTOCOL_VERSION) + ::GetSerializeSize(CTransaction(tx2), SER_NETWORK, PROTOCOL_VERSION));
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
+
+ CMutableTransaction tx4 = CMutableTransaction();
+ tx4.vin.resize(2);
+ tx4.vin[0].prevout.SetNull();
+ tx4.vin[0].scriptSig = CScript() << OP_4;
+ tx4.vin[1].prevout.SetNull();
+ tx4.vin[1].scriptSig = CScript() << OP_4;
+ tx4.vout.resize(2);
+ tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
+ tx4.vout[0].nValue = 10 * COIN;
+ tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
+ tx4.vout[1].nValue = 10 * COIN;
+
+ CMutableTransaction tx5 = CMutableTransaction();
+ tx5.vin.resize(2);
+ tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0);
+ tx5.vin[0].scriptSig = CScript() << OP_4;
+ tx5.vin[1].prevout.SetNull();
+ tx5.vin[1].scriptSig = CScript() << OP_5;
+ tx5.vout.resize(2);
+ tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
+ tx5.vout[0].nValue = 10 * COIN;
+ tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
+ tx5.vout[1].nValue = 10 * COIN;
+
+ CMutableTransaction tx6 = CMutableTransaction();
+ tx6.vin.resize(2);
+ tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1);
+ tx6.vin[0].scriptSig = CScript() << OP_4;
+ tx6.vin[1].prevout.SetNull();
+ tx6.vin[1].scriptSig = CScript() << OP_6;
+ tx6.vout.resize(2);
+ tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
+ tx6.vout[0].nValue = 10 * COIN;
+ tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
+ tx6.vout[1].nValue = 10 * COIN;
+
+ CMutableTransaction tx7 = CMutableTransaction();
+ tx7.vin.resize(2);
+ tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0);
+ tx7.vin[0].scriptSig = CScript() << OP_5;
+ tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0);
+ tx7.vin[1].scriptSig = CScript() << OP_6;
+ tx7.vout.resize(2);
+ tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
+ tx7.vout[0].nValue = 10 * COIN;
+ tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
+ tx7.vout[0].nValue = 10 * COIN;
+
+ pool.addUnchecked(tx4.GetHash(), CTxMemPoolEntry(tx4, 7000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx4)));
+ pool.addUnchecked(tx5.GetHash(), CTxMemPoolEntry(tx5, 1000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx5)));
+ pool.addUnchecked(tx6.GetHash(), CTxMemPoolEntry(tx6, 1100LL, 0, 10.0, 1, pool.HasNoInputsOf(tx6)));
+ pool.addUnchecked(tx7.GetHash(), CTxMemPoolEntry(tx7, 9000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx7)));
+
+ // we only require this remove, at max, 2 txn, because its not clear what we're really optimizing for aside from that
+ pool.TrimToSize(pool.DynamicMemoryUsage() - 1);
+ BOOST_CHECK(pool.exists(tx4.GetHash()));
+ BOOST_CHECK(pool.exists(tx6.GetHash()));
+ BOOST_CHECK(!pool.exists(tx7.GetHash()));
+
+ if (!pool.exists(tx5.GetHash()))
+ pool.addUnchecked(tx5.GetHash(), CTxMemPoolEntry(tx5, 1000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx5)));
+ pool.addUnchecked(tx7.GetHash(), CTxMemPoolEntry(tx7, 9000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx7)));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7
+ BOOST_CHECK(pool.exists(tx4.GetHash()));
+ BOOST_CHECK(!pool.exists(tx5.GetHash()));
+ BOOST_CHECK(pool.exists(tx6.GetHash()));
+ BOOST_CHECK(!pool.exists(tx7.GetHash()));
+
+ pool.addUnchecked(tx5.GetHash(), CTxMemPoolEntry(tx5, 1000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx5)));
+ pool.addUnchecked(tx7.GetHash(), CTxMemPoolEntry(tx7, 9000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx7)));
+
+ std::vector<CTransaction> vtx;
+ std::list<CTransaction> conflicts;
+ SetMockTime(42);
+ SetMockTime(42 + CTxMemPool::ROLLING_FEE_HALFLIFE);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
+ // ... we should keep the same min fee until we get a block
+ pool.removeForBlock(vtx, 1, conflicts);
+ SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/2);
+ // ... then feerate should drop 1/2 each halflife
+
+ SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 5 / 2).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/4);
+ // ... with a 1/2 halflife when mempool is < 1/2 its target size
+
+ SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 9 / 2).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/8);
+ // ... with a 1/4 halflife when mempool is < 1/4 its target size
+
+ SetMockTime(42 + 7*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), 1000);
+ // ... but feerate should never drop below 1000
+
+ SetMockTime(42 + 8*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), 0);
+ // ... unless it has gone all the way to 0 (after getting past 1000/2)
+
+ SetMockTime(0);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index ad79a558c..91a3a5738 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->vtx[0] = CTransaction(txCoinbase);
if (txFirst.size() < 2)
txFirst.push_back(new CTransaction(pblock->vtx[0]));
- pblock->hashMerkleRoot = pblock->BuildMerkleTree();
+ pblock->hashMerkleRoot = pblock->ComputeMerkleRoot();
pblock->nNonce = blockinfo[i].nonce;
CValidationState state;
BOOST_CHECK(ProcessNewBlock(state, NULL, pblock, true, NULL));
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 7154476c7..b1ef0ed24 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -7,6 +7,7 @@
#include <string>
+#include <boost/assign/list_of.hpp>
#include <boost/test/unit_test.hpp>
using namespace std;
@@ -148,12 +149,106 @@ BOOST_AUTO_TEST_CASE(subnet_test)
BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).IsValid());
BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.1")));
BOOST_CHECK(!CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.2")));
- BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).ToString() == "127.0.0.1/255.255.255.255");
+ BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).ToString() == "127.0.0.1/32");
BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).IsValid());
BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:8")));
BOOST_CHECK(!CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:9")));
- BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128");
+
+ CSubNet subnet = CSubNet("1.2.3.4/255.255.255.255");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
+ subnet = CSubNet("1.2.3.4/255.255.255.254");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31");
+ subnet = CSubNet("1.2.3.4/255.255.255.252");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30");
+ subnet = CSubNet("1.2.3.4/255.255.255.248");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29");
+ subnet = CSubNet("1.2.3.4/255.255.255.240");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28");
+ subnet = CSubNet("1.2.3.4/255.255.255.224");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27");
+ subnet = CSubNet("1.2.3.4/255.255.255.192");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26");
+ subnet = CSubNet("1.2.3.4/255.255.255.128");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25");
+ subnet = CSubNet("1.2.3.4/255.255.255.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24");
+ subnet = CSubNet("1.2.3.4/255.255.254.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23");
+ subnet = CSubNet("1.2.3.4/255.255.252.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22");
+ subnet = CSubNet("1.2.3.4/255.255.248.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21");
+ subnet = CSubNet("1.2.3.4/255.255.240.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20");
+ subnet = CSubNet("1.2.3.4/255.255.224.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19");
+ subnet = CSubNet("1.2.3.4/255.255.192.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18");
+ subnet = CSubNet("1.2.3.4/255.255.128.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17");
+ subnet = CSubNet("1.2.3.4/255.255.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16");
+ subnet = CSubNet("1.2.3.4/255.254.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15");
+ subnet = CSubNet("1.2.3.4/255.252.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14");
+ subnet = CSubNet("1.2.3.4/255.248.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13");
+ subnet = CSubNet("1.2.3.4/255.240.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12");
+ subnet = CSubNet("1.2.3.4/255.224.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11");
+ subnet = CSubNet("1.2.3.4/255.192.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10");
+ subnet = CSubNet("1.2.3.4/255.128.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9");
+ subnet = CSubNet("1.2.3.4/255.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
+ subnet = CSubNet("1.2.3.4/254.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7");
+ subnet = CSubNet("1.2.3.4/252.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6");
+ subnet = CSubNet("1.2.3.4/248.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5");
+ subnet = CSubNet("1.2.3.4/240.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4");
+ subnet = CSubNet("1.2.3.4/224.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3");
+ subnet = CSubNet("1.2.3.4/192.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2");
+ subnet = CSubNet("1.2.3.4/128.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1");
+ subnet = CSubNet("1.2.3.4/0.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
+
+ subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/128");
+ subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1::/16");
+ subnet = CSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "::/0");
+ subnet = CSubNet("1.2.3.4/255.255.232.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/255.255.232.0");
+ subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
+}
+
+BOOST_AUTO_TEST_CASE(netbase_getgroup)
+{
+ BOOST_CHECK(CNetAddr("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable()
+ BOOST_CHECK(CNetAddr("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable()
+ BOOST_CHECK(CNetAddr("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable()
+ BOOST_CHECK(CNetAddr("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable()
+ BOOST_CHECK(CNetAddr("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4
+ BOOST_CHECK(CNetAddr("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145
+ BOOST_CHECK(CNetAddr("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052
+ BOOST_CHECK(CNetAddr("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964
+ BOOST_CHECK(CNetAddr("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380
+ BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor
+ BOOST_CHECK(CNetAddr("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net
+ BOOST_CHECK(CNetAddr("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index f6d06d680..d9f3c3e46 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
}
// calculate actual merkle root and height
- uint256 merkleRoot1 = block.BuildMerkleTree();
+ uint256 merkleRoot1 = block.ComputeMerkleRoot();
std::vector<uint256> vTxid(nTx, uint256());
for (unsigned int j=0; j<nTx; j++)
vTxid[j] = block.vtx[j].GetHash();
diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp
new file mode 100644
index 000000000..e7e627ae0
--- /dev/null
+++ b/src/test/reverselock_tests.cpp
@@ -0,0 +1,64 @@
+// Copyright (c) 2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "reverselock.h"
+#include "test/test_bitcoin.h"
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(reverselock_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(reverselock_basics)
+{
+ boost::mutex mutex;
+ boost::unique_lock<boost::mutex> lock(mutex);
+
+ BOOST_CHECK(lock.owns_lock());
+ {
+ reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ BOOST_CHECK(!lock.owns_lock());
+ }
+ BOOST_CHECK(lock.owns_lock());
+}
+
+BOOST_AUTO_TEST_CASE(reverselock_errors)
+{
+ boost::mutex mutex;
+ boost::unique_lock<boost::mutex> lock(mutex);
+
+ // Make sure trying to reverse lock an unlocked lock fails
+ lock.unlock();
+
+ BOOST_CHECK(!lock.owns_lock());
+
+ bool failed = false;
+ try {
+ reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ } catch(...) {
+ failed = true;
+ }
+
+ BOOST_CHECK(failed);
+ BOOST_CHECK(!lock.owns_lock());
+
+ // Make sure trying to lock a lock after it has been reverse locked fails
+ failed = false;
+ bool locked = false;
+
+ lock.lock();
+ BOOST_CHECK(lock.owns_lock());
+
+ try {
+ reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ lock.lock();
+ locked = true;
+ } catch(...) {
+ failed = true;
+ }
+
+ BOOST_CHECK(locked && failed);
+ BOOST_CHECK(lock.owns_lock());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index a65572e6f..2a486f08e 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -13,7 +13,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
-#include "univalue/univalue.h"
+#include <univalue.h>
using namespace std;
@@ -224,21 +224,6 @@ BOOST_AUTO_TEST_CASE(json_parse_errors)
BOOST_CHECK_THROW(ParseNonRFCJSONValue("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL"), std::runtime_error);
}
-BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr)
-{
- // Check IPv4 addresses
- BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("1.2.3.4")).ToString(), "1.2.3.4");
- BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("127.0.0.1")).ToString(), "127.0.0.1");
- // Check IPv6 addresses
- BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::1")).ToString(), "::1");
- BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("123:4567:89ab:cdef:123:4567:89ab:cdef")).ToString(),
- "123:4567:89ab:cdef:123:4567:89ab:cdef");
- // v4 compatible must be interpreted as IPv4
- BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::0:127.0.0.1")).ToString(), "127.0.0.1");
- // v4 mapped must be interpreted as IPv4
- BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::ffff:127.0.0.1")).ToString(), "127.0.0.1");
-}
-
BOOST_AUTO_TEST_CASE(rpc_ban)
{
BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned")));
@@ -250,7 +235,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
UniValue ar = r.get_array();
UniValue o1 = ar[0].get_obj();
UniValue adr = find_value(o1, "address");
- BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.255");
+ BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/32");
BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0 remove")));;
BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
ar = r.get_array();
@@ -262,7 +247,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
o1 = ar[0].get_obj();
adr = find_value(o1, "address");
UniValue banned_until = find_value(o1, "banned_until");
- BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0");
+ BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
BOOST_CHECK_EQUAL(banned_until.get_int64(), 1607731200); // absolute time check
BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned")));
@@ -273,7 +258,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
o1 = ar[0].get_obj();
adr = find_value(o1, "address");
banned_until = find_value(o1, "banned_until");
- BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0");
+ BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
int64_t now = GetTime();
BOOST_CHECK(banned_until.get_int64() > now);
BOOST_CHECK(banned_until.get_int64()-now <= 200);
@@ -303,15 +288,15 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
ar = r.get_array();
o1 = ar[0].get_obj();
adr = find_value(o1, "address");
- BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/128");
BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned")));
- BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:db8::/30 add")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:db8::/ffff:fffc:0:0:0:0:0:0 add")));
BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
adr = find_value(o1, "address");
- BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/ffff:fffc:0:0:0:0:0:0");
+ BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/30");
BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned")));
BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128 add")));
@@ -319,7 +304,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
ar = r.get_array();
o1 = ar[0].get_obj();
adr = find_value(o1, "address");
- BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp
index 52f41be8a..2e652f76e 100644
--- a/src/test/rpc_wallet_tests.cpp
+++ b/src/test/rpc_wallet_tests.cpp
@@ -14,7 +14,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
-#include "univalue/univalue.h"
+#include <univalue.h>
using namespace std;
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 37c046935..882f9eb19 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -27,7 +27,7 @@
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
-#include "univalue/univalue.h"
+#include <univalue.h>
using namespace std;
@@ -840,7 +840,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
-}
+}
BOOST_AUTO_TEST_CASE(script_combineSigs)
{
@@ -983,4 +983,34 @@ BOOST_AUTO_TEST_CASE(script_IsPushOnly_on_invalid_scripts)
BOOST_CHECK(!CScript(direct, direct+sizeof(direct)).IsPushOnly());
}
+BOOST_AUTO_TEST_CASE(script_GetScriptAsm)
+{
+ BOOST_CHECK_EQUAL("OP_NOP2", ScriptToAsmStr(CScript() << OP_NOP2, true));
+ BOOST_CHECK_EQUAL("OP_NOP2", ScriptToAsmStr(CScript() << OP_CHECKLOCKTIMEVERIFY, true));
+ BOOST_CHECK_EQUAL("OP_NOP2", ScriptToAsmStr(CScript() << OP_NOP2));
+ BOOST_CHECK_EQUAL("OP_NOP2", ScriptToAsmStr(CScript() << OP_CHECKLOCKTIMEVERIFY));
+
+ string derSig("304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c5090");
+ string pubKey("03b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb2");
+ vector<unsigned char> vchPubKey = ToByteVector(ParseHex(pubKey));
+
+ BOOST_CHECK_EQUAL(derSig + "00 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "00")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "80 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "80")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[ALL] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "01")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[NONE] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "02")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[SINGLE] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "03")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[ALL|ANYONECANPAY] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "81")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[NONE|ANYONECANPAY] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "82")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[SINGLE|ANYONECANPAY] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "83")) << vchPubKey, true));
+
+ BOOST_CHECK_EQUAL(derSig + "00 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "00")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "80 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "80")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "01 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "01")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "02 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "02")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "03 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "03")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "81 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "81")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "82 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "82")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "83 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "83")) << vchPubKey));
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 4b9646156..6fca64d5d 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -20,7 +20,7 @@
#include <boost/test/unit_test.hpp>
-#include "univalue/univalue.h"
+#include <univalue.h>
extern UniValue read_json(const std::string& jsondata);
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
new file mode 100644
index 000000000..0ed8f363d
--- /dev/null
+++ b/src/test/streams_tests.cpp
@@ -0,0 +1,67 @@
+// Copyright (c) 2012-2013 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "streams.h"
+#include "support/allocators/zeroafterfree.h"
+#include "test/test_bitcoin.h"
+
+#include <boost/assign/std/vector.hpp> // for 'operator+=()'
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+using namespace boost::assign; // bring 'operator+=()' into scope
+
+BOOST_FIXTURE_TEST_SUITE(streams_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
+{
+ std::vector<char> in;
+ std::vector<char> expected_xor;
+ std::vector<unsigned char> key;
+ CDataStream ds(in, 0, 0);
+
+ // Degenerate case
+
+ key += '\x00','\x00';
+ ds.Xor(key);
+ BOOST_CHECK_EQUAL(
+ std::string(expected_xor.begin(), expected_xor.end()),
+ std::string(ds.begin(), ds.end()));
+
+ in += '\x0f','\xf0';
+ expected_xor += '\xf0','\x0f';
+
+ // Single character key
+
+ ds.clear();
+ ds.insert(ds.begin(), in.begin(), in.end());
+ key.clear();
+
+ key += '\xff';
+ ds.Xor(key);
+ BOOST_CHECK_EQUAL(
+ std::string(expected_xor.begin(), expected_xor.end()),
+ std::string(ds.begin(), ds.end()));
+
+ // Multi character key
+
+ in.clear();
+ expected_xor.clear();
+ in += '\xf0','\x0f';
+ expected_xor += '\x0f','\x00';
+
+ ds.clear();
+ ds.insert(ds.begin(), in.begin(), in.end());
+
+ key.clear();
+ key += '\xff','\x0f';
+
+ ds.Xor(key);
+ BOOST_CHECK_EQUAL(
+ std::string(expected_xor.begin(), expected_xor.end()),
+ std::string(ds.begin(), ds.end()));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 8d81275a6..a74fbfc0d 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -32,13 +32,13 @@ CWallet* pwalletMain;
extern bool fPrintToConsole;
extern void noui_connect();
-BasicTestingSetup::BasicTestingSetup(CBaseChainParams::Network network)
+BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
{
ECC_Start();
SetupEnvironment();
fPrintToDebugLog = false; // don't want to write to debug.log file
fCheckBlockIndex = true;
- SelectParams(network);
+ SelectParams(chainName);
noui_connect();
}
@@ -47,7 +47,7 @@ BasicTestingSetup::~BasicTestingSetup()
ECC_Stop();
}
-TestingSetup::TestingSetup(CBaseChainParams::Network network) : BasicTestingSetup(network)
+TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{
#ifdef ENABLE_WALLET
bitdb.MakeMock();
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index b9314d061..0bab4b683 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -12,7 +12,7 @@
* This just configures logging and chain parameters.
*/
struct BasicTestingSetup {
- BasicTestingSetup(CBaseChainParams::Network network = CBaseChainParams::MAIN);
+ BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
~BasicTestingSetup();
};
@@ -25,7 +25,7 @@ struct TestingSetup: public BasicTestingSetup {
boost::filesystem::path pathTemp;
boost::thread_group threadGroup;
- TestingSetup(CBaseChainParams::Network network = CBaseChainParams::MAIN);
+ TestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
~TestingSetup();
};
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index e70ebddc2..f9423bc0d 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -26,7 +26,7 @@
#include <boost/test/unit_test.hpp>
#include <boost/assign/list_of.hpp>
-#include "univalue/univalue.h"
+#include <univalue.h>
using namespace std;
@@ -345,18 +345,35 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
t.vout[0].nValue = 501; // dust
BOOST_CHECK(!IsStandardTx(t, reason));
- t.vout[0].nValue = 601; // not dust
+ t.vout[0].nValue = 2730; // not dust
BOOST_CHECK(IsStandardTx(t, reason));
t.vout[0].scriptPubKey = CScript() << OP_1;
BOOST_CHECK(!IsStandardTx(t, reason));
- // 80-byte TX_NULL_DATA (standard)
+ // MAX_OP_RETURN_RELAY-byte TX_NULL_DATA (standard)
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
+ BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size());
BOOST_CHECK(IsStandardTx(t, reason));
- // 81-byte TX_NULL_DATA (non-standard)
+ // MAX_OP_RETURN_RELAY+1-byte TX_NULL_DATA (non-standard)
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
+ BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
+ BOOST_CHECK(!IsStandardTx(t, reason));
+
+ // Data payload can be encoded in any way...
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("");
+ BOOST_CHECK(IsStandardTx(t, reason));
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("00") << ParseHex("01");
+ BOOST_CHECK(IsStandardTx(t, reason));
+ // OP_RESERVED *is* considered to be a PUSHDATA type opcode by IsPushOnly()!
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RESERVED << -1 << 0 << ParseHex("01") << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12 << 13 << 14 << 15 << 16;
+ BOOST_CHECK(IsStandardTx(t, reason));
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << 0 << ParseHex("01") << 2 << ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
+ BOOST_CHECK(IsStandardTx(t, reason));
+
+ // ...so long as it only contains PUSHDATA's
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RETURN;
BOOST_CHECK(!IsStandardTx(t, reason));
// TX_NULL_DATA w/o PUSHDATA
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index edad18644..9b8e1c088 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -23,7 +23,7 @@ ToMemPool(CMutableTransaction& tx)
LOCK(cs_main);
CValidationState state;
- return AcceptToMemoryPool(mempool, state, tx, false, NULL, false);
+ return AcceptToMemoryPool(mempool, state, tx, false, NULL, true, false);
}
BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp
index 67cb9b962..945c1acbe 100644
--- a/src/test/univalue_tests.cpp
+++ b/src/test/univalue_tests.cpp
@@ -6,7 +6,7 @@
#include <vector>
#include <string>
#include <map>
-#include "univalue/univalue.h"
+#include <univalue.h>
#include "test/test_bitcoin.h"
#include <boost/test/unit_test.hpp>
@@ -314,6 +314,21 @@ BOOST_AUTO_TEST_CASE(univalue_readwrite)
BOOST_CHECK(obj["key3"].isObject());
BOOST_CHECK_EQUAL(strJson1, v.write());
+
+ /* Check for (correctly reporting) a parsing error if the initial
+ JSON construct is followed by more stuff. Note that whitespace
+ is, of course, exempt. */
+
+ BOOST_CHECK(v.read(" {}\n "));
+ BOOST_CHECK(v.isObject());
+ BOOST_CHECK(v.read(" []\n "));
+ BOOST_CHECK(v.isArray());
+
+ BOOST_CHECK(!v.read("@{}"));
+ BOOST_CHECK(!v.read("{} garbage"));
+ BOOST_CHECK(!v.read("[]{}"));
+ BOOST_CHECK(!v.read("{}[]"));
+ BOOST_CHECK(!v.read("{} 42"));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index e956cc5b9..997dc3193 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -413,10 +413,10 @@ BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
comments.push_back(std::string("comment1"));
std::vector<std::string> comments2;
comments2.push_back(std::string("comment1"));
- comments2.push_back(std::string("comment2"));
+ comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:0.9.99/"));
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/"));
- BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; comment2)/"));
+ BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; Comment2; .,_?@-; )/"));
}
BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)