aboutsummaryrefslogtreecommitdiff
path: root/src/test/transaction_tests.cpp
diff options
context:
space:
mode:
authorMatt Corallo <matt@bluematt.me>2012-08-04 18:28:49 +0200
committerMatt Corallo <git@bluematt.me>2012-08-20 12:12:41 -0400
commitfc4743faa8cefb0eaecec51f6c8984a920c96d73 (patch)
tree15bc193b1c1766d524cf5bc18d99a5e2c1aee8f8 /src/test/transaction_tests.cpp
parent336a0abbbb40af3fa12b1219ed48779e6b583b6f (diff)
downloadbitcoin-fc4743faa8cefb0eaecec51f6c8984a920c96d73.tar.xz
Add data-driven transaction tests.
Diffstat (limited to 'src/test/transaction_tests.cpp')
-rw-r--r--src/test/transaction_tests.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index be0d976d51..de6e18f14d 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -1,12 +1,150 @@
+#include <map>
+#include <string>
#include <boost/test/unit_test.hpp>
+#include "json/json_spirit_writer_template.h"
#include "main.h"
#include "wallet.h"
using namespace std;
+using namespace json_spirit;
+
+// In script_tests.cpp
+extern Array read_json(const std::string& filename);
+extern CScript ParseScript(string s);
BOOST_AUTO_TEST_SUITE(transaction_tests)
+BOOST_AUTO_TEST_CASE(tx_valid)
+{
+ // Read tests from test/data/tx_valid.json
+ // Format is an array of arrays
+ // Inner arrays are either [ "comment" ]
+ // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
+ // ... where all scripts are stringified scripts.
+ Array tests = read_json("tx_valid.json");
+
+ BOOST_FOREACH(Value& tv, tests)
+ {
+ Array test = tv.get_array();
+ string strTest = write_string(tv, false);
+ if (test[0].type() == array_type)
+ {
+ if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+
+ map<COutPoint, CScript> mapprevOutScriptPubKeys;
+ Array inputs = test[0].get_array();
+ bool fValid = true;
+ BOOST_FOREACH(Value& input, inputs)
+ {
+ if (input.type() != array_type)
+ {
+ fValid = false;
+ break;
+ }
+ Array vinput = input.get_array();
+ if (vinput.size() != 3)
+ {
+ fValid = false;
+ break;
+ }
+
+ mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
+ }
+ if (!fValid)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+
+ string transaction = test[1].get_str();
+ CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
+ CTransaction tx;
+ stream >> tx;
+
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ {
+ if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ break;
+ }
+
+ BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(tx_invalid)
+{
+ // Read tests from test/data/tx_invalid.json
+ // Format is an array of arrays
+ // Inner arrays are either [ "comment" ]
+ // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
+ // ... where all scripts are stringified scripts.
+ Array tests = read_json("tx_invalid.json");
+
+ BOOST_FOREACH(Value& tv, tests)
+ {
+ Array test = tv.get_array();
+ string strTest = write_string(tv, false);
+ if (test[0].type() == array_type)
+ {
+ if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+
+ map<COutPoint, CScript> mapprevOutScriptPubKeys;
+ Array inputs = test[0].get_array();
+ bool fValid = true;
+ BOOST_FOREACH(Value& input, inputs)
+ {
+ if (input.type() != array_type)
+ {
+ fValid = false;
+ break;
+ }
+ Array vinput = input.get_array();
+ if (vinput.size() != 3)
+ {
+ fValid = false;
+ break;
+ }
+
+ mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
+ }
+ if (!fValid)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+
+ string transaction = test[1].get_str();
+ CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
+ CTransaction tx;
+ stream >> tx;
+
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ {
+ if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ break;
+ }
+
+ BOOST_CHECK_MESSAGE(!VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest);
+ }
+ }
+ }
+}
+
BOOST_AUTO_TEST_CASE(basic_transaction_tests)
{
// Random real transaction (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436)