diff options
Diffstat (limited to 'test/functional/test_framework/test_framework.py')
-rwxr-xr-x | test/functional/test_framework/test_framework.py | 111 |
1 files changed, 69 insertions, 42 deletions
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 921f12d9fb..c4b10af16c 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -18,6 +18,7 @@ import subprocess import sys import tempfile import time +import types from .address import create_deterministic_address_bcrt1_p2tr_op_true from .authproxy import JSONRPCException @@ -56,6 +57,48 @@ class SkipTest(Exception): self.message = message +class Binaries: + """Helper class to provide information about bitcoin binaries + + Attributes: + paths: Object returned from get_binary_paths() containing information + which binaries and command lines to use from environment variables and + the config file. + bin_dir: An optional string containing a directory path to look for + binaries, which takes precedence over the paths above, if specified. + This is used by tests calling binaries from previous releases. + """ + def __init__(self, paths, bin_dir): + self.paths = paths + self.bin_dir = bin_dir + + def daemon_argv(self): + "Return argv array that should be used to invoke bitcoind" + return self._argv(self.paths.bitcoind) + + def rpc_argv(self): + "Return argv array that should be used to invoke bitcoin-cli" + return self._argv(self.paths.bitcoincli) + + def util_argv(self): + "Return argv array that should be used to invoke bitcoin-util" + return self._argv(self.paths.bitcoinutil) + + def wallet_argv(self): + "Return argv array that should be used to invoke bitcoin-wallet" + return self._argv(self.paths.bitcoinwallet) + + def _argv(self, bin_path): + """Return argv array that should be used to invoke the command. + Normally this will return binary paths directly from the paths object, + but when bin_dir is set (by tests calling binaries from previous + releases) it will return paths relative to bin_dir instead.""" + if self.bin_dir is not None: + return [os.path.join(self.bin_dir, os.path.basename(bin_path))] + else: + return [bin_path] + + class BitcoinTestMetaClass(type): """Metaclass for BitcoinTestFramework. @@ -220,6 +263,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): config = configparser.ConfigParser() config.read_file(open(self.options.configfile)) self.config = config + self.binary_paths = self.get_binary_paths() if self.options.v1transport: self.options.v2transport=False @@ -229,23 +273,20 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): # So set it to None to force -disablewallet, because the wallet is not needed. self.options.descriptors = None elif self.options.descriptors is None: - # Some wallet is either required or optionally used by the test. - # Prefer SQLite unless it isn't available - if self.is_sqlite_compiled(): + if self.is_wallet_compiled(): self.options.descriptors = True - elif self.is_bdb_compiled(): - self.options.descriptors = False else: - # If neither are compiled, tests requiring a wallet will be skipped and the value of self.options.descriptors won't matter + # Tests requiring a wallet will be skipped and the value of self.options.descriptors won't matter # It still needs to exist and be None in order for tests to work however. # So set it to None, which will also set -disablewallet. self.options.descriptors = None PortSeed.n = self.options.port_seed - def set_binary_paths(self): - """Update self.options with the paths of all binaries from environment variables or their default values""" + def get_binary_paths(self): + """Get paths of all binaries from environment variables or their default values""" + paths = types.SimpleNamespace() binaries = { "bitcoind": ("bitcoind", "BITCOIND"), "bitcoin-cli": ("bitcoincli", "BITCOINCLI"), @@ -255,10 +296,14 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): for binary, [attribute_name, env_variable_name] in binaries.items(): default_filename = os.path.join( self.config["environment"]["BUILDDIR"], - "src", + "bin", binary + self.config["environment"]["EXEEXT"], ) - setattr(self.options, attribute_name, os.getenv(env_variable_name, default=default_filename)) + setattr(paths, attribute_name, os.getenv(env_variable_name, default=default_filename)) + return paths + + def get_binaries(self, bin_dir=None): + return Binaries(self.binary_paths, bin_dir) def setup(self): """Call this method to start up the test framework object with options set.""" @@ -269,11 +314,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): config = self.config - self.set_binary_paths() - os.environ['PATH'] = os.pathsep.join([ - os.path.join(config['environment']['BUILDDIR'], 'src'), - os.path.join(config['environment']['BUILDDIR'], 'src', 'qt'), os.environ['PATH'] + os.path.join(config['environment']['BUILDDIR'], 'bin'), + os.environ['PATH'] ]) # Set up temp directory and start logging @@ -477,14 +520,14 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): group.add_argument("--legacy-wallet", action='store_const', const=False, **kwargs, help="Run test using legacy wallets", dest='descriptors') - def add_nodes(self, num_nodes: int, extra_args=None, *, rpchost=None, binary=None, binary_cli=None, versions=None): + def add_nodes(self, num_nodes: int, extra_args=None, *, rpchost=None, versions=None): """Instantiate TestNode objects. Should only be called once after the nodes have been specified in set_test_params().""" - def get_bin_from_version(version, bin_name, bin_default): + def bin_dir_from_version(version): if not version: - return bin_default + return None if version > 219999: # Starting at client version 220000 the first two digits represent # the major version, e.g. v22.0 instead of v0.22.0. @@ -502,7 +545,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): ), ), 'bin', - bin_name, ) if self.bind_to_localhost_only: @@ -517,13 +559,12 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): extra_args[i] = extra_args[i] + ["-whitelist=noban,in,out@127.0.0.1"] if versions is None: versions = [None] * num_nodes - if binary is None: - binary = [get_bin_from_version(v, 'bitcoind', self.options.bitcoind) for v in versions] - if binary_cli is None: - binary_cli = [get_bin_from_version(v, 'bitcoin-cli', self.options.bitcoincli) for v in versions] + bin_dirs = [bin_dir_from_version(v) for v in versions] # Fail test if any of the needed release binaries is missing bins_missing = False - for bin_path in binary + binary_cli: + for bin_path in (argv[0] for bin_dir in bin_dirs + for binaries in (self.get_binaries(bin_dir),) + for argv in (binaries.daemon_argv(), binaries.rpc_argv())): if shutil.which(bin_path) is None: self.log.error(f"Binary not found: {bin_path}") bins_missing = True @@ -533,8 +574,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): assert_equal(len(extra_confs), num_nodes) assert_equal(len(extra_args), num_nodes) assert_equal(len(versions), num_nodes) - assert_equal(len(binary), num_nodes) - assert_equal(len(binary_cli), num_nodes) + assert_equal(len(bin_dirs), num_nodes) for i in range(num_nodes): args = list(extra_args[i]) test_node_i = TestNode( @@ -544,8 +584,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): rpchost=rpchost, timewait=self.rpc_timeout, timeout_factor=self.options.timeout_factor, - bitcoind=binary[i], - bitcoin_cli=binary_cli[i], + binaries=self.get_binaries(bin_dirs[i]), version=versions[i], coverage_dir=self.options.coveragedir, cwd=self.options.tmpdir, @@ -856,8 +895,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): rpchost=None, timewait=self.rpc_timeout, timeout_factor=self.options.timeout_factor, - bitcoind=self.options.bitcoind, - bitcoin_cli=self.options.bitcoincli, + binaries=self.get_binaries(), coverage_dir=None, cwd=self.options.tmpdir, descriptors=self.options.descriptors, @@ -966,16 +1004,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): self._requires_wallet = True if not self.is_wallet_compiled(): raise SkipTest("wallet has not been compiled.") - if self.options.descriptors: - self.skip_if_no_sqlite() - else: + if not self.options.descriptors: self.skip_if_no_bdb() - def skip_if_no_sqlite(self): - """Skip the running test if sqlite has not been compiled.""" - if not self.is_sqlite_compiled(): - raise SkipTest("sqlite has not been compiled.") - def skip_if_no_bdb(self): """Skip the running test if BDB has not been compiled.""" if not self.is_bdb_compiled(): @@ -1030,7 +1061,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): """Checks whether wallet support for the specified type (legacy or descriptor wallet) was compiled.""" if self.options.descriptors: - return self.is_sqlite_compiled() + return self.is_wallet_compiled() else: return self.is_bdb_compiled() @@ -1050,10 +1081,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): """Checks whether the USDT tracepoints were compiled.""" return self.config["components"].getboolean("ENABLE_USDT_TRACEPOINTS") - def is_sqlite_compiled(self): - """Checks whether the wallet module was compiled with Sqlite support.""" - return self.config["components"].getboolean("USE_SQLITE") - def is_bdb_compiled(self): """Checks whether the wallet module was compiled with BDB support.""" return self.config["components"].getboolean("USE_BDB") |