import contextlib import re import os import time from .portseed import electrum_monitoring_port from .environment import network, Network, node, node_supports, NodeFeature, Node class TestNode: # pylint: disable=too-many-arguments def __init__(self, rpc, datadir, process, node_number, rostrum_process): self.rpc = rpc self.datadir = datadir self.process = process self.node_number = node_number self.rostrum_process = rostrum_process def getrawtxpool(self, *args): if network() == Network.BCH: if len(args) == 2 and args[0] is False and args[1] == "id": # Defaults for BCH, but bch does not take the "id" arg. return self.rpc.getrawmempool() return self.rpc.getrawmempool(*args) if network() == Network.NEX: return self.rpc.getrawtxpool(*args) raise NotImplementedError() def getrawmempool(self, _): raise NotImplementedError("Use 'getrawtxpool'") def signrawtransactionwithwallet(self, _): raise NotImplementedError("Use 'signrawtransaction'") def signrawtransaction(self, *args): if node() == Node.BCHN: return self.rpc.signrawtransactionwithwallet(*args) return self.rpc.signrawtransaction(*args) def monitoring_url(self) -> str: return f"http://127.0.0.1:{electrum_monitoring_port(self.node_number)}" def __getattr__(self, name): """ Assume anything not implemented here is an rpc call and pass it on """ return getattr(self.rpc, name) def _raise_assertion_error(self, error): assert False, error @contextlib.contextmanager def assert_debug_log(self, *, expected_msgs, unexpected_msgs): if node_supports(node(), NodeFeature.RPC_LOGLINE): self.rpc.logline("flush log") debug_log = os.path.join(self.datadir, "regtest", "debug.log") with open(debug_log, encoding="utf-8") as dl: dl.seek(0, 2) prev_size = dl.tell() try: yield finally: # Travis test framework is so erratic that to make this reliable # but generally quick we need to try a bunch of time looking for # the appropriate log missing_expected = [] for _ in range(0, 90): if node_supports(node(), NodeFeature.RPC_LOGLINE): self.rpc.logline("flush log") with open(debug_log, encoding="utf-8") as dl: dl.seek(prev_size) log = dl.read() print_log = " - " + "\n - ".join(log.splitlines()) for unexpected in unexpected_msgs: if ( re.search(re.escape(unexpected), log, flags=re.MULTILINE) is not None ): self._raise_assertion_error( f'Unexpected message "{unexpected}" matched log:\n\n{print_log}\n\n' ) missing_expected = [] for expected_msg in expected_msgs: if ( re.search(re.escape(expected_msg), log, flags=re.MULTILINE) is None ): missing_expected.append(expected_msg) if not missing_expected: break time.sleep(1) if missing_expected: self._raise_assertion_error( f"Expected messages {missing_expected} do not partially match log:\n\n{print_log}\n\n" )