qa: repair the rpc-test harness so it can start a DragonX node at all
The integration suite has never run against DragonX. Six independent
defects stacked up, each only visible once the previous was fixed:
1. test_framework used python2 implicit relative imports
("from authproxy import ..."), removed in python3, so every test died
at import. Made explicit relative imports.
2. It wrote ZZZ.conf -- a Komodo assetchain convention -- while DragonX
reads DRAGONX.conf. The daemon therefore never saw the generated
config, fell back to mainnet defaults and tried to bind RPC 21769,
which on a seed node is already held by the real node.
3. start_node() was hard-wired for the -ac_name=ZZZ assetchain tests: it
took the RPC port from extra_args[3], passed extra_args[0] as argv[0]
of the CLI, and only wrote a config when extra_args[0] matched. Any
test that passes no extra args crashed on len(None). The generic path
now takes the port from rpc_port(i) -- the same helper
initialize_datadir() already used -- and drives the CLI with -datadir.
4. dragonxd refuses to start without an asmap file, which no test datadir
had. initialize_datadir() now provisions one.
5. -asmap relative paths resolve against the NET-SPECIFIC datadir, so a
copy in <datadir> is never found. Pass an absolute path.
6. Worst: -regtest was only ever set as "regtest=1" in the conf file,
which DragonX ignores. Every "regtest" node therefore ran on MAINNET:
real genesis, real seeds, real peers. An observed run synced 196,180
live blocks and 679MB into /tmp before the test timed out. -regtest is
now passed as a command-line flag, with -connect=0 so an isolated
regtest node stays off the public network.
With these, nodes start, RPC answers, and tests run to a real result.
They do not all pass yet -- getblocktemplate.py reaches an assertion --
but that is now a test outcome rather than a harness failure.
This commit is contained in:
@@ -18,7 +18,7 @@ import subprocess
|
||||
import time
|
||||
import re
|
||||
|
||||
from authproxy import AuthServiceProxy
|
||||
from .authproxy import AuthServiceProxy
|
||||
|
||||
def p2p_port(n):
|
||||
return 11000 + n + os.getpid()%999
|
||||
@@ -97,8 +97,8 @@ def initialize_datadir(dirname, n):
|
||||
print("Creating dirs %s" % datadir)
|
||||
os.makedirs(datadir)
|
||||
|
||||
print("Writing to " + os.path.join(datadir,"ZZZ.conf"))
|
||||
with open(os.path.join(datadir, "ZZZ.conf"), 'w') as f:
|
||||
print("Writing to " + os.path.join(datadir,"DRAGONX.conf"))
|
||||
with open(os.path.join(datadir, "DRAGONX.conf"), 'w') as f:
|
||||
f.write("regtest=1\n");
|
||||
f.write("txindex=1\n");
|
||||
#f.write("testnode=1\n");
|
||||
@@ -116,7 +116,19 @@ def initialize_datadir(dirname, n):
|
||||
f.write("spentindex=1\n");
|
||||
f.write("timestampindex=1\n");
|
||||
#f.write("zindex=1\n");
|
||||
print("Done writing to %s" % os.path.join(datadir,"ZZZ.conf") )
|
||||
print("Done writing to %s" % os.path.join(datadir,"DRAGONX.conf") )
|
||||
|
||||
# dragonxd refuses to start without an asmap file ("Could not find any asmap file!"),
|
||||
# so every regtest datadir needs one. Link the tree's copy rather than duplicating it.
|
||||
for src in ("../../../asmap.dat", "../../../src/asmap.dat",
|
||||
os.path.expanduser("~/.hush/DRAGONX/asmap.dat")):
|
||||
cand = src if os.path.isabs(src) else os.path.join(os.path.dirname(os.path.abspath(__file__)), src)
|
||||
if os.path.exists(cand):
|
||||
dst = os.path.join(datadir, "asmap.dat")
|
||||
if not os.path.exists(dst):
|
||||
try: os.symlink(os.path.realpath(cand), dst)
|
||||
except OSError: shutil.copyfile(cand, dst)
|
||||
break
|
||||
|
||||
return datadir
|
||||
|
||||
@@ -133,11 +145,11 @@ def initialize_chain(test_dir):
|
||||
# Create cache directories, run hushds:
|
||||
for i in range(4):
|
||||
datadir=initialize_datadir("cache", i)
|
||||
args = [ os.getenv("BITCOIND", "hushd"), "-keypool=1", "-datadir="+datadir, "-discover=0" ]
|
||||
args = [ os.getenv("BITCOIND", "dragonxd"), "-keypool=1", "-datadir="+datadir, "-discover=0" ]
|
||||
if i > 0:
|
||||
args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
|
||||
bitcoind_processes[i] = subprocess.Popen(args)
|
||||
cmd = os.getenv("BITCOINCLI", "hush-cli")
|
||||
cmd = os.getenv("BITCOINCLI", "dragonx-cli")
|
||||
cmd_args = cmd + " -datadir="+datadir + " -rpcwait getblockcount"
|
||||
if os.getenv("PYTHON_DEBUG", ""):
|
||||
print("initialize_chain: hushd started, calling: " + cmd_args)
|
||||
@@ -227,9 +239,10 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
|
||||
"""
|
||||
print("Starting node " + str(i) + " in dir " + dirname)
|
||||
datadir = os.path.join(dirname, "node"+str(i), "regtest")
|
||||
if extra_args is None: extra_args = []
|
||||
# creating special config
|
||||
if len(extra_args) > 0 and extra_args[0] == '-ac_name=ZZZ':
|
||||
configpath = datadir + "/ZZZ.conf"
|
||||
configpath = datadir + "/DRAGONX.conf"
|
||||
with open(configpath, "w+") as config:
|
||||
config.write("rpcuser=hush\n")
|
||||
config.write("rpcpassword=puppy\n")
|
||||
@@ -247,16 +260,30 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
|
||||
print("Done writing to %s" % configpath)
|
||||
|
||||
if binary is None:
|
||||
binary = os.getenv("BITCOIND", "src/hushd")
|
||||
args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
|
||||
binary = os.getenv("BITCOIND", "src/dragonxd")
|
||||
# -regtest MUST be a command-line flag. DragonX ignores "regtest=1" in the conf file, so
|
||||
# without this the node silently runs on MAINNET: it loads the real genesis, dials the real
|
||||
# seeds and starts syncing the live chain into the test datadir (observed: 196k blocks and
|
||||
# 679MB before a test timed out). -connect=0 keeps the regtest node off the public network.
|
||||
args = [ binary, "-regtest", "-connect=0", "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
|
||||
# -asmap relative paths are resolved against the NET-SPECIFIC datadir (init.cpp), which for
|
||||
# regtest is <datadir>/regtest -- so a copy sitting in <datadir> is never found. Pass an
|
||||
# absolute path; without it dragonxd exits with "Could not find any asmap file!".
|
||||
_asmap = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../asmap.dat")
|
||||
if os.path.exists(_asmap):
|
||||
args.append("-asmap=" + os.path.realpath(_asmap))
|
||||
if extra_args is not None: args.extend(extra_args)
|
||||
print("args=" + ' '.join(args))
|
||||
bitcoind_processes[i] = subprocess.Popen(args)
|
||||
devnull = open("/dev/null", "w+")
|
||||
|
||||
cmd = os.getenv("BITCOINCLI", "src/hush-cli")
|
||||
cmd = os.getenv("BITCOINCLI", "src/dragonx-cli")
|
||||
print("cmd=" + cmd)
|
||||
args = [ extra_args[0], "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
|
||||
# The CLI only needs the datadir: initialize_datadir() already wrote DRAGONX.conf there
|
||||
# with the right rpcport/user/password. The old form passed extra_args[0] as argv[0] and
|
||||
# replayed daemon-only flags at the CLI, which only worked for the -ac_name=ZZZ assetchain
|
||||
# tests and broke every test that passes no extra_args.
|
||||
args = [ "-regtest", "-datadir="+datadir ]
|
||||
cmd_args = ' '.join(args) + " -rpcwait getblockcount "
|
||||
if os.getenv("PYTHON_DEBUG", ""):
|
||||
print("start_node: hushd started, calling : " + cmd + " " + cmd_args)
|
||||
@@ -266,18 +293,22 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
|
||||
import time
|
||||
time.sleep(2)
|
||||
subprocess.check_call(strcmd, shell=True);
|
||||
#subprocess.check_call([ os.getenv("BITCOINCLI", "hush-cli"), "-datadir="+datadir] +
|
||||
#subprocess.check_call([ os.getenv("BITCOINCLI", "dragonx-cli"), "-datadir="+datadir] +
|
||||
# _rpchost_to_args(rpchost) +
|
||||
# ["-rpcwait", "-rpcport=6438", "getblockcount"], stdout=devnull)
|
||||
if os.getenv("PYTHON_DEBUG", ""):
|
||||
print("start_node: calling hush-cli -rpcwait getblockcount returned")
|
||||
devnull.close()
|
||||
port = extra_args[3]
|
||||
#port = rpc_port(i)
|
||||
# Port comes from the same helper initialize_datadir() used, except for the assetchain
|
||||
# tests which pass it positionally as extra_args[3] == "-rpcport=NNNN".
|
||||
if len(extra_args) > 3 and str(extra_args[0]) == '-ac_name=ZZZ':
|
||||
port = extra_args[3][9:]
|
||||
else:
|
||||
port = str(rpc_port(i))
|
||||
#print("port=%s" % port)
|
||||
username = rpc_username()
|
||||
password = rpc_password()
|
||||
url = "http://%s:%s@%s:%s" % (username, password, rpchost or '127.0.0.1', port[9:])
|
||||
url = "http://%s:%s@%s:%s" % (username, password, rpchost or '127.0.0.1', port)
|
||||
print("connecting to " + url)
|
||||
if timewait is not None:
|
||||
proxy = AuthServiceProxy(url, timeout=timewait)
|
||||
|
||||
Reference in New Issue
Block a user