rpc_misc.py raw
1 #!/usr/bin/env python3
2 # Copyright (c) 2019-present The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 """Test RPC misc output."""
6 import xml.etree.ElementTree as ET
7
8 from test_framework.test_framework import BitcoinTestFramework
9 from test_framework.util import (
10 assert_raises_rpc_error,
11 assert_equal,
12 assert_greater_than,
13 assert_greater_than_or_equal,
14 JSONRPCException,
15 )
16
17 import http
18 import subprocess
19
20
21 class RpcMiscTest(BitcoinTestFramework):
22 def set_test_params(self):
23 self.num_nodes = 1
24
25 def run_test(self):
26 node = self.nodes[0]
27
28 self.log.info("test CHECK_NONFATAL")
29 msg_internal_bug = 'request.params[9].get_str() != "trigger_internal_bug"'
30 self.restart_node(0) # Required to flush the chainstate
31 try:
32 node.echo(arg9="trigger_internal_bug")
33 assert False # Must hit one of the exceptions below
34 except (
35 subprocess.CalledProcessError,
36 http.client.CannotSendRequest,
37 http.client.RemoteDisconnected,
38 ):
39 self.log.info("Restart node after crash")
40 assert_equal(-6, node.process.wait(timeout=10))
41 self.start_node(0)
42 except JSONRPCException as e:
43 assert_equal(e.error["code"], -1)
44 assert f"Internal bug detected: {msg_internal_bug}" in e.error["message"]
45
46 self.log.info("test max arg size")
47 ARG_SZ_COMMON = 131071 # Common limit, used previously in the test framework, serves as a regression test
48 ARG_SZ_LARGE = 8 * 1024 * 1024 # A large size, which should be rare to hit in practice
49 for arg_sz in [0, 1, 100, ARG_SZ_COMMON, ARG_SZ_LARGE]:
50 arg_string = 'a' * arg_sz
51 assert_equal([arg_string, arg_string], node.echo(arg_string, arg_string))
52
53 self.log.info("test getmemoryinfo")
54 memory = node.getmemoryinfo()['locked']
55 assert_greater_than(memory['used'], 0)
56 assert_greater_than(memory['free'], 0)
57 assert_greater_than(memory['total'], 0)
58 # assert_greater_than_or_equal() for locked in case locking pages failed at some point
59 assert_greater_than_or_equal(memory['locked'], 0)
60 assert_greater_than(memory['chunks_used'], 0)
61 assert_greater_than(memory['chunks_free'], 0)
62 assert_equal(memory['used'] + memory['free'], memory['total'])
63
64 self.log.info("test mallocinfo")
65 try:
66 mallocinfo = node.getmemoryinfo(mode="mallocinfo")
67 self.log.info('getmemoryinfo(mode="mallocinfo") call succeeded')
68 tree = ET.fromstring(mallocinfo)
69 assert_equal(tree.tag, 'malloc')
70 except JSONRPCException:
71 self.log.info('getmemoryinfo(mode="mallocinfo") not available')
72 assert_raises_rpc_error(-8, 'mallocinfo mode not available', node.getmemoryinfo, mode="mallocinfo")
73
74 assert_raises_rpc_error(-8, "unknown mode foobar", node.getmemoryinfo, mode="foobar")
75
76 self.log.info("test logging rpc and help")
77
78 # Test toggling a logging category on/off/on with the logging RPC.
79 assert_equal(node.logging()['qt'], True)
80 node.logging(exclude=['qt'])
81 assert_equal(node.logging()['qt'], False)
82 node.logging(include=['qt'])
83 assert_equal(node.logging()['qt'], True)
84
85 # Test logging RPC returns the logging categories in alphabetical order.
86 sorted_logging_categories = sorted(node.logging())
87 assert_equal(list(node.logging()), sorted_logging_categories)
88
89 # Test logging help returns the logging categories string in alphabetical order.
90 categories = ', '.join(sorted_logging_categories)
91 logging_help = self.nodes[0].help('logging')
92 assert f"valid logging categories are: {categories}" in logging_help
93
94 self.log.info("test echoipc (testing spawned process in multiprocess build)")
95 assert_equal(node.echoipc("hello"), "hello")
96
97 self.log.info("test getindexinfo")
98 # Without any indices running the RPC returns an empty object
99 assert_equal(node.getindexinfo(), {})
100
101 # Restart the node with indices and wait for them to sync
102 self.restart_node(0, ["-txindex", "-blockfilterindex", "-coinstatsindex", "-txospenderindex"])
103 self.wait_until(lambda: all(i["synced"] for i in node.getindexinfo().values()))
104
105 # Returns a list of all running indices by default
106 values = {"synced": True, "best_block_height": 200}
107 assert_equal(
108 node.getindexinfo(),
109 {
110 "txindex": values,
111 "basic block filter index": values,
112 "coinstatsindex": values,
113 "txospenderindex": values,
114 }
115 )
116 # Specifying an index by name returns only the status of that index
117 for i in {"txindex", "basic block filter index", "coinstatsindex", "txospenderindex"}:
118 assert_equal(node.getindexinfo(i), {i: values})
119
120 # Specifying an unknown index name returns an empty result
121 assert_equal(node.getindexinfo("foo"), {})
122
123 # Test a deprecated category
124 all_result = node.logging(include=['all'])
125 assert_equal(True, all(enabled is True for category, enabled in all_result.items()))
126 assert_equal(True, 'libevent' not in all_result)
127 assert_equal(all_result, node.logging())
128 libevent_warning = "The logging category `libevent` is deprecated"
129 with self.nodes[0].assert_debug_log([libevent_warning]):
130 assert_equal(all_result, node.logging(include=['libevent']))
131 assert_equal(all_result, node.logging())
132 with self.nodes[0].assert_debug_log([libevent_warning]):
133 assert_equal(all_result, node.logging(exclude=['libevent']))
134 assert_equal(all_result, node.logging())
135
136
137 if __name__ == '__main__':
138 RpcMiscTest(__file__).main()
139