1818import sys
1919import tempfile
2020import time
21+ import types
2122
2223from .address import create_deterministic_address_bcrt1_p2tr_op_true
2324from .authproxy import JSONRPCException
@@ -56,6 +57,48 @@ def __init__(self, message):
5657 self .message = message
5758
5859
60+ class Binaries :
61+ """Helper class to provide information about bitcoin binaries
62+
63+ Attributes:
64+ paths: Object returned from get_binary_paths() containing information
65+ which binaries and command lines to use from environment variables and
66+ the config file.
67+ bin_dir: An optional string containing a directory path to look for
68+ binaries, which takes precedence over the paths above, if specified.
69+ This is used by tests calling binaries from previous releases.
70+ """
71+ def __init__ (self , paths , bin_dir ):
72+ self .paths = paths
73+ self .bin_dir = bin_dir
74+
75+ def daemon_argv (self ):
76+ "Return argv array that should be used to invoke bitcoind"
77+ return self ._argv (self .paths .bitcoind )
78+
79+ def rpc_argv (self ):
80+ "Return argv array that should be used to invoke bitcoin-cli"
81+ return self ._argv (self .paths .bitcoincli )
82+
83+ def util_argv (self ):
84+ "Return argv array that should be used to invoke bitcoin-util"
85+ return self ._argv (self .paths .bitcoinutil )
86+
87+ def wallet_argv (self ):
88+ "Return argv array that should be used to invoke bitcoin-wallet"
89+ return self ._argv (self .paths .bitcoinwallet )
90+
91+ def _argv (self , bin_path ):
92+ """Return argv array that should be used to invoke the command.
93+ Normally this will return binary paths directly from the paths object,
94+ but when bin_dir is set (by tests calling binaries from previous
95+ releases) it will return paths relative to bin_dir instead."""
96+ if self .bin_dir is not None :
97+ return [os .path .join (self .bin_dir , os .path .basename (bin_path ))]
98+ else :
99+ return [bin_path ]
100+
101+
59102class BitcoinTestMetaClass (type ):
60103 """Metaclass for BitcoinTestFramework.
61104
@@ -220,6 +263,7 @@ def parse_args(self, test_file):
220263 config = configparser .ConfigParser ()
221264 config .read_file (open (self .options .configfile ))
222265 self .config = config
266+ self .binary_paths = self .get_binary_paths ()
223267 if self .options .v1transport :
224268 self .options .v2transport = False
225269
@@ -239,9 +283,10 @@ def parse_args(self, test_file):
239283
240284 PortSeed .n = self .options .port_seed
241285
242- def set_binary_paths (self ):
243- """Update self.options with the paths of all binaries from environment variables or their default values"""
286+ def get_binary_paths (self ):
287+ """Get paths of all binaries from environment variables or their default values"""
244288
289+ paths = types .SimpleNamespace ()
245290 binaries = {
246291 "bitcoind" : ("bitcoind" , "BITCOIND" ),
247292 "bitcoin-cli" : ("bitcoincli" , "BITCOINCLI" ),
@@ -254,7 +299,11 @@ def set_binary_paths(self):
254299 "bin" ,
255300 binary + self .config ["environment" ]["EXEEXT" ],
256301 )
257- setattr (self .options , attribute_name , os .getenv (env_variable_name , default = default_filename ))
302+ setattr (paths , attribute_name , os .getenv (env_variable_name , default = default_filename ))
303+ return paths
304+
305+ def get_binaries (self , bin_dir = None ):
306+ return Binaries (self .binary_paths , bin_dir )
258307
259308 def setup (self ):
260309 """Call this method to start up the test framework object with options set."""
@@ -265,8 +314,6 @@ def setup(self):
265314
266315 config = self .config
267316
268- self .set_binary_paths ()
269-
270317 os .environ ['PATH' ] = os .pathsep .join ([
271318 os .path .join (config ['environment' ]['BUILDDIR' ], 'bin' ),
272319 os .environ ['PATH' ]
@@ -473,14 +520,14 @@ def add_wallet_options(self, parser, *, descriptors=True, legacy=True):
473520 group .add_argument ("--legacy-wallet" , action = 'store_const' , const = False , ** kwargs ,
474521 help = "Run test using legacy wallets" , dest = 'descriptors' )
475522
476- def add_nodes (self , num_nodes : int , extra_args = None , * , rpchost = None , binary = None , binary_cli = None , versions = None ):
523+ def add_nodes (self , num_nodes : int , extra_args = None , * , rpchost = None , versions = None ):
477524 """Instantiate TestNode objects.
478525
479526 Should only be called once after the nodes have been specified in
480527 set_test_params()."""
481- def get_bin_from_version (version , bin_name , bin_default ):
528+ def bin_dir_from_version (version ):
482529 if not version :
483- return bin_default
530+ return None
484531 if version > 219999 :
485532 # Starting at client version 220000 the first two digits represent
486533 # the major version, e.g. v22.0 instead of v0.22.0.
@@ -498,7 +545,6 @@ def get_bin_from_version(version, bin_name, bin_default):
498545 ),
499546 ),
500547 'bin' ,
501- bin_name ,
502548 )
503549
504550 if self .bind_to_localhost_only :
@@ -513,13 +559,12 @@ def get_bin_from_version(version, bin_name, bin_default):
513559 extra_args [
i ]
= extra_args [
i ]
+ [
"-whitelist=noban,in,[email protected] " ]
514560 if versions is None :
515561 versions = [None ] * num_nodes
516- if binary is None :
517- binary = [get_bin_from_version (v , 'bitcoind' , self .options .bitcoind ) for v in versions ]
518- if binary_cli is None :
519- binary_cli = [get_bin_from_version (v , 'bitcoin-cli' , self .options .bitcoincli ) for v in versions ]
562+ bin_dirs = [bin_dir_from_version (v ) for v in versions ]
520563 # Fail test if any of the needed release binaries is missing
521564 bins_missing = False
522- for bin_path in binary + binary_cli :
565+ for bin_path in (argv [0 ] for bin_dir in bin_dirs
566+ for binaries in (self .get_binaries (bin_dir ),)
567+ for argv in (binaries .daemon_argv (), binaries .rpc_argv ())):
523568 if shutil .which (bin_path ) is None :
524569 self .log .error (f"Binary not found: { bin_path } " )
525570 bins_missing = True
@@ -529,8 +574,7 @@ def get_bin_from_version(version, bin_name, bin_default):
529574 assert_equal (len (extra_confs ), num_nodes )
530575 assert_equal (len (extra_args ), num_nodes )
531576 assert_equal (len (versions ), num_nodes )
532- assert_equal (len (binary ), num_nodes )
533- assert_equal (len (binary_cli ), num_nodes )
577+ assert_equal (len (bin_dirs ), num_nodes )
534578 for i in range (num_nodes ):
535579 args = list (extra_args [i ])
536580 test_node_i = TestNode (
@@ -540,8 +584,7 @@ def get_bin_from_version(version, bin_name, bin_default):
540584 rpchost = rpchost ,
541585 timewait = self .rpc_timeout ,
542586 timeout_factor = self .options .timeout_factor ,
543- bitcoind = binary [i ],
544- bitcoin_cli = binary_cli [i ],
587+ binaries = self .get_binaries (bin_dirs [i ]),
545588 version = versions [i ],
546589 coverage_dir = self .options .coveragedir ,
547590 cwd = self .options .tmpdir ,
@@ -852,8 +895,7 @@ def _initialize_chain(self):
852895 rpchost = None ,
853896 timewait = self .rpc_timeout ,
854897 timeout_factor = self .options .timeout_factor ,
855- bitcoind = self .options .bitcoind ,
856- bitcoin_cli = self .options .bitcoincli ,
898+ binaries = self .get_binaries (),
857899 coverage_dir = None ,
858900 cwd = self .options .tmpdir ,
859901 descriptors = self .options .descriptors ,
0 commit comments