Skip to content

Commit ba4db7c

Browse files
committed
Refs #21355. Added regression test.
Signed-off-by: Miguel Company <miguelcompany@eprosima.com>
1 parent 39d3030 commit ba4db7c

1 file changed

Lines changed: 159 additions & 0 deletions

File tree

test/blackbox/common/DDSBlackboxTestsDiscovery.cpp

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,165 @@ TEST(DDSDiscovery, UpdateMatchedStatus)
483483
datawriter_2.destroy();
484484
}
485485

486+
/*
487+
* This is a regression test for redmine issue 21355.
488+
*
489+
* In order to check that the on_publication_matched() and on_subscription_matched() callbacks are always called with
490+
* either +1 or -1 as the current_count_change, this test creates and destroys multiple DataReaders and DataWriters in
491+
* different threads, with a listener that counts the number of times on_publication_matched() and
492+
* on_subscription_matched() are called with current_count_change equal to 1, -1 or other value.
493+
*
494+
* The test fails if any of the calls to on_publication_matched() or on_subscription_matched() is made with a
495+
* current_count_change different than 1 or -1, or if the total number of calls with current_count_change equal to 1
496+
* is different than the total number of calls with current_count_change equal to -1.
497+
*/
498+
TEST(DDSDiscovery, MatchedCallbackListenerMultithread)
499+
{
500+
constexpr size_t NUM_THREADS = 25;
501+
502+
struct TestListener
503+
: public eprosima::fastdds::dds::DataReaderListener
504+
, public eprosima::fastdds::dds::DataWriterListener
505+
{
506+
std::atomic<uint32_t> reader_plus_one_calls{ 0 };
507+
std::atomic<uint32_t> reader_minus_one_calls{ 0 };
508+
std::atomic<uint32_t> reader_other_calls{ 0 };
509+
std::atomic<uint32_t> reader_total_calls{ 0 };
510+
511+
std::atomic<uint32_t> writer_plus_one_calls{ 0 };
512+
std::atomic<uint32_t> writer_minus_one_calls{ 0 };
513+
std::atomic<uint32_t> writer_other_calls{ 0 };
514+
std::atomic<uint32_t> writer_total_calls{ 0 };
515+
516+
void on_publication_matched(
517+
eprosima::fastdds::dds::DataWriter*,
518+
const eprosima::fastdds::dds::PublicationMatchedStatus& info) override
519+
{
520+
if (info.current_count_change == 1)
521+
{
522+
++writer_plus_one_calls;
523+
}
524+
else if (info.current_count_change == -1)
525+
{
526+
++writer_minus_one_calls;
527+
}
528+
else
529+
{
530+
++writer_other_calls;
531+
}
532+
533+
++writer_total_calls;
534+
}
535+
536+
void on_subscription_matched(
537+
eprosima::fastdds::dds::DataReader*,
538+
const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) override
539+
{
540+
if (info.current_count_change == 1)
541+
{
542+
++reader_plus_one_calls;
543+
}
544+
else if (info.current_count_change == -1)
545+
{
546+
++reader_minus_one_calls;
547+
}
548+
else
549+
{
550+
++reader_other_calls;
551+
}
552+
553+
++reader_total_calls;
554+
}
555+
556+
};
557+
558+
std::ostringstream t;
559+
t << TEST_TOPIC_NAME << "_" << asio::ip::host_name() << "_" << GET_PID();
560+
std::string topic_name = t.str();
561+
TestListener listener;
562+
eprosima::fastdds::dds::TypeSupport type(new HelloWorldPubSubType());
563+
564+
auto create_entities = [&listener, &topic_name, &type]()
565+
{
566+
using namespace eprosima::fastdds::dds;
567+
568+
uint32_t domain_id = static_cast<uint32_t>(GET_PID()) % 100;
569+
auto factory = DomainParticipantFactory::get_shared_instance();
570+
DomainParticipantQos participant_qos;
571+
factory->get_default_participant_qos(participant_qos);
572+
participant_qos.setup_transports(eprosima::fastdds::rtps::BuiltinTransports::UDPv4);
573+
participant_qos.wire_protocol().builtin.discovery_config.leaseDuration.seconds = 0;
574+
participant_qos.wire_protocol().builtin.discovery_config.leaseDuration.nanosec = 100000000;
575+
participant_qos.wire_protocol().builtin.discovery_config.leaseDuration_announcementperiod.seconds = 0;
576+
participant_qos.wire_protocol().builtin.discovery_config.leaseDuration_announcementperiod.nanosec =
577+
50000000;
578+
579+
auto participant = factory->create_participant(domain_id, participant_qos);
580+
ASSERT_NE(participant, nullptr);
581+
582+
type.register_type(participant);
583+
auto topic = participant->create_topic(topic_name, type.get_type_name(), TOPIC_QOS_DEFAULT);
584+
ASSERT_NE(topic, nullptr);
585+
586+
auto publisher = participant->create_publisher(PUBLISHER_QOS_DEFAULT);
587+
ASSERT_NE(publisher, nullptr);
588+
589+
DataWriterQos datawriter_qos;
590+
publisher->get_default_datawriter_qos(datawriter_qos);
591+
datawriter_qos.data_sharing().off();
592+
auto datawriter = publisher->create_datawriter(topic, datawriter_qos, &listener);
593+
ASSERT_NE(datawriter, nullptr);
594+
595+
auto subscriber = participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
596+
ASSERT_NE(subscriber, nullptr);
597+
598+
DataReaderQos datareader_qos;
599+
subscriber->get_default_datareader_qos(datareader_qos);
600+
datareader_qos.data_sharing().off();
601+
auto datareader = subscriber->create_datareader(topic, datareader_qos, &listener);
602+
ASSERT_NE(datareader, nullptr);
603+
604+
HelloWorld msg;
605+
msg.index(1);
606+
datawriter->write(&msg);
607+
608+
SampleInfo info;
609+
datareader->take_next_sample(&msg, &info);
610+
611+
participant->delete_contained_entities();
612+
factory->delete_participant(participant);
613+
614+
std::this_thread::sleep_for(std::chrono::milliseconds(200));
615+
};
616+
617+
std::vector<std::thread> threads;
618+
for (int i = 0; i < NUM_THREADS; ++i)
619+
{
620+
threads.emplace_back(create_entities);
621+
}
622+
623+
for (auto& thread : threads)
624+
{
625+
thread.join();
626+
}
627+
628+
std::cout << "Reader +1 calls: " << listener.reader_plus_one_calls.load() << std::endl;
629+
std::cout << "Reader -1 calls: " << listener.reader_minus_one_calls.load() << std::endl;
630+
std::cout << "Reader other calls: " << listener.reader_other_calls.load() << std::endl;
631+
std::cout << "Reader total calls: " << listener.reader_total_calls.load() << std::endl;
632+
633+
std::cout << "Writer +1 calls: " << listener.writer_plus_one_calls.load() << std::endl;
634+
std::cout << "Writer -1 calls: " << listener.writer_minus_one_calls.load() << std::endl;
635+
std::cout << "Writer other calls: " << listener.writer_other_calls.load() << std::endl;
636+
std::cout << "Writer total calls: " << listener.writer_total_calls.load() << std::endl;
637+
638+
639+
EXPECT_EQ(listener.reader_other_calls.load(), 0u);
640+
EXPECT_EQ(listener.writer_other_calls.load(), 0u);
641+
EXPECT_GE(listener.reader_plus_one_calls.load(), listener.reader_minus_one_calls.load());
642+
EXPECT_GE(listener.writer_plus_one_calls.load(), listener.writer_minus_one_calls.load());
643+
}
644+
486645
TEST(DDSDiscovery, EndpointMatchingCallbackAlwaysTrue)
487646
{
488647
using namespace std::chrono_literals;

0 commit comments

Comments
 (0)