Browse Source

Refactor `conftest.py`:

* Uses shlex.split() to avoid unnecessary handling of command lists
* Removes unnecessary globals
* PEP8 fixes
* Uses `yield` instead of `addfinalizer` teardown
* Add docstrings
* Clean up functions
master
PulpCattel 3 years ago
parent
commit
a9deacc010
No known key found for this signature in database
GPG Key ID: BDFD82BA08D9F218
  1. 172
      conftest.py

172
conftest.py

@ -1,25 +1,33 @@
import pytest
import re
import os
import time
import re
import subprocess
from typing import Any
from shlex import split
from time import sleep
from typing import Any, Tuple
bitcoin_path = None
bitcoin_conf = None
bitcoin_rpcpassword = None
bitcoin_rpcusername = None
miniircd_procs = []
import pytest
def get_bitcoind_version(version_string: bytes) -> tuple:
# this utility function returns the version number
# as a tuple in the form (major, minor)
def get_bitcoind_version(bitcoind_path: str) -> Tuple[int, int]:
"""
This utility function returns the bitcoind version number
as a tuple in the form (major, minor)
"""
version = local_command(f'{bitcoind_path} -version')
if version.returncode != 0:
raise RuntimeError(version.stdout.decode('utf-8'))
version_string = version.stdout.split(b'\n')[0]
version_tuple = re.match(
br'.*v(?P<major>\d+)\.(?P<minor>\d+)',
version_string).groups()
return tuple(map(lambda x: int(x), version_tuple))
br'.*v(?P<major>\d+)\.(?P<minor>\d+)', version_string).groups()
major, minor = map(lambda x: int(x), version_tuple)
return major, minor
def local_command(command: str, bg: bool = False):
"""
Execute command in a new process.
"""
command = split(command)
if bg:
# using subprocess.PIPE seems to cause problems
FNULL = open(os.devnull, 'w')
@ -27,24 +35,37 @@ def local_command(command: str, bg: bool = False):
stdout=FNULL,
stderr=subprocess.STDOUT,
close_fds=True)
else:
# in case of foreground execution, we can use the output; if not
# it doesn't matter
return subprocess.run(command, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
def root_path() -> str:
# returns the directory in which this file is contained
"""
Returns the directory in which this file is contained.
"""
return os.path.dirname(os.path.realpath(__file__))
def btc_conf_test_path() -> str:
"""
Returns default Bitcoin conf test path.
"""
return os.path.join(root_path(), 'test/bitcoin.conf')
def pytest_addoption(parser: Any) -> None:
"""
Pytest initialization hook to register argparse-style options.
"""
parser.addoption("--btcroot", action="store", default='',
help="the fully qualified path to the directory containing "+\
help="the fully qualified path to the directory containing " +
"the bitcoin binaries, e.g. /home/user/bitcoin/bin/")
parser.addoption("--btcconf", action="store",
default=os.path.join(root_path(), 'test/bitcoin.conf'),
help="the fully qualified path to the location of the "+\
"bitcoin configuration file you use for testing, e.g. "+\
default=btc_conf_test_path(),
help="the fully qualified path to the location of the " +
"bitcoin configuration file you use for testing, e.g. " +
"/home/user/.bitcoin/bitcoin.conf")
parser.addoption("--btcpwd",
action="store",
@ -59,77 +80,68 @@ def pytest_addoption(parser: Any) -> None:
default=1,
help="the number of local miniircd instances")
def teardown() -> None:
#didn't find a stop command in miniircd, so just kill
global miniircd_procs
for m in miniircd_procs:
m.kill()
#shut down bitcoin and remove the regtest dir
local_command([os.path.join(bitcoin_path, "bitcoin-cli"), "-regtest",
"-rpcuser=" + bitcoin_rpcusername,
"-rpcpassword=" + bitcoin_rpcpassword, "stop"])
#note, it is better to clean out ~/.bitcoin/regtest but too
#dangerous to automate it here perhaps
@pytest.fixture(scope="session", autouse=True)
def setup(request) -> None:
request.addfinalizer(teardown)
global bitcoin_conf, bitcoin_path, bitcoin_rpcpassword, bitcoin_rpcusername
bitcoin_path = request.config.getoption("--btcroot")
bitcoin_conf = request.config.getoption("--btcconf")
print("Here is the bitcoin_conf path:")
print(bitcoin_conf)
bitcoin_rpcpassword = request.config.getoption("--btcpwd")
bitcoin_rpcusername = request.config.getoption("--btcuser")
#start up miniircd
#minor bug in miniircd (seems); need *full* unqualified path for motd file
def setup_miniircd(pytestconfig):
"""
Setup miniircd and handle its clean up.
"""
miniircd_procs = []
cwd = os.getcwd()
n_irc = request.config.getoption("--nirc")
global miniircd_procs
n_irc = pytestconfig.getoption("--nirc")
miniircd_path = os.path.join(root_path(), 'miniircd', 'miniircd')
# minor bug in miniircd (seems); need *full* unqualified path for motd file
motd_path = os.path.join(cwd, 'miniircd', 'testmotd')
for i in range(n_irc):
miniircd_proc = local_command(
["./miniircd/miniircd", "--ports=" + str(16667+i),
"--motd=" + cwd + "/miniircd/testmotd"],
bg=True)
command = f"{miniircd_path} --ports={16667 + i} --motd={motd_path}"
miniircd_proc = local_command(command, bg=True)
miniircd_procs.append(miniircd_proc)
yield
# didn't find a stop command in miniircd, so just kill
for m in miniircd_procs:
m.kill()
# determine bitcoind version
bitcoind_version_string = subprocess.check_output([
os.path.join(bitcoin_path, "bitcoind"), "-version"]).split(b'\n')[0]
bitcoind_version = get_bitcoind_version(bitcoind_version_string)
#start up regtest blockchain
bitcoin_args = ["-regtest", "-daemon", "-conf=" + bitcoin_conf]
btc_proc = subprocess.call([os.path.join(bitcoin_path, "bitcoind")] +
bitcoin_args)
root_cmd = [os.path.join(bitcoin_path, "bitcoin-cli"), "-regtest",
"-rpcuser=" + bitcoin_rpcusername,
"-rpcpassword=" + bitcoin_rpcpassword]
@pytest.fixture(scope="session", autouse=True)
def setup_regtest_bitcoind(pytestconfig):
"""
Setup regtest bitcoind and handle its clean up.
"""
conf = pytestconfig.getoption("--btcconf")
rpcuser = pytestconfig.getoption("--btcuser")
rpcpassword = pytestconfig.getoption("--btcpwd")
bitcoin_path = pytestconfig.getoption("--btcroot")
bitcoind_path = os.path.join(bitcoin_path, "bitcoind")
bitcoincli_path = os.path.join(bitcoin_path, "bitcoin-cli")
start_cmd = f'{bitcoind_path} -regtest -daemon -conf={conf}'
stop_cmd = f'{bitcoincli_path} -regtest -rpcuser={rpcuser} -rpcpassword={rpcpassword} stop'
local_command(start_cmd, bg=True)
# determine bitcoind version
try:
bitcoind_version = get_bitcoind_version(bitcoind_path)
except RuntimeError as exc:
pytest.exit(f"Cannot setup tests, bitcoind failing.\n{exc}")
root_cmd = f'{bitcoincli_path} -regtest -rpcuser={rpcuser} -rpcpassword={rpcpassword}'
wallet_name = 'jm-test-wallet'
# Bitcoin Core v0.21+ does not create default wallet
# From Bitcoin Core 0.21.0 there is support for descriptor wallets, which
# are default from 23.x+ (including 22.99.0 development versions).
# We don't support descriptor wallets yet.
if bitcoind_version[0] >= 22:
local_command(root_cmd + ["-rpcwait"] + ["-named"] +
["createwallet",
"wallet_name=jm-test-wallet", "descriptors=false"])
create_wallet = f'{root_cmd} -rpcwait -named createwallet wallet_name={wallet_name} descriptors=false'
else:
local_command(root_cmd + ["-rpcwait"] +
["createwallet", "jm-test-wallet"])
local_command(root_cmd + ["loadwallet", "jm-test-wallet"])
create_wallet = f'{root_cmd} -rpcwait createwallet {wallet_name}'
local_command(create_wallet)
local_command(f'{root_cmd} loadwallet {wallet_name}')
for i in range(2):
cpe = local_command(root_cmd + ["-rpcwallet=jm-test-wallet"] +
["getnewaddress"])
if cpe.returncode == 0:
cpe = local_command(f'{root_cmd} -rpcwallet={wallet_name} getnewaddress')
if cpe.returncode != 0:
pytest.exit(f"Cannot setup tests, bitcoin-cli failing.\n{cpe.stdout.decode('utf-8')}")
destn_addr = cpe.stdout[:-1].decode('utf-8')
local_command(root_cmd + ["-rpcwallet=jm-test-wallet"] +
["generatetoaddress", "301", destn_addr])
else:
pytest.exit("Cannot setup tests, bitcoin-cli failing.\n" +
str(cpe.stdout))
time.sleep(1)
local_command(f'{root_cmd} -rpcwallet={wallet_name} generatetoaddress 301 {destn_addr}')
sleep(1)
yield
# shut down bitcoind
local_command(stop_cmd)
# note, it is better to clean out ~/.bitcoin/regtest but too
# dangerous to automate it here perhaps

Loading…
Cancel
Save