What changed, and why it matters
This is a test-only cleanup change. It removes a dedicated helper file used to simulate external programs during testing and instead makes the main test program act as that helper when a special environment variable is set. There is no change to the Bitcoin Core software that users run, and no security issue is introduced or fixed.
No security action needed. Treat as ordinary test refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors how system_tests.cpp’s run_command test mocks subprocess behavior. Previously a separate source file (mock_process.cpp) containing disabled Boost.Test cases was compiled into test_bitcoin and invoked via –run_test=mock_process/
Changed components
src/test/mock_process.cpp (deleted)src/test/system_tests.cpp (test-only)src/test/CMakeLists.txt (test build)test/lint/lint-includes.py (lint allow-list)Inspect captured patch +48 / −60
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index 97a034de..b5a12f72 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -64,7 +64,6 @@ add_executable(test_bitcoin
miniminer_tests.cpp
miniscript_tests.cpp
minisketch_tests.cpp
- mock_process.cpp
multisig_tests.cpp
bip328_tests.cpp
net_peer_connection_tests.cpp
@@ -192,8 +191,6 @@ function(add_boost_test source_file)
list(TRANSFORM test_suite_macro
REPLACE "(BOOST_FIXTURE_TEST_SUITE|BOOST_AUTO_TEST_SUITE)\\(" ""
)
- # The mock_process test suite does not contain unit tests.
- list(REMOVE_ITEM test_suite_macro "mock_process")
foreach(test_suite_name IN LISTS test_suite_macro)
add_test(NAME ${test_suite_name}
COMMAND test_bitcoin --run_test=${test_suite_name} --catch_system_error=no --log_level=test_suite -- -printtoconsole=1
diff --git a/src/test/mock_process.cpp b/src/test/mock_process.cpp
deleted file mode 100644
index c9100c9f..00000000
--- a/src/test/mock_process.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2025-present The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or https://opensource.org/license/mit/.
-
-#include <boost/test/unit_test.hpp>
-
-#include <iostream>
-#include <string>
-
-BOOST_AUTO_TEST_SUITE(mock_process, *boost::unit_test::disabled())
-
-BOOST_AUTO_TEST_CASE(valid_json, *boost::unit_test::disabled())
-{
- std::cout << R"({"success": true})" << std::endl;
-}
-
-BOOST_AUTO_TEST_CASE(nonzeroexit_nooutput, *boost::unit_test::disabled())
-{
- BOOST_FAIL("Test unconditionally fails.");
-}
-
-BOOST_AUTO_TEST_CASE(nonzeroexit_stderroutput, *boost::unit_test::disabled())
-{
- std::cerr << "err\n";
- BOOST_FAIL("Test unconditionally fails.");
-}
-
-BOOST_AUTO_TEST_CASE(invalid_json, *boost::unit_test::disabled())
-{
- std::cout << "{\n";
-}
-
-BOOST_AUTO_TEST_CASE(pass_stdin_to_stdout, *boost::unit_test::disabled())
-{
- std::string s;
- std::getline(std::cin, s);
- std::cout << s << std::endl;
-}
-
-BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/system_tests.cpp b/src/test/system_tests.cpp
index 408666d6..1b1d6bc7 100644
--- a/src/test/system_tests.cpp
+++ b/src/test/system_tests.cpp
@@ -11,33 +11,65 @@
#include <univalue.h>
#include <util/string.h>
+#include <cstdlib>
+#include <iostream>
+#include <string_view>
+
#ifdef ENABLE_EXTERNAL_SIGNER
#include <util/subprocess.h>
#endif // ENABLE_EXTERNAL_SIGNER
-#include <boost/cstdlib.hpp>
#include <boost/test/unit_test.hpp>
#include <string>
+namespace {
+// When set in the environment, test_bitcoin acts as a mock subprocess for the
+// run_command test below instead of running unit tests.
+constexpr const char* MOCK_PROCESS_ENV = "BITCOIN_TEST_MOCK_PROCESS";
+
+const bool g_maybe_run_mock_dispatcher_before_main{[]() {
+ const char* name = std::getenv(MOCK_PROCESS_ENV);
+ if (!name) return false;
+ const std::string_view n{name};
+ if (n == "valid_json") {
+ std::cout << R"({"success": true})" << std::endl;
+ std::_Exit(EXIT_SUCCESS);
+ }
+ if (n == "nonzeroexit_nooutput") {
+ std::_Exit(EXIT_FAILURE);
+ }
+ if (n == "nonzeroexit_stderroutput") {
+ std::cerr << "err" << std::endl;
+ std::_Exit(EXIT_FAILURE);
+ }
+ if (n == "invalid_json") {
+ std::cout << "{" << std::endl;
+ std::_Exit(EXIT_SUCCESS);
+ }
+ if (n == "pass_stdin_to_stdout") {
+ std::string s;
+ std::getline(std::cin, s);
+ std::cout << s << std::endl;
+ std::_Exit(EXIT_SUCCESS);
+ }
+ std::cerr << "Unknown mock process: " << n << std::endl;
+ std::_Exit(EXIT_FAILURE);
+}()};
+} // namespace
+
BOOST_FIXTURE_TEST_SUITE(system_tests, BasicTestingSetup)
#ifdef ENABLE_EXTERNAL_SIGNER
-static std::vector<std::string> mock_executable(std::string name)
+static std::vector<std::string> mock_executable(const std::string& name)
{
- // Invoke the mock_process/* test case with all unsolicited output suppressed.
- return {
- boost::unit_test::framework::master_test_suite().argv[0],
- // Disable false-positive memory leak dumps to stderr
- // in debug builds when using the Windows UCRT.
- "--detect_memory_leaks=0",
- // Disable logging to stdout.
- "--log_level=nothing",
- // Disable the test report to stderr.
- "--report_level=no",
- "--run_test=mock_process/" + name,
- };
+#if defined(WIN32)
+ _putenv_s(MOCK_PROCESS_ENV, name.c_str());
+#else
+ setenv(MOCK_PROCESS_ENV, name.c_str(), /*overwrite=*/1);
+#endif
+ return {boost::unit_test::framework::master_test_suite().argv[0]};
}
BOOST_AUTO_TEST_CASE(run_command)
@@ -67,7 +99,7 @@ BOOST_AUTO_TEST_CASE(run_command)
const std::vector<std::string> command = mock_executable("nonzeroexit_nooutput");
BOOST_CHECK_EXCEPTION(RunCommandParseJSON(command), std::runtime_error, [&](const std::runtime_error& e) {
const std::string what{e.what()};
- BOOST_CHECK(what.find(strprintf("RunCommandParseJSON error: process(%s) returned %d: \n", util::Join(command, " "), boost::exit_test_failure)) != std::string::npos);
+ BOOST_CHECK(what.find(strprintf("RunCommandParseJSON error: process(%s) returned %d: \n", util::Join(command, " "), EXIT_FAILURE)) != std::string::npos);
return true;
});
}
@@ -77,7 +109,7 @@ BOOST_AUTO_TEST_CASE(run_command)
const std::string expected{"err"};
BOOST_CHECK_EXCEPTION(RunCommandParseJSON(command), std::runtime_error, [&](const std::runtime_error& e) {
const std::string what(e.what());
- BOOST_CHECK(what.find(strprintf("RunCommandParseJSON error: process(%s) returned %s: %s", util::Join(command, " "), boost::exit_test_failure, "err")) != std::string::npos);
+ BOOST_CHECK(what.find(strprintf("RunCommandParseJSON error: process(%s) returned %s: %s", util::Join(command, " "), EXIT_FAILURE, "err")) != std::string::npos);
BOOST_CHECK(what.find(expected) != std::string::npos);
return true;
});
diff --git a/test/lint/lint-includes.py b/test/lint/lint-includes.py
index 18f47240..2e8417ea 100755
--- a/test/lint/lint-includes.py
+++ b/test/lint/lint-includes.py
@@ -21,7 +21,6 @@ EXCLUDED_DIRS = ["contrib/devtools/bitcoin-tidy/",
] + SHARED_EXCLUDED_SUBTREES
EXPECTED_BOOST_INCLUDES = [
- "boost/cstdlib.hpp",
"boost/multi_index/detail/hash_index_iterator.hpp",
"boost/multi_index/hashed_index.hpp",
"boost/multi_index/identity.hpp",
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.