Skip to content

Commit 6707a98

Browse files
hdnsimpsonalex v
authored andcommitted
Added rpc help test (#392)
* Added rpc help test Tests the ability to generate help at runtime * Added check for compiled wallet and zmq * Setup clean chain to try avoid timeout on travis * Streamline test to only check invalid help calls and help categories * Added back removed functionality * Updated init
1 parent 1990d92 commit 6707a98

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

qa/pull-tester/rpc-tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
'staticr-staking-amount.py',
168168
'hardfork-451.py',
169169
'staticr-tx-send.py',
170+
'rpc-help.py',
170171
]
171172
#if ENABLE_ZMQ:
172173
# testScripts.append('zmq_test.py')

qa/rpc-tests/rpc-help.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/usr/bin/env python3
2+
# Tests RPC help output at runtime
3+
4+
from test_framework.test_framework import NavCoinTestFramework
5+
from test_framework.util import *
6+
7+
import os
8+
9+
10+
class HelpRpcTest(NavCoinTestFramework):
11+
def __init__(self):
12+
super().__init__()
13+
self.setup_clean_chain = True
14+
self.num_nodes = 1
15+
16+
def setup_network(self, split=False):
17+
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
18+
self.is_network_split = False
19+
20+
def run_test(self):
21+
self.test_categories()
22+
self.dump_help()
23+
24+
def test_categories(self):
25+
node = self.nodes[0]
26+
27+
# wrong argument count
28+
assert_raises_rpc_error(-1, 'help ( "command" )', node.help, 'foo', 'bar')
29+
30+
# invalid argument
31+
assert_raises_rpc_error(-1, 'JSON value is not a string as expected', node.help, 0)
32+
33+
# help of unknown command
34+
assert_equal(node.help('foo'), 'help: unknown command: foo')
35+
36+
# command titles
37+
titles = [line[3:-3] for line in node.help().splitlines() if line.startswith('==')]
38+
39+
components = ['Addressindex', 'Blockchain', 'Communityfund', 'Control', 'Generating', 'Hacking', 'Mining', 'Network', 'Rawtransactions', 'Util']
40+
41+
# titles and components will differ depending on whether wallet and/or zmq are compiled
42+
if 'Wallet' in titles:
43+
components.append('Wallet')
44+
45+
if 'Zmq' in titles:
46+
components.append('Zmq')
47+
48+
assert_equal(titles, components)
49+
50+
def dump_help(self):
51+
dump_dir = os.path.join(self.options.tmpdir, 'rpc_help_dump')
52+
os.mkdir(dump_dir)
53+
calls = [line.split(' ', 1)[0] for line in self.nodes[0].help().splitlines() if line and not line.startswith('==')]
54+
for call in calls:
55+
with open(os.path.join(dump_dir, call), 'w', encoding='utf-8') as f:
56+
# Make sure node can generate the help at runtime without crashing
57+
f.write(self.nodes[0].help(call))
58+
59+
60+
if __name__ == '__main__':
61+
HelpRpcTest().main()

qa/rpc-tests/test_framework/util.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,40 @@ def assert_array_result(object_array, to_match, expected, should_not_find = Fals
556556
if num_matched > 0 and should_not_find == True:
557557
raise AssertionError("Objects were found %s"%(str(to_match)))
558558

559+
def assert_raises_rpc_error(code, message, fun, *args, **kwds):
560+
"""Run an RPC and verify that a specific JSONRPC exception code and message is raised.
561+
Calls function `fun` with arguments `args` and `kwds`. Catches a JSONRPCException
562+
and verifies that the error code and message are as expected. Throws AssertionError if
563+
no JSONRPCException was raised or if the error code/message are not as expected.
564+
Args:
565+
code (int), optional: the error code returned by the RPC call (defined
566+
in src/rpc/protocol.h). Set to None if checking the error code is not required.
567+
message (string), optional: [a substring of] the error string returned by the
568+
RPC call. Set to None if checking the error string is not required.
569+
fun (function): the function to call. This should be the name of an RPC.
570+
args*: positional arguments for the function.
571+
kwds**: named arguments for the function.
572+
"""
573+
assert try_rpc(code, message, fun, *args, **kwds), "No exception raised"
574+
575+
def try_rpc(code, message, fun, *args, **kwds):
576+
"""Tries to run an rpc command.
577+
Test against error code and message if the rpc fails.
578+
Returns whether a JSONRPCException was raised."""
579+
try:
580+
fun(*args, **kwds)
581+
except JSONRPCException as e:
582+
# JSONRPCException was thrown as expected. Check the code and message values are correct.
583+
if (code is not None) and (code != e.error["code"]):
584+
raise AssertionError("Unexpected JSONRPC error code %i" % e.error["code"])
585+
if (message is not None) and (message not in e.error['message']):
586+
raise AssertionError("Expected substring not found:" + e.error['message'])
587+
return True
588+
except Exception as e:
589+
raise AssertionError("Unexpected exception raised: " + type(e).__name__)
590+
else:
591+
return False
592+
559593
def satoshi_round(amount):
560594
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
561595

0 commit comments

Comments
 (0)