From 2484640c764ce49ced7a535c30ef2252c82479a4 Mon Sep 17 00:00:00 2001 From: Carlos Espinoza Curto <148376273+Carlosespicur@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:45:48 +0200 Subject: [PATCH] Add IDL format to topic entities (#245) * Refs #21458: Add type IDL to Topic info json [WORK IN PROGRESS] Signed-off-by: Carlosespicur * Refs #21458: Add IDL getter for Monitor controller communication Signed-off-by: Carlosespicur * Refs #21458: Delete Topic IDLs in topic info JSON Signed-off-by: Carlosespicur * Refs #21458: Uncrustify Signed-off-by: Carlosespicur * Refs #21458: Fix tests and idl serialization in callbacks Signed-off-by: Carlosespicur * Refs #21458: Add review changes Signed-off-by: Carlosespicur --------- Signed-off-by: Carlosespicur --- .../StatisticsBackend.hpp | 10 +++ src/cpp/StatisticsBackend.cpp | 12 +++ src/cpp/database/database.cpp | 40 +++++++++- src/cpp/database/database.hpp | 46 +++++++++++ src/cpp/database/database_queue.cpp | 6 ++ src/cpp/database/database_queue.hpp | 4 +- .../StatisticsParticipantListener.cpp | 56 ++++++++++++- .../database/database/database/database.hpp | 7 ++ .../DatabaseQueue/DatabaseQueueTests.cpp | 17 ++++ .../StatisticsBackend/IsActiveTests.cpp | 1 - .../StatisticsParticipantListenerTests.cpp | 78 +++++++++++++++++++ 11 files changed, 271 insertions(+), 6 deletions(-) diff --git a/include/fastdds_statistics_backend/StatisticsBackend.hpp b/include/fastdds_statistics_backend/StatisticsBackend.hpp index 873876f84..236cd5630 100644 --- a/include/fastdds_statistics_backend/StatisticsBackend.hpp +++ b/include/fastdds_statistics_backend/StatisticsBackend.hpp @@ -263,6 +263,16 @@ class StatisticsBackend static Info get_info( EntityId entity_id); + /** + * @brief Get the IDL representation of a data type in string format for a given topic entity + * + * @param entity_id The entity for which the data type IDL is retrieved. + * @return String object describing the entity's data type IDL. + */ + FASTDDS_STATISTICS_BACKEND_DllAPI + static std::string get_type_idl( + EntityId entity_id); + /** * @brief Provides access to the data measured during the monitoring. * diff --git a/src/cpp/StatisticsBackend.cpp b/src/cpp/StatisticsBackend.cpp index a05858a3f..234f1be0b 100644 --- a/src/cpp/StatisticsBackend.cpp +++ b/src/cpp/StatisticsBackend.cpp @@ -537,6 +537,18 @@ Info StatisticsBackend::get_info( return StatisticsBackendData::get_instance()->database_->get_info(entity_id); } +std::string StatisticsBackend::get_type_idl( + EntityId entity_id) +{ + // Check if the entity is a topic + if (EntityKind::TOPIC != get_type(entity_id)) + { + throw BadParameter("EntityId received does not match with a valid topic entity"); + } + Info topic_info = StatisticsBackend::get_info(entity_id); + return StatisticsBackendData::get_instance()->database_->get_type_idl(topic_info[DATA_TYPE_TAG]); +} + std::vector StatisticsBackend::get_data( DataKind data_type, const std::vector& entity_ids_source, diff --git a/src/cpp/database/database.cpp b/src/cpp/database/database.cpp index 3bf404c8a..906ea55d5 100644 --- a/src/cpp/database/database.cpp +++ b/src/cpp/database/database.cpp @@ -264,6 +264,7 @@ EntityId Database::insert_new_topic( std::shared_ptr domain = std::const_pointer_cast( std::static_pointer_cast(get_entity_nts(domain_id))); + // Create the topic to insert in the database auto topic = std::make_shared( name, type_name, @@ -279,6 +280,24 @@ EntityId Database::insert_new_topic( return entity_id; } +bool Database::is_type_in_database( + const std::string& type_name) +{ + return (type_idls_.find(type_name) != type_idls_.end()); +} + +void Database::insert_new_type_idl( + const std::string& type_name, + const std::string& type_idl) +{ + std::lock_guard guard(mutex_); + if (type_name.empty()) + { + throw BadParameter("Type name cannot be empty"); + } + type_idls_[type_name] = type_idl; +} + EntityId Database::insert_new_endpoint( const std::string& endpoint_guid, const std::string& name, @@ -656,7 +675,7 @@ void Database::insert_nts( throw BadParameter("Topic data type cannot be empty"); } - /* Check that domain exits */ + /* Check that domain exists */ bool domain_exists = false; for (const auto& domain_it : domains_) { @@ -2103,6 +2122,24 @@ std::vector> Database::get_entities_by_name_nts( return entities; } +std::string Database::get_type_idl( + const std::string& type_name) const +{ + std::shared_lock lock(mutex_); + return get_type_idl_nts(type_name); +} + +std::string Database::get_type_idl_nts( + const std::string& type_name) const +{ + auto it = type_idls_.find(type_name); + if (it != type_idls_.end()) + { + return it->second; + } + throw BadParameter("Type " + type_name + " not found in the database"); +} + void Database::erase( EntityId& domain_id) { @@ -4624,7 +4661,6 @@ DatabaseDump Database::dump_entity_( entity_info[ALIAS_TAG] = entity->alias; entity_info[DATA_TYPE_TAG] = entity->data_type; entity_info[STATUS_TAG] = entity->status; - entity_info[DOMAIN_ENTITY_TAG] = id_to_string(entity->domain->id); // metatraffic and active attributes are stored but ignored when loading diff --git a/src/cpp/database/database.hpp b/src/cpp/database/database.hpp index f6b25a253..85105c0ac 100644 --- a/src/cpp/database/database.hpp +++ b/src/cpp/database/database.hpp @@ -156,6 +156,24 @@ class Database const std::string& alias, const EntityId& domain_id); + /** + * @brief Check if a Topic data type is already in the database + * @param type_name The type name of the Topic. + * + * @return True if the Topic data type is in the database. + */ + bool is_type_in_database( + const std::string& type_name); + + /** + * @brief Insert a new type IDL into the database. + * @param topic_type The type of the topic. + * @param topic_idl The IDL representation of the type + */ + void insert_new_type_idl( + const std::string& topic_type, + const std::string& topic_idl); + /** * @brief Create new Endpoint and corresponding Locator, and insert them in database. * @param endpoint_guid The GUID of the Endpoint. @@ -444,6 +462,16 @@ class Database EntityKind entity_kind, const std::string& name) const; + /** + * @brief Get the type IDL of a given type name, if it exists. + * + * @param type_name The name of the data type for which to search. + * @throws eprosima::statistics_backend::BadParameter if \c type_name does not exist in the database. + * @return The IDL representation of the type in std::string format. + */ + std::string get_type_idl( + const std::string& type_name) const; + /** * @brief Get the entity of a given EntityKind that matches with the requested GUID. * @@ -1167,6 +1195,16 @@ class Database EntityKind entity_kind, const std::string& name) const; + /** + * @brief Get the type IDL of a given type name, if it exists. This method is not thread safe. + * + * @param type_name The name of the data type for which to search. + * @throws eprosima::statistics_backend::BadParameter if \c type_name does not exist in the database. + * @return The IDL representation of the type in std::string format. + */ + std::string get_type_idl_nts( + const std::string& type_name) const; + /** * @brief Get the entity of a given EntityKind that matches with the requested GUID. This method is not thread safe. * @@ -1446,6 +1484,14 @@ class Database */ std::map>> topics_; + /** + * Collection of topic IDLs sorted by topic data types, with which they are biunivocally identified. + * This is used to store the IDLs of the discovered topics + * + * Each value in the collection is in turn a map of the actual Topic IDLs sorted by data type + */ + std::map type_idls_; + //! Graph map describing per domain complete topology of the entities. std::map domain_view_graph; diff --git a/src/cpp/database/database_queue.cpp b/src/cpp/database/database_queue.cpp index e94f11f3b..3c15d03d2 100644 --- a/src/cpp/database/database_queue.cpp +++ b/src/cpp/database/database_queue.cpp @@ -356,6 +356,12 @@ EntityId DatabaseEntityQueue::process_endpoint_discovery( details::StatisticsBackendData::DiscoveryStatus::DISCOVERY); } + // Store type IDL in the database if available and in case it is not already stored. Ignore metatraffic topics + if (!database_->is_type_in_database(info.type_name) && !info.is_virtual_metatraffic) + { + database_->insert_new_type_idl(info.type_name, info.type_idl); + } + // Create the endpoint EntityId endpoint_id; std::stringstream name; diff --git a/src/cpp/database/database_queue.hpp b/src/cpp/database/database_queue.hpp index 6c2ac7b7b..2ce348f54 100644 --- a/src/cpp/database/database_queue.hpp +++ b/src/cpp/database/database_queue.hpp @@ -32,7 +32,6 @@ #include #include #include - #include #include @@ -372,9 +371,10 @@ struct EntityDiscoveryInfo std::string user; std::string process; - // Enpoint data + // Endpoint data std::string topic_name; std::string type_name; + std::string type_idl; fastdds::rtps::RemoteLocatorList locators; // Alias diff --git a/src/cpp/subscriber/StatisticsParticipantListener.cpp b/src/cpp/subscriber/StatisticsParticipantListener.cpp index f0d3ed6f2..8e9377208 100644 --- a/src/cpp/subscriber/StatisticsParticipantListener.cpp +++ b/src/cpp/subscriber/StatisticsParticipantListener.cpp @@ -22,10 +22,14 @@ #include #include +#include #include #include -#include +#include +#include +#include #include +#include #include "database/database_queue.hpp" #include "subscriber/QosSerializer.hpp" @@ -318,6 +322,31 @@ void StatisticsParticipantListener::on_data_reader_discovery( } } + // In case of a new data reader discovered, add type info if available + if (ReaderDiscoveryStatus::DISCOVERED_READER == reason && info.type_information.assigned() == true) + { + // Create IDL representation of the discovered type + // Get remote type information + xtypes::TypeObject remote_type_object; + if (RETCODE_OK != DomainParticipantFactory::get_instance()->type_object_registry().get_type_object( + info.type_information.type_information.complete().typeid_with_size().type_id(), + remote_type_object)) + { + EPROSIMA_LOG_ERROR(STATISTICS_PARTICIPANT_LISTENER, + "Error getting type object for type " << info.type_name); + return; + } + + // Build remotely discovered type + DynamicType::_ref_type remote_type = DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object( + remote_type_object)->build(); + + // Serialize DynamicType into its IDL representation + std::stringstream idl; + idl_serialize(remote_type, idl); + discovery_info.type_idl = idl.str(); + } + entity_queue_->push(timestamp, discovery_info); // Wait until the entity queue is processed and restart the data queues @@ -376,6 +405,31 @@ void StatisticsParticipantListener::on_data_writer_discovery( } } + // In case of a new data writer discovered, add type info if available + if (WriterDiscoveryStatus::DISCOVERED_WRITER == reason && info.type_information.assigned() == true) + { + // Create IDL representation of the discovered type + // Get remote type information + xtypes::TypeObject remote_type_object; + if (RETCODE_OK != DomainParticipantFactory::get_instance()->type_object_registry().get_type_object( + info.type_information.type_information.complete().typeid_with_size().type_id(), + remote_type_object)) + { + EPROSIMA_LOG_ERROR(STATISTICS_PARTICIPANT_LISTENER, + "Error getting type object for type " << info.type_name); + return; + } + + // Build remotely discovered type + DynamicType::_ref_type remote_type = DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object( + remote_type_object)->build(); + + // Serialize DynamicType into its IDL representation + std::stringstream idl; + idl_serialize(remote_type, idl); + discovery_info.type_idl = idl.str(); + } + entity_queue_->push(timestamp, discovery_info); // Wait until the entity queue is processed and restart the data queues diff --git a/test/mock/database/database/database/database.hpp b/test/mock/database/database/database/database.hpp index 95ead6b37..aafcececd 100644 --- a/test/mock/database/database/database/database.hpp +++ b/test/mock/database/database/database/database.hpp @@ -79,6 +79,13 @@ class Database const std::string& topic_type, const EntityId& topic_id)); + MOCK_METHOD1(is_type_in_database, bool( + const std::string& type_name)); + + MOCK_METHOD2(insert_new_type_idl, void( + const std::string& type_name, + const std::string& type_idl)); + MOCK_METHOD4(insert_new_topic, EntityId( const std::string& name, const std::string& type_name, diff --git a/test/unittest/DatabaseQueue/DatabaseQueueTests.cpp b/test/unittest/DatabaseQueue/DatabaseQueueTests.cpp index c0a3c1bea..b347f9fff 100644 --- a/test/unittest/DatabaseQueue/DatabaseQueueTests.cpp +++ b/test/unittest/DatabaseQueue/DatabaseQueueTests.cpp @@ -1391,6 +1391,8 @@ TEST_F(database_queue_tests, push_datawriter) std::make_pair(EntityId(0), EntityId(2))))); EXPECT_CALL(database, is_topic_in_database(_, EntityId(2))).Times(AnyNumber()) .WillRepeatedly(Return(true)); + EXPECT_CALL(database, is_type_in_database(type_name)).Times(AnyNumber()) + .WillRepeatedly(Return(true)); // Datawriter undiscovery: FAILURE { @@ -1625,6 +1627,9 @@ TEST_F(database_queue_tests, push_datawriter_topic_does_not_exist) EXPECT_CALL(database, get_entities_by_name(EntityKind::TOPIC, topic_name)).Times(AnyNumber()) .WillOnce(Return(std::vector>())); + EXPECT_CALL(database, is_type_in_database(type_name)).Times(AnyNumber()) + .WillRepeatedly(Return(false)); + // Datawriter discovery: SUCCESS { // Precondition: The writer does not exist @@ -1681,6 +1686,10 @@ TEST_F(database_queue_tests, push_datawriter_topic_does_not_exist) EXPECT_CALL(database, insert_new_endpoint(_, _, _, _, _, _, _, _, _, _)).Times(1) .WillOnce(Invoke(&insert_datawriter_args, &InsertEndpointArgs::insert)); + // Expectation: Add the type to the database + EXPECT_CALL(database, is_type_in_database(type_name)).Times(1).WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(type_name, "")).Times(1); + // Expectation: Modify graph and notify user EXPECT_CALL(database, update_endpoint_in_graph(_, _, _, _)).Times(1).WillOnce(Return(true)); EXPECT_CALL(*details::StatisticsBackendData::get_instance(), on_domain_view_graph_update(_)).Times(1); @@ -1746,6 +1755,8 @@ TEST_F(database_queue_tests, push_datareader) std::make_pair(EntityId(0), EntityId(2))))); EXPECT_CALL(database, is_topic_in_database(_, EntityId(2))).Times(AnyNumber()) .WillRepeatedly(Return(true)); + EXPECT_CALL(database, is_type_in_database(type_name)).Times(AnyNumber()) + .WillRepeatedly(Return(true)); // Datareader undiscovery: FAILURE { @@ -1979,6 +1990,8 @@ TEST_F(database_queue_tests, push_datareader_topic_does_not_exist) // Precondition: The topic does not exist EXPECT_CALL(database, get_entities_by_name(EntityKind::TOPIC, topic_name)).Times(AnyNumber()) .WillOnce(Return(std::vector>())); + EXPECT_CALL(database, is_type_in_database(type_name)).Times(AnyNumber()) + .WillOnce(Return(false)); // Datareader discovery: SUCCESS { @@ -2036,6 +2049,10 @@ TEST_F(database_queue_tests, push_datareader_topic_does_not_exist) EXPECT_CALL(database, insert_new_endpoint(_, _, _, _, _, _, _, _, _, _)).Times(1) .WillOnce(Invoke(&insert_datareader_args, &InsertEndpointArgs::insert)); + // Expectation: Add the type to the database + EXPECT_CALL(database, is_type_in_database(type_name)).Times(1).WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(type_name, "")).Times(1); + // Expectation: Modify graph and notify user EXPECT_CALL(database, update_endpoint_in_graph(_, _, _, _)).Times(1).WillOnce(Return(true)); EXPECT_CALL(*details::StatisticsBackendData::get_instance(), on_domain_view_graph_update(_)).Times(1); diff --git a/test/unittest/StatisticsBackend/IsActiveTests.cpp b/test/unittest/StatisticsBackend/IsActiveTests.cpp index f080e50ff..2a2ef3f9b 100644 --- a/test/unittest/StatisticsBackend/IsActiveTests.cpp +++ b/test/unittest/StatisticsBackend/IsActiveTests.cpp @@ -544,7 +544,6 @@ TEST_F(is_active_tests, discover_datawriter_on_inactive_domain) // The discovered reader is in the topic data.topic_name = topic->name; data.type_name = topic->data_type; - // The discovered reader contains the locator eprosima::fastdds::rtps::Locator_t dds_existing_unicast_locator(LOCATOR_KIND_UDPv4, 1024); dds_existing_unicast_locator.address[12] = 127; diff --git a/test/unittest/StatisticsParticipantListener/StatisticsParticipantListenerTests.cpp b/test/unittest/StatisticsParticipantListener/StatisticsParticipantListenerTests.cpp index 9299708b5..44eae7ddf 100644 --- a/test/unittest/StatisticsParticipantListener/StatisticsParticipantListenerTests.cpp +++ b/test/unittest/StatisticsParticipantListener/StatisticsParticipantListenerTests.cpp @@ -608,6 +608,10 @@ TEST_F(statistics_participant_listener_tests, new_participant_discovered) on_domain_entity_discovery(EntityId(0), EntityId(11), EntityKind::TOPIC, eprosima::statistics_backend::details::StatisticsBackendData::DiscoveryStatus::DISCOVERY)).Times(1); + // Expectation: Metatraffic type is ignored + EXPECT_CALL(database, is_type_in_database(metatraffic_type_name_)).Times(1).WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(metatraffic_type_name_, "")).Times(0); + // Execution: Call the listener eprosima::fastdds::rtps::ParticipantDiscoveryStatus status = eprosima::fastdds::rtps::ParticipantDiscoveryStatus::DISCOVERED_PARTICIPANT; @@ -700,6 +704,11 @@ TEST_F(statistics_participant_listener_tests, new_participant_discovered_not_fir EXPECT_CALL(database, insert_new_participant(_, _, _, _, _, _, _)).Times(1) .WillOnce(Invoke(&insert_args, &InsertParticipantArgs::insert)); + // Expectation: Metatraffic topic types are ignored + EXPECT_CALL(database, is_type_in_database(metatraffic_type_name_)).Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(metatraffic_type_name_, "")).Times(0); + // Expectation: The host already exists with ID 13, the user already exists with ID 14 and the process already exists with ID 15 ProcessPhysicalArgs process_physical_args([&]( const std::string& host_name, @@ -935,6 +944,11 @@ TEST_F(statistics_participant_listener_tests, new_participant_discovered_empty_n EXPECT_CALL(database, insert_new_topic(_, _, _, _)).Times(1) .WillOnce(Invoke(&insert_topic_args, &InsertTopicArgs::insert)); + // Expectation: Metatraffic topic types are ignored + EXPECT_CALL(database, is_type_in_database(metatraffic_type_name_)).Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(metatraffic_prefix + "TYPE", "")).Times(0); + // Expectation: The Metatraffic Endpoint is added to the database. We do not care about the given ID InsertEndpointArgs insert_datawriter_args([&]( const std::string& endpoint_guid, @@ -1123,6 +1137,11 @@ TEST_F(statistics_participant_listener_tests, new_participant_discovered_empty_n EXPECT_CALL(database, insert_new_participant(_, _, _, _, _, _, _)).Times(1) .WillOnce(Invoke(&insert_args, &InsertParticipantArgs::insert)); + // Expectation: Metatraffic topic types are ignored + EXPECT_CALL(database, is_type_in_database(metatraffic_type_name_)).Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(metatraffic_prefix + "TYPE", "")).Times(0); + // Expectation: The host is created and given ID 13, the user is created and given ID 14 and the process is created and given ID 15 ProcessPhysicalArgs process_physical_args([&]( const std::string& host_name, @@ -1167,6 +1186,7 @@ TEST_F(statistics_participant_listener_tests, new_participant_discovered_empty_n EXPECT_CALL(database, insert_new_topic(_, _, _, _)).Times(1) .WillOnce(Invoke(&insert_topic_args, &InsertTopicArgs::insert)); + // Expectation: The Metatraffic Endpoint is added to the database. We do not care about the given ID InsertEndpointArgs insert_datawriter_args([&]( const std::string& endpoint_guid, @@ -1344,6 +1364,11 @@ TEST_F(statistics_participant_listener_tests, new_participant_discovered_empty_n EXPECT_CALL(database, insert_new_participant(_, _, _, _, _, _, _)).Times(1) .WillOnce(Invoke(&insert_args, &InsertParticipantArgs::insert)); + // Expectation: Metatraffic topic types are ignored + EXPECT_CALL(database, is_type_in_database(metatraffic_type_name_)).Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(metatraffic_type_name_, "")).Times(0); + // Expectation: The host is created and given ID 13, the user is created and given ID 14 and the process is created and given ID 15 ProcessPhysicalArgs process_physical_args([&]( const std::string& host_name, @@ -1570,6 +1595,11 @@ TEST_F(statistics_participant_listener_tests, new_participant_discovered_empty_n EXPECT_CALL(database, insert_new_participant(_, _, _, _, _, _, _)).Times(1) .WillOnce(Invoke(&insert_args, &InsertParticipantArgs::insert)); + // Expectation: Metatraffic topic types are ignored + EXPECT_CALL(database, is_type_in_database(metatraffic_type_name_)).Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(metatraffic_type_name_, "")).Times(0); + // Expectation: The host is created and given ID 13, the user is created and given ID 14 and the process is created and given ID 15 ProcessPhysicalArgs process_physical_args([&]( const std::string& host_name, @@ -1762,6 +1792,11 @@ TEST_F(statistics_participant_listener_tests, new_participant_discovered_empty_n EXPECT_CALL(database, insert_new_participant(_, _, _, _, _, _, _)).Times(1) .WillOnce(Invoke(&insert_args, &InsertParticipantArgs::insert)); + // Expectation: Metatraffic topic types are ignored + EXPECT_CALL(database, is_type_in_database(metatraffic_type_name_)).Times(1) + .WillOnce(Return(false)); + + EXPECT_CALL(database, insert_new_type_idl(metatraffic_type_name_, "")).Times(0); // Expectation: The host is created and given ID 13, the user is created and given ID 14 and the process is created and given ID 15 ProcessPhysicalArgs process_physical_args([&]( const std::string& host_name, @@ -1987,6 +2022,11 @@ TEST_F(statistics_participant_listener_tests, new_participant_discovered_empty_n EXPECT_CALL(database, insert_new_participant(_, _, _, _, _, _, _)).Times(1) .WillOnce(Invoke(&insert_args, &InsertParticipantArgs::insert)); + // Expectation: Metatraffic topic types are ignored + EXPECT_CALL(database, is_type_in_database(metatraffic_type_name_)).Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(metatraffic_type_name_, "")).Times(0); + // Expectation: The host is created and given ID 13, the user is created and given ID 14 and the process is created and given ID 15 ProcessPhysicalArgs process_physical_args([&]( const std::string& host_name, @@ -2403,6 +2443,10 @@ TEST_F(statistics_participant_listener_tests, new_reader_discovered) // Precondition: The reader change it status EXPECT_CALL(database, change_entity_status(EntityId(10), true)).Times(1); + // Expectation: Type is already added to the database + EXPECT_CALL(database, is_type_in_database(type_name_)).Times(1) + .WillOnce(Return(true)); + // Expectation: Modify graph and notify user EXPECT_CALL(database, update_endpoint_in_graph(EntityId(0), EntityId(1), EntityId(2), EntityId(10))).Times(1).WillOnce(Return( @@ -2573,6 +2617,11 @@ TEST_F(statistics_participant_listener_tests, new_reader_no_topic) // Precondition: The reader change it status EXPECT_CALL(database, change_entity_status(EntityId(11), true)).Times(1); + // Expectation: Add type to the database + EXPECT_CALL(database, is_type_in_database(type_name_)).Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(type_name_, "")).Times(1); + // Expectation: Modify graph and notify user (twice, also from participant update) EXPECT_CALL(database, update_endpoint_in_graph(EntityId(0), EntityId(1), EntityId(10), @@ -2703,6 +2752,10 @@ TEST_F(statistics_participant_listener_tests, new_reader_several_topics) // Precondition: The reader change it status EXPECT_CALL(database, change_entity_status(EntityId(10), true)).Times(1); + // Expectation: Type is already added to the database + EXPECT_CALL(database, is_type_in_database(type_name_)).Times(1) + .WillOnce(Return(true)); + // Expectation: Modify graph and notify user (twice, also from participant update) EXPECT_CALL(database, update_endpoint_in_graph(EntityId(0), EntityId(1), EntityId(2), EntityId(10))).Times(1).WillOnce(Return( @@ -2847,6 +2900,10 @@ TEST_F(statistics_participant_listener_tests, new_reader_several_locators) // Precondition: The reader change it status EXPECT_CALL(database, change_entity_status(EntityId(11), true)).Times(1); + // Expectation: Type already added to the database + EXPECT_CALL(database, is_type_in_database(type_name_)).Times(1) + .WillOnce(Return(true)); + // Expectation: Modify graph and notify user (twice, also from participant update) EXPECT_CALL(database, update_endpoint_in_graph(EntityId(0), EntityId(1), EntityId(2), EntityId(11))).Times(1).WillOnce(Return( @@ -2995,6 +3052,10 @@ TEST_F(statistics_participant_listener_tests, new_reader_several_locators_no_hos // Precondition: The reader change it status EXPECT_CALL(database, change_entity_status(EntityId(11), true)).Times(1); + // Expectation: Type already added to the database + EXPECT_CALL(database, is_type_in_database(type_name_)).Times(1) + .WillOnce(Return(true)); + // Expectation: Modify graph and notify user (twice, also from participant update) EXPECT_CALL(database, update_endpoint_in_graph(EntityId(0), EntityId(1), EntityId(2), EntityId(11))).Times(1).WillOnce(Return( @@ -3342,6 +3403,10 @@ TEST_F(statistics_participant_listener_tests, new_writer_discovered) // Precondition: The writer change it status EXPECT_CALL(database, change_entity_status(EntityId(10), true)).Times(1); + // Expectation: Type already added to the database + EXPECT_CALL(database, is_type_in_database(type_name_)).Times(1) + .WillOnce(Return(true)); + // Expectation: Modify graph and notify user EXPECT_CALL(database, update_endpoint_in_graph(EntityId(0), EntityId(1), EntityId(2), EntityId(10))).Times(1).WillOnce(Return( @@ -3512,6 +3577,11 @@ TEST_F(statistics_participant_listener_tests, new_writer_no_topic) // Precondition: The writer change it status EXPECT_CALL(database, change_entity_status(EntityId(11), true)).Times(1); + // Expectation: Add the type to the database + EXPECT_CALL(database, is_type_in_database(type_name_)).Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(database, insert_new_type_idl(type_name_, "")).Times(1); + // Expectation: Modify graph and notify user (twice, also from participant update) EXPECT_CALL(database, update_endpoint_in_graph(EntityId(0), EntityId(1), EntityId(10), @@ -3662,6 +3732,10 @@ TEST_F(statistics_participant_listener_tests, new_writer_several_locators) // Precondition: The writer change it status EXPECT_CALL(database, change_entity_status(EntityId(11), true)).Times(1); + // Expectation: Type already added to the database + EXPECT_CALL(database, is_type_in_database(type_name_)).Times(1) + .WillOnce(Return(true)); + // Expectation: Modify graph and notify user (twice, also from participant update) EXPECT_CALL(database, update_endpoint_in_graph(EntityId(0), EntityId(1), EntityId(2), EntityId(11))).Times(1).WillOnce(Return( @@ -3804,6 +3878,10 @@ TEST_F(statistics_participant_listener_tests, new_writer_several_locators_no_hos // Precondition: The writer change it status EXPECT_CALL(database, change_entity_status(EntityId(11), true)).Times(1); + // Expectation: Type already added to the database + EXPECT_CALL(database, is_type_in_database(type_name_)).Times(1) + .WillOnce(Return(true)); + // Expectation: Modify graph and notify user (twice, also from participant update) EXPECT_CALL(database, update_endpoint_in_graph(EntityId(0), EntityId(1), EntityId(2), EntityId(11))).Times(1).WillOnce(Return(