Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14864781
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
42 KB
Subscribers
None
View Options
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 92dda43108..c6a26a2cca 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -1,628 +1,631 @@
// Copyright (c) 2012-2019 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 <rpc/blockchain.h>
#include <rpc/client.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <config.h>
#include <interfaces/chain.h>
#include <node/context.h>
#include <util/time.h>
#include <test/util/setup_common.h>
#include <boost/test/unit_test.hpp>
#include <univalue.h>
#include <any>
static UniValue JSON(std::string_view json) {
UniValue value;
BOOST_CHECK(value.read(json));
return value;
}
class HasJSON {
public:
explicit HasJSON(std::string json) : m_json(std::move(json)) {}
bool operator()(const UniValue &value) const {
std::string json{value.write()};
BOOST_CHECK_EQUAL(json, m_json);
return json == m_json;
};
private:
const std::string m_json;
};
class RPCTestingSetup : public TestingSetup {
public:
UniValue TransformParams(const UniValue ¶ms,
std::vector<std::string> arg_names) const;
UniValue CallRPC(const std::string &args);
};
UniValue
RPCTestingSetup::TransformParams(const UniValue ¶ms,
std::vector<std::string> arg_names) const {
UniValue transformed_params;
CRPCTable table;
CRPCCommand command{"category", "method",
[&](const Config &, const JSONRPCRequest &request,
UniValue &, bool) -> bool {
transformed_params = request.params;
return true;
},
arg_names, /*unique_id=*/0};
table.appendCommand("method", &command);
JSONRPCRequest request;
request.strMethod = "method";
request.params = params;
if (RPCIsInWarmup(nullptr)) {
SetRPCWarmupFinished();
}
GlobalConfig config;
table.execute(config, request);
return transformed_params;
}
UniValue RPCTestingSetup::CallRPC(const std::string &args) {
std::vector<std::string> vArgs{SplitString(args, ' ')};
std::string strMethod = vArgs[0];
vArgs.erase(vArgs.begin());
GlobalConfig config;
JSONRPCRequest request;
request.context = &m_node;
request.strMethod = strMethod;
request.params = RPCConvertValues(strMethod, vArgs);
if (RPCIsInWarmup(nullptr)) {
SetRPCWarmupFinished();
}
try {
UniValue result = tableRPC.execute(config, request);
return result;
} catch (const UniValue &objError) {
throw std::runtime_error(objError.find_value("message").get_str());
}
}
BOOST_FIXTURE_TEST_SUITE(rpc_tests, RPCTestingSetup)
BOOST_AUTO_TEST_CASE(rpc_namedparams) {
const std::vector<std::string> arg_names{"arg1", "arg2", "arg3", "arg4",
"arg5"};
// Make sure named arguments are transformed into positional arguments in
// correct places separated by nulls
BOOST_CHECK_EQUAL(
TransformParams(JSON(R"({"arg2": 2, "arg4": 4})"), arg_names).write(),
"[null,2,null,4]");
// Make sure named argument specified multiple times raises an exception
BOOST_CHECK_EXCEPTION(
TransformParams(JSON(R"({"arg2": 2, "arg2": 4})"), arg_names), UniValue,
HasJSON(
R"({"code":-8,"message":"Parameter arg2 specified multiple times"})"));
// Make sure named and positional arguments can be combined.
BOOST_CHECK_EQUAL(
TransformParams(JSON(R"({"arg5": 5, "args": [1, 2], "arg4": 4})"),
arg_names)
.write(),
"[1,2,null,4,5]");
// Make sure a unknown named argument raises an exception
BOOST_CHECK_EXCEPTION(
TransformParams(JSON(R"({"arg2": 2, "unknown": 6})"), arg_names),
UniValue,
HasJSON(R"({"code":-8,"message":"Unknown named parameter unknown"})"));
// Make sure an overlap between a named argument and positional argument
// raises an exception
BOOST_CHECK_EXCEPTION(
TransformParams(JSON(R"({"args": [1,2,3], "arg4": 4, "arg2": 2})"),
arg_names),
UniValue,
HasJSON(
R"({"code":-8,"message":"Parameter arg2 specified twice both as positional and named argument"})"));
// Make sure extra positional arguments can be passed through to the method
// implementation, as long as they don't overlap with named arguments.
BOOST_CHECK_EQUAL(
TransformParams(JSON(R"({"args": [1,2,3,4,5,6,7,8,9,10]})"), arg_names)
.write(),
"[1,2,3,4,5,6,7,8,9,10]");
BOOST_CHECK_EQUAL(
TransformParams(JSON(R"([1,2,3,4,5,6,7,8,9,10])"), arg_names).write(),
"[1,2,3,4,5,6,7,8,9,10]");
}
BOOST_AUTO_TEST_CASE(rpc_rawparams) {
// Test raw transaction API argument handling
UniValue r;
BOOST_CHECK_THROW(CallRPC("getrawtransaction"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("getrawtransaction "
"a3b807410df0b60fcb9736768df5823938b2f838694939ba"
"45f3c0a1bff150ed not_int"),
std::runtime_error);
BOOST_CHECK_THROW(CallRPC("createrawtransaction"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"),
std::runtime_error);
BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"),
std::runtime_error);
BOOST_CHECK_THROW(CallRPC("createrawtransaction {} {}"),
std::runtime_error);
BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [] {}"));
BOOST_CHECK_THROW(CallRPC("createrawtransaction [] {} extra"),
std::runtime_error);
BOOST_CHECK_THROW(CallRPC("decoderawtransaction"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("decoderawtransaction null"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"),
std::runtime_error);
std::string rawtx =
"0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a9"
"9ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0ef"
"e71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b17"
"36ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc31071"
"1c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b383"
"9e2bbf32d826a1e222031fd888ac00000000";
BOOST_CHECK_NO_THROW(
r = CallRPC(std::string("decoderawtransaction ") + rawtx));
BOOST_CHECK_EQUAL(r.get_obj().find_value("version").getInt<int>(), 1);
BOOST_CHECK_EQUAL(r.get_obj().find_value("size").getInt<int>(), 193);
BOOST_CHECK_EQUAL(r.get_obj().find_value("locktime").getInt<int>(), 0);
BOOST_CHECK_THROW(
r = CallRPC(std::string("decoderawtransaction ") + rawtx + " extra"),
std::runtime_error);
// Only check failure cases for sendrawtransaction, there's no network to
// send to...
BOOST_CHECK_THROW(CallRPC("sendrawtransaction"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"),
std::runtime_error);
BOOST_CHECK_THROW(
CallRPC(std::string("sendrawtransaction ") + rawtx + " extra"),
std::runtime_error);
}
BOOST_AUTO_TEST_CASE(rpc_togglenetwork) {
UniValue r;
r = CallRPC("getnetworkinfo");
bool netState = r.get_obj().find_value("networkactive").get_bool();
BOOST_CHECK_EQUAL(netState, true);
BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive false"));
r = CallRPC("getnetworkinfo");
int numConnection = r.get_obj().find_value("connections").getInt<int>();
BOOST_CHECK_EQUAL(numConnection, 0);
netState = r.get_obj().find_value("networkactive").get_bool();
BOOST_CHECK_EQUAL(netState, false);
BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive true"));
r = CallRPC("getnetworkinfo");
netState = r.get_obj().find_value("networkactive").get_bool();
BOOST_CHECK_EQUAL(netState, true);
}
BOOST_AUTO_TEST_CASE(rpc_rawsign) {
UniValue r;
// input is a 1-of-2 multisig (so is output):
std::string prevout = "[{\"txid\":"
"\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b724"
"8f50977c8493f3\","
"\"vout\":1,\"scriptPubKey\":"
"\"a914b10c9df5f7edf436c697f02f1efdba4cf399615187\","
"\"amount\":3141590.00,"
"\"redeemScript\":"
"\"512103debedc17b3df2badbcdd86d5feb4562b86fe182e5998"
"abd8bcd4f122c6155b1b21027e940bb73ab8732bfdf7f9216ece"
"fca5b94d6df834e77e108f68e66f126044c052ae\"}]";
r = CallRPC(std::string("createrawtransaction ") + prevout + " " +
"{\"3HqAe9LtNBjnsfM4CyYaWTnvCaUYT7v4oZ\":11}");
std::string notsigned = r.get_str();
std::string privkey1 =
"\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
std::string privkey2 =
"\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
r = CallRPC(std::string("signrawtransactionwithkey ") + notsigned + " [] " +
prevout);
BOOST_CHECK(r.get_obj().find_value("complete").get_bool() == false);
r = CallRPC(std::string("signrawtransactionwithkey ") + notsigned + " [" +
privkey1 + "," + privkey2 + "] " + prevout);
BOOST_CHECK(r.get_obj().find_value("complete").get_bool() == true);
}
BOOST_AUTO_TEST_CASE(rpc_rawsign_missing_amount) {
// Old format, missing amount parameter for prevout should generate
// an RPC error. This is because of new replay-protected tx's require
// nonzero amount present in signed tx.
// See: https://github.com/Bitcoin-ABC/bitcoin-abc/issues/63
// (We will re-use the tx + keys from the above rpc_rawsign test for
// simplicity.)
UniValue r;
std::string prevout = "[{\"txid\":"
"\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b724"
"8f50977c8493f3\","
"\"vout\":1,\"scriptPubKey\":"
"\"a914b10c9df5f7edf436c697f02f1efdba4cf399615187\","
"\"redeemScript\":"
"\"512103debedc17b3df2badbcdd86d5feb4562b86fe182e5998"
"abd8bcd4f122c6155b1b21027e940bb73ab8732bfdf7f9216ece"
"fca5b94d6df834e77e108f68e66f126044c052ae\"}]";
r = CallRPC(std::string("createrawtransaction ") + prevout + " " +
"{\"3HqAe9LtNBjnsfM4CyYaWTnvCaUYT7v4oZ\":11}");
std::string notsigned = r.get_str();
std::string privkey1 =
"\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
std::string privkey2 =
"\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
bool exceptionThrownDueToMissingAmount = false,
errorWasMissingAmount = false;
try {
r = CallRPC(std::string("signrawtransactionwithkey ") + notsigned +
" [" + privkey1 + "," + privkey2 + "] " + prevout);
} catch (const std::runtime_error &e) {
exceptionThrownDueToMissingAmount = true;
if (std::string(e.what()).find("amount") != std::string::npos) {
errorWasMissingAmount = true;
}
}
BOOST_CHECK(exceptionThrownDueToMissingAmount == true);
BOOST_CHECK(errorWasMissingAmount == true);
}
BOOST_AUTO_TEST_CASE(rpc_createraw_op_return) {
BOOST_CHECK_NO_THROW(
CallRPC("createrawtransaction "
"[{\"txid\":"
"\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff1"
"50ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\"}"));
// Key not "data" (bad address)
BOOST_CHECK_THROW(
CallRPC("createrawtransaction "
"[{\"txid\":"
"\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff1"
"50ed\",\"vout\":0}] {\"somedata\":\"68656c6c6f776f726c64\"}"),
std::runtime_error);
// Bad hex encoding of data output
BOOST_CHECK_THROW(
CallRPC("createrawtransaction "
"[{\"txid\":"
"\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff1"
"50ed\",\"vout\":0}] {\"data\":\"12345\"}"),
std::runtime_error);
BOOST_CHECK_THROW(
CallRPC("createrawtransaction "
"[{\"txid\":"
"\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff1"
"50ed\",\"vout\":0}] {\"data\":\"12345g\"}"),
std::runtime_error);
// Data 81 bytes long
BOOST_CHECK_NO_THROW(
CallRPC("createrawtransaction "
"[{\"txid\":"
"\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff1"
"50ed\",\"vout\":0}] "
"{\"data\":"
"\"010203040506070809101112131415161718192021222324252627282930"
"31323334353637383940414243444546474849505152535455565758596061"
"6263646566676869707172737475767778798081\"}"));
}
BOOST_AUTO_TEST_CASE(rpc_format_monetary_values) {
BOOST_CHECK(UniValue(Amount::zero()).write() == "0.00");
BOOST_CHECK(UniValue(SATOSHI).write() == "0.01");
BOOST_CHECK(UniValue(17622195 * SATOSHI).write() == "176221.95");
BOOST_CHECK(UniValue(50000000 * SATOSHI).write() == "500000.00");
BOOST_CHECK(UniValue(89898989 * SATOSHI).write() == "898989.89");
BOOST_CHECK(UniValue(100000000 * SATOSHI).write() == "1000000.00");
BOOST_CHECK(UniValue(int64_t(2099999999999990) * SATOSHI).write() ==
"20999999999999.90");
BOOST_CHECK(UniValue(int64_t(2099999999999999) * SATOSHI).write() ==
"20999999999999.99");
BOOST_CHECK_EQUAL(UniValue(Amount::zero()).write(), "0.00");
BOOST_CHECK_EQUAL(UniValue(123456789 * (COIN / 10000)).write(),
"12345678900.00");
BOOST_CHECK_EQUAL(UniValue(-1 * COIN).write(), "-1000000.00");
BOOST_CHECK_EQUAL(UniValue(-1 * COIN / 10).write(), "-100000.00");
BOOST_CHECK_EQUAL(UniValue(100000000 * COIN).write(), "100000000000000.00");
BOOST_CHECK_EQUAL(UniValue(10000000 * COIN).write(), "10000000000000.00");
BOOST_CHECK_EQUAL(UniValue(1000000 * COIN).write(), "1000000000000.00");
BOOST_CHECK_EQUAL(UniValue(100000 * COIN).write(), "100000000000.00");
BOOST_CHECK_EQUAL(UniValue(10000 * COIN).write(), "10000000000.00");
BOOST_CHECK_EQUAL(UniValue(1000 * COIN).write(), "1000000000.00");
BOOST_CHECK_EQUAL(UniValue(100 * COIN).write(), "100000000.00");
BOOST_CHECK_EQUAL(UniValue(10 * COIN).write(), "10000000.00");
BOOST_CHECK_EQUAL(UniValue(COIN).write(), "1000000.00");
BOOST_CHECK_EQUAL(UniValue(COIN / 10).write(), "100000.00");
BOOST_CHECK_EQUAL(UniValue(COIN / 100).write(), "10000.00");
BOOST_CHECK_EQUAL(UniValue(COIN / 1000).write(), "1000.00");
BOOST_CHECK_EQUAL(UniValue(COIN / 10000).write(), "100.00");
BOOST_CHECK_EQUAL(UniValue(COIN / 100000).write(), "10.00");
BOOST_CHECK_EQUAL(UniValue(COIN / 1000000).write(), "1.00");
BOOST_CHECK_EQUAL(UniValue(COIN / 10000000).write(), "0.10");
BOOST_CHECK_EQUAL(UniValue(COIN / 100000000).write(), "0.01");
}
static UniValue ValueFromString(const std::string &str) noexcept {
UniValue value;
value.setNumStr(str);
return value;
}
BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values) {
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("-0.01")), UniValue);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0")), Amount::zero());
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00")), Amount::zero());
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.01")), SATOSHI);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("176221.95")),
17622195 * SATOSHI);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("500000")),
50000000 * SATOSHI);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("500000.00")),
50000000 * SATOSHI);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("898989.89")),
89898989 * SATOSHI);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1000000.00")),
100000000 * SATOSHI);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999999999.9")),
int64_t(2099999999999990) * SATOSHI);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999999999.99")),
int64_t(2099999999999999) * SATOSHI);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1e-2")),
COIN / 100000000);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.1e-1")),
COIN / 100000000);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.01e-0")),
COIN / 100000000);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString(
+ "0.00000000000000000000000000000000000001e+36")),
+ SATOSHI);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString(
"0."
"0000000000000000000000000000000000000000000000000000"
"000000000000000000000001e+74")),
COIN / 100000000);
BOOST_CHECK_EQUAL(
AmountFromValue(ValueFromString("10000000000000000000000000000000000000"
"000000000000000000000000000e-58")),
COIN);
BOOST_CHECK_EQUAL(
AmountFromValue(ValueFromString(
"0."
"000000000000000000000000000000000000000000000000000000000000000100"
"000000000000000000000000000000000000000000000000000e70")),
COIN);
// should fail
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e-9")), UniValue);
// should fail
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("0.000000019")),
UniValue);
// should pass, cut trailing 0
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.01000000")), SATOSHI);
// should fail
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("19e-9")), UniValue);
// should pass, leading 0 is present
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.19e-0")),
19 * SATOSHI);
// should fail, no leading 0
BOOST_CHECK_EXCEPTION(AmountFromValue(".19e-6"), UniValue,
HasJSON(R"({"code":-3,"message":"Invalid amount"})"));
// overflow error
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("92233720368.54775808")),
UniValue);
// overflow error
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e+17")), UniValue);
// overflow error signless
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e17")), UniValue);
// overflow error
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("93e+15")), UniValue);
}
BOOST_AUTO_TEST_CASE(rpc_ban) {
BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
UniValue r;
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0 add")));
// portnumber for setban not allowed
BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.0:8334")),
std::runtime_error);
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
UniValue ar = r.get_array();
UniValue o1 = ar[0].get_obj();
UniValue adr = o1.find_value("address");
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/32");
BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0 remove")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
BOOST_CHECK_EQUAL(ar.size(), 0UL);
// Set ban way in the future: 2283-12-18 19:33:20
BOOST_CHECK_NO_THROW(
r = CallRPC(std::string("setban 127.0.0.0/24 add 9907731200 true")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
adr = o1.find_value("address");
UniValue banned_until = o1.find_value("banned_until");
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
// absolute time check
BOOST_CHECK_EQUAL(banned_until.getInt<int64_t>(), 9907731200);
BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
BOOST_CHECK_NO_THROW(
r = CallRPC(std::string("setban 127.0.0.0/24 add 200")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
adr = o1.find_value("address");
banned_until = o1.find_value("banned_until");
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
int64_t now = GetTime();
BOOST_CHECK(banned_until.getInt<int64_t>() > now);
BOOST_CHECK(banned_until.getInt<int64_t>() - now <= 200);
// must throw an exception because 127.0.0.1 is in already banned subnet
// range
BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.1 add")),
std::runtime_error);
BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0/24 remove")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
BOOST_CHECK_EQUAL(ar.size(), 0UL);
BOOST_CHECK_NO_THROW(
r = CallRPC(std::string("setban 127.0.0.0/255.255.0.0 add")));
BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.1.1 add")),
std::runtime_error);
BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
BOOST_CHECK_EQUAL(ar.size(), 0UL);
// invalid IP
BOOST_CHECK_THROW(r = CallRPC(std::string("setban test add")),
std::runtime_error);
// IPv6 tests
BOOST_CHECK_NO_THROW(
r = CallRPC(
std::string("setban FE80:0000:0000:0000:0202:B3FF:FE1E:8329 add")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
adr = o1.find_value("address");
BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/128");
BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string(
"setban 2001:db8::/ffff:fffc:0:0:0:0:0:0 add")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
adr = o1.find_value("address");
BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/30");
BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
BOOST_CHECK_NO_THROW(
r = CallRPC(std::string(
"setban 2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128 add")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
adr = o1.find_value("address");
BOOST_CHECK_EQUAL(adr.get_str(),
"2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
}
BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress) {
UniValue result;
BOOST_CHECK_NO_THROW(result = RPCConvertValues(
"generatetoaddress",
{"101", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"}));
BOOST_CHECK_EQUAL(result[0].getInt<int>(), 101);
BOOST_CHECK_EQUAL(result[1].get_str(),
"mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
BOOST_CHECK_NO_THROW(result = RPCConvertValues(
"generatetoaddress",
{"101", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"}));
BOOST_CHECK_EQUAL(result[0].getInt<int>(), 101);
BOOST_CHECK_EQUAL(result[1].get_str(),
"mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
BOOST_CHECK_NO_THROW(result = RPCConvertValues(
"generatetoaddress",
{"1", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a", "9"}));
BOOST_CHECK_EQUAL(result[0].getInt<int>(), 1);
BOOST_CHECK_EQUAL(result[1].get_str(),
"mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
BOOST_CHECK_EQUAL(result[2].getInt<int>(), 9);
BOOST_CHECK_NO_THROW(result = RPCConvertValues(
"generatetoaddress",
{"1", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU", "9"}));
BOOST_CHECK_EQUAL(result[0].getInt<int>(), 1);
BOOST_CHECK_EQUAL(result[1].get_str(),
"mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
BOOST_CHECK_EQUAL(result[2].getInt<int>(), 9);
}
BOOST_AUTO_TEST_CASE(help_example) {
// test different argument types
const RPCArgList &args = {{"foo", "bar"}, {"b", true}, {"n", 1}};
BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", args),
"> bitcoin-cli -named test foo=bar b=true n=1\n");
BOOST_CHECK_EQUAL(HelpExampleRpcNamed("test", args),
"> curl --user myusername --data-binary '{\"jsonrpc\": "
"\"1.0\", \"id\": \"curltest\", \"method\": \"test\", "
"\"params\": {\"foo\":\"bar\",\"b\":true,\"n\":1}}' -H "
"'content-type: text/plain;' http://127.0.0.1:8332/\n");
// test shell escape
BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"foo", "b'ar"}}),
"> bitcoin-cli -named test foo='b'''ar'\n");
BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"foo", "b\"ar"}}),
"> bitcoin-cli -named test foo='b\"ar'\n");
BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"foo", "b ar"}}),
"> bitcoin-cli -named test foo='b ar'\n");
// test object params
UniValue obj_value(UniValue::VOBJ);
obj_value.pushKV("foo", "bar");
obj_value.pushKV("b", false);
obj_value.pushKV("n", 1);
BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"name", obj_value}}),
"> bitcoin-cli -named test "
"name='{\"foo\":\"bar\",\"b\":false,\"n\":1}'\n");
BOOST_CHECK_EQUAL(
HelpExampleRpcNamed("test", {{"name", obj_value}}),
"> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", "
"\"id\": \"curltest\", \"method\": \"test\", \"params\": "
"{\"name\":{\"foo\":\"bar\",\"b\":false,\"n\":1}}}' -H 'content-type: "
"text/plain;' http://127.0.0.1:8332/\n");
// test array params
UniValue arr_value(UniValue::VARR);
arr_value.push_back("bar");
arr_value.push_back(false);
arr_value.push_back(1);
BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"name", arr_value}}),
"> bitcoin-cli -named test name='[\"bar\",false,1]'\n");
BOOST_CHECK_EQUAL(HelpExampleRpcNamed("test", {{"name", arr_value}}),
"> curl --user myusername --data-binary '{\"jsonrpc\": "
"\"1.0\", \"id\": \"curltest\", \"method\": \"test\", "
"\"params\": {\"name\":[\"bar\",false,1]}}' -H "
"'content-type: text/plain;' http://127.0.0.1:8332/\n");
// test types don't matter for shell
BOOST_CHECK_EQUAL(HelpExampleCliNamed("foo", {{"arg", true}}),
HelpExampleCliNamed("foo", {{"arg", "true"}}));
// test types matter for Rpc
BOOST_CHECK_NE(HelpExampleRpcNamed("foo", {{"arg", true}}),
HelpExampleRpcNamed("foo", {{"arg", "true"}}));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp
index fd15fc3b02..e72cc90fad 100644
--- a/src/univalue/test/object.cpp
+++ b/src/univalue/test/object.cpp
@@ -1,472 +1,472 @@
// Copyright (c) 2014 BitPay Inc.
// Copyright (c) 2014-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://opensource.org/licenses/mit-license.php.
#include <univalue.h>
#include <cassert>
#include <cstdint>
#include <map>
#include <memory>
#include <stdexcept>
#include <string>
#include <string_view>
#include <vector>
#define BOOST_CHECK(expr) assert(expr)
#define BOOST_CHECK_EQUAL(v1, v2) assert((v1) == (v2))
#define BOOST_CHECK_THROW(stmt, excMatch) { \
try { \
(stmt); \
assert(0 && "No exception caught"); \
} catch (excMatch & e) { \
} catch (...) { \
assert(0 && "Wrong exception caught"); \
} \
}
#define BOOST_CHECK_NO_THROW(stmt) { \
try { \
(stmt); \
} catch (...) { \
assert(0); \
} \
}
void univalue_constructor()
{
UniValue v1;
BOOST_CHECK(v1.isNull());
UniValue v2(UniValue::VSTR);
BOOST_CHECK(v2.isStr());
UniValue v3(UniValue::VSTR, "foo");
BOOST_CHECK(v3.isStr());
BOOST_CHECK_EQUAL(v3.getValStr(), "foo");
UniValue numTest;
numTest.setNumStr("82");
BOOST_CHECK(numTest.isNum());
BOOST_CHECK_EQUAL(numTest.getValStr(), "82");
uint64_t vu64 = 82;
UniValue v4(vu64);
BOOST_CHECK(v4.isNum());
BOOST_CHECK_EQUAL(v4.getValStr(), "82");
int64_t vi64 = -82;
UniValue v5(vi64);
BOOST_CHECK(v5.isNum());
BOOST_CHECK_EQUAL(v5.getValStr(), "-82");
int vi = -688;
UniValue v6(vi);
BOOST_CHECK(v6.isNum());
BOOST_CHECK_EQUAL(v6.getValStr(), "-688");
double vd = -7.21;
UniValue v7(vd);
BOOST_CHECK(v7.isNum());
BOOST_CHECK_EQUAL(v7.getValStr(), "-7.21");
std::string vs("yawn");
UniValue v8(vs);
BOOST_CHECK(v8.isStr());
BOOST_CHECK_EQUAL(v8.getValStr(), "yawn");
const char *vcs = "zappa";
UniValue v9(vcs);
BOOST_CHECK(v9.isStr());
BOOST_CHECK_EQUAL(v9.getValStr(), "zappa");
}
void univalue_push_throw()
{
UniValue j;
BOOST_CHECK_THROW(j.push_back(1), std::runtime_error);
BOOST_CHECK_THROW(j.push_backV({1}), std::runtime_error);
BOOST_CHECK_THROW(j.pushKVEnd("k", 1), std::runtime_error);
BOOST_CHECK_THROW(j.pushKV("k", 1), std::runtime_error);
BOOST_CHECK_THROW(j.pushKVs({}), std::runtime_error);
}
void univalue_typecheck()
{
UniValue v1;
v1.setNumStr("1");
BOOST_CHECK(v1.isNum());
BOOST_CHECK_THROW(v1.get_bool(), std::runtime_error);
{
UniValue v_negative;
v_negative.setNumStr("-1");
BOOST_CHECK_THROW(v_negative.getInt<uint8_t>(), std::runtime_error);
BOOST_CHECK_EQUAL(v_negative.getInt<int8_t>(), -1);
}
UniValue v2;
v2.setBool(true);
BOOST_CHECK_EQUAL(v2.get_bool(), true);
BOOST_CHECK_THROW(v2.getInt<int>(), std::runtime_error);
UniValue v3;
v3.setNumStr("32482348723847471234");
BOOST_CHECK_THROW(v3.getInt<int64_t>(), std::runtime_error);
v3.setNumStr("1000");
BOOST_CHECK_EQUAL(v3.getInt<int64_t>(), 1000);
UniValue v4;
v4.setNumStr("2147483648");
BOOST_CHECK_EQUAL(v4.getInt<int64_t>(), 2147483648);
BOOST_CHECK_THROW(v4.getInt<int>(), std::runtime_error);
v4.setNumStr("1000");
BOOST_CHECK_EQUAL(v4.getInt<int>(), 1000);
BOOST_CHECK_THROW(v4.get_str(), std::runtime_error);
BOOST_CHECK_EQUAL(v4.get_real(), 1000);
BOOST_CHECK_THROW(v4.get_array(), std::runtime_error);
BOOST_CHECK_THROW(v4.getKeys(), std::runtime_error);
BOOST_CHECK_THROW(v4.getValues(), std::runtime_error);
BOOST_CHECK_THROW(v4.get_obj(), std::runtime_error);
UniValue v5;
BOOST_CHECK(v5.read("[true, 10]"));
BOOST_CHECK_NO_THROW(v5.get_array());
std::vector<UniValue> vals = v5.getValues();
BOOST_CHECK_THROW(vals[0].getInt<int>(), std::runtime_error);
BOOST_CHECK_EQUAL(vals[0].get_bool(), true);
BOOST_CHECK_EQUAL(vals[1].getInt<int>(), 10);
BOOST_CHECK_THROW(vals[1].get_bool(), std::runtime_error);
}
void univalue_set()
{
UniValue v(UniValue::VSTR, "foo");
v.clear();
BOOST_CHECK(v.isNull());
BOOST_CHECK_EQUAL(v.getValStr(), "");
v.setObject();
BOOST_CHECK(v.isObject());
BOOST_CHECK_EQUAL(v.size(), 0);
BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ);
BOOST_CHECK(v.empty());
v.setArray();
BOOST_CHECK(v.isArray());
BOOST_CHECK_EQUAL(v.size(), 0);
v.setStr("zum");
BOOST_CHECK(v.isStr());
BOOST_CHECK_EQUAL(v.getValStr(), "zum");
{
std::string_view sv{"ab\0c", 4};
UniValue j{sv};
BOOST_CHECK(j.isStr());
BOOST_CHECK_EQUAL(j.getValStr(), sv);
BOOST_CHECK_EQUAL(j.write(), "\"ab\\u0000c\"");
}
v.setFloat(-1.01);
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-1.01");
v.setInt(int{1023});
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "1023");
v.setInt(int64_t{-1023LL});
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-1023");
v.setInt(uint64_t{1023ULL});
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "1023");
v.setNumStr("-688");
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-688");
v.setBool(false);
BOOST_CHECK_EQUAL(v.isBool(), true);
BOOST_CHECK_EQUAL(v.isTrue(), false);
BOOST_CHECK_EQUAL(v.isFalse(), true);
BOOST_CHECK_EQUAL(v.get_bool(), false);
v.setBool(true);
BOOST_CHECK_EQUAL(v.isBool(), true);
BOOST_CHECK_EQUAL(v.isTrue(), true);
BOOST_CHECK_EQUAL(v.isFalse(), false);
BOOST_CHECK_EQUAL(v.get_bool(), true);
BOOST_CHECK_THROW(v.setNumStr("zombocom"), std::runtime_error);
v.setNull();
BOOST_CHECK(v.isNull());
}
void univalue_array()
{
UniValue arr(UniValue::VARR);
arr.reserve(9);
UniValue v((int64_t)1023LL);
arr.push_back(v);
std::string vStr("zippy");
arr.push_back(vStr);
const char *s = "pippy";
arr.push_back(s);
std::vector<UniValue> vec;
v.setStr("boing");
vec.push_back(v);
v.setStr("going");
vec.push_back(v);
arr.push_backV(vec);
arr.push_back(uint64_t{400ULL});
arr.push_back(int64_t{-400LL});
arr.push_back(int{-401});
arr.push_back(-40.1);
arr.push_back(true);
BOOST_CHECK_EQUAL(arr.empty(), false);
BOOST_CHECK_EQUAL(arr.size(), 10);
BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023");
BOOST_CHECK_EQUAL(arr[0].getType(), UniValue::VNUM);
BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy");
BOOST_CHECK_EQUAL(arr[1].getType(), UniValue::VSTR);
BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy");
BOOST_CHECK_EQUAL(arr[2].getType(), UniValue::VSTR);
BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing");
BOOST_CHECK_EQUAL(arr[3].getType(), UniValue::VSTR);
BOOST_CHECK_EQUAL(arr[4].getValStr(), "going");
BOOST_CHECK_EQUAL(arr[4].getType(), UniValue::VSTR);
BOOST_CHECK_EQUAL(arr[5].getValStr(), "400");
BOOST_CHECK_EQUAL(arr[5].getType(), UniValue::VNUM);
BOOST_CHECK_EQUAL(arr[6].getValStr(), "-400");
BOOST_CHECK_EQUAL(arr[6].getType(), UniValue::VNUM);
BOOST_CHECK_EQUAL(arr[7].getValStr(), "-401");
BOOST_CHECK_EQUAL(arr[7].getType(), UniValue::VNUM);
BOOST_CHECK_EQUAL(arr[8].getValStr(), "-40.1");
BOOST_CHECK_EQUAL(arr[8].getType(), UniValue::VNUM);
BOOST_CHECK_EQUAL(arr[9].getValStr(), "1");
BOOST_CHECK_EQUAL(arr[9].getType(), UniValue::VBOOL);
BOOST_CHECK_EQUAL(arr[999].getValStr(), "");
arr.clear();
BOOST_CHECK(arr.empty());
BOOST_CHECK_EQUAL(arr.size(), 0);
}
void univalue_object()
{
UniValue obj(UniValue::VOBJ);
std::string strKey, strVal;
UniValue v;
obj.reserve(11);
strKey = "age";
v.setInt(100);
obj.pushKV(strKey, v);
strKey = "first";
strVal = "John";
obj.pushKV(strKey, strVal);
strKey = "last";
const char* cVal = "Smith";
obj.pushKV(strKey, cVal);
strKey = "distance";
obj.pushKV(strKey, int64_t{25});
strKey = "time";
obj.pushKV(strKey, uint64_t{3600});
strKey = "calories";
obj.pushKV(strKey, int{12});
strKey = "temperature";
obj.pushKV(strKey, double{90.012});
strKey = "moon";
obj.pushKV(strKey, true);
strKey = "spoon";
obj.pushKV(strKey, false);
UniValue obj2(UniValue::VOBJ);
obj2.pushKV("cat1", 9000);
obj2.pushKV("cat2", 12345);
obj.pushKVs(obj2);
BOOST_CHECK_EQUAL(obj.empty(), false);
BOOST_CHECK_EQUAL(obj.size(), 11);
BOOST_CHECK_EQUAL(obj["age"].getValStr(), "100");
BOOST_CHECK_EQUAL(obj["first"].getValStr(), "John");
BOOST_CHECK_EQUAL(obj["last"].getValStr(), "Smith");
BOOST_CHECK_EQUAL(obj["distance"].getValStr(), "25");
BOOST_CHECK_EQUAL(obj["time"].getValStr(), "3600");
BOOST_CHECK_EQUAL(obj["calories"].getValStr(), "12");
BOOST_CHECK_EQUAL(obj["temperature"].getValStr(), "90.012");
BOOST_CHECK_EQUAL(obj["moon"].getValStr(), "1");
BOOST_CHECK_EQUAL(obj["spoon"].getValStr(), "");
BOOST_CHECK_EQUAL(obj["cat1"].getValStr(), "9000");
BOOST_CHECK_EQUAL(obj["cat2"].getValStr(), "12345");
BOOST_CHECK_EQUAL(obj["nyuknyuknyuk"].getValStr(), "");
BOOST_CHECK(obj.exists("age"));
BOOST_CHECK(obj.exists("first"));
BOOST_CHECK(obj.exists("last"));
BOOST_CHECK(obj.exists("distance"));
BOOST_CHECK(obj.exists("time"));
BOOST_CHECK(obj.exists("calories"));
BOOST_CHECK(obj.exists("temperature"));
BOOST_CHECK(obj.exists("moon"));
BOOST_CHECK(obj.exists("spoon"));
BOOST_CHECK(obj.exists("cat1"));
BOOST_CHECK(obj.exists("cat2"));
BOOST_CHECK(!obj.exists("nyuknyuknyuk"));
std::map<std::string, UniValue::VType> objTypes;
objTypes["age"] = UniValue::VNUM;
objTypes["first"] = UniValue::VSTR;
objTypes["last"] = UniValue::VSTR;
objTypes["distance"] = UniValue::VNUM;
objTypes["time"] = UniValue::VNUM;
objTypes["calories"] = UniValue::VNUM;
objTypes["temperature"] = UniValue::VNUM;
objTypes["moon"] = UniValue::VBOOL;
objTypes["spoon"] = UniValue::VBOOL;
objTypes["cat1"] = UniValue::VNUM;
objTypes["cat2"] = UniValue::VNUM;
BOOST_CHECK(obj.checkObject(objTypes));
objTypes["cat2"] = UniValue::VSTR;
BOOST_CHECK(!obj.checkObject(objTypes));
obj.clear();
BOOST_CHECK(obj.empty());
BOOST_CHECK_EQUAL(obj.size(), 0);
BOOST_CHECK_EQUAL(obj.getType(), UniValue::VNULL);
obj.setObject();
UniValue uv;
uv.setInt(42);
obj.pushKVEnd("age", uv);
BOOST_CHECK_EQUAL(obj.size(), 1);
BOOST_CHECK_EQUAL(obj["age"].getValStr(), "42");
uv.setInt(43);
obj.pushKV("age", uv);
BOOST_CHECK_EQUAL(obj.size(), 1);
BOOST_CHECK_EQUAL(obj["age"].getValStr(), "43");
obj.pushKV("name", "foo bar");
std::map<std::string,UniValue> kv;
obj.getObjMap(kv);
BOOST_CHECK_EQUAL(kv["age"].getValStr(), "43");
BOOST_CHECK_EQUAL(kv["name"].getValStr(), "foo bar");
}
static const char *json1 =
"[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian http://test.com\"}}]";
void univalue_readwrite()
{
UniValue v;
BOOST_CHECK(v.read(json1));
std::string strJson1(json1);
BOOST_CHECK(v.read(strJson1));
BOOST_CHECK(v.isArray());
BOOST_CHECK_EQUAL(v.size(), 2);
BOOST_CHECK_EQUAL(v[0].getValStr(), "1.10000000");
UniValue obj = v[1];
BOOST_CHECK(obj.isObject());
BOOST_CHECK_EQUAL(obj.size(), 3);
BOOST_CHECK(obj["key1"].isStr());
std::string correctValue("str");
correctValue.push_back('\0');
BOOST_CHECK_EQUAL(obj["key1"].getValStr(), correctValue);
BOOST_CHECK(obj["key2"].isNum());
BOOST_CHECK_EQUAL(obj["key2"].getValStr(), "800");
BOOST_CHECK(obj["key3"].isObject());
BOOST_CHECK_EQUAL(strJson1, v.write());
// Valid
BOOST_CHECK(v.read("1.0") && (v.get_real() == 1.0));
BOOST_CHECK(v.read("true") && v.get_bool());
BOOST_CHECK(v.read("[false]") && !v[0].get_bool());
BOOST_CHECK(v.read("{\"a\": true}") && v["a"].get_bool());
BOOST_CHECK(v.read("{\"1\": \"true\"}") && (v["1"].get_str() == "true"));
// Valid, with leading or trailing whitespace
BOOST_CHECK(v.read(" 1.0") && (v.get_real() == 1.0));
BOOST_CHECK(v.read("1.0 ") && (v.get_real() == 1.0));
- BOOST_CHECK(v.read("0.00000000000000000000000000000000000001e+30 ") && v.get_real() == 1e-8);
+ BOOST_CHECK(v.read("0.00000000000000000000000000000000000001e+30 "));
//should fail, missing leading 0, therefore invalid JSON
BOOST_CHECK(!v.read(".19e-6"));
// Invalid, initial garbage
BOOST_CHECK(!v.read("[1.0"));
BOOST_CHECK(!v.read("a1.0"));
// Invalid, trailing garbage
BOOST_CHECK(!v.read("1.0sds"));
BOOST_CHECK(!v.read("1.0]"));
// Invalid, keys have to be names
BOOST_CHECK(!v.read("{1: \"true\"}"));
BOOST_CHECK(!v.read("{true: 1}"));
BOOST_CHECK(!v.read("{[1]: 1}"));
BOOST_CHECK(!v.read("{{\"a\": \"a\"}: 1}"));
// BTC addresses should fail parsing
BOOST_CHECK(!v.read("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
BOOST_CHECK(!v.read("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL"));
/* 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"));
}
int main(int argc, char* argv[])
{
univalue_constructor();
univalue_push_throw();
univalue_typecheck();
univalue_set();
univalue_array();
univalue_object();
univalue_readwrite();
return 0;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, May 21, 22:17 (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5866047
Default Alt Text
(42 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment