|
39 | 39 | #include "PubSubReader.hpp"
|
40 | 40 | #include "PubSubWriter.hpp"
|
41 | 41 | #include "PubSubWriterReader.hpp"
|
| 42 | +#include "PubSubParticipant.hpp" |
42 | 43 |
|
43 | 44 | using namespace eprosima::fastrtps;
|
44 | 45 | using namespace eprosima::fastrtps::rtps;
|
@@ -1326,9 +1327,8 @@ TEST_P(Discovery, AsymmeticIgnoreParticipantFlags)
|
1326 | 1327 | // This will hold the multicast port. Since the test is not always run in the same domain, we'll need to set
|
1327 | 1328 | // its value when the first multicast datagram is sent.
|
1328 | 1329 | 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; |
1332 | 1332 |
|
1333 | 1333 | auto test_transport = std::make_shared<eprosima::fastdds::rtps::test_UDPv4TransportDescriptor>();
|
1334 | 1334 |
|
@@ -1364,6 +1364,115 @@ TEST_P(Discovery, AsymmeticIgnoreParticipantFlags)
|
1364 | 1364 | EXPECT_EQ(messages_on_port, allowed_messages_on_port);
|
1365 | 1365 | }
|
1366 | 1366 |
|
| 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 | + |
1367 | 1476 | #ifdef INSTANTIATE_TEST_SUITE_P
|
1368 | 1477 | #define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_SUITE_P(x, y, z, w)
|
1369 | 1478 | #else
|
|
0 commit comments