Skip to content

Commit 88a860d

Browse files
Refs #22506. Regression test.
Signed-off-by: Eugenio Collado <[email protected]>
1 parent e6d0844 commit 88a860d

File tree

1 file changed

+112
-3
lines changed

1 file changed

+112
-3
lines changed

test/blackbox/common/BlackboxTestsDiscovery.cpp

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "PubSubReader.hpp"
4040
#include "PubSubWriter.hpp"
4141
#include "PubSubWriterReader.hpp"
42+
#include "PubSubParticipant.hpp"
4243

4344
using namespace eprosima::fastrtps;
4445
using namespace eprosima::fastrtps::rtps;
@@ -1326,9 +1327,8 @@ TEST_P(Discovery, AsymmeticIgnoreParticipantFlags)
13261327
// This will hold the multicast port. Since the test is not always run in the same domain, we'll need to set
13271328
// its value when the first multicast datagram is sent.
13281329
std::atomic<uint32_t> multicast_port{ 0 };
1329-
// Only two multicast datagrams are allowed: the initial DATA(p) and the DATA(p) sent in response of the discovery
1330-
// of p1.
1331-
constexpr uint32_t allowed_messages_on_port = 2;
1330+
// Only one multicast datagram is allowed: the initial DATA(p)
1331+
constexpr uint32_t allowed_messages_on_port = 1;
13321332

13331333
auto test_transport = std::make_shared<eprosima::fastdds::rtps::test_UDPv4TransportDescriptor>();
13341334

@@ -1364,6 +1364,115 @@ TEST_P(Discovery, AsymmeticIgnoreParticipantFlags)
13641364
EXPECT_EQ(messages_on_port, allowed_messages_on_port);
13651365
}
13661366

1367+
//! Regression test for redmine issue 22506
1368+
TEST_P(Discovery, single_unicast_pdp_response)
1369+
{
1370+
// Leverage intraprocess so transport is only used for participant discovery
1371+
if (INTRAPROCESS != GetParam())
1372+
{
1373+
GTEST_SKIP() << "Only makes sense on INTRAPROCESS";
1374+
return;
1375+
}
1376+
1377+
using namespace eprosima::fastdds::rtps;
1378+
1379+
// All participants would restrict communication to UDP localhost.
1380+
// The main participant should send a single initial announcement, and have a big announcement period.
1381+
// This is to ensure that we only check the datagrams sent in response to the participant discovery,
1382+
// and not the ones sent in the periodic announcements.
1383+
// The main participant will use the test transport to count the number of unicast messages sent.
1384+
1385+
// This will hold the multicast port. Since the test is not always run in the same domain, we'll need to set
1386+
// its value when the first multicast datagram is sent.
1387+
std::atomic<uint32_t> multicast_port{ 0 };
1388+
// Declare a test transport that will count the number of unicast messages sent
1389+
std::atomic<size_t> num_unicast_sends{ 0 };
1390+
auto test_transport = std::make_shared<test_UDPv4TransportDescriptor>();
1391+
test_transport->interfaceWhiteList.push_back("127.0.0.1");
1392+
test_transport->locator_filter_ = [&num_unicast_sends, &multicast_port](
1393+
const Locator& destination)
1394+
{
1395+
if (IPLocator::isMulticast(destination))
1396+
{
1397+
uint32_t port = 0;
1398+
multicast_port.compare_exchange_strong(port, destination.port);
1399+
}
1400+
else
1401+
{
1402+
num_unicast_sends.fetch_add(1u, std::memory_order_seq_cst);
1403+
}
1404+
1405+
// Do not discard any message
1406+
return false;
1407+
};
1408+
1409+
// Create the main participant
1410+
auto main_participant = std::make_shared<PubSubParticipant<HelloWorldPubSubType>>(0, 0, 0, 0);
1411+
eprosima::fastdds::dds::WireProtocolConfigQos main_wire_protocol;
1412+
main_wire_protocol.builtin.avoid_builtin_multicast = true;
1413+
main_wire_protocol.builtin.discovery_config.leaseDuration = c_TimeInfinite;
1414+
main_wire_protocol.builtin.discovery_config.leaseDuration_announcementperiod = { 3600, 0 };
1415+
main_wire_protocol.builtin.discovery_config.initial_announcements.count = 1;
1416+
main_wire_protocol.builtin.discovery_config.initial_announcements.period = { 0, 100000000 };
1417+
1418+
// The main participant will use the test transport and a specific announcments configuration
1419+
main_participant->disable_builtin_transport().add_user_transport_to_pparams(test_transport)
1420+
.wire_protocol(main_wire_protocol);
1421+
1422+
// Start the main participant
1423+
ASSERT_TRUE(main_participant->init_participant());
1424+
1425+
// Wait for the initial announcements to be sent
1426+
std::this_thread::sleep_for(std::chrono::seconds(1));
1427+
// This would have set the multicast port
1428+
EXPECT_NE(multicast_port, 0u);
1429+
1430+
// The rest of the participants only send announcements to the main participant
1431+
// Calculate the metatraffic unicast port of the main participant
1432+
uint32_t port = multicast_port + main_wire_protocol.port.offsetd1 - main_wire_protocol.port.offsetd0;
1433+
1434+
// The rest of the participants only send announcements to the main participant
1435+
auto udp_localhost_transport = std::make_shared<test_UDPv4TransportDescriptor>();
1436+
udp_localhost_transport->interfaceWhiteList.push_back("127.0.0.1");
1437+
Locator peer_locator;
1438+
IPLocator::createLocator(LOCATOR_KIND_UDPv4, "127.0.0.1", port, peer_locator);
1439+
eprosima::fastdds::dds::WireProtocolConfigQos wire_protocol;
1440+
wire_protocol.builtin.avoid_builtin_multicast = true;
1441+
wire_protocol.builtin.initialPeersList.push_back(peer_locator);
1442+
1443+
std::vector<std::shared_ptr<PubSubParticipant<HelloWorldPubSubType>>> participants;
1444+
for (size_t i = 0; i < 5; ++i)
1445+
{
1446+
auto participant = std::make_shared<PubSubParticipant<HelloWorldPubSubType>>(0, 0, 0, 0);
1447+
// All participants use the same transport
1448+
participant->disable_builtin_transport().add_user_transport_to_pparams(udp_localhost_transport)
1449+
.wire_protocol(wire_protocol);
1450+
participants.push_back(participant);
1451+
}
1452+
1453+
// Start the rest of the participants
1454+
for (auto& participant : participants)
1455+
{
1456+
ASSERT_TRUE(participant->init_participant());
1457+
participant->wait_discovery();
1458+
}
1459+
1460+
// Destroy main participant
1461+
main_participant.reset();
1462+
for (auto& participant : participants)
1463+
{
1464+
participant->wait_discovery(std::chrono::seconds::zero(), 0, true);
1465+
}
1466+
1467+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
1468+
// Check that only two unicast messages per participant were sent
1469+
EXPECT_EQ(num_unicast_sends.load(std::memory_order::memory_order_seq_cst),
1470+
participants.size() + participants.size());
1471+
1472+
// Clean up
1473+
participants.clear();
1474+
}
1475+
13671476
#ifdef INSTANTIATE_TEST_SUITE_P
13681477
#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_SUITE_P(x, y, z, w)
13691478
#else

0 commit comments

Comments
 (0)