Repository: bitcoin/bitcoin
File: src/test/private_broadcast_tests.cpp (C++)

Code before:
    BOOST_CHECK(!pb.DidNodeConfirmReception(nonexistent_recipient));

    BOOST_CHECK_EQUAL(pb.GetStale().size(), 2);

    // Confirm reception by recipient1.
    pb.NodeConfirmedReception(nonexistent_recipient); // Dummy call.
    pb.NodeConfirmedReception(recipient1);

    BOOST_CHECK(pb.DidNodeConfirmReception(recipient1));
    BOOST_CHECK(!pb.DidNodeConfirmReception(recipient2));

    {
        const auto infos{pb.GetBroadcastInfo()};
        BOOST_CHECK_EQUAL(infos.size(), 2);

        const auto it_confirmed{std::ranges::find_if(infos, [&](const auto& info) { return info.tx->GetWitnessHash() == tx_for_recipient1->GetWitnessHash(); })};
        const auto it_unconfirmed{std::ranges::find_if(infos, [&](const auto& info) { return info.tx->GetWitnessHash() == tx_for_recipient2->GetWitnessHash(); })};
        BOOST_REQUIRE(it_confirmed != infos.end());
        BOOST_REQUIRE(it_unconfirmed != infos.end());
        const auto& confirmed_tx{*it_confirmed};
        const auto& unconfirmed_tx{*it_unconfirmed};

        BOOST_CHECK_EQUAL(confirmed_tx.peers.size(), 1);
        BOOST_CHECK_EQUAL(unconfirmed_tx.peers.size(), 1);
        BOOST_CHECK(confirmed_tx.peers[0].received.has_value());
        BOOST_CHECK(!unconfirmed_tx.peers[0].received.has_value());
    }

    BOOST_CHECK_EQUAL(pb.GetStale().size(), 1);
    BOOST_CHECK_EQUAL(pb.GetStale()[0], tx_for_recipient2);

    SetMockTime(Now<NodeSeconds>() + 10h);

    BOOST_CHECK_EQUAL(pb.GetStale().size(), 2);

    BOOST_CHECK_EQUAL(pb.Remove(tx_for_recipient1).value(), 1);
    BOOST_CHECK(!pb.Remove(tx_for_recipient1).has_value());
    BOOST_CHECK_EQUAL(pb.Remove(tx_for_recipient2).value(), 0);
    BOOST_CHECK(!pb.Remove(tx_for_recipient2).has_value());

    BOOST_CHECK_EQUAL(pb.GetBroadcastInfo().size(), 0);
    BOOST_CHECK(!pb.PickTxForSend(/*will_send_to_nodeid=*/nonexistent_recipient, /*will_send_to_address=*/CService{}).has_value());
}

BOOST_AUTO_TEST_SUITE_END()


Review comment (suggestion):
nit: we could also check that the node addresses match. I took a stab at adding this:

```diff
diff --git a/src/test/private_broadcast_tests.cpp b/src/test/private_broadcast_tests.cpp
index 4dbc768d74..9a86137c02 100644
--- a/src/test/private_broadcast_tests.cpp
+++ b/src/test/private_broadcast_tests.cpp
@@ -30,7 +30,9 @@ BOOST_AUTO_TEST_CASE(basic)
 
     PrivateBroadcast pb;
     const NodeId recipient1{1};
-    const CService addr1{};
+    in_addr ipv4Addr;
+    ipv4Addr.s_addr = 0xa0b0c001;
+    const CService addr1(ipv4Addr, 1111);
 
     // No transactions initially.
     BOOST_CHECK(!pb.PickTxForSend(/*will_send_to_nodeid=*/recipient1, /*will_send_to_address=*/addr1).has_value());
@@ -71,7 +73,7 @@ BOOST_AUTO_TEST_CASE(basic)
 
     // A second pick must return the other transaction.
     const NodeId recipient2{2};
-    const CService addr2{};
+    const CService addr2(ipv4Addr, 2222);
     const auto tx_for_recipient2{pb.PickTxForSend(/*will_send_to_nodeid=*/recipient2, /*will_send_to_address=*/addr2).value()};
     BOOST_CHECK(tx_for_recipient2 == tx1 || tx_for_recipient2 == tx2);
     BOOST_CHECK_NE(tx_for_recipient1, tx_for_recipient2);
@@ -124,7 +126,9 @@ BOOST_AUTO_TEST_CASE(basic)
         const auto& unconfirmed_tx{*it_unconfirmed};
 
         BOOST_CHECK_EQUAL(confirmed_tx.peers.size(), 1);
+        BOOST_CHECK_EQUAL(confirmed_tx.peers[0].address.ToStringAddrPort(), addr1.ToStringAddrPort());
         BOOST_CHECK_EQUAL(unconfirmed_tx.peers.size(), 1);
+        BOOST_CHECK_EQUAL(unconfirmed_tx.peers[0].address.ToStringAddrPort(), addr2.ToStringAddrPort());
         BOOST_CHECK(confirmed_tx.peers[0].received.has_value());
         BOOST_CHECK(!unconfirmed_tx.peers[0].received.has_value());
     }
```

Code after:
    {
        const auto& [tx, peers]{find_tx_info(infos, tx_for_recipient1)};
        BOOST_CHECK_EQUAL(peers.size(), 1);
        BOOST_CHECK_EQUAL(peers[0].address.ToStringAddrPort(), addr1.ToStringAddrPort());
        BOOST_CHECK(peers[0].received.has_value());
    }
    {
        const auto& [tx, peers]{find_tx_info(infos, tx_for_recipient2)};
        BOOST_CHECK_EQUAL(peers.size(), 1);
        BOOST_CHECK_EQUAL(peers[0].address.ToStringAddrPort(), addr2.ToStringAddrPort());
        BOOST_CHECK(!peers[0].received.has_value());
    }

    BOOST_CHECK_EQUAL(pb.GetStale().size(), 1);
    BOOST_CHECK_EQUAL(pb.GetStale()[0], tx_for_recipient2);

    SetMockTime(Now<NodeSeconds>() + 10h);

    BOOST_CHECK_EQUAL(pb.GetStale().size(), 2);

    BOOST_CHECK_EQUAL(pb.Remove(tx_for_recipient1).value(), 1);
    BOOST_CHECK(!pb.Remove(tx_for_recipient1).has_value());
    BOOST_CHECK_EQUAL(pb.Remove(tx_for_recipient2).value(), 0);
    BOOST_CHECK(!pb.Remove(tx_for_recipient2).has_value());

    BOOST_CHECK_EQUAL(pb.GetBroadcastInfo().size(), 0);
    const CService addr_nonexistent{ipv4Addr, 3333};
    BOOST_CHECK(!pb.PickTxForSend(/*will_send_to_nodeid=*/nonexistent_recipient, /*will_send_to_address=*/addr_nonexistent).has_value());
}

BOOST_AUTO_TEST_SUITE_END()