/ src / test / system_tests.cpp
system_tests.cpp
 1  // Copyright (c) 2019-2022 The Bitcoin Core developers
 2  // Distributed under the MIT software license, see the accompanying
 3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 4  //
 5  
 6  #if defined(HAVE_CONFIG_H)
 7  #include <config/bitcoin-config.h>
 8  #endif
 9  #include <test/util/setup_common.h>
10  #include <common/run_command.h>
11  #include <univalue.h>
12  
13  #ifdef ENABLE_EXTERNAL_SIGNER
14  #include <boost/process.hpp>
15  #endif // ENABLE_EXTERNAL_SIGNER
16  
17  #include <boost/test/unit_test.hpp>
18  
19  BOOST_FIXTURE_TEST_SUITE(system_tests, BasicTestingSetup)
20  
21  // At least one test is required (in case ENABLE_EXTERNAL_SIGNER is not defined).
22  // Workaround for https://github.com/bitcoin/bitcoin/issues/19128
23  BOOST_AUTO_TEST_CASE(dummy)
24  {
25      BOOST_CHECK(true);
26  }
27  
28  #ifdef ENABLE_EXTERNAL_SIGNER
29  
30  BOOST_AUTO_TEST_CASE(run_command)
31  {
32      {
33          const UniValue result = RunCommandParseJSON("");
34          BOOST_CHECK(result.isNull());
35      }
36      {
37          const UniValue result = RunCommandParseJSON("echo \"{\"success\": true}\"");
38          BOOST_CHECK(result.isObject());
39          const UniValue& success = result.find_value("success");
40          BOOST_CHECK(!success.isNull());
41          BOOST_CHECK_EQUAL(success.get_bool(), true);
42      }
43      {
44          // An invalid command is handled by Boost
45          const int expected_error{2};
46          BOOST_CHECK_EXCEPTION(RunCommandParseJSON("invalid_command"), boost::process::process_error, [&](const boost::process::process_error& e) {
47              BOOST_CHECK(std::string(e.what()).find("RunCommandParseJSON error:") == std::string::npos);
48              BOOST_CHECK_EQUAL(e.code().value(), expected_error);
49              return true;
50          });
51      }
52      {
53          // Return non-zero exit code, no output to stderr
54          const std::string command{"false"};
55          BOOST_CHECK_EXCEPTION(RunCommandParseJSON(command), std::runtime_error, [&](const std::runtime_error& e) {
56              const std::string what{e.what()};
57              BOOST_CHECK(what.find(strprintf("RunCommandParseJSON error: process(%s) returned 1: \n", command)) != std::string::npos);
58              return true;
59          });
60      }
61      {
62          // Return non-zero exit code, with error message for stderr
63          const std::string command{"ls nosuchfile"};
64          const std::string expected{"No such file or directory"};
65          BOOST_CHECK_EXCEPTION(RunCommandParseJSON(command), std::runtime_error, [&](const std::runtime_error& e) {
66              const std::string what(e.what());
67              BOOST_CHECK(what.find(strprintf("RunCommandParseJSON error: process(%s) returned", command)) != std::string::npos);
68              BOOST_CHECK(what.find(expected) != std::string::npos);
69              return true;
70          });
71      }
72      {
73          // Unable to parse JSON
74          const std::string command{"echo {"};
75          BOOST_CHECK_EXCEPTION(RunCommandParseJSON(command), std::runtime_error, HasReason("Unable to parse JSON: {"));
76      }
77      // Test std::in
78      {
79          const UniValue result = RunCommandParseJSON("cat", "{\"success\": true}");
80          BOOST_CHECK(result.isObject());
81          const UniValue& success = result.find_value("success");
82          BOOST_CHECK(!success.isNull());
83          BOOST_CHECK_EQUAL(success.get_bool(), true);
84      }
85  }
86  #endif // ENABLE_EXTERNAL_SIGNER
87  
88  BOOST_AUTO_TEST_SUITE_END()