diff --git a/contrib/valgrind.supp b/contrib/valgrind.supp index 969c597595..09f8135e1d 100644 --- a/contrib/valgrind.supp +++ b/contrib/valgrind.supp @@ -41,3 +41,32 @@ ... fun:_ZN7leveldbL14InitDefaultEnvEv } +{ + Suppress lbdb warning + Memcheck:Cond + fun:__log_putr.isra.0 +} +{ + Suppress libdb warning + Memcheck:Param + pwrite64(buf) + fun:__libc_pwrite64 + ... + fun:__db_open_pp +} +{ + Suppress SPV wallet + Memcheck:Cond + fun:bcmp + fun:BRBIP32PubKey + fun:BRWalletUnusedAddrs +} +{ + Suppress libdb warning + Memcheck:Param + pwrite64(buf) + fun:__libc_pwrite64 + fun:pwrite + fun:__os_io +} + diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 1ffb122eb7..ed19bc35dc 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -130,6 +130,8 @@ def main(self): help="use defi-cli instead of RPC for all commands") parser.add_argument("--perf", dest="perf", default=False, action="store_true", help="profile running nodes with perf for the duration of the test") + parser.add_argument("--valgrind", dest="valgrind", default=False, action="store_true", + help="run nodes under the valgrind memory error detector: expect at least a ~10x slowdown, valgrind 3.14 or later required") parser.add_argument("--randomseed", type=int, help="set a random seed for deterministically reproducing a previous test run") self.add_options(parser) @@ -439,6 +441,7 @@ def add_nodes(self, num_nodes, extra_args=None, *, rpchost=None, binary=None): extra_args=extra_args[i], use_cli=self.options.usecli, start_perf=self.options.perf, + use_valgrind=self.options.valgrind, )) def start_node(self, i, *args, **kwargs): diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 7cba1896a8..7a78f33935 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -58,7 +58,7 @@ class TestNode(): To make things easier for the test writer, any unrecognised messages will be dispatched to the RPC connection.""" - def __init__(self, i, datadir, *, chain, rpchost, timewait, defid, defi_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False): + def __init__(self, i, datadir, *, chain, rpchost, timewait, defid, defi_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False): """ Kwargs: start_perf (bool): If True, begin profiling the node with `perf` as soon as @@ -98,6 +98,15 @@ def __init__(self, i, datadir, *, chain, rpchost, timewait, defid, defi_cli, cov "-dummypos=1", "-txnotokens=1", ] + if use_valgrind: + default_suppressions_file = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "..", "..", "..", "contrib", "valgrind.supp") + suppressions_file = os.getenv("VALGRIND_SUPPRESSIONS_FILE", + default_suppressions_file) + self.args = ["valgrind", "--suppressions={}".format(suppressions_file), + "--gen-suppressions=all", "--exit-on-first-error=yes", + "--error-exitcode=1", "--quiet"] + self.args self.cli = TestNodeCLI(defi_cli, self.datadir) self.use_cli = use_cli