From 15860448d38ba7a436cf7c08fa5c0132fe10f8d3 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 20 Aug 2016 11:19:35 +0200 Subject: [Qt] RPC-Console: support nested commands and simple value queries Commands can be executed with bracket syntax, example: `getwalletinfo()`. Commands can be nested, example: `sendtoaddress(getnewaddress(), 10)`. Simple queries are possible: `listunspent()[0][txid]` Object values are accessed with a non-quoted string, example: [txid]. Fully backward compatible. `generate 101` is identical to `generate(101)` Result value queries indicated with `[]` require the new brackets syntax. Comma as argument separator is now also possible: `sendtoaddress,
,` Space as argument separator works also with the bracket syntax, example: `sendtoaddress(getnewaddress() 10) No dept limitation, complex commands are possible: `decoderawtransaction(getrawtransaction(getblock(getbestblockhash())[tx][0]))[vout][0][value]` --- src/qt/test/rpcnestedtests.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/qt/test/rpcnestedtests.cpp (limited to 'src/qt/test/rpcnestedtests.cpp') diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp new file mode 100644 index 000000000..3dae33baf --- /dev/null +++ b/src/qt/test/rpcnestedtests.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2016 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 "rpcnestedtests.h" + +#include "chainparams.h" +#include "consensus/validation.h" +#include "main.h" +#include "rpc/register.h" +#include "rpc/server.h" +#include "rpcconsole.h" +#include "test/testutil.h" +#include "univalue.h" +#include "util.h" + +#include + +#include + +void RPCNestedTests::rpcNestedTests() +{ + UniValue jsonRPCError; + + // do some test setup + // could be moved to a more generic place when we add more tests on QT level + const CChainParams& chainparams = Params(); + RegisterAllCoreRPCCommands(tableRPC); + ClearDatadirCache(); + std::string path = QDir::tempPath().toStdString() + "/" + strprintf("test_bitcoin_qt_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); + QDir dir(QString::fromStdString(path)); + dir.mkpath("."); + mapArgs["-datadir"] = path; + //mempool.setSanityCheck(1.0); + pblocktree = new CBlockTreeDB(1 << 20, true); + pcoinsdbview = new CCoinsViewDB(1 << 23, true); + pcoinsTip = new CCoinsViewCache(pcoinsdbview); + InitBlockIndex(chainparams); + { + CValidationState state; + bool ok = ActivateBestChain(state, chainparams); + QVERIFY(ok); + } + + SetRPCWarmupFinished(); + + std::string result; + std::string result2; + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[chain]"); //simple result filtering with path + QVERIFY(result=="main"); + + RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())"); //simple 2 level nesting + RPCConsole::RPCExecuteCommandLine(result, "getblock(getblock(getbestblockhash())[hash], true)"); + + RPCConsole::RPCExecuteCommandLine(result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter + + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo"); + QVERIFY(result.substr(0,1) == "{"); + + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()"); + QVERIFY(result.substr(0,1) == "{"); + + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo "); //whitespace at the end will be tolerated + QVERIFY(result.substr(0,1) == "{"); + +#if QT_VERSION >= 0x050300 + // do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3) + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()()()")); //tolerate non command brackts + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(True)"), UniValue); //invalid argument + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "a(getblockchaininfo(True))"), UniValue); //method not found +#endif + + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child contaning the quotes in the key + QVERIFY(result == "null"); + + (RPCConsole::RPCExecuteCommandLine(result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed + (RPCConsole::RPCExecuteCommandLine(result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed + QVERIFY(result == result2); + (RPCConsole::RPCExecuteCommandLine(result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parametres is allowed + QVERIFY(result == result2); + + RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())[tx][0]"); + QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + + delete pcoinsTip; + delete pcoinsdbview; + delete pblocktree; + + boost::filesystem::remove_all(boost::filesystem::path(path)); +} -- cgit v1.2.3 From 76faa3cdfedbd3fc91be4ecfff77fc6dc18134fb Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 1 Dec 2016 16:06:41 -0800 Subject: Rename the remaining main.{h,cpp} to validation.{h,cpp} --- src/qt/test/rpcnestedtests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qt/test/rpcnestedtests.cpp') diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 3dae33baf..69757f9a9 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -6,7 +6,7 @@ #include "chainparams.h" #include "consensus/validation.h" -#include "main.h" +#include "validation.h" #include "rpc/register.h" #include "rpc/server.h" #include "rpcconsole.h" -- cgit v1.2.3 From 6a32c0f69de1d9caf1af26e192efbb80f7534fdd Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 12 Dec 2016 23:04:10 +0000 Subject: Qt/Test: Check handling of empty arguments in RPC debug console --- src/qt/test/rpcnestedtests.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/qt/test/rpcnestedtests.cpp') diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 69757f9a9..0aeef0455 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -18,6 +18,19 @@ #include +static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request) +{ + if (request.fHelp) { + return "help message"; + } + return request.params.write(0, 0); +} + +static const CRPCCommand vRPCCommands[] = +{ + { "test", "rpcNestedTest", &rpcNestedTest_rpc, true }, +}; + void RPCNestedTests::rpcNestedTests() { UniValue jsonRPCError; @@ -26,6 +39,7 @@ void RPCNestedTests::rpcNestedTests() // could be moved to a more generic place when we add more tests on QT level const CChainParams& chainparams = Params(); RegisterAllCoreRPCCommands(tableRPC); + tableRPC.appendCommand("rpcNestedTest", &vRPCCommands[0]); ClearDatadirCache(); std::string path = QDir::tempPath().toStdString() + "/" + strprintf("test_bitcoin_qt_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); QDir dir(QString::fromStdString(path)); @@ -85,6 +99,23 @@ void RPCNestedTests::rpcNestedTests() RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())[tx][0]"); QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest"); + QVERIFY(result == "[]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest ''"); + QVERIFY(result == "[\"\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest \"\""); + QVERIFY(result == "[\"\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest '' abc"); + QVERIFY(result == "[\"\",\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc '' abc"); + QVERIFY(result == "[\"abc\",\"\",\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc abc"); + QVERIFY(result == "[\"abc\",\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc\t\tabc"); + QVERIFY(result == "[\"abc\",\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc,,abc"); + QVERIFY(result == "[\"abc\",\"\",\"abc\"]"); + delete pcoinsTip; delete pcoinsdbview; delete pblocktree; -- cgit v1.2.3 From 390bd14684a4f1a974014a31c71d44acd3d94d6a Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 14 Dec 2016 08:59:09 +0100 Subject: [Qt] Console: don't allow empty arguments when using the comma-syntax --- src/qt/test/rpcnestedtests.cpp | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'src/qt/test/rpcnestedtests.cpp') diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 0aeef0455..26ac5e211 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -15,6 +15,7 @@ #include "util.h" #include +#include #include @@ -77,16 +78,6 @@ void RPCNestedTests::rpcNestedTests() RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo "); //whitespace at the end will be tolerated QVERIFY(result.substr(0,1) == "{"); -#if QT_VERSION >= 0x050300 - // do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3) - QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax - QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax - (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments - (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()()()")); //tolerate non command brackts - QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(True)"), UniValue); //invalid argument - QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "a(getblockchaininfo(True))"), UniValue); //method not found -#endif - (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child contaning the quotes in the key QVERIFY(result == "null"); @@ -113,8 +104,25 @@ void RPCNestedTests::rpcNestedTests() QVERIFY(result == "[\"abc\",\"abc\"]"); RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc\t\tabc"); QVERIFY(result == "[\"abc\",\"abc\"]"); - RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc,,abc"); - QVERIFY(result == "[\"abc\",\"\",\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc )"); + QVERIFY(result == "[\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest( abc )"); + QVERIFY(result == "[\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest( abc , cba )"); + QVERIFY(result == "[\"abc\",\"cba\"]"); + +#if QT_VERSION >= 0x050300 + // do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3) + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()()()")); //tolerate non command brackts + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(True)"), UniValue); //invalid argument + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "a(getblockchaininfo(True))"), UniValue); //method not found + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tollerate empty arguments when using , + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using , + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using , +#endif delete pcoinsTip; delete pcoinsdbview; -- cgit v1.2.3 From 4cd373aea8d20356727f7d65e0bc818beb6523dc Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 29 Nov 2016 18:45:24 -0800 Subject: Un-expose mapArgs from utils.h --- src/qt/test/rpcnestedtests.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/qt/test/rpcnestedtests.cpp') diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 26ac5e211..972dad72d 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -19,6 +19,8 @@ #include +extern std::map mapArgs; + static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request) { if (request.fHelp) { -- cgit v1.2.3 From c2f61bebb190258753714b29ab2041e80651cec9 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 24 Dec 2016 11:28:44 -0500 Subject: Add a ForceSetArg method for testing --- src/qt/test/rpcnestedtests.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/qt/test/rpcnestedtests.cpp') diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 972dad72d..fb044489d 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -19,8 +19,6 @@ #include -extern std::map mapArgs; - static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request) { if (request.fHelp) { @@ -47,7 +45,7 @@ void RPCNestedTests::rpcNestedTests() std::string path = QDir::tempPath().toStdString() + "/" + strprintf("test_bitcoin_qt_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); QDir dir(QString::fromStdString(path)); dir.mkpath("."); - mapArgs["-datadir"] = path; + ForceSetArg("-datadir", path); //mempool.setSanityCheck(1.0); pblocktree = new CBlockTreeDB(1 << 20, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true); -- cgit v1.2.3 From a79598ddf4bf35b934ed3513900f2a9fae0bff45 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 16 Nov 2016 12:31:44 +0000 Subject: Qt/Test: Make sure filtering sensitive data works correctly in nested commands --- src/qt/test/rpcnestedtests.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'src/qt/test/rpcnestedtests.cpp') diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index fb044489d..fbec5722b 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -61,8 +61,10 @@ void RPCNestedTests::rpcNestedTests() std::string result; std::string result2; - RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[chain]"); //simple result filtering with path + std::string filtered; + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path QVERIFY(result=="main"); + QVERIFY(filtered == "getblockchaininfo()[chain]"); RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())"); //simple 2 level nesting RPCConsole::RPCExecuteCommandLine(result, "getblock(getblock(getbestblockhash())[hash], true)"); @@ -87,8 +89,30 @@ void RPCNestedTests::rpcNestedTests() (RPCConsole::RPCExecuteCommandLine(result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parametres is allowed QVERIFY(result == result2); - RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())[tx][0]"); + RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())[tx][0]", &filtered); QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]"); + + RPCConsole::RPCParseCommandLine(result, "importprivkey", false, &filtered); + QVERIFY(filtered == "importprivkey(…)"); + RPCConsole::RPCParseCommandLine(result, "signmessagewithprivkey abc", false, &filtered); + QVERIFY(filtered == "signmessagewithprivkey(…)"); + RPCConsole::RPCParseCommandLine(result, "signmessagewithprivkey abc,def", false, &filtered); + QVERIFY(filtered == "signmessagewithprivkey(…)"); + RPCConsole::RPCParseCommandLine(result, "signrawtransaction(abc)", false, &filtered); + QVERIFY(filtered == "signrawtransaction(…)"); + RPCConsole::RPCParseCommandLine(result, "walletpassphrase(help())", false, &filtered); + QVERIFY(filtered == "walletpassphrase(…)"); + RPCConsole::RPCParseCommandLine(result, "walletpassphrasechange(help(walletpassphrasechange(abc)))", false, &filtered); + QVERIFY(filtered == "walletpassphrasechange(…)"); + RPCConsole::RPCParseCommandLine(result, "help(encryptwallet(abc, def))", false, &filtered); + QVERIFY(filtered == "help(encryptwallet(…))"); + RPCConsole::RPCParseCommandLine(result, "help(importprivkey())", false, &filtered); + QVERIFY(filtered == "help(importprivkey(…))"); + RPCConsole::RPCParseCommandLine(result, "help(importprivkey(help()))", false, &filtered); + QVERIFY(filtered == "help(importprivkey(…))"); + RPCConsole::RPCParseCommandLine(result, "help(importprivkey(abc), walletpassphrase(def))", false, &filtered); + QVERIFY(filtered == "help(importprivkey(…), walletpassphrase(…))"); RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest"); QVERIFY(result == "[]"); -- cgit v1.2.3 From b8d1b81077e4d0efcf9aafc00954d6ecd3d72d31 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 20 Jan 2017 14:38:27 +0100 Subject: trivial: squash missing field 'argNames' initializer warning in qt tests The additional initializer is for the named arguments, which are unused in the test (and unfilled global fields will be initialized to 0 anyhow), so this is a no-op apart from the warning. --- src/qt/test/rpcnestedtests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qt/test/rpcnestedtests.cpp') diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index fbec5722b..bd496f149 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -29,7 +29,7 @@ static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request) static const CRPCCommand vRPCCommands[] = { - { "test", "rpcNestedTest", &rpcNestedTest_rpc, true }, + { "test", "rpcNestedTest", &rpcNestedTest_rpc, true, {} }, }; void RPCNestedTests::rpcNestedTests() -- cgit v1.2.3