test: add interface_ipc_cli.py testing bitcoin-cli -ipcconnect
What changed, and why it matters
This commit only adds new automated tests for the bitcoin-cli command-line tool's IPC (inter-process communication) connection feature. It does not change any production code, so it cannot introduce a security vulnerability or fix one in the software users run.
No security action needed. Review as ordinary test coverage improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit adds a new functional test file interface_ipc_cli.py and extends interface_bitcoin_cli.py to exercise bitcoin-cli’s -ipcconnect option, including error paths when IPC support is missing or conflicting options are supplied. It also registers the new test in test_runner.py. No C++/Python production logic is modified; only test code is added.
Changed components
test/functional/interface_bitcoin_cli.pytest/functional/interface_ipc_cli.pytest/functional/test_runner.pyInspect captured patch +80 / −0
diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index f626ee51..fbe753a6 100755
--- a/test/functional/interface_bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -6,6 +6,7 @@
from decimal import Decimal
import re
+import subprocess
from test_framework.blocktools import COINBASE_MATURITY
from test_framework.netutil import test_ipv6_local
@@ -434,6 +435,16 @@ class TestBitcoinCli(BitcoinTestFramework):
self.log.info("Test that only one of -addrinfo, -generate, -getinfo, -netinfo may be specified at a time")
assert_raises_process_error(1, "Only one of -getinfo, -netinfo may be specified", self.nodes[0].cli('-getinfo', '-netinfo').send_cli)
+ if not self.is_ipc_compiled():
+ # This tests behavior when ENABLE_IPC is off. When it is on,
+ # behavior is checked by the interface_ipc_cli.py test.
+ self.log.info("Test bitcoin-cli -ipcconnect triggers error if not built with IPC support")
+ args = [self.binary_paths.bitcoincli, "-ipcconnect=unix", "-getinfo"]
+ result = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
+ assert_equal(result.stdout, "error: bitcoin-cli was not built with IPC support\n")
+ assert_equal(result.stderr, None)
+ assert_equal(result.returncode, 1)
+
if __name__ == '__main__':
TestBitcoinCli(__file__).main()
diff --git a/test/functional/interface_ipc_cli.py b/test/functional/interface_ipc_cli.py
new file mode 100755
index 00000000..92ccc879
--- /dev/null
+++ b/test/functional/interface_ipc_cli.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+# Copyright (c) 2025 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test IPC with bitcoin-cli"""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ rpc_port
+)
+
+import subprocess
+
+class TestBitcoinIpcCli(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_ipc()
+
+ def setup_nodes(self):
+ self.extra_init = [{"ipcbind": True}]
+ super().setup_nodes()
+
+ def test_cli(self, args, error=None):
+ # Intentionally set wrong RPC password so only IPC not HTTP connections work
+ args = [self.binary_paths.bitcoincli, f"-datadir={self.nodes[0].datadir_path}", "-rpcpassword=wrong"] + args + ["echo", "foo"]
+ result = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
+ if error is None:
+ assert_equal(result.stdout, '[\n "foo"\n]\n')
+ else:
+ assert_equal(result.stdout, error)
+ assert_equal(result.stderr, None)
+ assert_equal(result.returncode, 0 if error is None else 1)
+
+ def run_test(self):
+ node = self.nodes[0]
+ if node.ipc_tmp_dir:
+ self.log.info("Skipping a few checks because temporary directory path is too long")
+
+ http_auth_error = "error: Authorization failed: Incorrect rpcuser or rpcpassword\n"
+ http_connect_error = f"error: timeout on transient error: Could not connect to the server 127.0.0.1:{rpc_port(node.index)}\n\nMake sure the bitcoind server is running and that you are connecting to the correct RPC port.\nUse \"bitcoin-cli -help\" for more info.\n"
+ ipc_connect_error = "error: timeout on transient error: Connection refused\n\nProbably bitcoin-node is not running or not listening on a unix socket. Can be started with:\n\n bitcoin-node -chain=regtest -ipcbind=unix\n"
+ ipc_http_conflict = "error: -rpcconnect and -ipcconnect options cannot both be enabled\n"
+
+ for started in (True, False):
+ auto_error = None if started else http_connect_error
+ http_error = http_auth_error if started else http_connect_error
+ ipc_error = None if started else ipc_connect_error
+
+ if not node.ipc_tmp_dir:
+ self.test_cli([], auto_error)
+ self.test_cli(["-rpcconnect=127.0.0.1"], http_error)
+ self.test_cli(["-ipcconnect=auto"], auto_error)
+ self.test_cli(["-ipcconnect=auto", "-rpcconnect=127.0.0.1"], http_error)
+ self.test_cli(["-ipcconnect=unix"], ipc_error)
+
+ self.test_cli([f"-ipcconnect=unix:{node.ipc_socket_path}"], ipc_error)
+ self.test_cli(["-noipcconnect"], http_error)
+ self.test_cli(["-ipcconnect=unix", "-rpcconnect=127.0.0.1"], ipc_http_conflict)
+
+ self.stop_node(0)
+
+
+if __name__ == '__main__':
+ TestBitcoinIpcCli(__file__).main()
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index a4052f91..8d80b5a7 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -379,6 +379,7 @@ BASE_SCRIPTS = [
'tool_rpcauth.py',
'p2p_handshake.py',
'p2p_handshake.py --v2transport',
+ 'interface_ipc_cli.py',
'feature_dirsymlinks.py',
'feature_help.py',
'feature_framework_startup_failures.py',
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.