diff --git a/docs/code/StatisticsBackendTests.cpp b/docs/code/StatisticsBackendTests.cpp index 19efef9c2..3152c25fd 100644 --- a/docs/code/StatisticsBackendTests.cpp +++ b/docs/code/StatisticsBackendTests.cpp @@ -38,23 +38,54 @@ void init_monitor_examples() { { //CONF-INIT-MONITOR-EXAMPLE - // Init a monitor in DDS domain 0 with no listener associated - EntityId domain_monitor_id = StatisticsBackend::init_monitor(0); + // Init a monitor in DDS domain 0 with no listener associated. + EntityId domain_monitor_id = + StatisticsBackend::init_monitor(0); // Init a monitor for a Fast DDS Discovery Server network which server is located in IPv4 - // address 127.0.0.1 and port 11811. The monitor has no listener associated - EntityId disc_server_monitor_id = StatisticsBackend::init_monitor("127.0.0.1:11811"); + // address 127.0.0.1 and port 11811, and that uses the default GUID prefix + // eprosima::fastdds::rtps::DEFAULT_ROS2_SERVER_GUIDPREFIX. + // The monitor has no listener associated. + EntityId disc_server_monitor_id = + StatisticsBackend::init_monitor("127.0.0.1:11811"); + + // Init a monitor for a Fast DDS Discovery Server network which serveris located in IPv4 + // address 127.0.0.1 and port 11811, and that uses the GUID prefix + // "44.53.01.5f.45.50.52.4f.53.49.4d.41". + // The monitor has no listener associated. + EntityId disc_server_prefix_monitor_id = + StatisticsBackend::init_monitor("44.53.01.5f.45.50.52.4f.53.49.4d.41", "127.0.0.1:11811"); //!-- static_cast(domain_monitor_id); static_cast(disc_server_monitor_id); + static_cast(disc_server_prefix_monitor_id); } { //CONF-INIT-MONITOR-LISTENER-EXAMPLE - // Init a monitor in DDS domain 0 with a custom listener CustomDomainListener domain_listener; - EntityId domain_monitor_id = StatisticsBackend::init_monitor(0, &domain_listener); + + // Init a monitor in DDS domain 0 with a custom listener. + EntityId domain_monitor_id = + StatisticsBackend::init_monitor(0, &domain_listener); + + // Init a monitor for a Fast DDS Discovery Server network which server is located in IPv4 + // address 127.0.0.1 and port 11811, and that uses the default GUID prefix + // eprosima::fastdds::rtps::DEFAULT_ROS2_SERVER_GUIDPREFIX. + // The monitor uses a custom listener. + EntityId disc_server_monitor_id = + StatisticsBackend::init_monitor("127.0.0.1:11811", &domain_listener); + + // Init a monitor for a Fast DDS Discovery Server network which serveris located in IPv4 + // address 127.0.0.1 and port 11811, and that uses the GUID prefix + // "44.53.01.5f.45.50.52.4f.53.49.4d.41". + // The monitor uses a custom listener. + EntityId disc_server_prefix_monitor_id = + StatisticsBackend::init_monitor("44.53.01.5f.45.50.52.4f.53.49.4d.41", "127.0.0.1:11811", + &domain_listener); //!-- static_cast(domain_monitor_id); + static_cast(disc_server_monitor_id); + static_cast(disc_server_prefix_monitor_id); } { //CONF-INIT-MONITOR-MASKS-EXAMPLE @@ -64,11 +95,30 @@ void init_monitor_examples() // Only get notificiations about network latency or subscription throughput DataKindMask datakind_mask = DataKind::NETWORK_LATENCY | DataKind::SUBSCRIPTION_THROUGHPUT; - // Init a monitor in DDS domain 0 with a custom listener, a CallbackMask, and a DataKindMask CustomDomainListener domain_listener; - EntityId domain_monitor_id = StatisticsBackend::init_monitor(0, &domain_listener, callback_mask, datakind_mask); + + // Init a monitor in DDS domain 0 with a custom listener, a CallbackMask, and a DataKindMask + EntityId domain_monitor_id = + StatisticsBackend::init_monitor(0, &domain_listener, callback_mask, datakind_mask); + + // Init a monitor for a Fast DDS Discovery Server network which server is located in IPv4 + // address 127.0.0.1 and port 11811, and that uses the default GUID prefix + // eprosima::fastdds::rtps::DEFAULT_ROS2_SERVER_GUIDPREFIX. + // The monitor uses a custom listener, a CallbackMask, and a DataKindMask. + EntityId disc_server_monitor_id = + StatisticsBackend::init_monitor("127.0.0.1:11811", &domain_listener, callback_mask, datakind_mask); + + // Init a monitor for a Fast DDS Discovery Server network which serveris located in IPv4 + // address 127.0.0.1 and port 11811, and that uses the GUID prefix + // "44.53.01.5f.45.50.52.4f.53.49.4d.41". + // The monitor uses a custom listener, a CallbackMask, and a DataKindMask. + EntityId disc_server_prefix_monitor_id = + StatisticsBackend::init_monitor("44.53.01.5f.45.50.52.4f.53.49.4d.41", "127.0.0.1:11811", + &domain_listener, callback_mask, datakind_mask); //!-- static_cast(domain_monitor_id); + static_cast(disc_server_monitor_id); + static_cast(disc_server_prefix_monitor_id); } } diff --git a/docs/rst/statistics_backend/init_monitor.rst b/docs/rst/statistics_backend/init_monitor.rst index 2ffb95891..cbdb87e5e 100644 --- a/docs/rst/statistics_backend/init_monitor.rst +++ b/docs/rst/statistics_backend/init_monitor.rst @@ -9,7 +9,7 @@ Initializing a monitor on a certain Domain ID makes *eProsima Fast DDS Statistic start monitoring the statistics data and entity discoveries on that domain. No statistics data will be gathered unless there is a monitor initialized in the required domain. -|StatisticsBackend-api| provides two overloads of |init_monitor-api| that can be used to start a monitorization on a +|StatisticsBackend-api| provides three overloads of |init_monitor-api| that can be used to start a monitorization on a DDS domain or a *Fast DDS* Discovery Server network. .. literalinclude:: /code/StatisticsBackendTests.cpp @@ -18,10 +18,6 @@ DDS domain or a *Fast DDS* Discovery Server network. :end-before: //! :dedent: 8 -.. warning:: - Initializing a monitor for a discovery server configuration is currently not supported. - It will be implemented on a future release of *Fast DDS Statistics Backend*. - Furthermore, it is possible to initialize a monitor with a custom |DomainListener-api|. Please refer to :ref:`listeners_domain_listener` for more information about the ``DomainListener`` and its functionality. diff --git a/include/fastdds_statistics_backend/StatisticsBackend.hpp b/include/fastdds_statistics_backend/StatisticsBackend.hpp index 3ddc1b545..f5d3be082 100644 --- a/include/fastdds_statistics_backend/StatisticsBackend.hpp +++ b/include/fastdds_statistics_backend/StatisticsBackend.hpp @@ -79,19 +79,56 @@ class FASTDDS_STATISTICS_BACKEND_DllAPI StatisticsBackend DataKindMask data_mask = DataKindMask::none()); /** - * @brief Starts monitoring the domain corresponding to a server. + * @brief Starts monitoring the network corresponding to a server. * * This function creates a new statistics DomainParticipant that starts monitoring - * the domain of the server with the given locator. + * the network of the server with the given locators. + * The server \c GuidPrefix_t is set to the default one: \c eprosima::fastdds::rtps::DEFAULT_ROS2_SERVER_GUIDPREFIX. + * If any other server is to be used, call the overload method that receives the \c GuidPrefix_t as parameter. + * + * The format to specify a locator is: kind:[IP]:port, where: + * * \b kind is one of { \c UDPv4, \c TCPv4, \c UDPv6, \c TCPv4 } + * * \b IP is the IP address + * * \b port is the IP port + * Note that \c SHM locators are not supported. For any server configured with shared memory locators, + * initialize the monitor using only the non shared memory locators. + * + * @param discovery_server_locators The locator list of the server whose network is to be monitored, + * formatted as a semicolon separated list of locators. + * @param domain_listener Listener with the callback to use to inform of events. + * @param callback_mask Mask of the callbacks. Only the events that have the mask bit set will be informed. + * @param data_mask Mask of the data types that will be monitored. + * @return The ID of the created statistics Domain. + */ + static EntityId init_monitor( + std::string discovery_server_locators, + DomainListener* domain_listener = nullptr, + CallbackMask callback_mask = CallbackMask::all(), + DataKindMask data_mask = DataKindMask::none()); + + /** + * @brief Starts monitoring the network corresponding to a server. * - * @param discovery_server_locators The locator of the server whose domain is to be monitored, - * formatted as "IPV4address:port". + * This function creates a new statistics DomainParticipant that starts monitoring + * the network of the server with the given \c GuidPrefix_t and with the given locators. + * + * The format to specify a locator is: kind:[IP]:port, where: + * * \b kind is one of { \c UDPv4, \c TCPv4, \c UDPv6, \c TCPv4 } + * * \b IP is the IP address + * * \b port is the IP port + * Note that \c SHM locators are not supported. For any server configured with shared memory locators, + * initialize the monitor using only the non shared memory locators. + * + * @param discovery_server_guid_prefix Server \c GuidPrefix_t to be monitored. + * @param discovery_server_locators The locator list of the server whose network is to be monitored, + * formatted as a semicolon separated list of locators. * @param domain_listener Listener with the callback to use to inform of events. * @param callback_mask Mask of the callbacks. Only the events that have the mask bit set will be informed. * @param data_mask Mask of the data types that will be monitored. * @return The ID of the created statistics Domain. */ static EntityId init_monitor( + std::string discovery_server_guid_prefix, std::string discovery_server_locators, DomainListener* domain_listener = nullptr, CallbackMask callback_mask = CallbackMask::all(), diff --git a/src/cpp/StatisticsBackend.cpp b/src/cpp/StatisticsBackend.cpp index 1079d934c..b4ca20272 100644 --- a/src/cpp/StatisticsBackend.cpp +++ b/src/cpp/StatisticsBackend.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -31,9 +32,13 @@ #include #include #include +#include +#include +#include #include #include #include +#include #include #include @@ -49,6 +54,7 @@ #include "detail/data_aggregation.hpp" using namespace eprosima::fastdds::dds; +using namespace eprosima::fastdds::rtps; using namespace eprosima::fastdds::statistics; namespace eprosima { @@ -87,6 +93,7 @@ void find_or_create_topic_and_type( { if (topic_desc->get_type_name() != type->getName()) { + details::StatisticsBackendData::get_instance()->unlock(); throw Error(topic_name + " is not using expected type " + type->getName() + " and is using instead type " + topic_desc->get_type_name()); } @@ -98,6 +105,7 @@ void find_or_create_topic_and_type( catch (const std::bad_cast& e) { // TODO[ILG]: Could we support other TopicDescription types in this context? + details::StatisticsBackendData::get_instance()->unlock(); throw Error(topic_name + " is already used but is not a simple Topic: " + e.what()); } @@ -107,6 +115,7 @@ void find_or_create_topic_and_type( if (ReturnCode_t::RETCODE_PRECONDITION_NOT_MET == monitor->participant->register_type(type, type->getName())) { // Name already in use + details::StatisticsBackendData::get_instance()->unlock(); throw Error(std::string("Type name ") + type->getName() + " is already in use"); } monitor->topics[topic_name] = @@ -163,48 +172,19 @@ void register_statistics_type_and_topic( } } -void StatisticsBackend::set_physical_listener( - PhysicalListener* listener, - CallbackMask callback_mask, - DataKindMask data_mask) -{ - details::StatisticsBackendData::get_instance()->lock(); - details::StatisticsBackendData::get_instance()->physical_listener_ = listener; - details::StatisticsBackendData::get_instance()->physical_callback_mask_ = callback_mask; - details::StatisticsBackendData::get_instance()->physical_data_mask_ = data_mask; - details::StatisticsBackendData::get_instance()->unlock(); -} - -void StatisticsBackend::set_domain_listener( - EntityId monitor_id, - DomainListener* listener, - CallbackMask callback_mask, - DataKindMask data_mask) -{ - auto monitor = details::StatisticsBackendData::get_instance()->monitors_by_entity_.find(monitor_id); - if (monitor == details::StatisticsBackendData::get_instance()->monitors_by_entity_.end()) - { - throw BadParameter("There is no monitor with the given ID"); - } - - monitor->second->domain_listener = listener; - monitor->second->domain_callback_mask = callback_mask; - monitor->second->data_mask = data_mask; -} - -EntityId StatisticsBackend::init_monitor( - DomainId domain_id, +EntityId create_and_register_monitor( + const std::string& domain_name, DomainListener* domain_listener, - CallbackMask callback_mask, - DataKindMask data_mask) + const CallbackMask& callback_mask, + const DataKindMask& data_mask, + const DomainParticipantQos& participant_qos, + const DomainId domain_id = 0) { details::StatisticsBackendData::get_instance()->lock(); /* Create monitor instance and register it in the database */ std::shared_ptr monitor = std::make_shared(); - std::stringstream domain_name; - domain_name << domain_id; - std::shared_ptr domain = std::make_shared(domain_name.str()); + std::shared_ptr domain = std::make_shared(domain_name); try { domain->id = details::StatisticsBackendData::get_instance()->database_->insert(domain); @@ -230,16 +210,6 @@ EntityId StatisticsBackend::init_monitor( details::StatisticsBackendData::get_instance()->data_queue_); /* Create DomainParticipant */ - DomainParticipantQos participant_qos = DomainParticipantFactory::get_instance()->get_default_participant_qos(); - /* Previous string conversion is needed for string_255 */ - std::string participant_name = "monitor_domain_" + std::to_string(domain_id); - participant_qos.name(participant_name); - /* Avoid using SHM transport by default */ - std::shared_ptr udp_transport = - std::make_shared(); - participant_qos.transport().user_transports.push_back(udp_transport); - participant_qos.transport().use_builtin_transports = false; - StatusMask participant_mask = StatusMask::all(); participant_mask ^= StatusMask::data_on_readers(); monitor->participant = DomainParticipantFactory::get_instance()->create_participant( @@ -295,6 +265,60 @@ EntityId StatisticsBackend::init_monitor( return domain->id; } +void StatisticsBackend::set_physical_listener( + PhysicalListener* listener, + CallbackMask callback_mask, + DataKindMask data_mask) +{ + details::StatisticsBackendData::get_instance()->lock(); + details::StatisticsBackendData::get_instance()->physical_listener_ = listener; + details::StatisticsBackendData::get_instance()->physical_callback_mask_ = callback_mask; + details::StatisticsBackendData::get_instance()->physical_data_mask_ = data_mask; + details::StatisticsBackendData::get_instance()->unlock(); +} + +void StatisticsBackend::set_domain_listener( + EntityId monitor_id, + DomainListener* listener, + CallbackMask callback_mask, + DataKindMask data_mask) +{ + auto monitor = details::StatisticsBackendData::get_instance()->monitors_by_entity_.find(monitor_id); + if (monitor == details::StatisticsBackendData::get_instance()->monitors_by_entity_.end()) + { + throw BadParameter("There is no monitor with the given ID"); + } + + monitor->second->domain_listener = listener; + monitor->second->domain_callback_mask = callback_mask; + monitor->second->data_mask = data_mask; +} + +EntityId StatisticsBackend::init_monitor( + DomainId domain_id, + DomainListener* domain_listener, + CallbackMask callback_mask, + DataKindMask data_mask) +{ + /* Set domain_name */ + std::stringstream domain_name; + domain_name << domain_id; + + /* Set DomainParticipantQoS */ + DomainParticipantQos participant_qos = DomainParticipantFactory::get_instance()->get_default_participant_qos(); + /* Previous string conversion is needed for string_255 */ + std::string participant_name = "monitor_domain_" + std::to_string(domain_id); + participant_qos.name(participant_name); + /* Avoid using SHM transport by default */ + std::shared_ptr udp_transport = + std::make_shared(); + participant_qos.transport().user_transports.push_back(udp_transport); + participant_qos.transport().use_builtin_transports = false; + + return create_and_register_monitor(domain_name.str(), domain_listener, callback_mask, data_mask, participant_qos, + domain_id); +} + void StatisticsBackend::stop_monitor( EntityId monitor_id) { @@ -340,11 +364,63 @@ EntityId StatisticsBackend::init_monitor( CallbackMask callback_mask, DataKindMask data_mask) { - static_cast(discovery_server_locators); - static_cast(domain_listener); - static_cast(callback_mask); - static_cast(data_mask); - return EntityId(); + return init_monitor(DEFAULT_ROS2_SERVER_GUIDPREFIX, discovery_server_locators, domain_listener, callback_mask, + data_mask); +} + +EntityId StatisticsBackend::init_monitor( + std::string discovery_server_guid_prefix, + std::string discovery_server_locators, + DomainListener* domain_listener, + CallbackMask callback_mask, + DataKindMask data_mask) +{ + /* Set DomainParticipantQoS */ + DomainParticipantQos participant_qos = DomainParticipantFactory::get_instance()->get_default_participant_qos(); + participant_qos.name("monitor_discovery_server_" + discovery_server_guid_prefix); + + /* Avoid using SHM transport by default */ + std::shared_ptr udp_transport = + std::make_shared(); + participant_qos.transport().user_transports.push_back(udp_transport); + participant_qos.transport().use_builtin_transports = false; + + participant_qos.wire_protocol().builtin.discovery_config.discoveryProtocol = + eprosima::fastrtps::rtps::DiscoveryProtocol_t::SUPER_CLIENT; + RemoteServerAttributes server; + // Set the server guidPrefix + server.ReadguidPrefix(discovery_server_guid_prefix.c_str()); + // Add locators + std::stringstream locators(discovery_server_locators); + std::string locator_str; + while (std::getline(locators, locator_str, ';')) + { + std::stringstream ss(locator_str); + eprosima::fastrtps::rtps::Locator_t locator; + ss >> locator; + if (!IsLocatorValid(locator) || !IsAddressDefined(locator) || ss.rdbuf()->in_avail() != 0) + { + throw BadParameter("Invalid locator format: " + locator_str); + } + if (locator.port > std::numeric_limits::max()) + { + throw BadParameter(locator.port + " is out of range"); + } + + // Check unicast/multicast address + if (eprosima::fastrtps::rtps::IPLocator::isMulticast(locator)) + { + server.metatrafficMulticastLocatorList.push_back(locator); + } + else + { + server.metatrafficUnicastLocatorList.push_back(locator); + } + } + participant_qos.wire_protocol().builtin.discovery_config.m_DiscoveryServers.push_back(server); + + return create_and_register_monitor(discovery_server_guid_prefix, domain_listener, callback_mask, data_mask, + participant_qos); } void StatisticsBackend::restart_monitor( diff --git a/test/unittest/StatisticsBackend/CMakeLists.txt b/test/unittest/StatisticsBackend/CMakeLists.txt index 4d11e2f53..1aca858d7 100644 --- a/test/unittest/StatisticsBackend/CMakeLists.txt +++ b/test/unittest/StatisticsBackend/CMakeLists.txt @@ -312,6 +312,7 @@ set(INIT_MONITOR_TEST_LIST init_monitor_domain_id_null_listener_all_data init_monitor_several_monitors init_monitor_twice + init_server_monitor_several_locators stop_monitor init_monitor_check_participant_name init_monitor_check_participant_transport @@ -379,6 +380,12 @@ set(INIT_MONITOR_TEST_LIST init_monitor_register_type_fails init_monitor_topic_exists init_monitor_topic_exists_with_another_type + init_monitor_invalid_ipv4 + init_monitor_invalid_ipv6 + init_monitor_invalid_port + init_monitor_port_out_of_range + init_monitor_unsupported_shm + init_monitor_extra_characters ) foreach(test_name ${INIT_MONITOR_TEST_LIST}) diff --git a/test/unittest/StatisticsBackend/InitMonitorFactoryFailsTests.cpp b/test/unittest/StatisticsBackend/InitMonitorFactoryFailsTests.cpp index 659d261ac..700a5d6e1 100644 --- a/test/unittest/StatisticsBackend/InitMonitorFactoryFailsTests.cpp +++ b/test/unittest/StatisticsBackend/InitMonitorFactoryFailsTests.cpp @@ -205,6 +205,50 @@ class init_monitor_factory_fails_tests : public ::testing::Test EXPECT_CALL(subscriber_, create_datareader(_, _, _, _)).Times(AnyNumber()); } + void check_init_monitor_failure() + { + DomainId domain_id = 0; + DomainListener domain_listener; + std::string server_guid_prefix = "44.53.01.5f.45.50.52.4f.53.49.4d.41"; + std::string server_locators = "UDPv4:[127.0.0.1]:11811"; + + EXPECT_THROW(StatisticsBackend::init_monitor( + domain_id, + &domain_listener, + all_callback_mask_, + all_datakind_mask_), Error); + EXPECT_THROW(StatisticsBackend::init_monitor( + server_locators, + &domain_listener, + all_callback_mask_, + all_datakind_mask_), Error); + EXPECT_THROW(StatisticsBackend::init_monitor( + server_guid_prefix, + server_locators, + &domain_listener, + all_callback_mask_, + all_datakind_mask_), Error); + } + + void check_init_monitor_discovery_server_failure( + const std::string& server_locators) + { + DomainListener domain_listener; + std::string server_guid_prefix = "44.53.01.5f.45.50.52.4f.53.49.4d.41"; + + EXPECT_THROW(StatisticsBackend::init_monitor( + server_locators, + &domain_listener, + all_callback_mask_, + all_datakind_mask_), BadParameter); + EXPECT_THROW(StatisticsBackend::init_monitor( + server_guid_prefix, + server_locators, + &domain_listener, + all_callback_mask_, + all_datakind_mask_), BadParameter); + } + ~init_monitor_factory_fails_tests() { // Clear memory @@ -222,54 +266,33 @@ constexpr const DataKind init_monitor_factory_fails_tests::all_data_kinds_[]; TEST_F(init_monitor_factory_fails_tests, init_monitor_participant_creation_fails) { - DomainId domain_id = 0; - DomainListener domain_listener; - // Expect failure on the participant creation - EXPECT_CALL(*domain_participant_factory_, create_participant(_, _, _, _)).Times(1) - .WillOnce(Return(nullptr)); - ASSERT_THROW(StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - all_callback_mask_, - all_datakind_mask_), Error); + EXPECT_CALL(*domain_participant_factory_, create_participant(_, _, _, _)).Times(3) + .WillRepeatedly(Return(nullptr)); + + check_init_monitor_failure(); } TEST_F(init_monitor_factory_fails_tests, init_monitor_subscriber_creation_fails) { - DomainId domain_id = 0; - DomainListener domain_listener; - // Expect failure on the subscriber creation - EXPECT_CALL(domain_participant_, create_subscriber(_, _, _)).Times(1) - .WillOnce(Return(nullptr)); - EXPECT_THROW(StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - all_callback_mask_, - all_datakind_mask_), Error); + EXPECT_CALL(domain_participant_, create_subscriber(_, _, _)).Times(3) + .WillRepeatedly(Return(nullptr)); + + check_init_monitor_failure(); } TEST_F(init_monitor_factory_fails_tests, init_monitor_datareader_creation_fails) { - DomainId domain_id = 0; - DomainListener domain_listener; - // Expect failure on the datareader creation - EXPECT_CALL(subscriber_, create_datareader(_, _, _, _)).Times(1) - .WillOnce(Return(nullptr)); - EXPECT_THROW(StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - all_callback_mask_, - all_datakind_mask_), Error); + EXPECT_CALL(subscriber_, create_datareader(_, _, _, _)).Times(3) + .WillRepeatedly(Return(nullptr)); + + check_init_monitor_failure(); } TEST_F(init_monitor_factory_fails_tests, init_monitor_topic_creation_fails) { - DomainId domain_id = 0; - DomainListener domain_listener; - // Expect failure on the topic creation // We need to cover all parameter cases to be implementation agnostic ON_CALL(domain_participant_, create_topic(_, _, _, _, _)) @@ -278,32 +301,25 @@ TEST_F(init_monitor_factory_fails_tests, init_monitor_topic_creation_fails) .WillByDefault(Return(nullptr)); ON_CALL(domain_participant_, create_topic(_, _, _)) .WillByDefault(Return(nullptr)); - EXPECT_THROW(StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - all_callback_mask_, - all_datakind_mask_), Error); + + check_init_monitor_failure(); } TEST_F(init_monitor_factory_fails_tests, init_monitor_register_type_fails) { - DomainId domain_id = 0; - DomainListener domain_listener; - // Expect failure on the type registration ON_CALL(domain_participant_, register_type(_, _)) .WillByDefault(Return(eprosima::fastrtps::types::ReturnCode_t::RETCODE_PRECONDITION_NOT_MET)); - EXPECT_THROW(StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - all_callback_mask_, - all_datakind_mask_), Error); + + check_init_monitor_failure(); } TEST_F(init_monitor_factory_fails_tests, init_monitor_topic_exists) { DomainId domain_id = 0; DomainListener domain_listener; + std::string server_guid_prefix = "44.53.01.5f.45.50.52.4f.53.49.4d.41"; + std::string server_locators = "UDPv4:[127.0.0.1]:11811"; for (auto topic_type : topic_types_) { @@ -322,21 +338,68 @@ TEST_F(init_monitor_factory_fails_tests, init_monitor_topic_exists) &domain_listener, all_callback_mask_, all_datakind_mask_)); + EXPECT_NO_THROW(StatisticsBackend::init_monitor( + server_locators, + &domain_listener, + all_callback_mask_, + all_datakind_mask_)); + EXPECT_NO_THROW(StatisticsBackend::init_monitor( + server_guid_prefix, + server_locators, + &domain_listener, + all_callback_mask_, + all_datakind_mask_)); } TEST_F(init_monitor_factory_fails_tests, init_monitor_topic_exists_with_another_type) { - DomainId domain_id = 0; - DomainListener domain_listener; - Topic topic("custom_topic", "custom_type"); ON_CALL(domain_participant_, lookup_topicdescription(_)) .WillByDefault(Return(&topic)); - EXPECT_THROW(StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - all_callback_mask_, - all_datakind_mask_), Error); + + check_init_monitor_failure(); +} + +TEST_F(init_monitor_factory_fails_tests, init_monitor_invalid_ipv4) +{ + std::string server_locators = "UDPv4:[192.356.0.1]:11811"; + + check_init_monitor_discovery_server_failure(server_locators); +} + +TEST_F(init_monitor_factory_fails_tests, init_monitor_invalid_ipv6) +{ + std::string server_locators = "UDPv6:[::0:G5a]:11811"; + + check_init_monitor_discovery_server_failure(server_locators); +} + +TEST_F(init_monitor_factory_fails_tests, init_monitor_invalid_port) +{ + std::string server_locators = "UDPv4:[192.356.0.1]:-11811"; + + check_init_monitor_discovery_server_failure(server_locators); +} + +TEST_F(init_monitor_factory_fails_tests, init_monitor_port_out_of_range) +{ + std::string server_locators = "UDPv4:[192.356.0.1]:4294967296"; + + check_init_monitor_discovery_server_failure(server_locators); +} + +TEST_F(init_monitor_factory_fails_tests, init_monitor_unsupported_shm) +{ + std::string server_locators = "SHM:[_]:11815"; + + check_init_monitor_discovery_server_failure(server_locators); +} + +TEST_F(init_monitor_factory_fails_tests, init_monitor_extra_characters) +{ + std::string server_locators = "UDPv4:[192.356.0.1]:1181:ABC"; + + check_init_monitor_discovery_server_failure(server_locators); } int main( diff --git a/test/unittest/StatisticsBackend/InitMonitorTests.cpp b/test/unittest/StatisticsBackend/InitMonitorTests.cpp index 3c4d4ced5..19c6339b1 100644 --- a/test/unittest/StatisticsBackend/InitMonitorTests.cpp +++ b/test/unittest/StatisticsBackend/InitMonitorTests.cpp @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -41,7 +44,9 @@ using namespace eprosima::statistics_backend; using namespace eprosima::fastdds::dds; +using namespace eprosima::fastdds::rtps; using namespace eprosima::fastdds::statistics; +using namespace eprosima::fastrtps::rtps; class init_monitor_tests : public ::testing::Test @@ -139,8 +144,121 @@ class init_monitor_tests : public ::testing::Test details::StatisticsBackendData::reset_instance(); } + std::map> init_monitors( + DomainId domain_id, + DomainListener* domain_listener, + const std::string& server_guid_prefix, + const std::string& server_locators, + const CallbackMask& callback_mask, + const DataKindMask& datakind_mask) + { + EntityId monitor_id = StatisticsBackend::init_monitor( + domain_id, + domain_listener, + callback_mask, + datakind_mask); + EntityId monitor_id_1 = StatisticsBackend::init_monitor( + server_locators, + domain_listener, + callback_mask, + datakind_mask); + EntityId monitor_id_2 = StatisticsBackend::init_monitor( + server_guid_prefix, + server_locators, + domain_listener, + callback_mask, + datakind_mask); + + EXPECT_TRUE(monitor_id.is_valid()); + EXPECT_TRUE(monitor_id_1.is_valid()); + EXPECT_TRUE(monitor_id_2.is_valid()); + + auto domain_monitors = details::StatisticsBackendData::get_instance()->monitors_by_entity_; + + /* Check that three monitors are created */ + EXPECT_EQ(domain_monitors.size(), 3); + + return domain_monitors; + } + + void check_locator( + const RemoteServerAttributes& server_qos, + int32_t kind, + const std::string& address, + uint32_t port, + bool is_unicast = true) + { + // Build the locator + Locator_t locator(kind, port); + if (kind == LOCATOR_KIND_UDPv4 || kind == LOCATOR_KIND_TCPv4) + { + IPLocator::setIPv4(locator, address); + } + else if (kind == LOCATOR_KIND_UDPv6 || kind == LOCATOR_KIND_TCPv6) + { + IPLocator::setIPv6(locator, address); + } + else + { + FAIL() << "Invalid locator kind"; + } + + // Look for it + if (is_unicast) + { + EXPECT_NE(std::find(server_qos.metatrafficUnicastLocatorList.begin(), + server_qos.metatrafficUnicastLocatorList.end(), locator), + server_qos.metatrafficUnicastLocatorList.end()); + } + else + { + EXPECT_NE(std::find(server_qos.metatrafficMulticastLocatorList.begin(), + server_qos.metatrafficMulticastLocatorList.end(), locator), + server_qos.metatrafficMulticastLocatorList.end()); + } + } + + void check_participant_qos( + const DomainParticipantQos& participant_qos, + const std::string& server_guid_prefix) + { + EXPECT_EQ(participant_qos.wire_protocol().builtin.discovery_config.discoveryProtocol, + eprosima::fastrtps::rtps::DiscoveryProtocol_t::SUPER_CLIENT); + + RemoteServerAttributes server_qos = + participant_qos.wire_protocol().builtin.discovery_config.m_DiscoveryServers.front(); + GuidPrefix_t guid_prefix; + std::istringstream(server_guid_prefix) >> guid_prefix; + EXPECT_EQ(server_qos.guidPrefix, guid_prefix); + + check_locator(server_qos, LOCATOR_KIND_UDPv4, "127.0.0.1", 11811); + } + + void check_dds_entities( + const std::shared_ptr monitor, + const std::string& server_guid_prefix = "") + { + EXPECT_NE(nullptr, monitor->participant); + + if (!server_guid_prefix.empty()) + { + DomainParticipantQos participant_qos; + monitor->participant->get_qos(participant_qos); + check_participant_qos(participant_qos, server_guid_prefix); + } + + EXPECT_NE(nullptr, monitor->subscriber); + + for (auto topic : topic_types_) + { + EXPECT_NE(nullptr, monitor->topics[topic.first]); + EXPECT_NE(nullptr, monitor->readers[topic.first]); + } + } + }; + constexpr const CallbackKind init_monitor_tests::all_callback_kinds_[]; constexpr const DataKind init_monitor_tests::all_data_kinds_[]; @@ -148,183 +266,171 @@ TEST_F(init_monitor_tests, init_monitor_domain_id_all_callback_all_data) { DomainId domain_id = 0; DomainListener domain_listener; + std::string server_guid_prefix = "44.53.01.5f.45.50.52.4f.53.49.4d.41"; + std::string server_locators = "UDPv4:[127.0.0.1]:11811"; - EntityId monitor_id = StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - all_callback_mask_, - all_datakind_mask_); - - EXPECT_TRUE(monitor_id.is_valid()); - - auto domain_monitors = details::StatisticsBackendData::get_instance()->monitors_by_entity_; + auto domain_monitors = init_monitors(domain_id, &domain_listener, server_guid_prefix, server_locators, + all_callback_mask_, all_datakind_mask_); - /* Check that only one monitor is created */ - EXPECT_EQ(domain_monitors.size(), 1); + std::vector monitor_ids; + for (const auto& monitor : domain_monitors) + { + /* Check that the domain listener is set correctly */ + EXPECT_EQ(&domain_listener, domain_monitors[monitor.first]->domain_listener); - /* Check that the domain listener is set correctly */ - EXPECT_EQ(&domain_listener, domain_monitors[monitor_id]->domain_listener); + /* Check that the CallbackMask is set correctly */ + for (const auto& callback : init_monitor_tests::all_callback_kinds_) + { + EXPECT_TRUE(domain_monitors[monitor.first]->domain_callback_mask.is_set(callback)); + } - /* Check that the CallbackMask is set correctly */ - for (auto callback : init_monitor_tests::all_callback_kinds_) - { - EXPECT_TRUE(domain_monitors[monitor_id]->domain_callback_mask.is_set(callback)); - } + /* Check that the DataKindMask is set correctly */ + for (const auto& datakind : init_monitor_tests::all_data_kinds_) + { + EXPECT_TRUE(domain_monitors[monitor.first]->data_mask.is_set(datakind)); + } - /* Check that the DataKindMask is set correctly */ - for (auto datakind : init_monitor_tests::all_data_kinds_) - { - EXPECT_TRUE(domain_monitors[monitor_id]->data_mask.is_set(datakind)); + monitor_ids.push_back(monitor.first); } /* Check the created DDS entities */ - EXPECT_NE(nullptr, domain_monitors[monitor_id]->participant); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->subscriber); - for (auto topic : topic_types_) - { - EXPECT_NE(nullptr, domain_monitors[monitor_id]->topics[topic.first]); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->readers[topic.first]); - } + check_dds_entities(domain_monitors[monitor_ids[0]]); + check_dds_entities(domain_monitors[monitor_ids[1]], DEFAULT_ROS2_SERVER_GUIDPREFIX); + check_dds_entities(domain_monitors[monitor_ids[2]], server_guid_prefix); // Stop the monitor to avoid interfering on the next test - StatisticsBackend::stop_monitor(monitor_id); + for (const auto& monitor : domain_monitors) + { + StatisticsBackend::stop_monitor(monitor.first); + } } TEST_F(init_monitor_tests, init_monitor_domain_id_no_callback_all_data) { DomainId domain_id = 0; DomainListener domain_listener; + std::string server_guid_prefix = "44.53.01.5f.45.50.52.4f.53.49.4d.41"; + std::string server_locators = "UDPv4:[127.0.0.1]:11811"; - EntityId monitor_id = StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - CallbackMask::none(), - all_datakind_mask_); - - EXPECT_TRUE(monitor_id.is_valid()); + auto domain_monitors = init_monitors(domain_id, &domain_listener, server_guid_prefix, server_locators, + CallbackMask::none(), all_datakind_mask_); - auto domain_monitors = details::StatisticsBackendData::get_instance()->monitors_by_entity_; - - /* Check that only one monitor is created */ - EXPECT_EQ(domain_monitors.size(), 1); + std::vector monitor_ids; + for (const auto& monitor : domain_monitors) + { + /* Check that the domain listener is set correctly */ + EXPECT_EQ(&domain_listener, domain_monitors[monitor.first]->domain_listener); - /* Check that the domain listener is set correctly */ - EXPECT_EQ(&domain_listener, domain_monitors[monitor_id]->domain_listener); + /* Check that the CallbackMask is set correctly */ + for (auto callback : init_monitor_tests::all_callback_kinds_) + { + EXPECT_FALSE(domain_monitors[monitor.first]->domain_callback_mask.is_set(callback)); + } - /* Check that the CallbackMask is set correctly */ - for (auto callback : init_monitor_tests::all_callback_kinds_) - { - EXPECT_FALSE(domain_monitors[monitor_id]->domain_callback_mask.is_set(callback)); - } + /* Check that the DataKindMask is set correctly */ + for (auto datakind : init_monitor_tests::all_data_kinds_) + { + EXPECT_TRUE(domain_monitors[monitor.first]->data_mask.is_set(datakind)); + } - /* Check that the DataKindMask is set correctly */ - for (auto datakind : init_monitor_tests::all_data_kinds_) - { - EXPECT_TRUE(domain_monitors[monitor_id]->data_mask.is_set(datakind)); + monitor_ids.push_back(monitor.first); } /* Check the created DDS entities */ - EXPECT_NE(nullptr, domain_monitors[monitor_id]->participant); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->subscriber); - for (auto topic : topic_types_) - { - EXPECT_NE(nullptr, domain_monitors[monitor_id]->topics[topic.first]); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->readers[topic.first]); - } + check_dds_entities(domain_monitors[monitor_ids[0]]); + check_dds_entities(domain_monitors[monitor_ids[1]], DEFAULT_ROS2_SERVER_GUIDPREFIX); + check_dds_entities(domain_monitors[monitor_ids[2]], server_guid_prefix); // Stop the monitor to avoid interfering on the next test - StatisticsBackend::stop_monitor(monitor_id); + for (const auto& monitor : domain_monitors) + { + StatisticsBackend::stop_monitor(monitor.first); + } } TEST_F(init_monitor_tests, init_monitor_domain_id_all_callback_no_data) { DomainId domain_id = 0; DomainListener domain_listener; + std::string server_guid_prefix = "44.53.01.5f.45.50.52.4f.53.49.4d.41"; + std::string server_locators = "UDPv4:[127.0.0.1]:11811"; - EntityId monitor_id = StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - all_callback_mask_, - DataKindMask::none()); + auto domain_monitors = init_monitors(domain_id, &domain_listener, server_guid_prefix, server_locators, + all_callback_mask_, DataKindMask::none()); - EXPECT_TRUE(monitor_id.is_valid()); - - auto domain_monitors = details::StatisticsBackendData::get_instance()->monitors_by_entity_; - - /* Check that only one monitor is created */ - EXPECT_EQ(domain_monitors.size(), 1); + std::vector monitor_ids; + for (const auto& monitor : domain_monitors) + { + /* Check that the domain listener is set correctly */ + EXPECT_EQ(&domain_listener, domain_monitors[monitor.first]->domain_listener); - /* Check that the domain listener is set correctly */ - EXPECT_EQ(&domain_listener, domain_monitors[monitor_id]->domain_listener); + /* Check that the CallbackMask is set correctly */ + for (auto callback : init_monitor_tests::all_callback_kinds_) + { + EXPECT_TRUE(domain_monitors[monitor.first]->domain_callback_mask.is_set(callback)); + } - /* Check that the CallbackMask is set correctly */ - for (auto callback : init_monitor_tests::all_callback_kinds_) - { - EXPECT_TRUE(domain_monitors[monitor_id]->domain_callback_mask.is_set(callback)); - } + /* Check that the DataKindMask is set correctly */ + for (auto datakind : init_monitor_tests::all_data_kinds_) + { + EXPECT_FALSE(domain_monitors[monitor.first]->data_mask.is_set(datakind)); + } - /* Check that the DataKindMask is set correctly */ - for (auto datakind : init_monitor_tests::all_data_kinds_) - { - EXPECT_FALSE(domain_monitors[monitor_id]->data_mask.is_set(datakind)); + monitor_ids.push_back(monitor.first); } /* Check the created DDS entities */ - EXPECT_NE(nullptr, domain_monitors[monitor_id]->participant); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->subscriber); - for (auto topic : topic_types_) - { - EXPECT_NE(nullptr, domain_monitors[monitor_id]->topics[topic.first]); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->readers[topic.first]); - } + check_dds_entities(domain_monitors[monitor_ids[0]]); + check_dds_entities(domain_monitors[monitor_ids[1]], DEFAULT_ROS2_SERVER_GUIDPREFIX); + check_dds_entities(domain_monitors[monitor_ids[2]], server_guid_prefix); // Stop the monitor to avoid interfering on the next test - StatisticsBackend::stop_monitor(monitor_id); + for (const auto& monitor : domain_monitors) + { + StatisticsBackend::stop_monitor(monitor.first); + } } TEST_F(init_monitor_tests, init_monitor_domain_id_null_listener_all_data) { DomainId domain_id = 0; + std::string server_guid_prefix = "44.53.01.5f.45.50.52.4f.53.49.4d.41"; + std::string server_locators = "UDPv4:[127.0.0.1]:11811"; - EntityId monitor_id = StatisticsBackend::init_monitor( - domain_id, - nullptr, - all_callback_mask_, - all_datakind_mask_); - - EXPECT_TRUE(monitor_id.is_valid()); - - auto domain_monitors = details::StatisticsBackendData::get_instance()->monitors_by_entity_; + auto domain_monitors = init_monitors(domain_id, nullptr, server_guid_prefix, server_locators, + all_callback_mask_, all_datakind_mask_); - /* Check that only one monitor is created */ - EXPECT_EQ(domain_monitors.size(), 1); + std::vector monitor_ids; + for (const auto& monitor : domain_monitors) + { + /* Check that the domain listener is set correctly */ + EXPECT_EQ(nullptr, domain_monitors[monitor.first]->domain_listener); - /* Check that the domain listener is set correctly */ - EXPECT_EQ(nullptr, domain_monitors[monitor_id]->domain_listener); + /* Check that the CallbackMask is set correctly */ + for (auto callback : init_monitor_tests::all_callback_kinds_) + { + EXPECT_TRUE(domain_monitors[monitor.first]->domain_callback_mask.is_set(callback)); + } - /* Check that the CallbackMask is set correctly */ - for (auto callback : init_monitor_tests::all_callback_kinds_) - { - EXPECT_TRUE(domain_monitors[monitor_id]->domain_callback_mask.is_set(callback)); - } + /* Check that the DataKindMask is set correctly */ + for (auto datakind : init_monitor_tests::all_data_kinds_) + { + EXPECT_TRUE(domain_monitors[monitor.first]->data_mask.is_set(datakind)); + } - /* Check that the DataKindMask is set correctly */ - for (auto datakind : init_monitor_tests::all_data_kinds_) - { - EXPECT_TRUE(domain_monitors[monitor_id]->data_mask.is_set(datakind)); + monitor_ids.push_back(monitor.first); } /* Check the created DDS entities */ - EXPECT_NE(nullptr, domain_monitors[monitor_id]->participant); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->subscriber); - for (auto topic : topic_types_) - { - EXPECT_NE(nullptr, domain_monitors[monitor_id]->topics[topic.first]); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->readers[topic.first]); - } + check_dds_entities(domain_monitors[monitor_ids[0]]); + check_dds_entities(domain_monitors[monitor_ids[1]], DEFAULT_ROS2_SERVER_GUIDPREFIX); + check_dds_entities(domain_monitors[monitor_ids[2]], server_guid_prefix); // Stop the monitor to avoid interfering on the next test - StatisticsBackend::stop_monitor(monitor_id); + for (const auto& monitor : domain_monitors) + { + StatisticsBackend::stop_monitor(monitor.first); + } } TEST_F(init_monitor_tests, init_monitor_several_monitors) @@ -372,20 +478,8 @@ TEST_F(init_monitor_tests, init_monitor_several_monitors) } /* Check the created DDS entities */ - EXPECT_NE(nullptr, domain_monitors[monitor_id1]->participant); - EXPECT_NE(nullptr, domain_monitors[monitor_id2]->participant); - - EXPECT_NE(nullptr, domain_monitors[monitor_id1]->subscriber); - EXPECT_NE(nullptr, domain_monitors[monitor_id2]->subscriber); - - for (auto topic : topic_types_) - { - EXPECT_NE(nullptr, domain_monitors[monitor_id1]->topics[topic.first]); - EXPECT_NE(nullptr, domain_monitors[monitor_id2]->topics[topic.first]); - - EXPECT_NE(nullptr, domain_monitors[monitor_id1]->readers[topic.first]); - EXPECT_NE(nullptr, domain_monitors[monitor_id2]->readers[topic.first]); - } + check_dds_entities(domain_monitors[monitor_id1]); + check_dds_entities(domain_monitors[monitor_id2]); // Stop the monitor to avoid interfering on the next test StatisticsBackend::stop_monitor(monitor_id1); @@ -396,49 +490,99 @@ TEST_F(init_monitor_tests, init_monitor_twice) { DomainId domain_id = 0; DomainListener domain_listener; - EntityId monitor_id = StatisticsBackend::init_monitor( - domain_id, - &domain_listener, - all_callback_mask_, - all_datakind_mask_); + std::string server_guid_prefix = "44.53.01.5f.45.50.52.4f.53.49.4d.41"; + std::string server_locators = "UDPv4:[127.0.0.1]:11811"; - EXPECT_TRUE(monitor_id.is_valid()); + init_monitors(domain_id, &domain_listener, server_guid_prefix, server_locators, + all_callback_mask_, all_datakind_mask_); EXPECT_THROW(StatisticsBackend::init_monitor( domain_id, nullptr, CallbackMask::none(), DataKindMask::none()), BadParameter); + EXPECT_THROW(StatisticsBackend::init_monitor( + server_locators, + nullptr, + CallbackMask::none(), + DataKindMask::none()), BadParameter); + EXPECT_THROW(StatisticsBackend::init_monitor( + server_guid_prefix, + server_locators, + nullptr, + CallbackMask::none(), + DataKindMask::none()), BadParameter); auto domain_monitors = details::StatisticsBackendData::get_instance()->monitors_by_entity_; - /* Check that only one monitor is created */ - EXPECT_EQ(domain_monitors.size(), 1); + /* Check that three monitors are created */ + EXPECT_EQ(domain_monitors.size(), 3); - /* Check that the domain listener is set correctly */ - EXPECT_EQ(&domain_listener, domain_monitors[monitor_id]->domain_listener); - - /* Check that the CallbackMask is set correctly */ - for (auto callback : init_monitor_tests::all_callback_kinds_) + std::vector monitor_ids; + for (const auto& monitor : domain_monitors) { - EXPECT_TRUE(domain_monitors[monitor_id]->domain_callback_mask.is_set(callback)); - } + /* Check that the domain listener is set correctly */ + EXPECT_EQ(&domain_listener, domain_monitors[monitor.first]->domain_listener); - /* Check that the DataKindMask is set correctly */ - for (auto datakind : init_monitor_tests::all_data_kinds_) - { - EXPECT_TRUE(domain_monitors[monitor_id]->data_mask.is_set(datakind)); + /* Check that the CallbackMask is set correctly */ + for (auto callback : init_monitor_tests::all_callback_kinds_) + { + EXPECT_TRUE(domain_monitors[monitor.first]->domain_callback_mask.is_set(callback)); + } + + /* Check that the DataKindMask is set correctly */ + for (auto datakind : init_monitor_tests::all_data_kinds_) + { + EXPECT_TRUE(domain_monitors[monitor.first]->data_mask.is_set(datakind)); + } + + monitor_ids.push_back(monitor.first); } /* Check the created DDS entities */ - EXPECT_NE(nullptr, domain_monitors[monitor_id]->participant); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->subscriber); + check_dds_entities(domain_monitors[monitor_ids[0]]); + check_dds_entities(domain_monitors[monitor_ids[1]], DEFAULT_ROS2_SERVER_GUIDPREFIX); + check_dds_entities(domain_monitors[monitor_ids[2]], server_guid_prefix); - for (auto topic : topic_types_) + // Stop the monitor to avoid interfering on the next test + for (const auto& monitor : domain_monitors) { - EXPECT_NE(nullptr, domain_monitors[monitor_id]->topics[topic.first]); - EXPECT_NE(nullptr, domain_monitors[monitor_id]->readers[topic.first]); + StatisticsBackend::stop_monitor(monitor.first); } +} + +TEST_F(init_monitor_tests, init_server_monitor_several_locators) +{ + std::string server_locators = + // unicast addresses + "UDPv4:[127.0.0.1]:11811;TCPv4:[127.0.0.1]:11812;UDPv6:[::1]:11813;TCPv6:[::1]:11814;" + // multicast addresses + "UDPv4:[239.255.0.1]:11821;UDPv6:[ff1e::ffff:efff:1]:11823"; + EntityId monitor_id = StatisticsBackend::init_monitor(server_locators); + + EXPECT_TRUE(monitor_id.is_valid()); + + auto domain_monitors = details::StatisticsBackendData::get_instance()->monitors_by_entity_; + + /* Check that a monitor is created */ + EXPECT_EQ(domain_monitors.size(), 1); + + DomainParticipantQos participant_qos; + domain_monitors[monitor_id]->participant->get_qos(participant_qos); + + EXPECT_EQ(participant_qos.wire_protocol().builtin.discovery_config.discoveryProtocol, + eprosima::fastrtps::rtps::DiscoveryProtocol_t::SUPER_CLIENT); + + const RemoteServerAttributes& server_qos = + participant_qos.wire_protocol().builtin.discovery_config.m_DiscoveryServers.front(); + + check_locator(server_qos, LOCATOR_KIND_UDPv4, "127.0.0.1", 11811); + check_locator(server_qos, LOCATOR_KIND_TCPv4, "127.0.0.1", 11812); + check_locator(server_qos, LOCATOR_KIND_UDPv6, "::1", 11813); + check_locator(server_qos, LOCATOR_KIND_TCPv6, "::1", 11814); + + check_locator(server_qos, LOCATOR_KIND_UDPv4, "239.255.0.1", 11821, false); + check_locator(server_qos, LOCATOR_KIND_UDPv6, "ff1e::ffff:efff:1", 11823, false); // Stop the monitor to avoid interfering on the next test StatisticsBackend::stop_monitor(monitor_id);