From 0919ff294457546c72d5f8810eb61ec48b67e95e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Dom=C3=ADnguez=20L=C3=B3pez?= <116071334+Mario-DL@users.noreply.github.com> Date: Wed, 22 May 2024 14:36:40 +0200 Subject: [PATCH] Use absolute paths when loading XML files (#4751) * Refs #10173: Add XMLLoadFile unittest Signed-off-by: Mario Dominguez * Refs #10173: Use absolute paths when loading XML files Signed-off-by: Mario Dominguez * Refs #10173: Fix windows.h INTERFACE name collision Signed-off-by: Mario Dominguez * Refs #10173: Avoid MINMAX windows warning as error in unittests Signed-off-by: Mario Dominguez * Refs #10173: Use DEFAULT_FASTDDS_PROFILES for windows Signed-off-by: Mario Dominguez * Refs #10173: Enable internal debug in test Signed-off-by: Mario Dominguez * Refs #10173: Force log info in the test Signed-off-by: Mario Dominguez * Refs #10173: Correct windows FASTDDS_DEFAULT PROFILES env and include fastdds/log instead of fastrtps Signed-off-by: Mario Dominguez --------- Signed-off-by: Mario Dominguez --- src/cpp/xmlparser/XMLParser.cpp | 48 ++++++- src/cpp/xmlparser/XMLParser.h | 12 ++ src/cpp/xmlparser/XMLParserCommon.cpp | 4 +- src/cpp/xmlparser/XMLParserCommon.h | 4 +- src/cpp/xmlparser/XMLProfileManager.cpp | 62 ++++++++- src/cpp/xmlparser/XMLProfileManager.h | 12 ++ test/unittest/dds/status/CMakeLists.txt | 1 + test/unittest/logging/mock/MockConsumer.h | 24 +++- test/unittest/xmlparser/CMakeLists.txt | 92 +++++++++++++ test/unittest/xmlparser/XMLLoadFileTests.cpp | 136 +++++++++++++++++++ 10 files changed, 377 insertions(+), 18 deletions(-) create mode 100644 test/unittest/xmlparser/XMLLoadFileTests.cpp diff --git a/src/cpp/xmlparser/XMLParser.cpp b/src/cpp/xmlparser/XMLParser.cpp index e394a63349b..08867970224 100644 --- a/src/cpp/xmlparser/XMLParser.cpp +++ b/src/cpp/xmlparser/XMLParser.cpp @@ -18,6 +18,11 @@ #include #include #include +#ifdef _WIN32 +#include +#else +#include +#endif // _WIN32 #include @@ -49,7 +54,32 @@ using namespace eprosima::fastdds::xml::detail; XMLP_ret XMLParser::loadDefaultXMLFile( up_base_node_t& root) { - return loadXML(DEFAULT_FASTDDS_PROFILES, root); + // Use absolute path to ensure that the file is loaded only once +#ifdef _WIN32 + char current_directory[MAX_PATH]; + if (GetCurrentDirectory(MAX_PATH, current_directory) == 0) + { + EPROSIMA_LOG_ERROR(XMLPARSER, "GetCurrentDirectory failed " << GetLastError()); + } + else + { + strcat_s(current_directory, MAX_PATH, DEFAULT_FASTDDS_PROFILES); + return loadXML(current_directory, root, true); + } +#else + char current_directory[PATH_MAX]; + if (getcwd(current_directory, PATH_MAX) == NULL) + { + EPROSIMA_LOG_ERROR(XMLPARSER, "getcwd failed " << std::strerror(errno)); + } + else + { + strcat(current_directory, "/"); + strcat(current_directory, DEFAULT_FASTDDS_PROFILES); + return loadXML(current_directory, root, true); + } +#endif // _WIN32 + return XMLP_ret::XML_ERROR; } XMLP_ret XMLParser::parseXML( @@ -421,7 +451,7 @@ XMLP_ret XMLParser::validateXMLTransportElements( strcmp(name, MAX_INITIAL_PEERS_RANGE) == 0 || strcmp(name, WHITE_LIST) == 0 || strcmp(name, NETMASK_FILTER) == 0 || - strcmp(name, INTERFACES) == 0 || + strcmp(name, NETWORK_INTERFACES) == 0 || strcmp(name, TTL) == 0 || strcmp(name, NON_BLOCKING_SEND) == 0 || strcmp(name, UDP_OUTPUT_PORT) == 0 || @@ -606,7 +636,7 @@ XMLP_ret XMLParser::parseXMLSocketTransportData( p_aux1 != nullptr; p_aux1 = p_aux1->NextSiblingElement()) { address = p_aux1->Name(); - if (strcmp(address, ADDRESS) == 0 || strcmp(address, INTERFACE) == 0) + if (strcmp(address, ADDRESS) == 0 || strcmp(address, NETWORK_INTERFACE) == 0) { std::string text = get_element_text(p_aux1); if (!text.empty()) @@ -641,7 +671,7 @@ XMLP_ret XMLParser::parseXMLSocketTransportData( return XMLP_ret::XML_ERROR; } } - else if (strcmp(name, INTERFACES) == 0) + else if (strcmp(name, NETWORK_INTERFACES) == 0) { if (XMLP_ret::XML_OK != parseXMLInterfaces(p_aux0, p_transport)) { @@ -2057,6 +2087,14 @@ XMLP_ret XMLParser::parseXMLConsumer( XMLP_ret XMLParser::loadXML( const std::string& filename, up_base_node_t& root) +{ + return loadXML(filename, root, false); +} + +XMLP_ret XMLParser::loadXML( + const std::string& filename, + up_base_node_t& root, + bool is_default) { if (filename.empty()) { @@ -2067,7 +2105,7 @@ XMLP_ret XMLParser::loadXML( tinyxml2::XMLDocument xmlDoc; if (tinyxml2::XMLError::XML_SUCCESS != xmlDoc.LoadFile(filename.c_str())) { - if (filename != std::string(DEFAULT_FASTDDS_PROFILES)) + if (!is_default) { EPROSIMA_LOG_ERROR(XMLPARSER, "Error opening '" << filename << "'"); } diff --git a/src/cpp/xmlparser/XMLParser.h b/src/cpp/xmlparser/XMLParser.h index fe12c2a39a7..89ce3d32746 100644 --- a/src/cpp/xmlparser/XMLParser.h +++ b/src/cpp/xmlparser/XMLParser.h @@ -121,6 +121,18 @@ class XMLParser const std::string& filename, up_base_node_t& root); + /** + * Load a XML file. + * @param filename Name for the file to be loaded. + * @param root Root node. + * @param is_default Is the default XML file. + * @return XMLP_ret::XML_OK on success, XMLP_ret::XML_ERROR in other case. + */ + static XMLP_ret loadXML( + const std::string& filename, + up_base_node_t& root, + bool is_default); + /** * Load a XML data from buffer. * @param data XML data to load. diff --git a/src/cpp/xmlparser/XMLParserCommon.cpp b/src/cpp/xmlparser/XMLParserCommon.cpp index 11b01382b21..1c15c3263d5 100644 --- a/src/cpp/xmlparser/XMLParserCommon.cpp +++ b/src/cpp/xmlparser/XMLParserCommon.cpp @@ -48,9 +48,9 @@ const char* SEND_BUFFER_SIZE = "sendBufferSize"; const char* TTL = "TTL"; const char* NON_BLOCKING_SEND = "non_blocking_send"; const char* WHITE_LIST = "interfaceWhiteList"; -const char* INTERFACE = "interface"; +const char* NETWORK_INTERFACE = "interface"; const char* NETMASK_FILTER = "netmask_filter"; -const char* INTERFACES = "interfaces"; +const char* NETWORK_INTERFACES = "interfaces"; const char* ALLOWLIST = "allowlist"; const char* BLOCKLIST = "blocklist"; const char* MAX_MESSAGE_SIZE = "maxMessageSize"; diff --git a/src/cpp/xmlparser/XMLParserCommon.h b/src/cpp/xmlparser/XMLParserCommon.h index d157facebb2..784d802c824 100644 --- a/src/cpp/xmlparser/XMLParserCommon.h +++ b/src/cpp/xmlparser/XMLParserCommon.h @@ -61,9 +61,9 @@ extern const char* SEND_BUFFER_SIZE; extern const char* TTL; extern const char* NON_BLOCKING_SEND; extern const char* WHITE_LIST; -extern const char* INTERFACE; +extern const char* NETWORK_INTERFACE; extern const char* NETMASK_FILTER; -extern const char* INTERFACES; +extern const char* NETWORK_INTERFACES; extern const char* ALLOWLIST; extern const char* BLOCKLIST; extern const char* MAX_MESSAGE_SIZE; diff --git a/src/cpp/xmlparser/XMLProfileManager.cpp b/src/cpp/xmlparser/XMLProfileManager.cpp index 8b8a671d124..4e0e084b3cd 100644 --- a/src/cpp/xmlparser/XMLProfileManager.cpp +++ b/src/cpp/xmlparser/XMLProfileManager.cpp @@ -17,7 +17,9 @@ #include #ifdef _WIN32 #include -#endif // ifdef _WIN32 +#else +#include +#endif // _WIN32 #include @@ -197,10 +199,21 @@ void XMLProfileManager::loadDefaultXMLFile() // Try to load the default XML file set with an environment variable. #ifdef _WIN32 char file_path[MAX_PATH]; + char absolute_path[MAX_PATH]; + char current_directory[MAX_PATH]; + char** filename = {nullptr}; size_t size = MAX_PATH; if (getenv_s(&size, file_path, size, DEFAULT_FASTDDS_ENV_VARIABLE) == 0 && size > 0) { - loadXMLFile(file_path); + // Use absolute path to ensure the file is loaded only once + if (GetFullPathName(file_path, MAX_PATH, absolute_path, filename) == 0) + { + EPROSIMA_LOG_ERROR(XMLPARSER, "GetFullPathName failed " << GetLastError()); + } + else + { + loadXMLFile(absolute_path); + } } // Should take into account '\0' @@ -210,13 +223,32 @@ void XMLProfileManager::loadDefaultXMLFile() // Try to load the default XML file if variable does not exist or is not set to '1' if (!(getenv_s(&size, skip_xml, size, SKIP_DEFAULT_XML_FILE) == 0 && skip_xml[0] == '1')) { - loadXMLFile(DEFAULT_FASTDDS_PROFILES); + // Try to load the default XML file. + if (GetCurrentDirectory(MAX_PATH, current_directory) == 0) + { + EPROSIMA_LOG_ERROR(XMLPARSER, "GetCurrentDirectory failed " << GetLastError()); + } + else + { + strcat_s(current_directory, MAX_PATH, "\\"); + strcat_s(current_directory, MAX_PATH, DEFAULT_FASTDDS_PROFILES); + loadXMLFile(current_directory, true); + } } #else + char absolute_path[PATH_MAX]; if (const char* file_path = std::getenv(DEFAULT_FASTDDS_ENV_VARIABLE)) { - loadXMLFile(file_path); + char* res = realpath(file_path, absolute_path); + if (res) + { + loadXMLFile(absolute_path); + } + else + { + EPROSIMA_LOG_ERROR(XMLPARSER, "realpath failed " << std::strerror(errno)); + } } const char* skip_xml = std::getenv(SKIP_DEFAULT_XML_FILE); @@ -224,7 +256,16 @@ void XMLProfileManager::loadDefaultXMLFile() // Try to load the default XML file if variable does not exist or is not set to '1' if (!(skip_xml != nullptr && skip_xml[0] == '1')) { - loadXMLFile(DEFAULT_FASTDDS_PROFILES); + if (getcwd(absolute_path, PATH_MAX) == NULL) + { + EPROSIMA_LOG_ERROR(XMLPARSER, "getcwd failed " << std::strerror(errno)); + } + else + { + strcat(absolute_path, "/"); + strcat(absolute_path, DEFAULT_FASTDDS_PROFILES); + loadXMLFile(absolute_path, true); + } } #endif // ifdef _WIN32 @@ -310,6 +351,13 @@ XMLP_ret XMLProfileManager::loadXMLNode( XMLP_ret XMLProfileManager::loadXMLFile( const std::string& filename) +{ + return loadXMLFile(filename, false); +} + +XMLP_ret XMLProfileManager::loadXMLFile( + const std::string& filename, + bool is_default) { if (filename.empty()) { @@ -325,10 +373,10 @@ XMLP_ret XMLProfileManager::loadXMLFile( } up_base_node_t root_node; - XMLP_ret loaded_ret = XMLParser::loadXML(filename, root_node); + XMLP_ret loaded_ret = XMLParser::loadXML(filename, root_node, is_default); if (!root_node || loaded_ret != XMLP_ret::XML_OK) { - if (filename != std::string(DEFAULT_FASTDDS_PROFILES)) + if (!is_default) { EPROSIMA_LOG_ERROR(XMLPARSER, "Error parsing '" << filename << "'"); } diff --git a/src/cpp/xmlparser/XMLProfileManager.h b/src/cpp/xmlparser/XMLProfileManager.h index fb1c449d092..9f133b8f356 100644 --- a/src/cpp/xmlparser/XMLProfileManager.h +++ b/src/cpp/xmlparser/XMLProfileManager.h @@ -73,6 +73,18 @@ class XMLProfileManager static XMLP_ret loadXMLFile( const std::string& filename); + /** + * Load a profiles XML file. + * @param filename Name for the file to be loaded. + * @param is_default Flag to indicate if the file is a default profiles file. + * @return XMLP_ret::XML_OK if all profiles are correct, XMLP_ret::XML_NOK if some are and some are not, + * XMLP_ret::XML_ERROR in other case. + */ + + static XMLP_ret loadXMLFile( + const std::string& filename, + bool is_default); + /** * Load a profiles XML string. * @param data Buffer containing the data. diff --git a/test/unittest/dds/status/CMakeLists.txt b/test/unittest/dds/status/CMakeLists.txt index 711073a5c04..872b77ecc49 100644 --- a/test/unittest/dds/status/CMakeLists.txt +++ b/test/unittest/dds/status/CMakeLists.txt @@ -136,6 +136,7 @@ target_compile_definitions(ListenerTests PRIVATE $<$>,$>:__DEBUG> $<$:__INTERNALDEBUG> # Internal debug activated. $<$:_ENABLE_ATOMIC_ALIGNMENT_FIX> + $<$:NOMINMAX> # avoid conflic with std::min & std::max in visual studio ) target_include_directories(ListenerTests PRIVATE ${Asio_INCLUDE_DIR} diff --git a/test/unittest/logging/mock/MockConsumer.h b/test/unittest/logging/mock/MockConsumer.h index 0337ad23c5d..d39f5038145 100644 --- a/test/unittest/logging/mock/MockConsumer.h +++ b/test/unittest/logging/mock/MockConsumer.h @@ -60,10 +60,20 @@ class MockConsumer : public StdoutConsumer template void wait( - Pred pred) + Pred pred, + std::chrono::seconds timeout = std::chrono::seconds::zero()) { std::unique_lock lock(mMutex); - cv_.wait(lock, pred); + + if (timeout == std::chrono::seconds::zero()) + { + cv_.wait(lock, pred); + } + else + { + cv_.wait_for(lock, timeout, pred); + } + } void wait_for_at_least_entries( @@ -75,6 +85,16 @@ class MockConsumer : public StdoutConsumer }); } + void wait_for_at_least_entries_for( + size_t num_entries, + std::chrono::seconds timeout) + { + return wait([this, num_entries]() -> bool + { + return mEntriesConsumed.size() >= num_entries; + }, timeout); + } + void clear_entries() { std::unique_lock guard(mMutex); diff --git a/test/unittest/xmlparser/CMakeLists.txt b/test/unittest/xmlparser/CMakeLists.txt index a5575b364fe..a8bb8358570 100644 --- a/test/unittest/xmlparser/CMakeLists.txt +++ b/test/unittest/xmlparser/CMakeLists.txt @@ -132,6 +132,7 @@ target_compile_definitions(XMLProfileParserTests PRIVATE ASIO_STANDALONE $<$>,$>:__DEBUG> $<$:__INTERNALDEBUG> # Internal debug activated. + $<$:NOMINMAX> # avoid conflic with std::min & std::max in visual studio ) target_include_directories(XMLProfileParserTests PRIVATE ${PROJECT_SOURCE_DIR}/test/mock/dds/TypeObjectRegistry @@ -221,6 +222,7 @@ target_compile_definitions(XMLParserTests PRIVATE ASIO_STANDALONE $<$>,$>:__DEBUG> $<$:__INTERNALDEBUG> # Internal debug activated. + $<$:NOMINMAX> # avoid conflic with std::min & std::max in visual studio ) target_include_directories(XMLParserTests PRIVATE ${PROJECT_SOURCE_DIR}/test/mock/dds/TypeObjectRegistry @@ -373,3 +375,93 @@ if(QNX) target_link_libraries(XMLEndpointParserTests socket) endif() gtest_discover_tests(XMLEndpointParserTests) + +###################################### XMLLoadFileTests ###################################################### +set(XMLLOADFILE_SOURCE + XMLLoadFileTests.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/WriterQos.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/ReaderQos.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/TopicDataType.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/xtypes/exception/Exception.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/ThreadSettings.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/LocatorWithMask.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Time_t.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/FlowControllerConsts.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/ThroughputControllerDescriptor.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/network/utils/netmask_filter.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/network/utils/network.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/network/NetmaskFilterKind.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/network/NetworkInterface.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/network/NetworkInterfaceWithFilter.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/PortBasedTransportDescriptor.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/utils/string_convert.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/utils/UnitsParser.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/xmlparser/XMLDynamicParser.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/xmlparser/XMLElementParser.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/xmlparser/XMLParser.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/xmlparser/XMLParserCommon.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/xmlparser/XMLProfileManager.cpp + + # locators + ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPFinder.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/utils/SystemInfo.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/utils/UnitsParser.cpp + ) + +# External sources +if(TINYXML2_SOURCE_DIR) + list(APPEND XMLLOADFILE_SOURCE + ${TINYXML2_SOURCE_DIR}/tinyxml2.cpp + ) +endif() + +if(ANDROID) + if (ANDROID_NATIVE_API_LEVEL LESS 24) + list(APPEND XMLLOADFILE_SOURCE + ${ANDROID_IFADDRS_SOURCE_DIR}/ifaddrs.c + ) + endif() +endif() + +add_executable(XMLLoadFileTests ${XMLLOADFILE_SOURCE}) +target_compile_definitions(XMLLoadFileTests PRIVATE + BOOST_ASIO_STANDALONE + ASIO_STANDALONE + $<$:NOMINMAX> # avoid conflict with std::min & std::max in visual studio + $<$>,$>:__DEBUG> + $<$:__INTERNALDEBUG> # Internal debug activated. + HAVE_LOG_NO_INFO=0 FASTDDS_ENFORCE_LOG_INFO # Need LOG_INFO in this test + ) +target_include_directories(XMLLoadFileTests PRIVATE + ${PROJECT_SOURCE_DIR}/test/mock/dds/TypeObjectRegistry + ${PROJECT_SOURCE_DIR}/test/mock/dds/TypeObjectUtils + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSDomainImpl # Dependency of fastdds::xtypes::type_representation + ${PROJECT_SOURCE_DIR}/test/mock/rtps/SharedMemTransportDescriptor + ${PROJECT_SOURCE_DIR}/test/mock/rtps/TCPTransportDescriptor + ${PROJECT_SOURCE_DIR}/test/mock/rtps/TCPv4TransportDescriptor + ${PROJECT_SOURCE_DIR}/test/mock/rtps/TCPv6TransportDescriptor + ${PROJECT_SOURCE_DIR}/test/mock/rtps/UDPTransportDescriptor + ${PROJECT_SOURCE_DIR}/test/mock/rtps/UDPv4TransportDescriptor + ${PROJECT_SOURCE_DIR}/test/mock/rtps/UDPv6TransportDescriptor + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSParticipantAttributes + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_BINARY_DIR}/include + ${PROJECT_SOURCE_DIR}/src/cpp + ${Asio_INCLUDE_DIR} + $<$:${ANDROID_IFADDRS_INCLUDE_DIR}> + ) + +target_link_libraries(XMLLoadFileTests GTest::gtest + $<$:iphlpapi$Shlwapi> + $<$:ws2_32> + ${TINYXML2_LIBRARY} + fastcdr + fastdds::log + fastdds::xtypes::dynamic-types::impl + ) +if(QNX) + target_link_libraries(XMLLoadFileTests socket) +endif() +gtest_discover_tests(XMLLoadFileTests) diff --git a/test/unittest/xmlparser/XMLLoadFileTests.cpp b/test/unittest/xmlparser/XMLLoadFileTests.cpp new file mode 100644 index 00000000000..557170d7710 --- /dev/null +++ b/test/unittest/xmlparser/XMLLoadFileTests.cpp @@ -0,0 +1,136 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#ifdef _WIN32 +#include +#else +#include +#include +#endif // ifdef _WIN32 + +#include +#include +#include "../logging/mock/MockConsumer.h" + +#include +#include + +using namespace eprosima::fastdds::dds; +using namespace eprosima::fastrtps; +using namespace ::testing; + +class XMLLoadFileTests : public ::testing::Test +{ +public: + + void helper_block_for_at_least_entries_for( + uint32_t amount, + std::chrono::seconds timeout) + { + mock_consumer_->wait_for_at_least_entries_for( + amount, + timeout); + } + +protected: + + void SetUp() override + { + mock_consumer_ = new eprosima::fastdds::dds::MockConsumer(); + log_consumer_.reset(mock_consumer_); + } + + void TearDown() override + { + //! mock_consumer_ is going to be cleared in log_consumer_ destructor + } + + eprosima::fastdds::dds::MockConsumer* mock_consumer_; + std::unique_ptr log_consumer_; + +private: + + std::mutex xml_mutex_; +}; + +/* + * This test checks that the default XML file is loaded only once when there is a DEFAULT_FASTDDS_PROFILES.xml file + * in the current directory and the environment variable FASTRTPS_DEFAULT_PROFILES_FILE is set pointing to the same + * file. + * 1. Initialize Mock Consumer to consume the LogInfo entry that the library generates when the file has been already + * parsed. Set filters to consume only the desired entry. + * 2. Get current path to set the environment variable to the DEFAULT_FASTDDS_PROFILES.xml file. + * 3. Write the DEFAULT_FASTDDS_PROFILES.xml file in the current directory. + * 4. Load the default XML file. + * 5. Wait for the log entry to be consumed. + */ +TEST_F(XMLLoadFileTests, load_twice_default_xml) +{ + // Register Mock Consumer + Log::ClearConsumers(); + Log::RegisterConsumer(std::move(log_consumer_)); + Log::SetVerbosity(Log::Info); + Log::SetCategoryFilter(std::regex("(XMLPARSER)")); + Log::SetErrorStringFilter(std::regex("(already parsed)")); + + // Current directory +#ifdef _WIN32 + char current_directory[MAX_PATH]; + uint32_t ret = GetCurrentDirectory(MAX_PATH, current_directory); + ASSERT_NE(ret, 0u); + strcat_s(current_directory, MAX_PATH, "\\"); + strcat_s(current_directory, MAX_PATH, xmlparser::DEFAULT_FASTDDS_PROFILES); + // Set environment variable + _putenv_s("FASTDDS_DEFAULT_PROFILES_FILE", current_directory); +#else + char current_directory[PATH_MAX]; + ASSERT_NE(getcwd(current_directory, PATH_MAX), (void*)NULL); + strcat(current_directory, "/"); + strcat(current_directory, xmlparser::DEFAULT_FASTDDS_PROFILES); + // Set environment variable + setenv("FASTDDS_DEFAULT_PROFILES_FILE", current_directory, 1); +#endif // _WIN32 + + // Write DEFAULT_FASTDDS_PROFILES.xml + std::ofstream xmlFile; + xmlFile.open("DEFAULT_FASTDDS_PROFILES.xml"); + xmlFile << ""; + xmlFile << ""; + xmlFile << "truetest_name"; + xmlFile << ""; + xmlFile.close(); + + // Load default XML file + xmlparser::XMLProfileManager::loadDefaultXMLFile(); + + // Log consumer + helper_block_for_at_least_entries_for(1, std::chrono::seconds(2)); + auto consumed_entries = mock_consumer_->ConsumedEntries(); + EXPECT_EQ(consumed_entries.size(), 1u); + + Log::Reset(); + Log::KillThread(); + + std::remove("DEFAULT_FASTDDS_PROFILES.xml"); +} + +int main( + int argc, + char** argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}