Browse Source

Merge JoinMarket-Org/joinmarket-clientserver#1427: Test: refactor `conftest.py`

a9deacc010 Refactor `conftest.py`: (PulpCattel)

Pull request description:

  * Uses [shlex.split()](https://docs.python.org/3/library/shlex.html#shlex.split) to avoid unnecessary handling of command lists
  * Removes unnecessary globals
  * PEP8 fixes
  * Uses [`yield`](https://docs.pytest.org/en/7.2.x/how-to/fixtures.html#yield-fixtures-recommended) instead of `addfinalizer` teardown
  * Add docstrings
  * Clean up functions

  Tests pass for me, let me know if/what it breaks for you.

ACKs for top commit:
  kristapsk:
    ACK a9deacc010

Tree-SHA512: 1a1e4056c06054afbe57405605961265c8629b553e82270204b30dc79b1267bf313403066369a3b446ebe0ccc487a56a00f58e49525d720f89c074f01b236a9c
master
Kristaps Kaupe 3 years ago
parent
commit
975e94ffff
No known key found for this signature in database
GPG Key ID: 33E472FE870C7E5D
  1. 172
      conftest.py

172
conftest.py

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

Loading…
Cancel
Save