/ src / qt / test / rpcnestedtests.cpp
rpcnestedtests.cpp
  1  // Copyright (c) 2016-present The Bitcoin Core developers
  2  // Distributed under the MIT software license, see the accompanying
  3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4  
  5  #include <qt/test/rpcnestedtests.h>
  6  
  7  #include <common/system.h>
  8  #include <interfaces/node.h>
  9  #include <qt/rpcconsole.h>
 10  #include <rpc/server.h>
 11  #include <test/util/setup_common.h>
 12  #include <univalue.h>
 13  
 14  #include <QTest>
 15  
 16  #include <string>
 17  #include <stdexcept>
 18  
 19  static RPCMethod rpcNestedTest_rpc()
 20  {
 21      return RPCMethod{
 22          "rpcNestedTest",
 23          "echo the passed string(s)",
 24          {
 25              {"arg1", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
 26              {"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
 27              {"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
 28          },
 29          RPCResult{RPCResult::Type::ANY, "", ""},
 30          RPCExamples{""},
 31          [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue {
 32              return request.params.write(0, 0);
 33          },
 34      };
 35  }
 36  
 37  static const CRPCCommand vRPCCommands[] = {
 38      {"rpcNestedTest", &rpcNestedTest_rpc},
 39  };
 40  
 41  void RPCNestedTests::rpcNestedTests()
 42  {
 43      // do some test setup
 44      // could be moved to a more generic place when we add more tests on QT level
 45      for (const auto& c : vRPCCommands) {
 46          tableRPC.appendCommand(c.name, &c);
 47      }
 48  
 49      TestingSetup test;
 50      m_node.setContext(&test.m_node);
 51  
 52      if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
 53  
 54      std::string result;
 55      std::string result2;
 56      std::string filtered;
 57      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path
 58      QVERIFY(result=="main");
 59      QVERIFY(filtered == "getblockchaininfo()[chain]");
 60  
 61      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getbestblockhash())"); //simple 2 level nesting
 62      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getblock(getbestblockhash())[hash], true)");
 63  
 64      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter
 65  
 66      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo");
 67      QVERIFY(result.starts_with("{"));
 68  
 69      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()");
 70      QVERIFY(result.starts_with("{"));
 71  
 72      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo "); //whitespace at the end will be tolerated
 73      QVERIFY(result.starts_with("{"));
 74  
 75      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()[\"chain\"]"); //Quote path identifier are allowed, but look after a child containing the quotes in the key
 76      QVERIFY(result == "null");
 77  
 78      RPCConsole::RPCExecuteCommandLine(m_node, result, "createrawtransaction [] {} 0"); //parameter not in brackets are allowed
 79      RPCConsole::RPCExecuteCommandLine(m_node, result2, "createrawtransaction([],{},0)"); //parameter in brackets are allowed
 80      QVERIFY(result == result2);
 81      RPCConsole::RPCExecuteCommandLine(m_node, result2, "createrawtransaction( [],  {} , 0   )"); //whitespace between parameters is allowed
 82      QVERIFY(result == result2);
 83  
 84      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getbestblockhash())[tx][0]", &filtered);
 85      QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
 86      QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]");
 87  
 88      RPCConsole::RPCParseCommandLine(nullptr, result, "createwallet test true", false, &filtered);
 89      QVERIFY(filtered == "createwallet(…)");
 90      RPCConsole::RPCParseCommandLine(nullptr, result, "createwalletdescriptor abc", false, &filtered);
 91      QVERIFY(filtered == "createwalletdescriptor(…)");
 92      RPCConsole::RPCParseCommandLine(nullptr, result, "migratewallet abc abc", false, &filtered);
 93      QVERIFY(filtered == "migratewallet(…)");
 94      RPCConsole::RPCParseCommandLine(nullptr, result, "signmessagewithprivkey abc", false, &filtered);
 95      QVERIFY(filtered == "signmessagewithprivkey(…)");
 96      RPCConsole::RPCParseCommandLine(nullptr, result, "signmessagewithprivkey abc,def", false, &filtered);
 97      QVERIFY(filtered == "signmessagewithprivkey(…)");
 98      RPCConsole::RPCParseCommandLine(nullptr, result, "signrawtransactionwithkey(abc)", false, &filtered);
 99      QVERIFY(filtered == "signrawtransactionwithkey(…)");
100      RPCConsole::RPCParseCommandLine(nullptr, result, "walletpassphrase(help())", false, &filtered);
101      QVERIFY(filtered == "walletpassphrase(…)");
102      RPCConsole::RPCParseCommandLine(nullptr, result, "walletpassphrasechange(help(walletpassphrasechange(abc)))", false, &filtered);
103      QVERIFY(filtered == "walletpassphrasechange(…)");
104      RPCConsole::RPCParseCommandLine(nullptr, result, "help(encryptwallet(abc, def))", false, &filtered);
105      QVERIFY(filtered == "help(encryptwallet(…))");
106  
107      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest");
108      QVERIFY(result == "[]");
109      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest ''");
110      QVERIFY(result == "[\"\"]");
111      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest \"\"");
112      QVERIFY(result == "[\"\"]");
113      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest '' abc");
114      QVERIFY(result == "[\"\",\"abc\"]");
115      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc '' abc");
116      QVERIFY(result == "[\"abc\",\"\",\"abc\"]");
117      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc  abc");
118      QVERIFY(result == "[\"abc\",\"abc\"]");
119      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc\t\tabc");
120      QVERIFY(result == "[\"abc\",\"abc\"]");
121      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc )");
122      QVERIFY(result == "[\"abc\"]");
123      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest( abc )");
124      QVERIFY(result == "[\"abc\"]");
125      RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(   abc   ,   cba )");
126      QVERIFY(result == "[\"abc\",\"cba\"]");
127  
128  // Handle deprecated macro, can be removed once minimum Qt is at least 6.3.0.
129  #if (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0))
130  #undef QVERIFY_EXCEPTION_THROWN
131  #define QVERIFY_EXCEPTION_THROWN(expression, exceptiontype) QVERIFY_THROWS_EXCEPTION(exceptiontype, expression)
132  #endif
133      QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
134      QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
135      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo("); //tolerate non closing brackets if we have no arguments
136      RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()()()"); //tolerate non command brackets
137      QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo(True)"), UniValue); //invalid argument
138      QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "a(getblockchaininfo(True))"), UniValue); //method not found
139      QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tolerate empty arguments when using ,
140      QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tolerate empty arguments when using ,
141      QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tolerate empty arguments when using ,
142  }