Files
bitcoin/test/functional/tool_bitcoin.py
MarcoFalke fa03fbf7e3 test: Fix broken --valgrind handling after bitcoin wrapper
Prior to this commit, tool_bitcoin.py was failing:

```sh
$ ./bld-cmake/test/functional/tool_bitcoin.py --valgrind
TestFramework (ERROR): Unexpected exception
Traceback (most recent call last):
  File "./test/functional/test_framework/test_framework.py", line 138, in main
    self.setup()
    ~~~~~~~~~~^^
  File "./test/functional/test_framework/test_framework.py", line 269, in setup
    self.setup_network()
    ~~~~~~~~~~~~~~~~~~^^
  File "./test/functional/tool_bitcoin.py", line 38, in setup_network
    assert all(node.args[:len(node_argv)] == node_argv for node in self.nodes)
           ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
```

This commit fixes this issue by running `bitcoin` under valgrind. Also,
it comes with other improvements:

* Drop the outdated valgrind 3.14 requirement, because there is no
  distro that ships a version that old anymore.
* Drop the VALGRIND_SUPPRESSIONS_FILE env var handling, because it was
  presumably never used since it was introduced. Also, the use-case
  seems limited.

Review note:

The set_cmd_args was ignoring the --valgrind test option.

In theory, this could be fixed by refactoring Binaries::node_argv() to
be used here. However, for now, just re-implement the node_argv logic in
set_cmd_args to prepend the valgrind cmd.
2026-02-24 13:15:57 +01:00

114 lines
4.4 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (c) 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 the bitcoin wrapper tool."""
from test_framework.test_framework import (
BitcoinTestFramework,
SkipTest,
)
from test_framework.util import (
append_config,
assert_equal,
)
import platform
import re
class ToolBitcoinTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
def skip_test_if_missing_module(self):
# Skip test on windows because currently when `bitcoin node -version` is
# run on windows, python doesn't capture output from the child
# `bitcoind` and `bitcoin-node` process started with _wexecvp, and
# stdout/stderr are always empty. See
# https://github.com/bitcoin/bitcoin/pull/33229#issuecomment-3265524908
if platform.system() == "Windows":
raise SkipTest("Test does not currently work on windows")
def setup_network(self):
"""Set up nodes normally, but save a copy of their arguments before starting them."""
self.add_nodes(self.num_nodes, self.extra_args)
node_argv = self.get_binaries().node_argv()
self.node_options = [node.args[len(node_argv):] for node in self.nodes]
assert all(node.args[:len(node_argv)] == node_argv for node in self.nodes)
def set_cmd_args(self, node, args):
"""Set up node so it will be started through bitcoin wrapper command with specified arguments."""
# Manually construct the `bitcoin node` command, similar to Binaries::node_argv()
bitcoin_cmd = node.binaries.valgrind_cmd + [node.binaries.paths.bitcoin_bin]
node.args = bitcoin_cmd + args + ["node"] + self.node_options[node.index]
def test_args(self, cmd_args, node_args, expect_exe=None, expect_error=None):
node = self.nodes[0]
self.set_cmd_args(node, cmd_args)
extra_args = node_args + ["-version"]
if expect_error is not None:
node.assert_start_raises_init_error(expected_msg=expect_error, extra_args=extra_args)
else:
assert expect_exe
node.start(extra_args=extra_args)
ret, out, err = get_node_output(node)
try:
assert_equal(get_exe_name(out), expect_exe.encode())
assert_equal(err, b"")
except Exception as e:
raise RuntimeError(f"Unexpected output from {node.args + extra_args}: {out=!r} {err=!r} {ret=!r}") from e
def run_test(self):
node = self.nodes[0]
self.log.info("Ensure bitcoin node command invokes bitcoind by default")
self.test_args([], [], expect_exe="bitcoind")
self.log.info("Ensure bitcoin -M invokes bitcoind")
self.test_args(["-M"], [], expect_exe="bitcoind")
self.log.info("Ensure bitcoin -M does not accept -ipcbind")
self.test_args(["-M"], ["-ipcbind=unix"], expect_error='Error: Error parsing command line arguments: Invalid parameter -ipcbind=unix')
if self.is_ipc_compiled():
self.log.info("Ensure bitcoin -m invokes bitcoin-node")
self.test_args(["-m"], [], expect_exe="bitcoin-node")
self.log.info("Ensure bitcoin -m does accept -ipcbind")
self.test_args(["-m"], ["-ipcbind=unix"], expect_exe="bitcoin-node")
self.log.info("Ensure bitcoin accepts -ipcbind by default")
self.test_args([], ["-ipcbind=unix"], expect_exe="bitcoin-node")
self.log.info("Ensure bitcoin recognizes -ipcbind in config file")
append_config(node.datadir_path, ["ipcbind=unix"])
self.test_args([], [], expect_exe="bitcoin-node")
def get_node_output(node):
ret = node.process.wait(timeout=60)
node.stdout.seek(0)
node.stderr.seek(0)
out = node.stdout.read()
err = node.stderr.read()
node.stdout.close()
node.stderr.close()
# Clean up TestNode state
node.running = False
node.process = None
node.rpc_connected = False
node.rpc = None
return ret, out, err
def get_exe_name(version_str):
"""Get exe name from last word of first line of version string."""
return re.match(rb".*?(\S+)\s*?(?:\n|$)", version_str.strip()).group(1)
if __name__ == '__main__':
ToolBitcoinTest(__file__).main()