LCOV - code coverage report
Current view: top level - src/ipc/test - ipc_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 99.6 % 229 228
Test Date: 2026-10-11 08:27:57 Functions: 100.0 % 25 25
Branches: 49.3 % 986 486

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2023-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                 :             : #include <interfaces/init.h>
       6                 :             : #include <ipc/capnp/mining.capnp.h>
       7                 :             : #include <ipc/capnp/protocol.h>
       8                 :             : #include <interfaces/ipc.h>
       9                 :             : #include <ipc/process.h>
      10                 :             : #include <ipc/protocol.h>
      11                 :             : #include <ipc/test/ipc_test.capnp.h>
      12                 :             : #include <ipc/test/ipc_test.capnp.proxy.h>
      13                 :             : #include <ipc/test/ipc_test.h>
      14                 :             : #include <mp/proxy-types.h>
      15                 :             : #include <ipc/types.h>
      16                 :             : 
      17                 :             : #include <test/util/common.h>
      18                 :             : #include <test/util/setup_common.h>
      19                 :             : #include <tinyformat.h>
      20                 :             : #include <util/log.h>
      21                 :             : #include <validation.h>
      22                 :             : 
      23                 :             : #include <future>
      24                 :             : #include <optional>
      25                 :             : #include <thread>
      26                 :             : #include <kj/common.h>
      27                 :             : #include <kj/memory.h>
      28                 :             : #include <kj/test.h>
      29                 :             : #include <stdexcept>
      30                 :             : 
      31                 :             : #include <boost/test/unit_test.hpp>
      32                 :             : 
      33                 :             : static_assert(ipc::capnp::messages::MAX_MONEY == MAX_MONEY);
      34                 :             : static_assert(ipc::capnp::messages::MAX_DOUBLE == std::numeric_limits<double>::max());
      35                 :             : static_assert(ipc::capnp::messages::DEFAULT_BLOCK_RESERVED_WEIGHT == DEFAULT_BLOCK_RESERVED_WEIGHT);
      36                 :             : static_assert(ipc::capnp::messages::DEFAULT_COINBASE_OUTPUT_MAX_ADDITIONAL_SIGOPS == DEFAULT_COINBASE_OUTPUT_MAX_ADDITIONAL_SIGOPS);
      37                 :             : 
      38                 :             : //! Remote init class.
      39                 :           3 : class TestInit : public interfaces::Init
      40                 :             : {
      41                 :             : public:
      42                 :           8 :     std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
      43                 :             : };
      44                 :             : 
      45                 :             : //! Generate a temporary path with temp_directory_path and mkstemp
      46                 :           3 : static std::string TempPath(std::string_view pattern)
      47                 :             : {
      48   [ +  -  +  -  :          24 :     std::string temp{fs::PathToString(fs::path{fs::temp_directory_path()} / fs::PathFromString(std::string{pattern}))};
             +  -  -  + ]
      49         [ +  - ]:           3 :     temp.push_back('\0');
      50         [ +  - ]:           3 :     int fd{mkstemp(temp.data())};
      51   [ +  -  +  - ]:           3 :     BOOST_CHECK_GE(fd, 0);
      52   [ +  -  +  -  :           3 :     BOOST_CHECK_EQUAL(close(fd), 0);
                   +  - ]
      53   [ -  +  +  - ]:           3 :     temp.resize(temp.size() - 1);
      54   [ +  -  +  - ]:           3 :     fs::remove(fs::PathFromString(temp));
      55                 :           3 :     return temp;
      56                 :           0 : }
      57                 :             : 
      58                 :             : //! Unit test that tests execution of IPC calls without actually creating a
      59                 :             : //! separate process. This test is primarily intended to verify behavior of type
      60                 :             : //! conversion code that converts C++ objects to Cap'n Proto messages and vice
      61                 :             : //! versa.
      62                 :             : //!
      63                 :             : //! The test creates a thread which creates a FooImplementation object (defined
      64                 :             : //! in ipc_test.h) and a two-way pipe accepting IPC requests which call methods
      65                 :             : //! on the object through FooInterface (defined in ipc_test.capnp).
      66                 :           1 : void IpcPipeTest()
      67                 :             : {
      68                 :             :     // Setup: create FooImplementation object and listen for FooInterface requests
      69                 :           1 :     std::promise<std::unique_ptr<mp::ProxyClient<gen::FooInterface>>> foo_promise;
      70                 :           2 :     std::thread thread([&]() {
      71         [ +  - ]:          68 :         mp::EventLoop loop("IpcPipeTest", [](bool raise, const std::string& log) { LogInfo("LOG%i: %s", raise, log); });
      72         [ +  - ]:           1 :         auto pipe = loop.m_io_context.provider->newTwoWayPipe();
      73                 :             : 
      74         [ +  - ]:           1 :         auto connection_client = std::make_unique<mp::Connection>(loop, kj::mv(pipe.ends[0]));
      75                 :           1 :         auto foo_client = std::make_unique<mp::ProxyClient<gen::FooInterface>>(
      76   [ +  -  +  -  :           1 :             connection_client->m_rpc_system->bootstrap(mp::ServerVatId().vat_id).castAs<gen::FooInterface>(),
             +  -  +  - ]
      77   [ +  -  +  - ]:           2 :             connection_client.get(), /* destroy_connection= */ true);
      78         [ +  - ]:           1 :         (void)connection_client.release();
      79         [ +  - ]:           1 :         foo_promise.set_value(std::move(foo_client));
      80                 :             : 
      81                 :           2 :         auto connection_server = std::make_unique<mp::Connection>(loop, kj::mv(pipe.ends[1]), [&](mp::Connection& connection) {
      82         [ +  - ]:           1 :             auto foo_server = kj::heap<mp::ProxyServer<gen::FooInterface>>(std::make_shared<FooImplementation>(), connection);
      83   [ +  -  +  - ]:           1 :             return capnp::Capability::Client(kj::mv(foo_server));
      84         [ +  - ]:           2 :         });
      85   [ +  -  +  - ]:           2 :         connection_server->onDisconnect([&] { connection_server.reset(); });
      86         [ +  - ]:           1 :         loop.loop();
      87   [ +  -  +  - ]:           2 :     });
      88   [ +  -  +  - ]:           2 :     std::unique_ptr<mp::ProxyClient<gen::FooInterface>> foo{foo_promise.get_future().get()};
      89                 :             : 
      90                 :             :     // Test: make sure arguments were sent and return value is received
      91   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(foo->add(1, 2), 3);
                   +  - ]
      92                 :             : 
      93         [ +  - ]:           1 :     COutPoint txout1{Txid::FromUint256(uint256{100}), 200};
      94         [ +  - ]:           1 :     COutPoint txout2{foo->passOutPoint(txout1)};
      95   [ +  -  +  - ]:           2 :     BOOST_CHECK(txout1 == txout2);
      96                 :             : 
      97                 :           1 :     UniValue uni1{UniValue::VOBJ};
      98   [ +  -  +  -  :           2 :     uni1.pushKV("i", 1);
                   +  - ]
      99   [ +  -  +  -  :           2 :     uni1.pushKV("s", "two");
                   +  - ]
     100   [ +  -  +  - ]:           1 :     UniValue uni2{foo->passUniValue(uni1)};
     101   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(uni1.write(), uni2.write());
             +  -  +  - ]
     102                 :             : 
     103         [ +  - ]:           1 :     CMutableTransaction mtx;
     104                 :           1 :     mtx.version = 2;
     105                 :           1 :     mtx.nLockTime = 3;
     106         [ +  - ]:           1 :     mtx.vin.emplace_back(txout1);
     107         [ +  - ]:           1 :     mtx.vout.emplace_back(COIN, CScript());
     108         [ +  - ]:           1 :     CTransactionRef tx1{MakeTransactionRef(mtx)};
     109   [ +  -  +  - ]:           2 :     CTransactionRef tx2{foo->passTransaction(tx1)};
     110   [ +  -  -  +  :           2 :     BOOST_CHECK(Assert(tx1)->Equals(*Assert(tx2)));
          -  +  +  -  +  
                      - ]
     111                 :             : 
     112                 :           1 :     std::vector<CTransactionRef> txs1;
     113         [ +  - ]:           1 :     txs1.push_back(tx1);
     114   [ +  -  -  + ]:           1 :     txs1.push_back(nullptr);
     115   [ +  -  +  - ]:           1 :     std::vector<CTransactionRef> txs2(foo->passTransactions(txs1));
     116   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(txs2.size(), 2);
                   +  - ]
     117   [ +  -  -  +  :           2 :     BOOST_CHECK(Assert(txs1[0])->Equals(*Assert(txs2[0])));
          -  +  +  -  +  
                      - ]
     118   [ +  -  +  -  :           2 :     BOOST_CHECK(!txs2[1]);
                   +  - ]
     119                 :             : 
     120         [ +  - ]:           1 :     std::vector<char> vec1{'H', 'e', 'l', 'l', 'o'};
     121   [ +  -  +  - ]:           1 :     std::vector<char> vec2{foo->passVectorChar(vec1)};
     122   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(std::string_view(vec1.begin(), vec1.end()), std::string_view(vec2.begin(), vec2.end()));
     123                 :             : 
     124         [ +  - ]:           1 :     auto script1{CScript() << OP_11};
     125         [ +  - ]:           1 :     auto script2{foo->passScript(script1)};
     126   [ +  -  -  +  :           3 :     BOOST_CHECK_EQUAL(HexStr(script1), HexStr(script2));
          +  -  +  -  +  
                      - ]
     127                 :             : 
     128                 :             :     // Test cleanup: disconnect and join thread
     129         [ +  - ]:           1 :     foo.reset();
     130         [ +  - ]:           1 :     thread.join();
     131   [ +  -  +  - ]:           4 : }
     132                 :             : 
     133                 :             : //! Test ipc::Protocol connect() and serve() methods connecting over a socketpair.
     134                 :           1 : void IpcSocketPairTest()
     135                 :             : {
     136                 :           1 :     std::unique_ptr<interfaces::Init> init{std::make_unique<TestInit>()};
     137         [ +  - ]:           1 :     std::unique_ptr<ipc::Protocol> protocol{ipc::capnp::MakeCapnpProtocol("IpcSocketPairTest")};
     138                 :           1 :     mp::Stream client_stream;
     139         [ +  - ]:           1 :     std::promise<void> promise;
     140                 :           2 :     std::thread thread([&]() {
     141         [ +  - ]:           1 :         protocol->serve(*init, [&] {
     142                 :           1 :             auto pair{mp::SocketPair()};
     143                 :           1 :             client_stream = protocol->makeStream(pair[0]);
     144                 :           1 :             promise.set_value();
     145                 :           1 :             return protocol->makeStream(pair[1]);
     146                 :             :         });
     147         [ +  - ]:           2 :     });
     148   [ +  -  +  - ]:           2 :     promise.get_future().wait();
     149         [ +  - ]:           1 :     std::unique_ptr<interfaces::Init> remote_init{protocol->connect(std::move(client_stream))};
     150         [ +  - ]:           1 :     std::unique_ptr<interfaces::Echo> remote_echo{remote_init->makeEcho()};
     151   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(remote_echo->echo("echo test"), "echo test");
             +  -  +  - ]
     152         [ +  - ]:           1 :     remote_echo.reset();
     153         [ +  - ]:           1 :     remote_init.reset();
     154         [ +  - ]:           1 :     thread.join();
     155                 :           1 : }
     156                 :             : 
     157                 :             : //! Test ipc::Process bind() and connect() methods connecting over a unix socket.
     158                 :           1 : void IpcSocketTest(const fs::path& datadir)
     159                 :             : {
     160                 :           1 :     std::unique_ptr<interfaces::Init> init{std::make_unique<TestInit>()};
     161         [ +  - ]:           1 :     std::unique_ptr<ipc::Protocol> protocol{ipc::capnp::MakeCapnpProtocol("IpcSocketTest")};
     162         [ +  - ]:           1 :     std::unique_ptr<ipc::Process> process{ipc::MakeProcess()};
     163                 :             : 
     164         [ +  - ]:           1 :     std::string invalid_bind{"invalid:"};
     165   [ +  -  +  -  :           3 :     BOOST_CHECK_THROW(process->bind(datadir, "test_bitcoin", invalid_bind), std::invalid_argument);
          -  +  -  -  -  
          -  -  +  +  -  
                   +  - ]
     166   [ +  -  +  -  :           3 :     BOOST_CHECK_THROW(process->connect(datadir, "test_bitcoin", invalid_bind), std::invalid_argument);
          -  +  -  -  -  
          -  -  +  +  -  
                   +  - ]
     167                 :             : 
     168                 :           3 :     auto bind_and_listen{[&](const std::string& bind_address) {
     169         [ -  + ]:           2 :         std::string address{bind_address};
     170   [ +  -  +  - ]:           2 :         mp::SocketId serve_fd = process->bind(datadir, "test_bitcoin", address);
     171   [ +  -  +  - ]:           2 :         BOOST_CHECK_NE(serve_fd, mp::SocketError);
     172   [ +  -  +  - ]:           2 :         BOOST_CHECK_EQUAL(address, bind_address);
     173         [ +  - ]:           2 :         protocol->listen(serve_fd, *init);
     174                 :           2 :     }};
     175                 :             : 
     176                 :           6 :     auto connect_and_test{[&](const std::string& connect_address) {
     177         [ -  + ]:           5 :         std::string address{connect_address};
     178   [ +  -  +  - ]:           5 :         mp::SocketId connect_fd{process->connect(datadir, "test_bitcoin", address)};
     179   [ +  -  +  - ]:           5 :         BOOST_CHECK_EQUAL(address, connect_address);
     180   [ +  -  +  - ]:           5 :         std::unique_ptr<interfaces::Init> remote_init{protocol->connect(protocol->makeStream(connect_fd))};
     181         [ +  - ]:           5 :         std::unique_ptr<interfaces::Echo> remote_echo{remote_init->makeEcho()};
     182   [ +  -  +  -  :           5 :         BOOST_CHECK_EQUAL(remote_echo->echo("echo test"), "echo test");
             +  -  +  - ]
     183                 :           5 :     }};
     184                 :             : 
     185                 :             :     // Need to specify explicit socket addresses outside the data directory, because the data
     186                 :             :     // directory path is so long that the default socket address and any other
     187                 :             :     // addresses in the data directory would fail with errors like:
     188                 :             :     //   Address 'unix' path '"/tmp/test_common_Bitcoin Core/ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff/test_bitcoin.sock"' exceeded maximum socket path length
     189                 :           1 :     std::vector<std::string> addresses{
     190         [ +  - ]:           1 :         strprintf("unix:%s", TempPath("bitcoin_sock0_XXXXXX")),
     191         [ +  - ]:           2 :         strprintf("unix:%s", TempPath("bitcoin_sock1_XXXXXX")),
     192   [ -  +  +  +  :           3 :     };
                   -  - ]
     193                 :             : 
     194                 :             :     // Bind and listen on multiple addresses
     195         [ +  + ]:           3 :     for (const auto& address : addresses) {
     196         [ +  - ]:           2 :         bind_and_listen(address);
     197                 :             :     }
     198                 :             : 
     199                 :             :     // Connect and test each address multiple times.
     200         [ +  + ]:           6 :     for (int i : {0, 1, 0, 0, 1}) {
     201         [ +  - ]:           5 :         connect_and_test(addresses[i]);
     202                 :             :     }
     203   [ +  -  +  -  :           3 : }
                   -  - ]
     204                 :             : 
     205                 :             : //! Test ipc::Protocol listen() local connection limiting over a unix socket.
     206                 :           1 : void IpcSocketMaxConnectionsTest(const fs::path& datadir)
     207                 :             : {
     208                 :           1 :     std::unique_ptr<interfaces::Init> init{std::make_unique<TestInit>()};
     209         [ +  - ]:           1 :     std::unique_ptr<ipc::Protocol> protocol{ipc::capnp::MakeCapnpProtocol("IpcSocketMaxConnectionsTest")};
     210         [ +  - ]:           1 :     std::unique_ptr<ipc::Process> process{ipc::MakeProcess()};
     211                 :             : 
     212   [ +  -  +  - ]:           1 :     std::string address{strprintf("unix:%s", TempPath("bitcoin_sock_limit_XXXXXX"))};
     213   [ +  -  +  - ]:           1 :     mp::SocketId serve_fd = process->bind(datadir, "test_bitcoin", address);
     214   [ +  -  +  - ]:           1 :     BOOST_CHECK_NE(serve_fd, mp::SocketError);
     215         [ +  - ]:           1 :     protocol->listen(serve_fd, *init, /*max_connections=*/1);
     216                 :             : 
     217                 :           2 :     auto connect_fd{[&](const std::string& connect_address) {
     218         [ -  + ]:           1 :         std::string addr{connect_address};
     219   [ +  -  +  - ]:           1 :         mp::SocketId fd{process->connect(datadir, "test_bitcoin", addr)};
     220         [ -  + ]:           2 :         return std::make_pair(fd, addr);
     221                 :           1 :     }};
     222                 :             : 
     223   [ +  -  +  - ]:           1 :     auto [fd1, addr1] = connect_fd(address);
     224   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(addr1, address);
     225   [ +  -  +  - ]:           1 :     std::unique_ptr<interfaces::Init> remote_init1{protocol->connect(protocol->makeStream(fd1))};
     226         [ +  - ]:           1 :     std::unique_ptr<interfaces::Echo> remote_echo1{remote_init1->makeEcho()};
     227   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(remote_echo1->echo("echo test 1"), "echo test 1");
             +  -  +  - ]
     228                 :             : 
     229                 :           2 :     auto second_call = std::async(std::launch::async, [&] {
     230         [ -  + ]:           1 :         std::string addr{address};
     231   [ +  -  +  - ]:           1 :         mp::SocketId fd{process->connect(datadir, "test_bitcoin", addr)};
     232   [ +  -  +  - ]:           1 :         std::unique_ptr<interfaces::Init> remote_init{protocol->connect(protocol->makeStream(fd))};
     233         [ +  - ]:           1 :         std::unique_ptr<interfaces::Echo> remote_echo{remote_init->makeEcho()};
     234   [ +  -  +  - ]:           2 :         return std::make_pair(remote_echo->echo("echo test 2"), addr);
     235         [ +  - ]:           2 :     });
     236                 :             : 
     237   [ +  -  +  -  :           2 :     BOOST_CHECK(second_call.wait_for(std::chrono::milliseconds{100}) == std::future_status::timeout);
             +  -  +  - ]
     238                 :             : 
     239         [ +  - ]:           1 :     remote_echo1.reset();
     240         [ +  - ]:           1 :     remote_init1.reset();
     241                 :             : 
     242   [ +  -  +  -  :           2 :     BOOST_REQUIRE(second_call.wait_for(std::chrono::seconds{5}) == std::future_status::ready);
             +  -  +  - ]
     243   [ +  -  +  - ]:           1 :     auto [echo2, addr2] = second_call.get();
     244   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(addr2, address);
     245   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(echo2, "echo test 2");
     246         [ -  + ]:           2 : }
     247                 :             : 
     248                 :             : BOOST_FIXTURE_TEST_SUITE(ipc_tests, BasicTestingSetup)
     249   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(ipc_tests)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     250                 :             : {
     251                 :           1 :     IpcPipeTest();
     252                 :           1 :     IpcSocketPairTest();
     253         [ +  - ]:           1 :     IpcSocketTest(m_args.GetDataDirNet());
     254         [ +  - ]:           1 :     IpcSocketMaxConnectionsTest(m_args.GetDataDirNet());
     255                 :           1 : }
     256                 :             : 
     257                 :             : // Test address parsing.
     258   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(parse_address_test)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     259                 :             : {
     260                 :           1 :     std::unique_ptr<ipc::Process> process{ipc::MakeProcess()};
     261         [ +  - ]:           1 :     fs::path datadir{"/var/empty/notexist"};
     262                 :           4 :     auto check_notexist{[](const std::system_error& e) { return e.code() == std::errc::no_such_file_or_directory; }};
     263                 :           6 :     auto check_address{[&](std::string address, std::string expect_address, std::string expect_error) {
     264         [ +  + ]:           5 :         if (expect_error.empty()) {
     265   [ +  -  +  -  :           9 :             BOOST_CHECK_EXCEPTION(process->connect(datadir, "test_bitcoin", address), std::system_error, check_notexist);
          -  +  -  -  -  
          -  -  +  +  -  
                   +  - ]
     266                 :             :         } else {
     267   [ +  -  +  -  :           6 :             BOOST_CHECK_EXCEPTION(process->connect(datadir, "test_bitcoin", address), std::invalid_argument, HasReason(expect_error));
          -  +  -  -  -  
          -  -  +  +  -  
          -  +  +  -  +  
                      - ]
     268                 :             :         }
     269         [ +  - ]:           5 :         BOOST_CHECK_EQUAL(address, expect_address);
     270                 :           6 :     }};
     271   [ +  -  +  -  :           4 :     std::string prefix{fs::PathToString(datadir / "")};
                   -  + ]
     272   [ +  -  +  -  :           3 :     check_address("unix", "unix:" + prefix + "test_bitcoin.sock", "");
             +  -  +  - ]
     273   [ +  -  +  -  :           3 :     check_address("unix:", "unix:" + prefix + "test_bitcoin.sock", "");
             +  -  +  - ]
     274   [ +  -  +  -  :           3 :     check_address("unix:path.sock", "unix:" + prefix + "path.sock", "");
             +  -  +  - ]
     275         [ +  - ]:           2 :     check_address("unix:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.sock",
     276         [ +  - ]:           2 :                   "unix:" + prefix + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.sock",
     277   [ +  -  +  - ]:           3 :                   "Unix address path \"" + prefix + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.sock\" exceeded maximum socket path length");
     278   [ +  -  +  -  :           2 :     check_address("invalid", "invalid", "Unrecognized address 'invalid'");
             +  -  +  - ]
     279                 :             : 
     280                 :          22 :     auto check_listen_address{[](const std::string& configured_address, const std::string& expected_address, size_t expected_max_connections, const std::string& expected_error = "") {
     281   [ -  +  +  - ]:          42 :         auto listen_address{interfaces::Ipc::parseListenAddress(configured_address)};
     282         [ +  + ]:          21 :         if (!expected_error.empty()) {
     283   [ +  -  +  -  :          24 :             BOOST_CHECK(!listen_address);
                   +  - ]
     284   [ +  -  +  -  :          12 :             BOOST_CHECK_EQUAL(util::ErrorString(listen_address).original, expected_error);
                   +  - ]
     285                 :          12 :             return;
     286                 :             :         }
     287   [ +  -  +  -  :          18 :         BOOST_REQUIRE(listen_address);
                   +  - ]
     288   [ +  -  +  - ]:           9 :         BOOST_CHECK_EQUAL(listen_address->address, expected_address);
     289   [ +  -  +  - ]:           9 :         BOOST_CHECK_EQUAL(listen_address->max_connections, expected_max_connections);
     290                 :          21 :     }};
     291   [ +  -  +  -  :           2 :     check_listen_address("unix", "unix", ipc::DEFAULT_MAX_CONNECTIONS);
             +  -  +  - ]
     292   [ +  -  +  -  :           2 :     check_listen_address("unix:", "unix:", ipc::DEFAULT_MAX_CONNECTIONS);
             +  -  +  - ]
     293   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=8", "unix:", 8);
             +  -  +  - ]
     294   [ +  -  +  -  :           2 :     check_listen_address("unix:path.sock,max-connections=8", "unix:path.sock", 8);
             +  -  +  - ]
     295   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=1", "unix:", 1);
             +  -  +  - ]
     296   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=256", "unix:", ipc::MAX_CONNECTIONS);
             +  -  +  - ]
     297   [ +  -  +  -  :           2 :     check_listen_address("unix:path.sock,max-connections=8,unknown=1", "", 0, "Unknown socket option 'unknown'");
             +  -  +  - ]
     298   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=8,", "", 0, "Empty socket option");
             +  -  +  - ]
     299   [ +  -  +  -  :           2 :     check_listen_address("unix:,,max-connections=8", "", 0, "Empty socket option");
             +  -  +  - ]
     300   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=8,,max-connections=8", "", 0, "Empty socket option");
             +  -  +  - ]
     301   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=0", "", 0, "max-connections must be at least 1");
             +  -  +  - ]
     302   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=-1", "", 0, "max-connections must be at least 1");
             +  -  +  - ]
     303   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=-9223372036854775808", "", 0, "max-connections must be at least 1");
             +  -  +  - ]
     304   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=257", "", 0, "max-connections must be at most 256");
             +  -  +  - ]
     305   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=9223372036854775808", "", 0, "Invalid max-connections value '9223372036854775808'");
             +  -  +  - ]
     306   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=", "", 0, "Missing value for max-connections option");
             +  -  +  - ]
     307   [ +  -  +  -  :           2 :     check_listen_address("unix:path,backup.sock=1", "", 0, "Unknown socket option 'backup.sock'");
             +  -  +  - ]
     308   [ +  -  +  -  :           2 :     check_listen_address("unix:path%2Cbackup.sock=1", "unix:path,backup.sock=1", ipc::DEFAULT_MAX_CONNECTIONS);
             +  -  +  - ]
     309   [ +  -  +  -  :           2 :     check_listen_address("unix:path%2Cbackup.sock=1,max-connections=8", "unix:path,backup.sock=1", 8);
             +  -  +  - ]
     310   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections", "", 0, "Missing value for max-connections option");
             +  -  +  - ]
     311   [ +  -  +  -  :           2 :     check_listen_address("unix:,max-connections=2,max-connections=1", "unix:", 1);
             +  -  +  - ]
     312                 :           2 : }
     313                 :             : 
     314                 :             : // Test command line parsing in ipc::Process::checkSpawned().
     315   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(check_spawned_test)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     316                 :             : {
     317                 :           1 :     std::unique_ptr<ipc::Process> process{ipc::MakeProcess()};
     318                 :           1 :     char arg0[]{"bitcoin-node"};
     319                 :           1 :     char arg_spawn[]{"-ipcchild"};
     320                 :           1 :     char arg_invalid[]{"invalid"};
     321                 :           1 :     char arg_other[]{"-ipcbind=unix"};
     322                 :             : 
     323                 :             :     // no -ipcchild arg.
     324                 :           1 :     {
     325                 :           1 :         char* argv[]{arg0};
     326   [ +  -  +  -  :           2 :         BOOST_CHECK(!process->checkSpawned(1, argv));
             +  -  +  - ]
     327                 :             :     }
     328                 :           1 :     {
     329                 :           1 :         char* argv[]{arg0, arg_other};
     330   [ +  -  +  -  :           2 :         BOOST_CHECK(!process->checkSpawned(2, argv));
             +  -  +  - ]
     331                 :             :     }
     332                 :           1 :     {
     333                 :           1 :         char* argv[]{arg0, arg_other, arg_invalid};
     334   [ +  -  +  -  :           2 :         BOOST_CHECK(!process->checkSpawned(3, argv));
             +  -  +  - ]
     335                 :             :     }
     336                 :             :     // -ipcchild without a value.
     337                 :           1 :     {
     338                 :           1 :         char* argv[]{arg0, arg_spawn};
     339   [ +  -  +  -  :           2 :         BOOST_CHECK(!process->checkSpawned(2, argv));
             +  -  +  - ]
     340                 :             :     }
     341                 :             :     // -ipcchild combined with other arguments.
     342                 :           1 :     {
     343                 :           1 :         char* argv[]{arg0, arg_spawn, arg_invalid, arg_other};
     344   [ +  -  +  -  :           2 :         BOOST_CHECK(!process->checkSpawned(4, argv));
             +  -  +  - ]
     345                 :             :     }
     346                 :             :     // -ipcchild with a value that is not a valid way of connecting to the
     347                 :             :     // parent process.
     348                 :           1 :     {
     349                 :           1 :         char* argv[]{arg0, arg_spawn, arg_invalid};
     350   [ +  -  -  +  :           2 :         BOOST_CHECK_THROW(process->checkSpawned(3, argv), std::runtime_error);
          -  -  -  -  -  
             +  +  -  +  
                      - ]
     351                 :             :     }
     352                 :           1 : }
     353                 :             : 
     354                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1