/ test / functional / rpc_misc.py
rpc_misc.py
  1  #!/usr/bin/env python3
  2  # Copyright (c) 2019-2022 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  )
 15  
 16  from test_framework.authproxy import JSONRPCException
 17  
 18  import http
 19  import subprocess
 20  
 21  
 22  class RpcMiscTest(BitcoinTestFramework):
 23      def set_test_params(self):
 24          self.num_nodes = 1
 25  
 26      def run_test(self):
 27          node = self.nodes[0]
 28  
 29          self.log.info("test CHECK_NONFATAL")
 30          msg_internal_bug = 'request.params[9].get_str() != "trigger_internal_bug"'
 31          self.restart_node(0)  # Required to flush the chainstate
 32          try:
 33              node.echo(arg9="trigger_internal_bug")
 34              assert False  # Must hit one of the exceptions below
 35          except (
 36                  subprocess.CalledProcessError,
 37                  http.client.CannotSendRequest,
 38                  http.client.RemoteDisconnected,
 39          ):
 40              self.log.info("Restart node after crash")
 41              assert_equal(-6, node.process.wait(timeout=10))
 42              self.start_node(0)
 43          except JSONRPCException as e:
 44              assert_equal(e.error["code"], -1)
 45              assert f"Internal bug detected: {msg_internal_bug}" in e.error["message"]
 46  
 47          self.log.info("test max arg size")
 48          ARG_SZ_COMMON = 131071  # Common limit, used previously in the test framework, serves as a regression test
 49          ARG_SZ_LARGE = 8 * 1024 * 1024  # A large size, which should be rare to hit in practice
 50          for arg_sz in [0, 1, 100, ARG_SZ_COMMON, ARG_SZ_LARGE]:
 51              arg_string = 'a' * arg_sz
 52              assert_equal([arg_string, arg_string], node.echo(arg_string, arg_string))
 53  
 54          self.log.info("test getmemoryinfo")
 55          memory = node.getmemoryinfo()['locked']
 56          assert_greater_than(memory['used'], 0)
 57          assert_greater_than(memory['free'], 0)
 58          assert_greater_than(memory['total'], 0)
 59          # assert_greater_than_or_equal() for locked in case locking pages failed at some point
 60          assert_greater_than_or_equal(memory['locked'], 0)
 61          assert_greater_than(memory['chunks_used'], 0)
 62          assert_greater_than(memory['chunks_free'], 0)
 63          assert_equal(memory['used'] + memory['free'], memory['total'])
 64  
 65          self.log.info("test mallocinfo")
 66          try:
 67              mallocinfo = node.getmemoryinfo(mode="mallocinfo")
 68              self.log.info('getmemoryinfo(mode="mallocinfo") call succeeded')
 69              tree = ET.fromstring(mallocinfo)
 70              assert_equal(tree.tag, 'malloc')
 71          except JSONRPCException:
 72              self.log.info('getmemoryinfo(mode="mallocinfo") not available')
 73              assert_raises_rpc_error(-8, 'mallocinfo mode not available', node.getmemoryinfo, mode="mallocinfo")
 74  
 75          assert_raises_rpc_error(-8, "unknown mode foobar", node.getmemoryinfo, mode="foobar")
 76  
 77          self.log.info("test logging rpc and help")
 78  
 79          # Test toggling a logging category on/off/on with the logging RPC.
 80          assert_equal(node.logging()['qt'], True)
 81          node.logging(exclude=['qt'])
 82          assert_equal(node.logging()['qt'], False)
 83          node.logging(include=['qt'])
 84          assert_equal(node.logging()['qt'], True)
 85  
 86          # Test logging RPC returns the logging categories in alphabetical order.
 87          sorted_logging_categories = sorted(node.logging())
 88          assert_equal(list(node.logging()), sorted_logging_categories)
 89  
 90          # Test logging help returns the logging categories string in alphabetical order.
 91          categories = ', '.join(sorted_logging_categories)
 92          logging_help = self.nodes[0].help('logging')
 93          assert f"valid logging categories are: {categories}" in logging_help
 94  
 95          self.log.info("test echoipc (testing spawned process in multiprocess build)")
 96          assert_equal(node.echoipc("hello"), "hello")
 97  
 98          self.log.info("test getindexinfo")
 99          # Without any indices running the RPC returns an empty object
100          assert_equal(node.getindexinfo(), {})
101  
102          # Restart the node with indices and wait for them to sync
103          self.restart_node(0, ["-txindex", "-blockfilterindex", "-coinstatsindex"])
104          self.wait_until(lambda: all(i["synced"] for i in node.getindexinfo().values()))
105  
106          # Returns a list of all running indices by default
107          values = {"synced": True, "best_block_height": 200}
108          assert_equal(
109              node.getindexinfo(),
110              {
111                  "txindex": values,
112                  "basic block filter index": values,
113                  "coinstatsindex": 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"}:
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  
124  if __name__ == '__main__':
125      RpcMiscTest(__file__).main()