Branch data Line data Source code
1 : : // Copyright (c) 2019-present 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 : : #include <bitcoin-build-config.h> // IWYU pragma: keep
7 : :
8 : : #include <common/run_command.h>
9 : : #include <test/util/setup_common.h>
10 : : #include <univalue.h>
11 : : #include <util/string.h>
12 : :
13 : : #ifdef ENABLE_EXTERNAL_SIGNER
14 : : #include <util/subprocess.h>
15 : : #endif // ENABLE_EXTERNAL_SIGNER
16 : :
17 : : #include <boost/test/unit_test.hpp>
18 : :
19 : : BOOST_FIXTURE_TEST_SUITE(system_tests, BasicTestingSetup)
20 : :
21 : : #ifdef ENABLE_EXTERNAL_SIGNER
22 : :
23 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(run_command)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
24 : : {
25 : 1 : {
26 [ + - ]: 1 : const UniValue result = RunCommandParseJSON({});
27 [ + - + - ]: 2 : BOOST_CHECK(result.isNull());
28 : 1 : }
29 : 1 : {
30 : : #ifdef WIN32
31 : : const UniValue result = RunCommandParseJSON({"cmd.exe", "/c", "echo", "{\"success\":", "true}"}); // The command is intentionally split "incorrectly", to exactly preserve previous behavior. This is due to the cmd.exe internal echo quoting strings with spaces in it, unlike the normal 'echo' below.
32 : : #else
33 [ + - + - ]: 1 : const UniValue result = RunCommandParseJSON({"echo", "{\"success\": true}"});
34 : : #endif
35 [ + - + - : 2 : BOOST_CHECK(result.isObject());
+ - ]
36 [ + - ]: 1 : const UniValue& success = result.find_value("success");
37 [ + - + - : 2 : BOOST_CHECK(!success.isNull());
+ - ]
38 [ + - + - : 1 : BOOST_CHECK_EQUAL(success.get_bool(), true);
+ - ]
39 : 1 : }
40 : 1 : {
41 : : // An invalid command is handled by cpp-subprocess
42 : : #ifdef WIN32
43 : : const std::string expected{"CreateProcess failed: "};
44 : : #else
45 : 1 : const std::string expected{"execve failed: "};
46 : : #endif
47 [ + - + - : 3 : BOOST_CHECK_EXCEPTION(RunCommandParseJSON({"invalid_command"}), subprocess::CalledProcessError, HasReason(expected));
+ - - + -
- - - - +
+ - - + +
- + - ]
48 : 0 : }
49 : 1 : {
50 : : // Return non-zero exit code, no output to stderr
51 : : #ifdef WIN32
52 : : const std::vector<std::string> command = {"cmd.exe", "/c", "exit 1"};
53 : : #else
54 : 1 : const std::vector<std::string> command = {"false"};
55 : : #endif
56 [ + - + - : 6 : BOOST_CHECK_EXCEPTION(RunCommandParseJSON(command), std::runtime_error, [&](const std::runtime_error& e) {
+ + + - -
- - + + -
+ - + - ]
57 : : const std::string what{e.what()};
58 : : BOOST_CHECK(what.find(strprintf("RunCommandParseJSON error: process(%s) returned 1: \n", util::Join(command, " "))) != std::string::npos);
59 : : return true;
60 : : });
61 : 1 : }
62 : 1 : {
63 : : // Return non-zero exit code, with error message for stderr
64 : : #ifdef WIN32
65 : : const std::vector<std::string> command = {"cmd.exe", "/c", "echo err 1>&2 && exit 1"};
66 : : #else
67 : 1 : const std::vector<std::string> command = {"sh", "-c", "echo err 1>&2 && false"};
68 : : #endif
69 [ + - ]: 1 : const std::string expected{"err"};
70 [ + - + - : 8 : BOOST_CHECK_EXCEPTION(RunCommandParseJSON(command), std::runtime_error, [&](const std::runtime_error& e) {
+ + + - +
- - + + -
+ - + - ]
71 : : const std::string what(e.what());
72 : : BOOST_CHECK(what.find(strprintf("RunCommandParseJSON error: process(%s) returned %s: %s", util::Join(command, " "), 1, "err")) != std::string::npos);
73 : : BOOST_CHECK(what.find(expected) != std::string::npos);
74 : : return true;
75 : : });
76 : 1 : }
77 : 1 : {
78 : : // Unable to parse JSON
79 : : #ifdef WIN32
80 : : const std::vector<std::string> command = {"cmd.exe", "/c", "echo {"};
81 : : #else
82 : 1 : const std::vector<std::string> command = {"echo", "{"};
83 : : #endif
84 [ + - + - : 3 : BOOST_CHECK_EXCEPTION(RunCommandParseJSON(command), std::runtime_error, HasReason("Unable to parse JSON: {"));
- + - - -
- - + + -
+ - + - ]
85 : 1 : }
86 : : #ifndef WIN32
87 : 1 : {
88 : : // Test stdin
89 [ + - + - ]: 1 : const UniValue result = RunCommandParseJSON({"cat"}, "{\"success\": true}");
90 [ + - + - : 2 : BOOST_CHECK(result.isObject());
+ - ]
91 [ + - ]: 1 : const UniValue& success = result.find_value("success");
92 [ + - + - : 2 : BOOST_CHECK(!success.isNull());
+ - ]
93 [ + - + - : 1 : BOOST_CHECK_EQUAL(success.get_bool(), true);
+ - ]
94 : 1 : }
95 : : #endif
96 : 1 : }
97 : : #endif // ENABLE_EXTERNAL_SIGNER
98 : :
99 : : BOOST_AUTO_TEST_SUITE_END()
|