import contextlib
import re
import os
import subprocess
import time
from .portseed import electrum_monitoring_port
from .environment import network, Network, node, node_supports, NodeFeature, Node
class TestNode:
def __init__(
self,
rpc,
datadir,
process: subprocess.Popen,
node_number: int,
rostrum_process: subprocess.Popen | None,
):
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":
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):
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:
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"
)