LCOV - code coverage report
Current view: top level - src/test - i2p_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 100.0 % 80 80
Test Date: 2024-11-04 05:10:19 Functions: 100.0 % 10 10
Branches: 50.9 % 340 173

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2021-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                 :             : #include <common/args.h>
       6                 :             : #include <i2p.h>
       7                 :             : #include <logging.h>
       8                 :             : #include <netaddress.h>
       9                 :             : #include <netbase.h>
      10                 :             : #include <test/util/logging.h>
      11                 :             : #include <test/util/net.h>
      12                 :             : #include <test/util/setup_common.h>
      13                 :             : #include <util/readwritefile.h>
      14                 :             : #include <util/threadinterrupt.h>
      15                 :             : 
      16                 :             : #include <boost/test/unit_test.hpp>
      17                 :             : 
      18                 :             : #include <memory>
      19                 :             : #include <string>
      20                 :             : 
      21                 :             : /// Save the log level and the value of CreateSock and restore them when the test ends.
      22                 :             : class EnvTestingSetup : public BasicTestingSetup
      23                 :             : {
      24                 :             : public:
      25                 :           3 :     explicit EnvTestingSetup(const ChainType chainType = ChainType::MAIN,
      26                 :             :                              TestOpts opts = {})
      27                 :           3 :         : BasicTestingSetup{chainType, opts},
      28         [ +  - ]:           3 :           m_prev_log_level{LogInstance().LogLevel()},
      29   [ +  -  +  -  :           6 :           m_create_sock_orig{CreateSock}
                   +  - ]
      30                 :             :     {
      31         [ +  - ]:           3 :         LogInstance().SetLogLevel(BCLog::Level::Trace);
      32                 :           3 :     }
      33                 :             : 
      34                 :           3 :     ~EnvTestingSetup()
      35                 :           3 :     {
      36                 :           3 :         CreateSock = m_create_sock_orig;
      37                 :           3 :         LogInstance().SetLogLevel(m_prev_log_level);
      38                 :           3 :     }
      39                 :             : 
      40                 :             : private:
      41                 :             :     const BCLog::Level m_prev_log_level;
      42                 :             :     const decltype(CreateSock) m_create_sock_orig;
      43                 :             : };
      44                 :             : 
      45                 :             : BOOST_FIXTURE_TEST_SUITE(i2p_tests, EnvTestingSetup)
      46                 :             : 
      47   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(unlimited_recv)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      48                 :             : {
      49                 :           2 :     CreateSock = [](int, int, int) {
      50         [ +  - ]:           2 :         return std::make_unique<StaticContentsSock>(std::string(i2p::sam::MAX_MSG_SIZE + 1, 'a'));
      51                 :           1 :     };
      52                 :             : 
      53                 :           1 :     CThreadInterrupt interrupt;
      54   [ +  -  +  -  :           2 :     const std::optional<CService> addr{Lookup("127.0.0.1", 9000, false)};
                   +  - ]
      55         [ +  - ]:           1 :     const Proxy sam_proxy(addr.value(), false);
      56   [ +  -  +  -  :           3 :     i2p::sam::Session session(gArgs.GetDataDirNet() / "test_i2p_private_key", sam_proxy, &interrupt);
                   +  - ]
      57                 :             : 
      58                 :           1 :     {
      59   [ +  -  +  - ]:           2 :         ASSERT_DEBUG_LOG("Creating persistent SAM session");
      60   [ +  -  +  - ]:           2 :         ASSERT_DEBUG_LOG("too many bytes without a terminator");
      61                 :             : 
      62         [ +  - ]:           1 :         i2p::Connection conn;
      63                 :           1 :         bool proxy_error;
      64   [ +  -  +  -  :           2 :         BOOST_REQUIRE(!session.Connect(CService{}, conn, proxy_error));
             +  -  +  - ]
      65                 :           1 :     }
      66                 :           2 : }
      67                 :             : 
      68   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(listen_ok_accept_fail)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      69                 :             : {
      70                 :           1 :     size_t num_sockets{0};
      71                 :          11 :     CreateSock = [&num_sockets](int, int, int) {
      72                 :             :         // clang-format off
      73                 :          10 :         ++num_sockets;
      74                 :             :         // First socket is the control socket for creating the session.
      75         [ +  + ]:          10 :         if (num_sockets == 1) {
      76                 :           1 :             return std::make_unique<StaticContentsSock>(
      77                 :             :                 // reply to HELLO
      78                 :             :                 "HELLO REPLY RESULT=OK VERSION=3.1\n"
      79                 :             :                 // reply to DEST GENERATE
      80                 :             :                 "DEST REPLY PUB=WnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqLE4SD-yjT48UNI7qiTUfIPiDitCoiTTz2cr4QGfw89rBQAEAAcAAA== PRIV=WnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqFpxji10Qah0IXVYxZVqkcScM~Yccf9v8BnNlaZbWtSoWnGOLXRBqHQhdVjFlWqRxJwz9hxx~2~wGc2Vplta1KhacY4tdEGodCF1WMWVapHEnDP2HHH~b~AZzZWmW1rUqLE4SD-yjT48UNI7qiTUfIPiDitCoiTTz2cr4QGfw89rBQAEAAcAAOvuCIKTyv5f~1QgGq7XQl-IqBULTB5WzB3gw5yGPtd1p0AeoADrq1ccZggLPQ4ZLUsGK-HVw373rcTfvxrcuwenqVjiN4tbbYLWtP7xXGWj6fM6HyORhU63GphrjEePpMUHDHXd3o7pWGM-ieVVQSK~1MzF9P93pQWI3Do52EeNAayz4HbpPjNhVBzG1hUEFwznfPmUZBPuaOR4-uBm1NEWEuONlNOCctE4-U0Ukh94z-Qb55U5vXjR5G4apmBblr68t6Wm1TKlzpgFHzSqLryh3stWqrOKY1H0z9eZ2z1EkHFOpD5LyF6nf51e-lV7HLMl44TYzoEHK8RRVodtLcW9lacVdBpv~tOzlZERIiDziZODPETENZMz5oy9DQ7UUw==\n"
      81                 :             :                 // reply to SESSION CREATE
      82                 :             :                 "SESSION STATUS RESULT=OK\n"
      83                 :             :                 // dummy to avoid reporting EOF on the socket
      84                 :             :                 "a"
      85                 :           1 :             );
      86                 :             :         }
      87                 :             :         // Subsequent sockets are for recreating the session or for listening and accepting incoming connections.
      88         [ +  + ]:           9 :         if (num_sockets % 2 == 0) {
      89                 :             :             // Replies to Listen() and Accept()
      90                 :           5 :             return std::make_unique<StaticContentsSock>(
      91                 :             :                 // reply to HELLO
      92                 :             :                 "HELLO REPLY RESULT=OK VERSION=3.1\n"
      93                 :             :                 // reply to STREAM ACCEPT
      94                 :             :                 "STREAM STATUS RESULT=OK\n"
      95                 :             :                 // continued reply to STREAM ACCEPT, violating the protocol described at
      96                 :             :                 // https://geti2p.net/en/docs/api/samv3#Accept%20Response
      97                 :             :                 // should be base64, something like
      98                 :             :                 // "IchV608baDoXbqzQKSqFDmTXPVgoDbPAhZJvNRXXxi4hyFXrTxtoOhdurNApKoUOZNc9WCgNs8CFkm81FdfGLiHIVetPG2g6F26s0CkqhQ5k1z1YKA2zwIWSbzUV18YuIchV608baDoXbqzQKSqFDmTXPVgoDbPAhZJvNRXXxi4hyFXrTxtoOhdurNApKoUOZNc9WCgNs8CFkm81FdfGLiHIVetPG2g6F26s0CkqhQ5k1z1YKA2zwIWSbzUV18YuIchV608baDoXbqzQKSqFDmTXPVgoDbPAhZJvNRXXxi4hyFXrTxtoOhdurNApKoUOZNc9WCgNs8CFkm81FdfGLiHIVetPG2g6F26s0CkqhQ5k1z1YKA2zwIWSbzUV18YuIchV608baDoXbqzQKSqFDmTXPVgoDbPAhZJvNRXXxi4hyFXrTxtoOhdurNApKoUOZNc9WCgNs8CFkm81FdfGLlSreVaCuCS5sdb-8ToWULWP7kt~lRPDeUNxQMq3cRSBBQAEAAcAAA==\n"
      99                 :             :                 "STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"Session was closed\"\n"
     100                 :           5 :             );
     101                 :             :         } else {
     102                 :             :             // Another control socket, but without creating a destination (it is cached in the session).
     103                 :           4 :             return std::make_unique<StaticContentsSock>(
     104                 :             :                 // reply to HELLO
     105                 :             :                 "HELLO REPLY RESULT=OK VERSION=3.1\n"
     106                 :             :                 // reply to SESSION CREATE
     107                 :             :                 "SESSION STATUS RESULT=OK\n"
     108                 :             :                 // dummy to avoid reporting EOF on the socket
     109                 :             :                 "a"
     110                 :           4 :             );
     111                 :             :         }
     112                 :             :         // clang-format on
     113                 :           1 :     };
     114                 :             : 
     115                 :           1 :     CThreadInterrupt interrupt;
     116         [ +  - ]:           1 :     const CService addr{in6_addr(IN6ADDR_LOOPBACK_INIT), /*port=*/7656};
     117                 :           1 :     const Proxy sam_proxy(addr, false);
     118   [ +  -  +  - ]:           2 :     i2p::sam::Session session(gArgs.GetDataDirNet() / "test_i2p_private_key",
     119                 :             :                               sam_proxy,
     120         [ +  - ]:           1 :                               &interrupt);
     121                 :             : 
     122         [ +  - ]:           1 :     i2p::Connection conn;
     123         [ +  + ]:           6 :     for (size_t i = 0; i < 5; ++i) {
     124   [ +  -  +  - ]:          10 :         ASSERT_DEBUG_LOG("Creating persistent SAM session");
     125   [ +  -  +  - ]:          10 :         ASSERT_DEBUG_LOG("Persistent SAM session" /* ... created */);
     126   [ +  -  +  - ]:          10 :         ASSERT_DEBUG_LOG("Error accepting");
     127   [ +  -  +  - ]:          10 :         ASSERT_DEBUG_LOG("Destroying SAM session");
     128   [ +  -  +  -  :          10 :         BOOST_REQUIRE(session.Listen(conn));
             +  -  +  - ]
     129   [ +  -  +  -  :          10 :         BOOST_REQUIRE(!session.Accept(conn));
                   +  - ]
     130                 :           5 :     }
     131                 :           2 : }
     132                 :             : 
     133   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(damaged_private_key)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     134                 :             : {
     135                 :           6 :     CreateSock = [](int, int, int) {
     136                 :           5 :         return std::make_unique<StaticContentsSock>("HELLO REPLY RESULT=OK VERSION=3.1\n"
     137                 :           5 :                                                     "SESSION STATUS RESULT=OK DESTINATION=\n");
     138                 :           1 :     };
     139                 :             : 
     140         [ +  - ]:           2 :     const auto i2p_private_key_file = m_args.GetDataDirNet() / "test_i2p_private_key_damaged";
     141                 :             : 
     142         [ +  - ]:           6 :     for (const auto& [file_contents, expected_error] : std::vector<std::tuple<std::string, std::string>>{
     143                 :             :              {"", "The private key is too short (0 < 387)"},
     144                 :             : 
     145                 :             :              {"abcd", "The private key is too short (4 < 387)"},
     146                 :             : 
     147         [ +  - ]:           1 :              {std::string(386, '\0'), "The private key is too short (386 < 387)"},
     148                 :             : 
     149   [ +  -  +  - ]:           1 :              {std::string(385, '\0') + '\0' + '\1',
     150                 :             :               "Certificate length (1) designates that the private key should be 388 bytes, but it is only "
     151                 :             :               "387 bytes"},
     152                 :             : 
     153   [ +  -  +  -  :           2 :              {std::string(385, '\0') + '\0' + '\5' + "abcd",
                   +  - ]
     154                 :             :               "Certificate length (5) designates that the private key should be 392 bytes, but it is only "
     155   [ +  +  +  -  :          12 :               "391 bytes"}}) {
             +  +  -  - ]
     156   [ +  -  +  -  :          10 :         BOOST_REQUIRE(WriteBinaryFile(i2p_private_key_file, file_contents));
             +  -  +  - ]
     157                 :             : 
     158         [ +  - ]:           5 :         CThreadInterrupt interrupt;
     159         [ +  - ]:           5 :         const CService addr{in6_addr(IN6ADDR_LOOPBACK_INIT), /*port=*/7656};
     160                 :           5 :         const Proxy sam_proxy{addr, false};
     161         [ +  - ]:           5 :         i2p::sam::Session session(i2p_private_key_file, sam_proxy, &interrupt);
     162                 :             : 
     163                 :           5 :         {
     164   [ +  -  +  - ]:          10 :             ASSERT_DEBUG_LOG("Creating persistent SAM session");
     165   [ +  -  +  - ]:          10 :             ASSERT_DEBUG_LOG(expected_error);
     166                 :             : 
     167         [ +  - ]:           5 :             i2p::Connection conn;
     168                 :           5 :             bool proxy_error;
     169   [ +  -  +  -  :          10 :             BOOST_CHECK(!session.Connect(CService{}, conn, proxy_error));
             +  -  +  - ]
     170                 :           5 :         }
     171                 :          11 :     }
     172   [ +  -  +  -  :           7 : }
          +  -  +  -  +  
             -  +  -  -  
                      - ]
     173                 :             : 
     174                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1