1111#include < univalue.h>
1212#include < util/string.h>
1313
14+ #include < cstdlib>
15+ #include < iostream>
16+ #include < string_view>
17+
1418#ifdef ENABLE_EXTERNAL_SIGNER
1519#include < util/subprocess.h>
1620#endif // ENABLE_EXTERNAL_SIGNER
1721
18- #include < boost/cstdlib.hpp>
1922#include < boost/test/unit_test.hpp>
2023
2124#include < string>
2225
26+ namespace {
27+ // When set in the environment, test_bitcoin acts as a mock subprocess for the
28+ // run_command test below instead of running unit tests.
29+ constexpr const char * MOCK_PROCESS_ENV = " BITCOIN_TEST_MOCK_PROCESS" ;
30+
31+ const bool g_maybe_run_mock_dispatcher_before_main{[]() {
32+ const char * name = std::getenv (MOCK_PROCESS_ENV );
33+ if (!name) return false ;
34+ const std::string_view n{name};
35+ if (n == " valid_json" ) {
36+ std::cout << R"( {"success": true})" << std::endl;
37+ std::_Exit (EXIT_SUCCESS );
38+ }
39+ if (n == " nonzeroexit_nooutput" ) {
40+ std::_Exit (EXIT_FAILURE );
41+ }
42+ if (n == " nonzeroexit_stderroutput" ) {
43+ std::cerr << " err" << std::endl;
44+ std::_Exit (EXIT_FAILURE );
45+ }
46+ if (n == " invalid_json" ) {
47+ std::cout << " {" << std::endl;
48+ std::_Exit (EXIT_SUCCESS );
49+ }
50+ if (n == " pass_stdin_to_stdout" ) {
51+ std::string s;
52+ std::getline (std::cin, s);
53+ std::cout << s << std::endl;
54+ std::_Exit (EXIT_SUCCESS );
55+ }
56+ std::cerr << " Unknown mock process: " << n << std::endl;
57+ std::_Exit (EXIT_FAILURE );
58+ }()};
59+ } // namespace
60+
2361BOOST_FIXTURE_TEST_SUITE (system_tests, BasicTestingSetup)
2462
2563#ifdef ENABLE_EXTERNAL_SIGNER
2664
27- static std::vector<std::string> mock_executable (std::string name)
65+ static std::vector<std::string> mock_executable (const std::string& name)
2866{
29- // Invoke the mock_process/* test case with all unsolicited output suppressed.
30- return {
31- boost::unit_test::framework::master_test_suite ().argv [0 ],
32- // Disable false-positive memory leak dumps to stderr
33- // in debug builds when using the Windows UCRT.
34- " --detect_memory_leaks=0" ,
35- // Disable logging to stdout.
36- " --log_level=nothing" ,
37- // Disable the test report to stderr.
38- " --report_level=no" ,
39- " --run_test=mock_process/" + name,
40- };
67+ #if defined(WIN32)
68+ _putenv_s (MOCK_PROCESS_ENV , name.c_str ());
69+ #else
70+ setenv (MOCK_PROCESS_ENV , name.c_str (), /* overwrite=*/ 1 );
71+ #endif
72+ return {boost::unit_test::framework::master_test_suite ().argv [0 ]};
4173}
4274
4375BOOST_AUTO_TEST_CASE (run_command)
@@ -67,7 +99,7 @@ BOOST_AUTO_TEST_CASE(run_command)
6799 const std::vector<std::string> command = mock_executable (" nonzeroexit_nooutput" );
68100 BOOST_CHECK_EXCEPTION (RunCommandParseJSON (command), std::runtime_error, [&](const std::runtime_error& e) {
69101 const std::string what{e.what ()};
70- BOOST_CHECK (what.find (strprintf (" RunCommandParseJSON error: process(%s) returned %d: \n " , util::Join (command, " " ), boost::exit_test_failure )) != std::string::npos);
102+ BOOST_CHECK (what.find (strprintf (" RunCommandParseJSON error: process(%s) returned %d: \n " , util::Join (command, " " ), EXIT_FAILURE )) != std::string::npos);
71103 return true ;
72104 });
73105 }
@@ -77,7 +109,7 @@ BOOST_AUTO_TEST_CASE(run_command)
77109 const std::string expected{" err" };
78110 BOOST_CHECK_EXCEPTION (RunCommandParseJSON (command), std::runtime_error, [&](const std::runtime_error& e) {
79111 const std::string what (e.what ());
80- BOOST_CHECK (what.find (strprintf (" RunCommandParseJSON error: process(%s) returned %s: %s" , util::Join (command, " " ), boost::exit_test_failure , " err" )) != std::string::npos);
112+ BOOST_CHECK (what.find (strprintf (" RunCommandParseJSON error: process(%s) returned %s: %s" , util::Join (command, " " ), EXIT_FAILURE , " err" )) != std::string::npos);
81113 BOOST_CHECK (what.find (expected) != std::string::npos);
82114 return true ;
83115 });
0 commit comments