test: Move get_binary_paths and Binaries to util.py
What changed, and why it matters
This commit is a simple code cleanup in Bitcoin Core's test framework. It moves two helper pieces—the Binaries class and get_binary_paths function—from one test file to another shared utility file, and updates the imports. There is no change to how Bitcoin works, no bug fix, and no security impact.
No security action needed; treat as routine refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors the functional test framework by relocating the Binaries class and get_binary_paths() function from test_framework.py to util.py. The logic, behavior, and environment-variable handling remain identical; only imports and call sites are adjusted (self.get_binary_paths() becomes get_binary_paths(self.config)). This is a pure maintainability refactor with no functional or security changes.
Changed components
test/functional/test_framework/test_framework.pytest/functional/test_framework/util.pyInspect captured patch +90 / −87
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 47339761..58933c9d 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -14,13 +14,11 @@ import platform
import pdb
import random
import re
-import shlex
import shutil
import subprocess
import sys
import tempfile
import time
-import types
from .address import create_deterministic_address_bcrt1_p2tr_op_true
from .authproxy import JSONRPCException
@@ -28,11 +26,13 @@ from . import coverage
from .p2p import NetworkThread
from .test_node import TestNode
from .util import (
+ Binaries,
MAX_NODES,
PortSeed,
assert_equal,
check_json_precision,
find_vout_for_address,
+ get_binary_paths,
get_datadir_path,
initialize_datadir,
p2p_port,
@@ -60,63 +60,6 @@ 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 node_argv(self, **kwargs):
- "Return argv array that should be used to invoke bitcoind"
- return self._argv("node", self.paths.bitcoind, **kwargs)
-
- def rpc_argv(self):
- "Return argv array that should be used to invoke bitcoin-cli"
- # Add -nonamed because "bitcoin rpc" enables -named by default, but bitcoin-cli doesn't
- return self._argv("rpc", self.paths.bitcoincli) + ["-nonamed"]
-
- def tx_argv(self):
- "Return argv array that should be used to invoke bitcoin-tx"
- return self._argv("tx", self.paths.bitcointx)
-
- def util_argv(self):
- "Return argv array that should be used to invoke bitcoin-util"
- return self._argv("util", self.paths.bitcoinutil)
-
- def wallet_argv(self):
- "Return argv array that should be used to invoke bitcoin-wallet"
- return self._argv("wallet", self.paths.bitcoinwallet)
-
- def chainstate_argv(self):
- "Return argv array that should be used to invoke bitcoin-chainstate"
- return self._argv("chainstate", self.paths.bitcoinchainstate)
-
- def _argv(self, command, bin_path, need_ipc=False):
- """Return argv array that should be used to invoke the command. It
- either uses the bitcoin wrapper executable (if BITCOIN_CMD is set or
- need_ipc is True), or the direct binary path (bitcoind, etc). When
- bin_dir is set (by tests calling binaries from previous releases) it
- always uses the direct path."""
- if self.bin_dir is not None:
- return [os.path.join(self.bin_dir, os.path.basename(bin_path))]
- elif self.paths.bitcoin_cmd is not None or need_ipc:
- # If the current test needs IPC functionality, use the bitcoin
- # wrapper binary and append -m so it calls multiprocess binaries.
- bitcoin_cmd = self.paths.bitcoin_cmd or [self.paths.bitcoin_bin]
- return bitcoin_cmd + (["-m"] if need_ipc else []) + [command]
- else:
- return [bin_path]
-
-
class BitcoinTestMetaClass(type):
"""Metaclass for BitcoinTestFramework.
@@ -270,39 +213,12 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.config = configparser.ConfigParser()
self.config.read_file(open(self.options.configfile))
- self.binary_paths = self.get_binary_paths()
+ self.binary_paths = get_binary_paths(self.config)
if self.options.v1transport:
self.options.v2transport=False
PortSeed.n = self.options.port_seed
- def get_binary_paths(self):
- """Get paths of all binaries from environment variables or their default values"""
-
- paths = types.SimpleNamespace()
- binaries = {
- "bitcoin": "BITCOIN_BIN",
- "bitcoind": "BITCOIND",
- "bitcoin-cli": "BITCOINCLI",
- "bitcoin-util": "BITCOINUTIL",
- "bitcoin-tx": "BITCOINTX",
- "bitcoin-chainstate": "BITCOINCHAINSTATE",
- "bitcoin-wallet": "BITCOINWALLET",
- }
- # Set paths to bitcoin core binaries allowing overrides with environment
- # variables.
- for binary, env_variable_name in binaries.items():
- default_filename = os.path.join(
- self.config["environment"]["BUILDDIR"],
- "bin",
- binary + self.config["environment"]["EXEEXT"],
- )
- setattr(paths, env_variable_name.lower(), os.getenv(env_variable_name, default=default_filename))
- # BITCOIN_CMD environment variable can be specified to invoke bitcoin
- # wrapper binary instead of other executables.
- paths.bitcoin_cmd = shlex.split(os.getenv("BITCOIN_CMD", "")) or None
- return paths
-
def get_binaries(self, bin_dir=None):
return Binaries(self.binary_paths, bin_dir)
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index da90e374..4ee65494 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -16,7 +16,9 @@ import pathlib
import platform
import random
import re
+import shlex
import time
+import types
from . import coverage
from .authproxy import AuthServiceProxy, JSONRPCException
@@ -235,6 +237,91 @@ def check_json_precision():
raise RuntimeError("JSON encode/decode loses precision")
+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 node_argv(self, **kwargs):
+ "Return argv array that should be used to invoke bitcoind"
+ return self._argv("node", self.paths.bitcoind, **kwargs)
+
+ def rpc_argv(self):
+ "Return argv array that should be used to invoke bitcoin-cli"
+ # Add -nonamed because "bitcoin rpc" enables -named by default, but bitcoin-cli doesn't
+ return self._argv("rpc", self.paths.bitcoincli) + ["-nonamed"]
+
+ def tx_argv(self):
+ "Return argv array that should be used to invoke bitcoin-tx"
+ return self._argv("tx", self.paths.bitcointx)
+
+ def util_argv(self):
+ "Return argv array that should be used to invoke bitcoin-util"
+ return self._argv("util", self.paths.bitcoinutil)
+
+ def wallet_argv(self):
+ "Return argv array that should be used to invoke bitcoin-wallet"
+ return self._argv("wallet", self.paths.bitcoinwallet)
+
+ def chainstate_argv(self):
+ "Return argv array that should be used to invoke bitcoin-chainstate"
+ return self._argv("chainstate", self.paths.bitcoinchainstate)
+
+ def _argv(self, command, bin_path, need_ipc=False):
+ """Return argv array that should be used to invoke the command. It
+ either uses the bitcoin wrapper executable (if BITCOIN_CMD is set or
+ need_ipc is True), or the direct binary path (bitcoind, etc). When
+ bin_dir is set (by tests calling binaries from previous releases) it
+ always uses the direct path."""
+ if self.bin_dir is not None:
+ return [os.path.join(self.bin_dir, os.path.basename(bin_path))]
+ elif self.paths.bitcoin_cmd is not None or need_ipc:
+ # If the current test needs IPC functionality, use the bitcoin
+ # wrapper binary and append -m so it calls multiprocess binaries.
+ bitcoin_cmd = self.paths.bitcoin_cmd or [self.paths.bitcoin_bin]
+ return bitcoin_cmd + (["-m"] if need_ipc else []) + [command]
+ else:
+ return [bin_path]
+
+
+def get_binary_paths(config):
+ """Get paths of all binaries from environment variables or their default values"""
+
+ paths = types.SimpleNamespace()
+ binaries = {
+ "bitcoin": "BITCOIN_BIN",
+ "bitcoind": "BITCOIND",
+ "bitcoin-cli": "BITCOINCLI",
+ "bitcoin-util": "BITCOINUTIL",
+ "bitcoin-tx": "BITCOINTX",
+ "bitcoin-chainstate": "BITCOINCHAINSTATE",
+ "bitcoin-wallet": "BITCOINWALLET",
+ }
+ # Set paths to bitcoin core binaries allowing overrides with environment
+ # variables.
+ for binary, env_variable_name in binaries.items():
+ default_filename = os.path.join(
+ config["environment"]["BUILDDIR"],
+ "bin",
+ binary + config["environment"]["EXEEXT"],
+ )
+ setattr(paths, env_variable_name.lower(), os.getenv(env_variable_name, default=default_filename))
+ # BITCOIN_CMD environment variable can be specified to invoke bitcoin
+ # wrapper binary instead of other executables.
+ paths.bitcoin_cmd = shlex.split(os.getenv("BITCOIN_CMD", "")) or None
+ return paths
+
+
def count_bytes(hex_string):
return len(bytearray.fromhex(hex_string))
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.