LCOV - code coverage report
Current view: top level - src/test - addrman_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 541 543 99.6 %
Date: 2025-02-23 09:33:43 Functions: 45 45 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2012-2015 The Bitcoin Core developers
       2             : // Copyright (c) 2019-2021 The PIVX Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "test/test_pivx.h"
       7             : #include "test/data/asmap.raw.h"
       8             : 
       9             : #include "addrman.h"
      10             : #include "crypto/common.h" // for ReadLE64
      11             : #include "hash.h"
      12             : #include "netbase.h"
      13             : #include "optional.h"
      14             : #include "util/asmap.h"
      15             : #include "random.h"
      16             : 
      17             : #include <string>
      18             : 
      19             : #include <boost/test/unit_test.hpp>
      20             : 
      21           0 : class CAddrManTest : public CAddrMan
      22             : {
      23             : private:
      24             :     bool deterministic;
      25             : public:
      26          19 :     explicit CAddrManTest(bool makeDeterministic = true,
      27             :         std::vector<bool> asmap = std::vector<bool>())
      28          19 :     {
      29          19 :         if (makeDeterministic) {
      30             :             //  Set addrman addr placement to be deterministic.
      31          19 :             MakeDeterministic();
      32             :         }
      33          19 :         deterministic = makeDeterministic;
      34          19 :         m_asmap = asmap;
      35          19 :     }
      36             : 
      37             :     //! Ensure that bucket placement is always the same for testing purposes.
      38          19 :     void MakeDeterministic()
      39             :     {
      40          19 :         nKey.SetNull();
      41          19 :         insecure_rand = FastRandomContext(true);
      42          19 :     }
      43             : 
      44           5 :     CAddrInfo* Find(const CNetAddr& addr, int* pnId = nullptr)
      45             :     {
      46           5 :         LOCK(cs);
      47          10 :         return CAddrMan::Find(addr, pnId);
      48             :     }
      49             : 
      50           2 :     CAddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr)
      51             :     {
      52           2 :         LOCK(cs);
      53           4 :         return CAddrMan::Create(addr, addrSource, pnId);
      54             :     }
      55             : 
      56           1 :     void Delete(int nId)
      57             :     {
      58           1 :         LOCK(cs);
      59           1 :         CAddrMan::Delete(nId);
      60           1 :     }
      61             : 
      62             :     // Used to test deserialization
      63           8 :     std::pair<int, int> GetBucketAndEntry(const CAddress& addr)
      64             :     {
      65          16 :         LOCK(cs);
      66           8 :         int nId = mapAddr[addr];
      67        3256 :         for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; ++bucket) {
      68      211423 :             for (int entry = 0; entry < ADDRMAN_BUCKET_SIZE; ++entry) {
      69      208175 :                 if (nId == vvNew[bucket][entry]) {
      70           8 :                     return std::pair<int, int>(bucket, entry);
      71             :                 }
      72             :             }
      73             :         }
      74           0 :         return std::pair<int, int>(-1, -1);
      75             :     }
      76             : 
      77             :     // Simulates connection failure so that we can test eviction of offline nodes
      78           1 :     void SimConnFail(CService& addr)
      79             :     {
      80           1 :          LOCK(cs);
      81           1 :          int64_t nLastSuccess = 1;
      82           1 :          Good_(addr, true, nLastSuccess); // Set last good connection in the deep past.
      83             : 
      84           1 :          bool count_failure = false;
      85           1 :          int64_t nLastTry = GetAdjustedTime()-61;
      86           1 :          Attempt(addr, count_failure, nLastTry);
      87           1 :      }
      88             : 
      89           5 :     void Clear()
      90             :     {
      91           5 :         CAddrMan::Clear();
      92           5 :         if (deterministic) {
      93           5 :             nKey.SetNull();
      94           5 :             insecure_rand = FastRandomContext(true);
      95             :         }
      96           5 :     }
      97             : 
      98             : };
      99             : 
     100        6400 : static CNetAddr ResolveIP(const std::string& ip)
     101             : {
     102        6400 :     CNetAddr addr;
     103       19200 :     BOOST_CHECK_MESSAGE(LookupHost(ip, addr, false), strprintf("failed to resolve: %s", ip));
     104        6400 :     return addr;
     105             : }
     106             : 
     107        6622 : static CService ResolveService(const std::string& ip, const int port = 0)
     108             : {
     109        6622 :     CService serv;
     110       19866 :     BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port));
     111        6622 :     return serv;
     112             : }
     113             : 
     114             : 
     115           3 : static std::vector<bool> FromBytes(const unsigned char* source, int vector_size) {
     116           3 :     std::vector<bool> result(vector_size);
     117         180 :     for (int byte_i = 0; byte_i < vector_size / 8; ++byte_i) {
     118         177 :         unsigned char cur_byte = source[byte_i];
     119        1593 :         for (int bit_i = 0; bit_i < 8; ++bit_i) {
     120        2832 :             result[byte_i * 8 + bit_i] = (cur_byte >> bit_i) & 1;
     121             :         }
     122             :     }
     123           3 :     return result;
     124             : }
     125             : 
     126             : 
     127             : BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
     128             : 
     129           2 : BOOST_AUTO_TEST_CASE(addrman_simple)
     130             : {
     131           1 :     CAddrManTest addrman;
     132             : 
     133           2 :     CNetAddr source = ResolveIP("252.2.2.2");
     134             : 
     135             :     // Test 1: Does Addrman respond correctly when empty.
     136           2 :     BOOST_CHECK(addrman.size() == 0);
     137           2 :     CAddrInfo addr_null = addrman.Select();
     138           3 :     BOOST_CHECK(addr_null.ToString() == "[::]:0");
     139             : 
     140             :     // Test 2: Does Addrman::Add work as expected.
     141           2 :     CService addr1 = ResolveService("250.1.1.1", 8333);
     142           2 :     addrman.Add(CAddress(addr1, NODE_NONE), source);
     143           2 :     BOOST_CHECK(addrman.size() == 1);
     144           2 :     CAddrInfo addr_ret1 = addrman.Select();
     145           3 :     BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
     146             : 
     147             :     // Test 3: Does IP address deduplication work correctly.
     148             :     //  Expected dup IP should not be added.
     149           2 :     CService addr1_dup = ResolveService("250.1.1.1", 8333);
     150           2 :     addrman.Add(CAddress(addr1_dup, NODE_NONE), source);
     151           2 :     BOOST_CHECK(addrman.size() == 1);
     152             : 
     153             : 
     154             :     // Test 5: New table has one addr and we add a diff addr we should
     155             :     //  have two addrs.
     156           2 :     CService addr2 = ResolveService("250.1.1.2", 8333);
     157           2 :     addrman.Add(CAddress(addr2, NODE_NONE), source);
     158           2 :     BOOST_CHECK(addrman.size() == 2);
     159             : 
     160             :     // Test 6: AddrMan::Clear() should empty the new table.
     161           1 :     addrman.Clear();
     162           2 :     BOOST_CHECK(addrman.size() == 0);
     163           2 :     CAddrInfo addr_null2 = addrman.Select();
     164           3 :     BOOST_CHECK(addr_null2.ToString() == "[::]:0");
     165           1 : }
     166             : 
     167           2 : BOOST_AUTO_TEST_CASE(addrman_ports)
     168             : {
     169           1 :     CAddrManTest addrman;
     170             : 
     171           2 :     CNetAddr source = ResolveIP("252.2.2.2");
     172             : 
     173           2 :     BOOST_CHECK(addrman.size() == 0);
     174             : 
     175             :     // Test 7; Addr with same IP but diff port does not replace existing addr.
     176           2 :     CService addr1 = ResolveService("250.1.1.1", 8333);
     177           2 :     addrman.Add(CAddress(addr1, NODE_NONE), source);
     178           2 :     BOOST_CHECK(addrman.size() == 1);
     179             : 
     180           2 :     CService addr1_port = ResolveService("250.1.1.1", 8334);
     181           2 :     addrman.Add(CAddress(addr1_port, NODE_NONE), source);
     182           2 :     BOOST_CHECK(addrman.size() == 1);
     183           2 :     CAddrInfo addr_ret2 = addrman.Select();
     184           3 :     BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333");
     185             : 
     186             :     // Test 8: Add same IP but diff port to tried table, it doesn't get added.
     187             :     //  Perhaps this is not ideal behavior but it is the current behavior.
     188           2 :     addrman.Good(CAddress(addr1_port, NODE_NONE));
     189           2 :     BOOST_CHECK(addrman.size() == 1);
     190           1 :     bool newOnly = true;
     191           2 :     CAddrInfo addr_ret3 = addrman.Select(newOnly);
     192           3 :     BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
     193           1 : }
     194             : 
     195             : 
     196           2 : BOOST_AUTO_TEST_CASE(addrman_select)
     197             : {
     198           1 :     CAddrManTest addrman;
     199             : 
     200           2 :     CNetAddr source = ResolveIP("252.2.2.2");
     201             : 
     202             :     // Test 9: Select from new with 1 addr in new.
     203           2 :     CService addr1 = ResolveService("250.1.1.1", 8333);
     204           2 :     addrman.Add(CAddress(addr1, NODE_NONE), source);
     205           2 :     BOOST_CHECK(addrman.size() == 1);
     206             : 
     207           1 :     bool newOnly = true;
     208           2 :     CAddrInfo addr_ret1 = addrman.Select(newOnly);
     209           3 :     BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
     210             : 
     211             :     // Test 10: move addr to tried, select from new expected nothing returned.
     212           2 :     addrman.Good(CAddress(addr1, NODE_NONE));
     213           2 :     BOOST_CHECK(addrman.size() == 1);
     214           2 :     CAddrInfo addr_ret2 = addrman.Select(newOnly);
     215           3 :     BOOST_CHECK(addr_ret2.ToString() == "[::]:0");
     216             : 
     217           1 :     CAddrInfo addr_ret3 = addrman.Select();
     218           3 :     BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
     219             : 
     220           2 :     BOOST_CHECK(addrman.size() == 1);
     221             : 
     222             : 
     223             :     // Add three addresses to new table.
     224           2 :     CService addr2 = ResolveService("250.3.1.1", 8333);
     225           2 :     CService addr3 = ResolveService("250.3.2.2", 9999);
     226           2 :     CService addr4 = ResolveService("250.3.3.3", 9999);
     227             : 
     228           3 :     addrman.Add(CAddress(addr2, NODE_NONE), ResolveService("250.3.1.1", 8333));
     229           3 :     addrman.Add(CAddress(addr3, NODE_NONE), ResolveService("250.3.1.1", 8333));
     230           3 :     addrman.Add(CAddress(addr4, NODE_NONE), ResolveService("250.4.1.1", 8333));
     231             : 
     232             :     // Add three addresses to tried table.
     233           2 :     CService addr5 = ResolveService("250.4.4.4", 8333);
     234           2 :     CService addr6 = ResolveService("250.4.5.5", 7777);
     235           2 :     CService addr7 = ResolveService("250.4.6.6", 8333);
     236             : 
     237           3 :     addrman.Add(CAddress(addr5, NODE_NONE), ResolveService("250.3.1.1", 8333));
     238           2 :     addrman.Good(CAddress(addr5, NODE_NONE));
     239           3 :     addrman.Add(CAddress(addr6, NODE_NONE), ResolveService("250.3.1.1", 8333));
     240           2 :     addrman.Good(CAddress(addr6, NODE_NONE));
     241           3 :     addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333));
     242           2 :     addrman.Good(CAddress(addr7, NODE_NONE));
     243             : 
     244             :     // Test 11: 6 addrs + 1 addr from last test = 7.
     245           2 :     BOOST_CHECK(addrman.size() == 7);
     246             : 
     247             :     // Test 12: Select pulls from new and tried regardless of port number.
     248           2 :     std::set<uint16_t> ports;
     249          21 :     for (int i = 0; i < 20; ++i) {
     250          20 :         ports.insert(addrman.Select().GetPort());
     251             :     }
     252           1 :     BOOST_CHECK_EQUAL(ports.size(), 3);
     253           1 : }
     254             : 
     255           2 : BOOST_AUTO_TEST_CASE(addrman_new_collisions)
     256             : {
     257           1 :     CAddrManTest addrman;
     258             : 
     259           2 :     CNetAddr source = ResolveIP("252.2.2.2");
     260             : 
     261           2 :     BOOST_CHECK(addrman.size() == 0);
     262             : 
     263          18 :     for (unsigned int i = 1; i < 18; i++) {
     264          51 :         CService addr = ResolveService("250.1.1." + std::to_string(i));
     265          34 :         addrman.Add(CAddress(addr, NODE_NONE), source);
     266             : 
     267             :         //Test 13: No collision in new table yet.
     268          34 :         BOOST_CHECK(addrman.size() == i);
     269             :     }
     270             : 
     271             :     //Test 14: new table collision!
     272           2 :     CService addr1 = ResolveService("250.1.1.18");
     273           2 :     addrman.Add(CAddress(addr1, NODE_NONE), source);
     274           2 :     BOOST_CHECK(addrman.size() == 17);
     275             : 
     276           2 :     CService addr2 = ResolveService("250.1.1.19");
     277           2 :     addrman.Add(CAddress(addr2, NODE_NONE), source);
     278           2 :     BOOST_CHECK(addrman.size() == 18);
     279           1 : }
     280             : 
     281           2 : BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
     282             : {
     283           1 :     CAddrManTest addrman;
     284             : 
     285           2 :     CNetAddr source = ResolveIP("252.2.2.2");
     286             : 
     287           2 :     BOOST_CHECK(addrman.size() == 0);
     288             : 
     289          80 :     for (unsigned int i = 1; i < 80; i++) {
     290         237 :         CService addr = ResolveService("250.1.1." + std::to_string(i));
     291         158 :         addrman.Add(CAddress(addr, NODE_NONE), source);
     292         158 :         addrman.Good(CAddress(addr, NODE_NONE));
     293             : 
     294             :         //Test 15: No collision in tried table yet.
     295          79 :         BOOST_TEST_MESSAGE(addrman.size());
     296         158 :         BOOST_CHECK(addrman.size() == i);
     297             :     }
     298             : 
     299             :     //Test 16: tried table collision!
     300           2 :     CService addr1 = ResolveService("250.1.1.80");
     301           2 :     addrman.Add(CAddress(addr1, NODE_NONE), source);
     302           2 :     BOOST_CHECK(addrman.size() == 79);
     303             : 
     304           2 :     CService addr2 = ResolveService("250.1.1.81");
     305           2 :     addrman.Add(CAddress(addr2, NODE_NONE), source);
     306           2 :     BOOST_CHECK(addrman.size() == 80);
     307           1 : }
     308             : 
     309           2 : BOOST_AUTO_TEST_CASE(addrman_find)
     310             : {
     311           1 :     CAddrManTest addrman;
     312             : 
     313           1 :     BOOST_CHECK_EQUAL(addrman.size(), 0);
     314             : 
     315           3 :     CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
     316           3 :     CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
     317           3 :     CAddress addr3 = CAddress(ResolveService("251.255.2.1", 8333), NODE_NONE);
     318             : 
     319           2 :     CNetAddr source1 = ResolveIP("250.1.2.1");
     320           2 :     CNetAddr source2 = ResolveIP("250.1.2.2");
     321             : 
     322           1 :     addrman.Add(addr1, source1);
     323           1 :     addrman.Add(addr2, source2);
     324           1 :     addrman.Add(addr3, source1);
     325             : 
     326             :     // Test 17: ensure Find returns an IP matching what we searched on.
     327           1 :     CAddrInfo* info1 = addrman.Find(addr1);
     328           2 :     BOOST_CHECK(info1);
     329           1 :     if (info1)
     330           3 :         BOOST_CHECK(info1->ToString() == "250.1.2.1:8333");
     331             : 
     332             :     // Test 18; Find does not discriminate by port number.
     333           1 :     CAddrInfo* info2 = addrman.Find(addr2);
     334           2 :     BOOST_CHECK(info2);
     335           1 :     if (info2)
     336           2 :         BOOST_CHECK(info2->ToString() == info1->ToString());
     337             : 
     338             :     // Test 19: Find returns another IP matching what we searched on.
     339           1 :     CAddrInfo* info3 = addrman.Find(addr3);
     340           2 :     BOOST_CHECK(info3);
     341           1 :     if (info3)
     342           4 :         BOOST_CHECK(info3->ToString() == "251.255.2.1:8333");
     343           1 : }
     344             : 
     345           2 : BOOST_AUTO_TEST_CASE(addrman_create)
     346             : {
     347           1 :     CAddrManTest addrman;
     348             : 
     349           1 :     BOOST_CHECK_EQUAL(addrman.size(), 0);
     350             : 
     351           3 :     CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
     352           2 :     CNetAddr source1 = ResolveIP("250.1.2.1");
     353             : 
     354           1 :     int nId;
     355           1 :     CAddrInfo* pinfo = addrman.Create(addr1, source1, &nId);
     356             : 
     357             :     // Test 20: The result should be the same as the input addr.
     358           3 :     BOOST_CHECK(pinfo->ToString() == "250.1.2.1:8333");
     359             : 
     360           1 :     CAddrInfo* info2 = addrman.Find(addr1);
     361           3 :     BOOST_CHECK(info2->ToString() == "250.1.2.1:8333");
     362           1 : }
     363             : 
     364             : 
     365           2 : BOOST_AUTO_TEST_CASE(addrman_delete)
     366             : {
     367           1 :     CAddrManTest addrman;
     368             : 
     369           1 :     BOOST_CHECK_EQUAL(addrman.size(), 0);
     370             : 
     371           3 :     CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
     372           2 :     CNetAddr source1 = ResolveIP("250.1.2.1");
     373             : 
     374           1 :     int nId;
     375           1 :     addrman.Create(addr1, source1, &nId);
     376             : 
     377             :     // Test 21: Delete should actually delete the addr.
     378           2 :     BOOST_CHECK(addrman.size() == 1);
     379           1 :     addrman.Delete(nId);
     380           2 :     BOOST_CHECK(addrman.size() == 0);
     381           1 :     CAddrInfo* info2 = addrman.Find(addr1);
     382           2 :     BOOST_CHECK(info2 == nullptr);
     383           1 : }
     384             : 
     385           2 : BOOST_AUTO_TEST_CASE(addrman_getaddr)
     386             : {
     387           1 :     CAddrManTest addrman;
     388             : 
     389             :     // Test: Sanity check, GetAddr should never return anything if addrman
     390             :     //  is empty.
     391           2 :     BOOST_CHECK(addrman.size() == 0);
     392           2 :     std::vector<CAddress> vAddr1 = addrman.GetAddr(/* max_addresses */ 0, /* max_pct */0, /* network */ nullopt);
     393           2 :     BOOST_CHECK(vAddr1.size() == 0);
     394             : 
     395           3 :     CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
     396           1 :     addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
     397           3 :     CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
     398           1 :     addr2.nTime = GetAdjustedTime();
     399           3 :     CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
     400           1 :     addr3.nTime = GetAdjustedTime();
     401           3 :     CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
     402           1 :     addr4.nTime = GetAdjustedTime();
     403           3 :     CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
     404           1 :     addr5.nTime = GetAdjustedTime();
     405           2 :     CNetAddr source1 = ResolveIP("250.1.2.1");
     406           2 :     CNetAddr source2 = ResolveIP("250.2.3.3");
     407             : 
     408             :     // Test 23: Ensure GetAddr works with new addresses.
     409           1 :     addrman.Add(addr1, source1);
     410           1 :     addrman.Add(addr2, source2);
     411           1 :     addrman.Add(addr3, source1);
     412           1 :     addrman.Add(addr4, source2);
     413           1 :     addrman.Add(addr5, source1);
     414             : 
     415           1 :     BOOST_CHECK_EQUAL(addrman.GetAddr(/* max_addresses */ 0, /* max_pct */ 0, /* network */ nullopt).size(), 5U);
     416             :     // Net processing asks for 23% of addresses. 23% of 5 is 1 rounded down.
     417           1 :     BOOST_CHECK_EQUAL(addrman.GetAddr(/* max_addresses */ 2500, /* max_pct */ 23, /* network */ nullopt).size(), 1U);
     418             : 
     419             :     // Test 24: Ensure GetAddr works with new and tried addresses.
     420           2 :     addrman.Good(CAddress(addr1, NODE_NONE));
     421           2 :     addrman.Good(CAddress(addr2, NODE_NONE));
     422           1 :     BOOST_CHECK_EQUAL(addrman.GetAddr(/* max_addresses */ 0, /* max_pct */ 0, /* network */ nullopt).size(), 5U);
     423           1 :     BOOST_CHECK_EQUAL(addrman.GetAddr(/* max_addresses */ 2500, /* max_pct */ 23, /* network */ nullopt).size(), 1U);
     424             : 
     425             :     // Test 25: Ensure GetAddr still returns 23% when addrman has many addrs.
     426        2048 :     for (unsigned int i = 1; i < (8 * 256); i++) {
     427        2047 :         int octet1 = i % 256;
     428        2047 :         int octet2 = (i / 256) % 256;
     429        2047 :         int octet3 = (i / (256 * 2)) % 256;
     430        6141 :         std::string strAddr = std::to_string(octet1) + "." + std::to_string(octet2) + "." + std::to_string(octet3) + ".23";
     431        6141 :         CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
     432             : 
     433             :         // Ensure that for all addrs in addrman, isTerrible == false.
     434        2047 :         addr.nTime = GetAdjustedTime();
     435        2047 :         addrman.Add(addr, ResolveIP(strAddr));
     436        2047 :         if (i % 8 == 0)
     437         255 :             addrman.Good(addr);
     438             :     }
     439           2 :     std::vector<CAddress> vAddr = addrman.GetAddr(/* max_addresses */ 2500, /* max_pct */ 23, /* network */ nullopt);
     440             : 
     441           1 :     size_t percent23 = (addrman.size() * 23) / 100;
     442           2 :     BOOST_CHECK(vAddr.size() == percent23);
     443           2 :     BOOST_CHECK(vAddr.size() == 461);
     444             :     // (Addrman.size() < number of addresses added) due to address collisions.
     445           2 :     BOOST_CHECK(addrman.size() == 2007);
     446           1 : }
     447             : 
     448             : 
     449           2 : BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
     450             : {
     451           1 :     CAddrManTest addrman;
     452             : 
     453           3 :     CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
     454           3 :     CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
     455             : 
     456           2 :     CNetAddr source1 = ResolveIP("250.1.1.1");
     457             : 
     458             : 
     459           2 :     CAddrInfo info1 = CAddrInfo(addr1, source1);
     460             : 
     461           1 :     uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
     462           1 :     uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
     463             : 
     464           2 :     std::vector<bool> asmap; // use /16
     465             : 
     466           1 :     BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, asmap), 40);
     467             : 
     468             :     // Test 26: Make sure key actually randomizes bucket placement. A fail on
     469             :     //  this test could be a security issue.
     470           2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info1.GetTriedBucket(nKey2, asmap));
     471             : 
     472             :     // Test 27: Two addresses with same IP but different ports can map to
     473             :     //  different buckets because they have different keys.
     474           2 :     CAddrInfo info2 = CAddrInfo(addr2, source1);
     475             : 
     476           5 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
     477           2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info2.GetTriedBucket(nKey1, asmap));
     478             : 
     479           2 :     std::set<int> buckets;
     480         256 :     for (int i = 0; i < 255; i++) {
     481         255 :         CAddrInfo infoi = CAddrInfo(
     482         510 :             CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE),
     483         765 :             ResolveIP("250.1.1." + std::to_string(i)));
     484         255 :         int bucket = infoi.GetTriedBucket(nKey1, asmap);
     485         255 :         buckets.insert(bucket);
     486             :     }
     487             :     // Test: IP addresses in the same /16 prefix should
     488             :     // never get more than 8 buckets with legacy grouping
     489           1 :     BOOST_CHECK_EQUAL(buckets.size(), 8U);
     490             : 
     491           1 :     buckets.clear();
     492         256 :     for (int j = 0; j < 255; j++) {
     493         255 :         CAddrInfo infoj = CAddrInfo(
     494         510 :             CAddress(ResolveService("250." + std::to_string(j) + ".1.1"), NODE_NONE),
     495         765 :             ResolveIP("250." + std::to_string(j) + ".1.1"));
     496         255 :         int bucket = infoj.GetTriedBucket(nKey1, asmap);
     497         255 :         buckets.insert(bucket);
     498             :     }
     499             :     // Test: IP addresses in the different /16 prefix should map to more than
     500             :     // 8 buckets with legacy grouping
     501           1 :     BOOST_CHECK_EQUAL(buckets.size(), 160U);
     502           1 : }
     503             : 
     504           2 : BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket_legacy)
     505             : {
     506           1 :     CAddrManTest addrman;
     507             : 
     508           3 :     CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
     509           3 :     CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
     510             : 
     511           2 :     CNetAddr source1 = ResolveIP("250.1.2.1");
     512             : 
     513           2 :     CAddrInfo info1 = CAddrInfo(addr1, source1);
     514             : 
     515           1 :     uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
     516           1 :     uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
     517             : 
     518           2 :     std::vector<bool> asmap; // use /16
     519             : 
     520             :     // Test: Make sure the buckets are what we expect
     521           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), 786);
     522           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, asmap), 786);
     523             : 
     524             :     // Test 30: Make sure key actually randomizes bucket placement. A fail on
     525             :     //  this test could be a security issue.
     526           2 :     BOOST_CHECK(info1.GetNewBucket(nKey1, asmap) != info1.GetNewBucket(nKey2, asmap));
     527             : 
     528             :     // Test 31: Ports should not effect bucket placement in the addr
     529           2 :     CAddrInfo info2 = CAddrInfo(addr2, source1);
     530           5 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
     531           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), info2.GetNewBucket(nKey1, asmap));
     532             : 
     533           2 :     std::set<int> buckets;
     534         256 :     for (int i = 0; i < 255; i++) {
     535         255 :         CAddrInfo infoi = CAddrInfo(
     536         510 :             CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE),
     537         765 :             ResolveIP("250.1.1." + std::to_string(i)));
     538         255 :         int bucket = infoi.GetNewBucket(nKey1, asmap);
     539         255 :         buckets.insert(bucket);
     540             :     }
     541             :     // Test 32: IP addresses in the same group (\16 prefix for IPv4) should
     542             :     //  always map to the same bucket.
     543           2 :     BOOST_CHECK(buckets.size() == 1);
     544             : 
     545           1 :     buckets.clear();
     546        1021 :     for (int j = 0; j < 4 * 255; j++) {
     547        2040 :         CAddrInfo infoj = CAddrInfo(CAddress(
     548        2040 :                                         ResolveService(
     549        2040 :                                             std::to_string(250 + (j / 255)) + "." + std::to_string(j % 256) + ".1.1"), NODE_NONE),
     550        3060 :             ResolveIP("251.4.1.1"));
     551        1020 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
     552        1020 :         buckets.insert(bucket);
     553             :     }
     554             :     // Test: IP addresses in the same source groups should map to NO MORE
     555             :     //  than 64 buckets.
     556           2 :     BOOST_CHECK(buckets.size() <= 64);
     557             : 
     558           1 :     buckets.clear();
     559         256 :     for (int p = 0; p < 255; p++) {
     560         255 :         CAddrInfo infoj = CAddrInfo(
     561         510 :             CAddress(ResolveService("250.1.1.1"), NODE_NONE),
     562         765 :             ResolveIP("250." + std::to_string(p) + ".1.1"));
     563         255 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
     564         255 :         buckets.insert(bucket);
     565             :     }
     566             :     // Test: IP addresses in the different source groups should map to MORE
     567             :     //  than 64 buckets.
     568           2 :     BOOST_CHECK(buckets.size() > 64);
     569           1 : }
     570             : 
     571             : // The following three test cases use asmap.raw
     572             : // We use an artificial minimal mock mapping
     573             : // 250.0.0.0/8 AS1000
     574             : // 101.1.0.0/16 AS1
     575             : // 101.2.0.0/16 AS2
     576             : // 101.3.0.0/16 AS3
     577             : // 101.4.0.0/16 AS4
     578             : // 101.5.0.0/16 AS5
     579             : // 101.6.0.0/16 AS6
     580             : // 101.7.0.0/16 AS7
     581             : // 101.8.0.0/16 AS8
     582           2 : BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
     583             : {
     584           1 :     CAddrManTest addrman;
     585             : 
     586           3 :     CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
     587           3 :     CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
     588             : 
     589           2 :     CNetAddr source1 = ResolveIP("250.1.1.1");
     590             : 
     591             : 
     592           2 :     CAddrInfo info1 = CAddrInfo(addr1, source1);
     593             : 
     594           1 :     uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
     595           1 :     uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
     596             : 
     597           2 :     std::vector<bool> asmap = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
     598             : 
     599           1 :     BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, asmap), 236);
     600             : 
     601             :     // Test: Make sure key actually randomizes bucket placement. A fail on
     602             :     //  this test could be a security issue.
     603           2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info1.GetTriedBucket(nKey2, asmap));
     604             : 
     605             :     // Test: Two addresses with same IP but different ports can map to
     606             :     //  different buckets because they have different keys.
     607           2 :     CAddrInfo info2 = CAddrInfo(addr2, source1);
     608             : 
     609           5 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
     610           2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info2.GetTriedBucket(nKey1, asmap));
     611             : 
     612           2 :     std::set<int> buckets;
     613         256 :     for (int j = 0; j < 255; j++) {
     614         255 :         CAddrInfo infoj = CAddrInfo(
     615         510 :             CAddress(ResolveService("101." + std::to_string(j) + ".1.1"), NODE_NONE),
     616         765 :             ResolveIP("101." + std::to_string(j) + ".1.1"));
     617         255 :         int bucket = infoj.GetTriedBucket(nKey1, asmap);
     618         255 :         buckets.insert(bucket);
     619             :     }
     620             :     // Test: IP addresses in the different /16 prefix MAY map to more than
     621             :     // 8 buckets.
     622           2 :     BOOST_CHECK(buckets.size() > 8);
     623             : 
     624           1 :     buckets.clear();
     625         256 :     for (int j = 0; j < 255; j++) {
     626         255 :         CAddrInfo infoj = CAddrInfo(
     627         510 :             CAddress(ResolveService("250." + std::to_string(j) + ".1.1"), NODE_NONE),
     628         765 :             ResolveIP("250." + std::to_string(j) + ".1.1"));
     629         255 :         int bucket = infoj.GetTriedBucket(nKey1, asmap);
     630         255 :         buckets.insert(bucket);
     631             :     }
     632             :     // Test: IP addresses in the different /16 prefix MAY NOT map to more than
     633             :     // 8 buckets.
     634           2 :     BOOST_CHECK(buckets.size() == 8);
     635           1 : }
     636             : 
     637           2 : BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
     638             : {
     639           1 :     CAddrManTest addrman;
     640             : 
     641           3 :     CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
     642           3 :     CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
     643             : 
     644           2 :     CNetAddr source1 = ResolveIP("250.1.2.1");
     645             : 
     646           2 :     CAddrInfo info1 = CAddrInfo(addr1, source1);
     647             : 
     648           1 :     uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
     649           1 :     uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
     650             : 
     651           2 :     std::vector<bool> asmap = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
     652             : 
     653             :     // Test: Make sure the buckets are what we expect
     654           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), 795);
     655           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, asmap), 795);
     656             : 
     657             :     // Test: Make sure key actually randomizes bucket placement. A fail on
     658             :     //  this test could be a security issue.
     659           2 :     BOOST_CHECK(info1.GetNewBucket(nKey1, asmap) != info1.GetNewBucket(nKey2, asmap));
     660             : 
     661             :     // Test: Ports should not affect bucket placement in the addr
     662           2 :     CAddrInfo info2 = CAddrInfo(addr2, source1);
     663           5 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
     664           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), info2.GetNewBucket(nKey1, asmap));
     665             : 
     666           2 :     std::set<int> buckets;
     667         256 :     for (int i = 0; i < 255; i++) {
     668         255 :         CAddrInfo infoi = CAddrInfo(
     669         510 :             CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE),
     670         765 :             ResolveIP("250.1.1." + std::to_string(i)));
     671         255 :         int bucket = infoi.GetNewBucket(nKey1, asmap);
     672         255 :         buckets.insert(bucket);
     673             :     }
     674             :     // Test: IP addresses in the same /16 prefix
     675             :     // usually map to the same bucket.
     676           1 :     BOOST_CHECK_EQUAL(buckets.size(), 1U);
     677             : 
     678           1 :     buckets.clear();
     679        1021 :     for (int j = 0; j < 4 * 255; j++) {
     680        2040 :         CAddrInfo infoj = CAddrInfo(CAddress(
     681        2040 :                                         ResolveService(
     682        2040 :                                             std::to_string(250 + (j / 255)) + "." + std::to_string(j % 256) + ".1.1"), NODE_NONE),
     683        3060 :             ResolveIP("251.4.1.1"));
     684        1020 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
     685        1020 :         buckets.insert(bucket);
     686             :     }
     687             :     // Test: IP addresses in the same source /16 prefix should not map to more
     688             :     // than 64 buckets.
     689           2 :     BOOST_CHECK(buckets.size() <= 64);
     690             : 
     691           1 :     buckets.clear();
     692         256 :     for (int p = 0; p < 255; p++) {
     693         255 :         CAddrInfo infoj = CAddrInfo(
     694         510 :             CAddress(ResolveService("250.1.1.1"), NODE_NONE),
     695         765 :             ResolveIP("101." + std::to_string(p) + ".1.1"));
     696         255 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
     697         255 :         buckets.insert(bucket);
     698             :     }
     699             :     // Test: IP addresses in the different source /16 prefixes usually map to MORE
     700             :     // than 1 bucket.
     701           2 :     BOOST_CHECK(buckets.size() > 1);
     702             : 
     703           1 :     buckets.clear();
     704         256 :     for (int p = 0; p < 255; p++) {
     705         255 :         CAddrInfo infoj = CAddrInfo(
     706         510 :             CAddress(ResolveService("250.1.1.1"), NODE_NONE),
     707         765 :             ResolveIP("250." + std::to_string(p) + ".1.1"));
     708         255 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
     709         255 :         buckets.insert(bucket);
     710             :     }
     711             :     // Test: IP addresses in the different source /16 prefixes sometimes map to NO MORE
     712             :     // than 1 bucket.
     713           2 :     BOOST_CHECK(buckets.size() == 1);
     714             : 
     715           1 : }
     716             : 
     717           2 : BOOST_AUTO_TEST_CASE(addrman_serialization)
     718             : {
     719           1 :     std::vector<bool> asmap1 = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
     720             : 
     721           2 :     CAddrManTest addrman_asmap1(true, asmap1);
     722           2 :     CAddrManTest addrman_asmap1_dup(true, asmap1);
     723           2 :     CAddrManTest addrman_noasmap;
     724           2 :     CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
     725             : 
     726           3 :     CAddress addr = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
     727           2 :     CNetAddr default_source;
     728             : 
     729             : 
     730           1 :     addrman_asmap1.Add(addr, default_source);
     731             : 
     732           1 :     stream << addrman_asmap1;
     733             :     // serizalizing/deserializing addrman with the same asmap
     734           1 :     stream >> addrman_asmap1_dup;
     735             : 
     736           1 :     std::pair<int, int> bucketAndEntry_asmap1 = addrman_asmap1.GetBucketAndEntry(addr);
     737           1 :     std::pair<int, int> bucketAndEntry_asmap1_dup = addrman_asmap1_dup.GetBucketAndEntry(addr);
     738           2 :     BOOST_CHECK(bucketAndEntry_asmap1.second != -1);
     739           2 :     BOOST_CHECK(bucketAndEntry_asmap1_dup.second != -1);
     740             : 
     741           2 :     BOOST_CHECK(bucketAndEntry_asmap1.first == bucketAndEntry_asmap1_dup.first);
     742           2 :     BOOST_CHECK(bucketAndEntry_asmap1.second == bucketAndEntry_asmap1_dup.second);
     743             : 
     744             :     // deserializing asmaped peers.dat to non-asmaped addrman
     745           1 :     stream << addrman_asmap1;
     746           1 :     stream >> addrman_noasmap;
     747           1 :     std::pair<int, int> bucketAndEntry_noasmap = addrman_noasmap.GetBucketAndEntry(addr);
     748           2 :     BOOST_CHECK(bucketAndEntry_noasmap.second != -1);
     749           2 :     BOOST_CHECK(bucketAndEntry_asmap1.first != bucketAndEntry_noasmap.first);
     750           2 :     BOOST_CHECK(bucketAndEntry_asmap1.second != bucketAndEntry_noasmap.second);
     751             : 
     752             :     // deserializing non-asmaped peers.dat to asmaped addrman
     753           1 :     addrman_asmap1.Clear();
     754           1 :     addrman_noasmap.Clear();
     755           1 :     addrman_noasmap.Add(addr, default_source);
     756           1 :     stream << addrman_noasmap;
     757           1 :     stream >> addrman_asmap1;
     758           1 :     std::pair<int, int> bucketAndEntry_asmap1_deser = addrman_asmap1.GetBucketAndEntry(addr);
     759           2 :     BOOST_CHECK(bucketAndEntry_asmap1_deser.second != -1);
     760           2 :     BOOST_CHECK(bucketAndEntry_asmap1_deser.first != bucketAndEntry_noasmap.first);
     761           2 :     BOOST_CHECK(bucketAndEntry_asmap1_deser.first == bucketAndEntry_asmap1_dup.first);
     762           2 :     BOOST_CHECK(bucketAndEntry_asmap1_deser.second == bucketAndEntry_asmap1_dup.second);
     763             : 
     764             :     // used to map to different buckets, now maps to the same bucket.
     765           1 :     addrman_asmap1.Clear();
     766           1 :     addrman_noasmap.Clear();
     767           3 :     CAddress addr1 = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
     768           3 :     CAddress addr2 = CAddress(ResolveService("250.2.1.1"), NODE_NONE);
     769           1 :     addrman_noasmap.Add(addr, default_source);
     770           1 :     addrman_noasmap.Add(addr2, default_source);
     771           1 :     std::pair<int, int> bucketAndEntry_noasmap_addr1 = addrman_noasmap.GetBucketAndEntry(addr1);
     772           1 :     std::pair<int, int> bucketAndEntry_noasmap_addr2 = addrman_noasmap.GetBucketAndEntry(addr2);
     773           2 :     BOOST_CHECK(bucketAndEntry_noasmap_addr1.first != bucketAndEntry_noasmap_addr2.first);
     774           2 :     BOOST_CHECK(bucketAndEntry_noasmap_addr1.second != bucketAndEntry_noasmap_addr2.second);
     775           1 :     stream << addrman_noasmap;
     776           1 :     stream >> addrman_asmap1;
     777           1 :     std::pair<int, int> bucketAndEntry_asmap1_deser_addr1 = addrman_asmap1.GetBucketAndEntry(addr1);
     778           1 :     std::pair<int, int> bucketAndEntry_asmap1_deser_addr2 = addrman_asmap1.GetBucketAndEntry(addr2);
     779           2 :     BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.first == bucketAndEntry_asmap1_deser_addr2.first);
     780           2 :     BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.second != bucketAndEntry_asmap1_deser_addr2.second);
     781           1 : }
     782             : 
     783             : 
     784           2 : BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
     785             : {
     786           1 :     CAddrManTest addrman;
     787             : 
     788           2 :     BOOST_CHECK(addrman.size() == 0);
     789             : 
     790             :     // Empty addrman should return blank addrman info.
     791           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     792             : 
     793             :     // Add twenty two addresses.
     794           2 :     CNetAddr source = ResolveIP("252.2.2.2");
     795          23 :     for (unsigned int i = 1; i < 23; i++) {
     796          66 :         CService addr = ResolveService("250.1.1."+std::to_string(i));
     797          44 :         addrman.Add(CAddress(addr, NODE_NONE), source);
     798          22 :         addrman.Good(addr);
     799             : 
     800             :         // No collisions yet.
     801          44 :         BOOST_CHECK(addrman.size() == i);
     802          66 :         BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     803             :     }
     804             : 
     805             :     // Ensure Good handles duplicates well.
     806          23 :     for (unsigned int i = 1; i < 23; i++) {
     807          66 :         CService addr = ResolveService("250.1.1."+std::to_string(i));
     808          22 :         addrman.Good(addr);
     809             : 
     810          44 :         BOOST_CHECK(addrman.size() == 22);
     811          66 :         BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     812             :     }
     813             : 
     814           1 : }
     815             : 
     816           2 : BOOST_AUTO_TEST_CASE(addrman_noevict)
     817             : {
     818           1 :     CAddrManTest addrman;
     819             : 
     820             :     // Add twenty two addresses.
     821           2 :     CNetAddr source = ResolveIP("252.2.2.2");
     822          23 :     for (unsigned int i = 1; i < 23; i++) {
     823          66 :         CService addr = ResolveService("250.1.1."+std::to_string(i));
     824          44 :         addrman.Add(CAddress(addr, NODE_NONE), source);
     825          22 :         addrman.Good(addr);
     826             : 
     827             :         // No collision yet.
     828          44 :         BOOST_CHECK(addrman.size() == i);
     829          66 :         BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     830             :     }
     831             : 
     832             :     // Collision between 23 and 19.
     833           2 :     CService addr23 = ResolveService("250.1.1.23");
     834           2 :     addrman.Add(CAddress(addr23, NODE_NONE), source);
     835           1 :     addrman.Good(addr23);
     836             : 
     837           2 :     BOOST_CHECK(addrman.size() == 23);
     838           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.19:0");
     839             : 
     840             :     // 23 should be discarded and 19 not evicted.
     841           1 :     addrman.ResolveCollisions();
     842           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     843             : 
     844             :     // Lets create two collisions.
     845          10 :     for (unsigned int i = 24; i < 33; i++) {
     846          27 :         CService addr = ResolveService("250.1.1."+std::to_string(i));
     847          18 :         addrman.Add(CAddress(addr, NODE_NONE), source);
     848           9 :         addrman.Good(addr);
     849             : 
     850          18 :         BOOST_CHECK(addrman.size() == i);
     851          27 :         BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     852             :     }
     853             : 
     854             :     // Cause a collision.
     855           2 :     CService addr33 = ResolveService("250.1.1.33");
     856           2 :     addrman.Add(CAddress(addr33, NODE_NONE), source);
     857           1 :     addrman.Good(addr33);
     858           2 :     BOOST_CHECK(addrman.size() == 33);
     859             : 
     860           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.27:0");
     861             : 
     862             :     // Cause a second collision.
     863           2 :     addrman.Add(CAddress(addr23, NODE_NONE), source);
     864           1 :     addrman.Good(addr23);
     865           2 :     BOOST_CHECK(addrman.size() == 33);
     866             : 
     867           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() != "[::]:0");
     868           1 :     addrman.ResolveCollisions();
     869           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     870           1 : }
     871             : 
     872           2 : BOOST_AUTO_TEST_CASE(addrman_evictionworks)
     873             : {
     874           1 :     CAddrManTest addrman;
     875             : 
     876           2 :     BOOST_CHECK(addrman.size() == 0);
     877             : 
     878             :     // Empty addrman should return blank addrman info.
     879           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     880             : 
     881             :     // Add twenty two addresses.
     882           2 :     CNetAddr source = ResolveIP("252.2.2.2");
     883          23 :     for (unsigned int i = 1; i < 23; i++) {
     884          66 :         CService addr = ResolveService("250.1.1."+std::to_string(i));
     885          44 :         addrman.Add(CAddress(addr, NODE_NONE), source);
     886          22 :         addrman.Good(addr);
     887             : 
     888             :         // No collision yet.
     889          44 :         BOOST_CHECK(addrman.size() == i);
     890          66 :         BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     891             :     }
     892             : 
     893             :     // Collision between 23 and 19.
     894           2 :     CService addr = ResolveService("250.1.1.23");
     895           2 :     addrman.Add(CAddress(addr, NODE_NONE), source);
     896           1 :     addrman.Good(addr);
     897             : 
     898           2 :     BOOST_CHECK(addrman.size() == 23);
     899           2 :     CAddrInfo info = addrman.SelectTriedCollision();
     900           3 :     BOOST_CHECK(info.ToString() == "250.1.1.19:0");
     901             : 
     902             :     // Ensure test of address fails, so that it is evicted.
     903           1 :     addrman.SimConnFail(info);
     904             : 
     905             :     // Should swap 23 for 19.
     906           1 :     addrman.ResolveCollisions();
     907           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     908             : 
     909             :     // If 23 was swapped for 19, then this should cause no collisions.
     910           2 :     addrman.Add(CAddress(addr, NODE_NONE), source);
     911           1 :     addrman.Good(addr);
     912             : 
     913           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     914             : 
     915             :     // If we insert 19 is should collide with 23.
     916           2 :     CService addr19 = ResolveService("250.1.1.19");
     917           2 :     addrman.Add(CAddress(addr19, NODE_NONE), source);
     918           1 :     addrman.Good(addr19);
     919             : 
     920           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.23:0");
     921             : 
     922           1 :     addrman.ResolveCollisions();
     923           3 :     BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     924           1 : }
     925             : 
     926             : 
     927             : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.14