From def3c10d00d2da78eafcc7acd44e97de13e52dfd Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Tue, 31 Oct 2023 14:48:24 +0000 Subject: [PATCH 01/10] Remove duplicated functionality from test_config Signed-off-by: Michael Carroll --- log/src/CMakeLists.txt | 9 +- log/src/Log_TEST.cc | 10 +- log/test/CMakeLists.txt | 4 - log/test/integration/CMakeLists.txt | 46 +-- log/test/integration/ChirpParams.cc | 57 ++++ log/test/integration/ChirpParams.hh | 184 ++---------- log/test/integration/playback.cc | 46 +-- log/test/integration/recorder.cc | 30 +- log/test/integration/topicChirp_aux.cc | 11 +- log/test/test_config.hh.in | 24 -- src/CIface_TEST.cc | 9 +- src/Discovery_TEST.cc | 34 +-- src/Helpers_TEST.cc | 5 +- src/NodeOptions_TEST.cc | 7 +- src/Node_TEST.cc | 9 +- src/cmd/CMakeLists.txt | 10 +- src/cmd/cmdtransport.rb.in | 1 + src/cmd/gz_TEST.cc | 282 +++++------------- src/cmd/gz_src_TEST.cc | 7 +- test/integration/CMakeLists.txt | 31 +- test/integration/authPubSub.cc | 25 +- .../authPubSubSubscriberInvalid_aux.cc | 9 +- test/integration/fastPub_aux.cc | 5 +- test/integration/pub_aux.cc | 5 +- test/integration/pub_aux_throttled.cc | 7 +- test/integration/scopedTopic.cc | 18 +- test/integration/scopedTopicSubscriber_aux.cc | 5 +- test/integration/statistics.cc | 7 +- test/integration/twoProcsPubSub.cc | 120 ++------ .../twoProcsPubSubSubscriber_aux.cc | 7 +- test/integration/twoProcsPublisher_aux.cc | 5 +- test/integration/twoProcsSrvCall.cc | 69 +---- .../twoProcsSrvCallReplierInc_aux.cc | 5 +- .../integration/twoProcsSrvCallReplier_aux.cc | 5 +- test/integration/twoProcsSrvCallStress.cc | 19 +- test/integration/twoProcsSrvCallSync1.cc | 21 +- .../twoProcsSrvCallWithoutInput.cc | 64 ++-- ...oProcsSrvCallWithoutInputReplierInc_aux.cc | 5 +- .../twoProcsSrvCallWithoutInputReplier_aux.cc | 5 +- .../twoProcsSrvCallWithoutInputStress.cc | 20 +- .../twoProcsSrvCallWithoutInputSync1.cc | 22 +- .../twoProcsSrvCallWithoutOutput.cc | 42 +-- ...ProcsSrvCallWithoutOutputReplierInc_aux.cc | 5 +- ...twoProcsSrvCallWithoutOutputReplier_aux.cc | 5 +- .../twoProcsSrvCallWithoutOutputStress.cc | 20 +- test/test_config.hh.in | 201 +------------ 46 files changed, 499 insertions(+), 1038 deletions(-) create mode 100644 log/test/integration/ChirpParams.cc delete mode 100644 log/test/test_config.hh.in diff --git a/log/src/CMakeLists.txt b/log/src/CMakeLists.txt index 4a9398da4..c285c0efb 100644 --- a/log/src/CMakeLists.txt +++ b/log/src/CMakeLists.txt @@ -24,9 +24,11 @@ gz_build_tests( ) foreach(test_target ${logging_tests}) - - set_tests_properties(${logging_tests} PROPERTIES + set_tests_properties(${test_target} PROPERTIES ENVIRONMENT GZ_TRANSPORT_LOG_SQL_PATH=${PROJECT_SOURCE_DIR}/log/sql) + target_compile_definitions(${test_target} PRIVATE + "CORRUPT_DB_TEST_PATH=\"${CMAKE_SOURCE_DIR}/log/test/data/state.tlog\"" + ) endforeach() @@ -46,9 +48,6 @@ install(DIRECTORY ../sql DESTINATION ${SCHEMA_INSTALL_BASE}) set(SCHEMA_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/${SCHEMA_INSTALL_BASE}/sql) configure_file(build_config.hh.in build_config.hh @ONLY) - -message(STATUS "CMAKE_CURRENT_SOURCE_DIR:${CMAKE_CURRENT_SOURCE_DIR}") - target_include_directories(${log_lib_target} PUBLIC # Add this component's include directory to the build interface include diff --git a/log/src/Log_TEST.cc b/log/src/Log_TEST.cc index f1d683cf8..4ac008344 100644 --- a/log/src/Log_TEST.cc +++ b/log/src/Log_TEST.cc @@ -22,13 +22,16 @@ #include "gz/transport/log/Log.hh" #include "test_config.hh" -#include "log/test_config.hh" #include "gtest/gtest.h" using namespace gz; using namespace gz::transport; using namespace std::chrono_literals; +namespace { +constexpr const char * kCorruptDbTestPath = CORRUPT_DB_TEST_PATH; +} + ////////////////////////////////////////////////// TEST(Log, OpenMemoryDatabase) { @@ -251,10 +254,7 @@ TEST(Log, NullDescriptorUnopenedLog) TEST(Log, OpenCorruptDatabase) { log::Log logFile; - std::string path = - testing::portablePathUnion(GZ_TRANSPORT_LOG_TEST_PATH, "data"); - path = testing::portablePathUnion(path, "state.tlog"); - logFile.Open(path); + logFile.Open(kCorruptDbTestPath); EXPECT_GT(logFile.EndTime(), 0ns) << "logFile.EndTime() == " << logFile.EndTime().count() << "ns";; } diff --git a/log/test/CMakeLists.txt b/log/test/CMakeLists.txt index c11c67f90..26e40e61e 100644 --- a/log/test/CMakeLists.txt +++ b/log/test/CMakeLists.txt @@ -1,5 +1 @@ -configure_file (test_config.hh.in - ${PROJECT_BINARY_DIR}/include/log/test_config.hh -) - add_subdirectory(integration) diff --git a/log/test/integration/CMakeLists.txt b/log/test/integration/CMakeLists.txt index 3459c8aa9..5537f4511 100644 --- a/log/test/integration/CMakeLists.txt +++ b/log/test/integration/CMakeLists.txt @@ -1,5 +1,14 @@ # Integration tests + +add_library(ChirpParams STATIC ./ChirpParams.cc) +target_link_libraries(ChirpParams PUBLIC ${PROJECT_LIBRARY_TARGET_NAME}-log ${EXTRA_TEST_LIB_DEPS}) +target_compile_definitions(ChirpParams + PRIVATE TOPIC_CHIRP_EXE="$") + +gz_add_executable(topicChirp_aux topicChirp_aux.cc) +target_link_libraries(topicChirp_aux ChirpParams) + gz_build_tests( TYPE "INTEGRATION" TEST_LIST logging_tests @@ -8,6 +17,7 @@ gz_build_tests( playback.cc query.cc LIB_DEPS + ChirpParams ${PROJECT_LIBRARY_TARGET_NAME}-log ${EXTRA_TEST_LIB_DEPS} INCLUDE_DIRS @@ -21,48 +31,12 @@ if (UNIX AND NOT APPLE) endif() foreach(test_target ${logging_tests}) - set_tests_properties(${test_target} PROPERTIES ENVIRONMENT GZ_TRANSPORT_LOG_SQL_PATH=${PROJECT_SOURCE_DIR}/log/sql) target_compile_definitions(${test_target} PRIVATE GZ_TRANSPORT_LOG_SQL_PATH="${PROJECT_SOURCE_DIR}/log/sql") - target_compile_definitions(${test_target} - PRIVATE GZ_TRANSPORT_LOG_BUILD_PATH="$") - endforeach() -set (aux - topicChirp_aux.cc -) - -foreach(source_file ${aux}) - string(REGEX REPLACE ".cc" "" AUX_EXECUTABLE ${source_file}) - set(BINARY_NAME ${TEST_TYPE}_${AUX_EXECUTABLE}) - - gz_add_executable(${BINARY_NAME} ${AUX_EXECUTABLE}.cc) - - # Include the interface directories that we always need. - gz_target_interface_include_directories(${BINARY_NAME} - ${PROJECT_LIBRARY_TARGET_NAME}) - - # Link the libraries that we always need. - target_link_libraries(${BINARY_NAME} - PRIVATE - ${PROJECT_LIBRARY_TARGET_NAME} - ${log_lib_target} - gtest - ${EXTRA_TEST_LIB_DEPS} - ) - - if(UNIX) - # pthread is only available on Unix machines - target_link_libraries(${BINARY_NAME} - PRIVATE pthread) - endif() - - target_compile_definitions(${BINARY_NAME} - PRIVATE GZ_TRANSPORT_LOG_BUILD_PATH="$") -endforeach() # gz log CLI test if (HAVE_GZ_TOOLS) diff --git a/log/test/integration/ChirpParams.cc b/log/test/integration/ChirpParams.cc new file mode 100644 index 000000000..1f606f1d6 --- /dev/null +++ b/log/test/integration/ChirpParams.cc @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * 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 "ChirpParams.hh" + + +static constexpr const char* kTopicChirpExe = TOPIC_CHIRP_EXE; + +namespace gz::transport::log::test +{ + ////////////////////////////////////////////////// + /// \brief Similar to testing::forkAndRun(), except this function + /// specifically calls the INTEGRATION_topicChirp_aux process and passes + /// it arguments to determine how it should chirp out messages over its + /// topics. + /// \param _topics A list of topic names to chirp on + /// \param _chirps The number of messages to chirp out. Each message + /// will count up starting from the value 1 and ending with the value + /// _chirps. + /// \return A handle to the process. This can be used with + /// testing::waitAndCleanupFork(). + gz::utils::Subprocess BeginChirps( + const std::vector &_topics, + const int _chirps, + const std::string &_partitionName) + { + // Argument list: + // [0]: Executable name + // [1]: Partition name + // [2]: Number of chirps + // [3]-[N]: Each topic name + // [N+1]: Null terminator, required by execv + const std::size_t numArgs = 3 + _topics.size() + 1; + + std::vector strArgs; + strArgs.reserve(numArgs-1); + strArgs.push_back(kTopicChirpExe); + strArgs.push_back(_partitionName); + strArgs.push_back(std::to_string(_chirps)); + strArgs.insert(strArgs.end(), _topics.begin(), _topics.end()); + return gz::utils::Subprocess(strArgs); + } +} // namespace gz::transport::log::test diff --git a/log/test/integration/ChirpParams.hh b/log/test/integration/ChirpParams.hh index 5a4ddaec4..e194cac84 100644 --- a/log/test/integration/ChirpParams.hh +++ b/log/test/integration/ChirpParams.hh @@ -18,162 +18,44 @@ #ifndef GZ_TRANSPORT_LOG_TEST_INTEGRATION_CHIRPPARAMS_HH_ #define GZ_TRANSPORT_LOG_TEST_INTEGRATION_CHIRPPARAMS_HH_ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4251) -#endif -#include -#ifdef _MSC_VER -#pragma warning(pop) -#endif -#include - #include #include +#include #include +#include - -namespace gz +namespace gz::transport::log::test { - namespace transport - { - namespace log - { - namespace test - { - /// \brief Parameter used to determine how long the topicChirp_aux - /// program will wait between emitting message chirps from its topic. - /// Value is in milliseconds. - const int DelayBetweenChirps_ms = 1; - - /// \brief Parameter used to determine how long the topicChirp_aux - /// program will wait (after it advertises) before it begins publishing - /// its message chirps. Value is in milliseconds. - const int DelayBeforePublishing_ms = 1000; - - /// \brief This is the message type that will be used by the chirping - /// topics. - using ChirpMsgType = gz::msgs::Int32; - - - ////////////////////////////////////////////////// - /// \brief Similar to testing::forkAndRun(), except this function - /// specifically calls the INTEGRATION_topicChirp_aux process and passes - /// it arguments to determine how it should chirp out messages over its - /// topics. - /// \param _topics A list of topic names to chirp on - /// \param _chirps The number of messages to chirp out. Each message - /// will count up starting from the value 1 and ending with the value - /// _chirps. - /// \return A handle to the process. This can be used with - /// testing::waitAndCleanupFork(). - testing::forkHandlerType BeginChirps( - const std::vector &_topics, - const int _chirps, - const std::string &_partitionName) - { - // Set the chirping process name - const std::string process = - GZ_TRANSPORT_LOG_BUILD_PATH"/INTEGRATION_topicChirp_aux"; - - // Argument list: - // [0]: Executable name - // [1]: Partition name - // [2]: Number of chirps - // [3]-[N]: Each topic name - // [N+1]: Null terminator, required by execv - const std::size_t numArgs = 3 + _topics.size() + 1; - - std::vector strArgs; - strArgs.reserve(numArgs-1); - strArgs.push_back(process); - strArgs.push_back(_partitionName); - strArgs.push_back(std::to_string(_chirps)); - strArgs.insert(strArgs.end(), _topics.begin(), _topics.end()); - - #ifdef _MSC_VER - std::string fullArgs; - for (std::size_t i = 0; i < strArgs.size(); ++i) - { - if (i == 0) - { - // Windows prefers quotes around the process name - fullArgs += "\""; - } - else - { - fullArgs += " "; - } - - fullArgs += strArgs[i]; - - if (i == 0) - { - fullArgs += "\""; - } - } - - char * args = new char[fullArgs.size()+1]; - std::snprintf(args, fullArgs.size()+1, "%s", fullArgs.c_str()); - - STARTUPINFO info = {sizeof(info)}; - PROCESS_INFORMATION processInfo; - - if (!CreateProcess(nullptr, args, nullptr, nullptr, - TRUE, 0, nullptr, nullptr, &info, &processInfo)) - { - std::cerr << "Error running the chirp process [" - << args << "]\n"; - } - - delete[] args; - - return processInfo; - #else - // Create a raw char* array to pass to execv - char * * args = new char*[numArgs]; - - // Allocate a char array for each argument and copy the data to it - for (std::size_t i = 0; i < strArgs.size(); ++i) - { - const std::string &arg = strArgs[i]; - args[i] = new char[arg.size()+1]; - std::snprintf(args[i], arg.size()+1, "%s", arg.c_str()); - } - - // The last item in the char array must be a nullptr, according to the - // documentation of execv - args[numArgs-1] = nullptr; - - testing::forkHandlerType pid = fork(); - - if (pid == 0) - { - if (execv(process.c_str(), args) == -1) - { - int err = errno; - std::cerr << "Error running the chirp process [" << err << "]: " - << strerror(err) << "\n"; - } - } - - // Clean up the array of arguments - for (std::size_t i = 0; i < numArgs; ++i) - { - char *arg = args[i]; - delete[] arg; - arg = nullptr; - } - delete[] args; - args = nullptr; - - return pid; - #endif - } - } - } - } -} + /// \brief Parameter used to determine how long the topicChirp_aux + /// program will wait between emitting message chirps from its topic. + /// Value is in milliseconds. + const int DelayBetweenChirps_ms = 1; + + /// \brief Parameter used to determine how long the topicChirp_aux + /// program will wait (after it advertises) before it begins publishing + /// its message chirps. Value is in milliseconds. + const int DelayBeforePublishing_ms = 1000; + + /// \brief This is the message type that will be used by the chirping + /// topics. + using ChirpMsgType = gz::msgs::Int32; + + ////////////////////////////////////////////////// + /// \brief Similar to testing::forkAndRun(), except this function + /// specifically calls the INTEGRATION_topicChirp_aux process and passes + /// it arguments to determine how it should chirp out messages over its + /// topics. + /// \param _topics A list of topic names to chirp on + /// \param _chirps The number of messages to chirp out. Each message + /// will count up starting from the value 1 and ending with the value + /// _chirps. + /// \return A handle to the process. This can be used with + /// testing::waitAndCleanupFork(). + gz::utils::Subprocess BeginChirps( + const std::vector &_topics, + const int _chirps, + const std::string &_partitionName); +} // namespace gz::transport::log::test #endif diff --git a/log/test/integration/playback.cc b/log/test/integration/playback.cc index 7ad283fa5..df892ec05 100644 --- a/log/test/integration/playback.cc +++ b/log/test/integration/playback.cc @@ -21,9 +21,13 @@ #include #include #include + +#include #include +#include #include "ChirpParams.hh" +#include "test_config.hh" static std::string partition; @@ -123,11 +127,11 @@ TEST(playback, GZ_UTILS_TEST_DISABLED_ON_MAC(ReplayLog)) recorder.Start(logName)); const int numChirps = 100; - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -224,11 +228,11 @@ TEST(playback, GZ_UTILS_TEST_DISABLED_ON_MAC(ReplayLogRegex)) recorder.Start(logName)); const int numChirps = 100; - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -291,11 +295,11 @@ TEST(playback, GZ_UTILS_TEST_DISABLED_ON_MAC(RemoveTopic)) recorder.Start(logName)); const int numChirps = 100; - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -402,11 +406,11 @@ TEST(playback, GZ_UTILS_TEST_DISABLED_ON_MAC(ReplayLogMoveInstances)) recorder.Start(logName)); const int numChirps = 100; - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -469,11 +473,11 @@ TEST(playback, GZ_UTILS_TEST_DISABLED_ON_MAC(ReplayPauseResume)) recorder.Start(logName)); const int numChirps = 100; - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -591,11 +595,11 @@ TEST(playback, GZ_UTILS_TEST_DISABLED_ON_MAC(ReplayStep)) recorder.Start(logName)); const int numChirps = 100; - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -707,11 +711,11 @@ TEST(playback, GZ_UTILS_TEST_DISABLED_ON_MAC(ReplaySeek)) recorder.Start(logName)); const int numChirps = 100; - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -800,17 +804,17 @@ int main(int argc, char **argv) partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", partition); - setenv("GZ_TRANSPORT_LOG_SQL_PATH", - GZ_TRANSPORT_LOG_SQL_PATH, 1); + gz::utils::setenv("GZ_TRANSPORT_LOG_SQL_PATH", + GZ_TRANSPORT_LOG_SQL_PATH); // TODO(CH3): Deprecated. Remove this on tick-tock. - setenv("IGN_TRANSPORT_LOG_SQL_PATH", - GZ_TRANSPORT_LOG_SQL_PATH, 1); + gz::utils::setenv("IGN_TRANSPORT_LOG_SQL_PATH", + GZ_TRANSPORT_LOG_SQL_PATH); - setenv(gz::transport::log::SchemaLocationEnvVar.c_str(), - GZ_TRANSPORT_LOG_SQL_PATH, 1); + gz::utils::setenv(gz::transport::log::SchemaLocationEnvVar, + GZ_TRANSPORT_LOG_SQL_PATH); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/log/test/integration/recorder.cc b/log/test/integration/recorder.cc index 333d111a2..ff6eade39 100644 --- a/log/test/integration/recorder.cc +++ b/log/test/integration/recorder.cc @@ -24,8 +24,12 @@ #include #include #include + +#include #include +#include "test_config.hh" + #include "ChirpParams.hh" static std::string partition; @@ -94,11 +98,11 @@ TEST(recorder, EXPECT_EQ(logName, recorder.Filename()); const int numChirps = 100; - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -158,7 +162,7 @@ TEST(recorder, BeginRecordingTopicsAfterAdvertisement) const int numChirps = static_cast( std::ceil(secondsToChirpFor * 1000.0/static_cast(delay_ms))); - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); const int waitBeforeSubscribing_ms = @@ -180,7 +184,7 @@ TEST(recorder, BeginRecordingTopicsAfterAdvertisement) gz::transport::log::RecorderError::SUCCESS); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -231,11 +235,11 @@ void RecordPatternBeforeAdvertisement(const std::regex &_pattern) gz::transport::log::RecorderError::SUCCESS); const int numChirps = 100; - testing::forkHandlerType chirper = + auto chirper = gz::transport::log::test::BeginChirps(topics, numChirps, partition); // Wait for the chirping to finish - testing::waitAndCleanupFork(chirper); + chirper.Join(); // Wait to make sure our callbacks are done processing the incoming messages std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -538,17 +542,17 @@ int main(int argc, char **argv) partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", partition); - setenv("GZ_TRANSPORT_LOG_SQL_PATH", - GZ_TRANSPORT_LOG_SQL_PATH, 1); + gz::utils::setenv("GZ_TRANSPORT_LOG_SQL_PATH", + GZ_TRANSPORT_LOG_SQL_PATH); // TODO(CH3): Deprecated. Remove this on tick-tock. - setenv("IGN_TRANSPORT_LOG_SQL_PATH", - GZ_TRANSPORT_LOG_SQL_PATH, 1); + gz::utils::setenv("IGN_TRANSPORT_LOG_SQL_PATH", + GZ_TRANSPORT_LOG_SQL_PATH); - setenv(gz::transport::log::SchemaLocationEnvVar.c_str(), - GZ_TRANSPORT_LOG_SQL_PATH, 1); + gz::utils::setenv(gz::transport::log::SchemaLocationEnvVar, + GZ_TRANSPORT_LOG_SQL_PATH); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/log/test/integration/topicChirp_aux.cc b/log/test/integration/topicChirp_aux.cc index ae67e26ec..aa9a18b11 100644 --- a/log/test/integration/topicChirp_aux.cc +++ b/log/test/integration/topicChirp_aux.cc @@ -15,13 +15,14 @@ * */ -#include - #include #include +#include #include +#include + #include "ChirpParams.hh" ////////////////////////////////////////////////// @@ -38,13 +39,11 @@ void chirp(const std::vector &_topicNames, gz::transport::Node node; - using MsgType = gz::transport::log::test::ChirpMsgType; - std::vector publishers; for (const std::string &topic : _topicNames) { - publishers.push_back(node.Advertise(topic)); + publishers.push_back(node.Advertise(topic)); } std::this_thread::sleep_for( @@ -90,7 +89,7 @@ int main(int argc, char **argv) return -2; } - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); const int chirps = atoi(argv[2]); diff --git a/log/test/test_config.hh.in b/log/test/test_config.hh.in deleted file mode 100644 index 9c354ae0b..000000000 --- a/log/test/test_config.hh.in +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2019 Open Source Robotics Foundation - * - * 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. - * -*/ - -#ifndef GZ_TRANSPORT_LOG_TEST_CONFIG_HH_ -#define GZ_TRANSPORT_LOG_TEST_CONFIG_HH_ - - -#define GZ_TRANSPORT_LOG_TEST_PATH "@CMAKE_SOURCE_DIR@/log/test" - -#endif diff --git a/src/CIface_TEST.cc b/src/CIface_TEST.cc index a3dc0e765..1f1b70c57 100644 --- a/src/CIface_TEST.cc +++ b/src/CIface_TEST.cc @@ -16,8 +16,11 @@ */ #include -#include "gtest/gtest.h" #include "gz/transport/CIface.h" + +#include + +#include "gtest/gtest.h" #include "test_config.hh" static int count; @@ -180,10 +183,10 @@ int main(int argc, char **argv) std::string partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", partition); // Enable verbose mode. - // setenv("GZ_VERBOSE", "1", 1); + // gz::utils::setenv("GZ_VERBOSE", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/src/Discovery_TEST.cc b/src/Discovery_TEST.cc index b113ccbff..f83ed2950 100644 --- a/src/Discovery_TEST.cc +++ b/src/Discovery_TEST.cc @@ -27,20 +27,11 @@ #include "gz/transport/Publisher.hh" #include "gz/transport/TransportTypes.hh" #include "gz/transport/Uuid.hh" -#include "test_config.hh" -// Temporarily introduce a "DISABLED_ON_LINUX" macro. -// It currently does not exist upstream. -// This can be removed when it is in upstream gz-utils -// or the discovery WrongGzIp test passes on linux -#include -#if defined __linux__ - #define GZ_UTILS_TEST_DISABLED_ON_LINUX(TestName) \ - DETAIL_GZ_UTILS_ADD_DISABLED_PREFIX(TestName) -#else - #define GZ_UTILS_TEST_DISABLED_ON_LINUX(TestName) \ - TestName -#endif // defined __linux__ +#include "gz/utils/Environment.hh" +#include "gz/utils/ExtraTestMacros.hh" + +#include "test_config.hh" using namespace gz; using namespace transport; @@ -540,31 +531,24 @@ TEST(DiscoveryTest, TestActivity) discovery1.TestActivity(proc2Uuid, false); } -/// Logic to disable the following test via Linux -#if defined __linux__ - #define TEST_NAME DISABLED_WrongIgnIp -#else - #define TEST_NAME WrongIgnIp -#endif // defined __linux__ - ////////////////////////////////////////////////// /// \brief Check that a wrong GZ_IP value makes HostAddr() to return 127.0.0.1 -TEST(DiscoveryTest, TEST_NAME) +TEST(DiscoveryTest, GZ_UTILS_TEST_DISABLED_ON_LINUX(WrongIgnIp)) { // Save the current value of GZ_IP environment variable. std::string gzIp; - env("GZ_IP", gzIp); + gz::utils::env("GZ_IP", gzIp); // Incorrect value for GZ_IP - setenv("GZ_IP", "127.0.0.0", 1); + ASSERT_TRUE(gz::utils::setenv("GZ_IP", "127.0.0.0")); transport::Discovery discovery1(pUuid1, g_ip, g_msgPort); EXPECT_EQ(discovery1.HostAddr(), "127.0.0.1"); // Unset GZ_IP. - unsetenv("GZ_IP"); + ASSERT_TRUE(gz::utils::unsetenv("GZ_IP")); // Restore GZ_IP. if (!gzIp.empty()) - setenv("GZ_IP", gzIp.c_str(), 1); + gz::utils::setenv("GZ_IP", gzIp); } diff --git a/src/Helpers_TEST.cc b/src/Helpers_TEST.cc index c7f79c167..518090e11 100644 --- a/src/Helpers_TEST.cc +++ b/src/Helpers_TEST.cc @@ -16,6 +16,9 @@ */ #include "gz/transport/Helpers.hh" + +#include + #include "test_config.hh" #include "gtest/gtest.h" @@ -33,7 +36,7 @@ TEST(HelpersTest, env) EXPECT_FALSE(transport::env(name, value)); // Create a random environment variable and give it its name as value. - setenv(name.c_str(), name.c_str(), 1); + ASSERT_TRUE(gz::utils::setenv(name, name)); // Check that we find the environment variable and the value is correct. EXPECT_TRUE(transport::env(name, value)); diff --git a/src/NodeOptions_TEST.cc b/src/NodeOptions_TEST.cc index b8a78c2fc..d28a40e5a 100644 --- a/src/NodeOptions_TEST.cc +++ b/src/NodeOptions_TEST.cc @@ -19,6 +19,9 @@ #include "gz/transport/NetUtils.hh" #include "gz/transport/NodeOptions.hh" + +#include + #include "test_config.hh" #include "gtest/gtest.h" @@ -30,7 +33,7 @@ TEST(NodeOptionsTest, ignPartition) { // Set GZ_PARTITION std::string aPartition = "customPartition"; - setenv("GZ_PARTITION", aPartition.c_str(), 1); + ASSERT_TRUE(gz::utils::setenv("GZ_PARTITION", aPartition)); transport::NodeOptions opts; EXPECT_EQ(opts.Partition(), aPartition); @@ -53,7 +56,7 @@ TEST(NodeOptionsTest, ignPartition) TEST(NodeOptionsTest, accessors) { // Check the default values. - unsetenv("GZ_PARTITION"); + gz::utils::unsetenv("GZ_PARTITION"); transport::NodeOptions opts; EXPECT_TRUE(opts.NameSpace().empty()); auto defaultPartition = transport::hostname() + ":" + transport::username(); diff --git a/src/Node_TEST.cc b/src/Node_TEST.cc index 4e2b69716..80427368e 100644 --- a/src/Node_TEST.cc +++ b/src/Node_TEST.cc @@ -26,7 +26,6 @@ #include #include -#include "gtest/gtest.h" #include "gz/transport/AdvertiseOptions.hh" #include "gz/transport/MessageInfo.hh" #include "gz/transport/Node.hh" @@ -34,6 +33,10 @@ #include "gz/transport/TopicStatistics.hh" #include "gz/transport/TopicUtils.hh" #include "gz/transport/TransportTypes.hh" + +#include + +#include "gtest/gtest.h" #include "test_config.hh" using namespace gz; @@ -2324,10 +2327,10 @@ int main(int argc, char **argv) g_FQNPartition = std::string("/") + partition; // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", partition); // Enable verbose mode. - setenv("GZ_VERBOSE", "1", 1); + gz::utils::setenv("GZ_VERBOSE", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt index 269d66f38..f077906dc 100644 --- a/src/cmd/CMakeLists.txt +++ b/src/cmd/CMakeLists.txt @@ -40,15 +40,19 @@ gz_build_tests(TYPE UNIT SOURCES ${gtest_sources} LIB_DEPS ${EXTRA_TEST_LIB_DEPS}) foreach(test ${test_list}) - target_link_libraries(${test} gz) + target_link_libraries(${test} gz gz-utils${GZ_UTILS_VER}::gz-utils${GZ_UTILS_VER}) # Inform each test of its output directory so it knows where to call the # auxiliary files from. Using a generator expression here is useful for # multi-configuration generators, like Visual Studio. target_compile_definitions(${test} PRIVATE - "DETAIL_GZ_TRANSPORT_TEST_DIR=\"$\"" "GZ_TEST_LIBRARY_PATH=\"$\"" - "PROJECT_SOURCE_DIR=\"${PROJECT_SOURCE_DIR}\"") + "PROJECT_SOURCE_DIR=\"${PROJECT_SOURCE_DIR}\"" + "TWO_PROCS_PUBLISHER_EXE=\"$\"" + "TWO_PROCS_SRV_CALL_REPLIER_EXE=\"$\"" + "DETAIL_GZ_TRANSPORT_TEST_DIR=\"$\"" + "GZ_EXE=\"${HAVE_GZ_TOOLS}\"" + ) endforeach() diff --git a/src/cmd/cmdtransport.rb.in b/src/cmd/cmdtransport.rb.in index 74d96000b..671c65348 100644 --- a/src/cmd/cmdtransport.rb.in +++ b/src/cmd/cmdtransport.rb.in @@ -42,6 +42,7 @@ class Cmd conf_version = LIBRARY_VERSION exe_version = `#{exe_name} --version`.strip + # Sanity check: Verify that the version of the yaml file matches the version # of the library that we are using. unless exe_version.eql? conf_version diff --git a/src/cmd/gz_TEST.cc b/src/cmd/gz_TEST.cc index 4babd53e0..c443506a0 100644 --- a/src/cmd/gz_TEST.cc +++ b/src/cmd/gz_TEST.cc @@ -22,45 +22,27 @@ #include #include #include + +#include #include +#include #include "gtest/gtest.h" #include "gz/transport/Node.hh" #include "test_config.hh" -#ifdef _MSC_VER -# define popen _popen -# define pclose _pclose -#endif - using namespace gz; static std::string g_partition; // NOLINT(*) static std::string g_topicCBStr; // NOLINT(*) -static const std::string g_gzVersion("--force-version " + // NOLINT(*) - std::string(GZ_VERSION_FULL)); -///////////////////////////////////////////////// -std::string custom_exec_str(std::string _cmd) +namespace { - _cmd += " 2>&1"; - FILE *pipe = popen(_cmd.c_str(), "r"); - - if (!pipe) - return "ERROR"; - - char buffer[128]; - std::string result = ""; - - while (!feof(pipe)) - { - if (fgets(buffer, 128, pipe) != NULL) - result += buffer; - } - - pclose(pipe); - return result; -} +constexpr const char * kGzExe = GZ_EXE; +constexpr const char * kTwoProcsPublisherExe = TWO_PROCS_PUBLISHER_EXE; +constexpr const char * kTwoProcsSrvCallReplierExe = TWO_PROCS_SRV_CALL_REPLIER_EXE; +constexpr const char * kGzVersion = GZ_VERSION_FULL; +} // namespace ////////////////////////////////////////////////// /// \brief Provide a service. @@ -77,35 +59,38 @@ void topicCB(const msgs::StringMsg &_msg) g_topicCBStr = _msg.data(); } +////////////////////////////////////////////////// +std::string custom_exec_str(const std::vector &_args) +{ + auto fullArgs = std::vector{kGzExe}; + std::copy(std::begin(_args), std::end(_args), std::back_inserter(fullArgs)); + fullArgs.push_back("--force-version"); + fullArgs.push_back(kGzVersion); + auto proc = gz::utils::Subprocess(fullArgs); + proc.Join(); + + return proc.Stdout(); +} + ////////////////////////////////////////////////// /// \brief Check 'gz topic -l' running the advertiser on a different process. TEST(gzTest, GZ_UTILS_TEST_DISABLED_ON_MAC(TopicList)) { - // Launch a new publisher process that advertises a topic. - std::string publisher_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisher_path.c_str(), - g_partition.c_str()); - - // Check the 'gz topic -l' command. - std::string gz = std::string(GZ_PATH); + auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); unsigned int retries = 0u; bool topicFound = false; + std::string output; while (!topicFound && retries++ < 10u) { - std::string output = custom_exec_str(gz + " topic -l " + g_gzVersion); + output = custom_exec_str({"topic", "-l"}); topicFound = output == "/foo\n"; std::this_thread::sleep_for(std::chrono::milliseconds(300)); + break; } EXPECT_TRUE(topicFound); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -113,15 +98,7 @@ TEST(gzTest, GZ_UTILS_TEST_DISABLED_ON_MAC(TopicList)) TEST(gzTest, TopicInfo) { // Launch a new publisher process that advertises a topic. - std::string publisher_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisher_path.c_str(), - g_partition.c_str()); - - // Check the 'gz topic -i' command. - std::string gz = std::string(GZ_PATH); + auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); unsigned int retries = 0u; bool infoFound = false; @@ -129,7 +106,7 @@ TEST(gzTest, TopicInfo) while (!infoFound && retries++ < 10u) { - output = custom_exec_str(gz + " topic -t /foo -i " + g_gzVersion); + output = custom_exec_str({"topic", "-t", "/foo", "-i"}); infoFound = output.size() > 50u; std::this_thread::sleep_for(std::chrono::milliseconds(300)); } @@ -138,9 +115,6 @@ TEST(gzTest, TopicInfo) << output << "] Size[" << output.size() << "]. Expected Size=50" << std::endl; EXPECT_TRUE(output.find("gz.msgs.Vector3d") != std::string::npos); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -149,46 +123,27 @@ TEST(gzTest, TopicInfo) TEST(gzTest, ServiceList) { // Launch a new responser process that advertises a service. - std::string replier_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(replier_path.c_str(), - g_partition.c_str()); - - // Check the 'gz service -l' command. - std::string gz = std::string(GZ_PATH); + auto proc = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, g_partition}); unsigned int retries = 0u; bool serviceFound = false; while (!serviceFound && retries++ < 10u) { - std::string output = custom_exec_str(gz + " service -l " + g_gzVersion); + std::string output = custom_exec_str({"service", "-l"}); serviceFound = output == "/foo\n"; std::this_thread::sleep_for(std::chrono::milliseconds(300)); } EXPECT_TRUE(serviceFound); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// /// \brief Check 'gz service -i' running the advertiser on a different process. TEST(gzTest, ServiceInfo) { - // Launch a new publisher process that advertises a topic. - std::string replier_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(replier_path.c_str(), - g_partition.c_str()); - - // Check the 'gz service -i' command. - std::string gz = std::string(GZ_PATH); + // Launch a new responser process that advertises a service. + auto proc = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, g_partition}); unsigned int retries = 0u; bool infoFound = false; @@ -196,16 +151,13 @@ TEST(gzTest, ServiceInfo) while (!infoFound && retries++ < 10u) { - output = custom_exec_str(gz + " service -s /foo -i " + g_gzVersion); + output = custom_exec_str({"service", "-s", "/foo", "-i"}); infoFound = output.size() > 50u; std::this_thread::sleep_for(std::chrono::milliseconds(300)); } EXPECT_TRUE(infoFound); EXPECT_TRUE(output.find("gz.msgs.Int32") != std::string::npos); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -223,15 +175,12 @@ TEST(gzTest, TopicListSameProc) EXPECT_TRUE(pub); EXPECT_TRUE(pub.Publish(msg)); - // Check the 'gz topic -l' command. - std::string gz = std::string(GZ_PATH); - unsigned int retries = 0u; bool topicFound = false; while (!topicFound && retries++ < 10u) { - std::string output = custom_exec_str(gz + " topic -l " + g_gzVersion); + std::string output = custom_exec_str({"topic", "-l"}); topicFound = output == "/foo\n"; std::this_thread::sleep_for(std::chrono::milliseconds(300)); } @@ -254,16 +203,13 @@ TEST(gzTest, TopicInfoSameProc) EXPECT_TRUE(pub); EXPECT_TRUE(pub.Publish(msg)); - // Check the 'gz topic -i' command. - std::string gz = std::string(GZ_PATH); - unsigned int retries = 0u; bool infoFound = false; std::string output; while (!infoFound && retries++ < 10u) { - output = custom_exec_str(gz + " topic -t /foo -i " + g_gzVersion); + output = custom_exec_str({"topic", "-t", "/foo", "-i"}); infoFound = output.size() > 50u; std::this_thread::sleep_for(std::chrono::milliseconds(300)); } @@ -279,15 +225,12 @@ TEST(gzTest, ServiceListSameProc) transport::Node node; EXPECT_TRUE(node.Advertise("/foo", srvEcho)); - // Check the 'gz service -l' command. - std::string gz = std::string(GZ_PATH); - unsigned int retries = 0u; bool serviceFound = false; while (!serviceFound && retries++ < 10u) { - std::string output = custom_exec_str(gz + " service -l " + g_gzVersion); + std::string output = custom_exec_str({"service", "-l"}); serviceFound = output == "/foo\n"; std::this_thread::sleep_for(std::chrono::milliseconds(300)); } @@ -302,16 +245,13 @@ TEST(gzTest, ServiceInfoSameProc) transport::Node node; EXPECT_TRUE(node.Advertise("/foo", srvEcho)); - // Check the 'gz service -i' command. - std::string gz = std::string(GZ_PATH); - unsigned int retries = 0u; bool infoFound = false; std::string output; while (!infoFound && retries++ < 10u) { - output = custom_exec_str(gz + " service -s /foo -i " + g_gzVersion); + output = custom_exec_str({"service", "-s", "/foo", "-i"}); infoFound = output.size() > 50u; std::this_thread::sleep_for(std::chrono::milliseconds(300)); } @@ -329,8 +269,6 @@ TEST(gzTest, TopicPublish) g_topicCBStr = "bad_value"; EXPECT_TRUE(node.Subscribe("/bar", topicCB)); - // Check the 'gz topic -p' command. - std::string gz = std::string(GZ_PATH); std::string output; unsigned int retries = 0; @@ -339,9 +277,10 @@ TEST(gzTest, TopicPublish) // Send on alternating retries if (retries % 2) { - output = custom_exec_str(gz + - " topic -t /bar -m gz_msgs.StringMsg -p 'data:\"good_value\"' " + - g_gzVersion); + output = custom_exec_str({"topic", + "-t", "/bar", + "-m", "gz_msgs.StringMsg", + "-p", R"('data: "good_value"')"}); EXPECT_TRUE(output.empty()) << output; } std::this_thread::sleep_for(std::chrono::milliseconds(30)); @@ -350,23 +289,26 @@ TEST(gzTest, TopicPublish) // Try to publish a message not included in Gazebo Messages. std::string error = "Unable to create message of type"; - output = custom_exec_str(gz + - " topic -t /bar -m gz_msgs.__bad_msg_type -p 'data:\"good_value\"' " + - g_gzVersion); + output = custom_exec_str({"topic", + "-t", "/bar", + "-m", "gz_msgs.__bad_msg_type", + "-p", R"('data:"good_value"')"}); EXPECT_EQ(output.compare(0, error.size(), error), 0); // Try to publish using an incorrect topic name. error = "Topic [/] is not valid"; - output = custom_exec_str(gz + - " topic -t / -m gz_msgs.StringMsg -p 'data:\"good_value\"' "+ - g_gzVersion); + output = custom_exec_str({"topic", + "-t", "/", + "-m", "gz_msgs.StringMsg", + "-p", R"('data: "good_value"')"}); EXPECT_EQ(output.compare(0, error.size(), error), 0) << output; // Try to publish using an incorrect number of arguments. error = "The following argument was not expected: wrong_topic"; - output = custom_exec_str(gz + - " topic -t / wrong_topic -m gz_msgs.StringMsg -p 'data:\"good_value\"' "+ - g_gzVersion); + output = custom_exec_str({"topic", + "-t", "/", "wrong_topic", + "-m", "gz_msgs.StringMsg", + "-p", R"('data: "good_value"')"}); EXPECT_EQ(output.compare(0, error.size(), error), 0) << output; } @@ -385,12 +327,12 @@ TEST(gzTest, ServiceRequest) msg.set_data(10); // Check the 'gz service -r' command. - std::string gz = std::string(GZ_PATH); - std::string output = custom_exec_str(gz + - " service -s " + service + " --reqtype gz_msgs.Int32 " + - "--reptype gz_msgs.Int32 --timeout 1000 " + - "--req 'data: " + value + "' " + g_gzVersion); - + std::string output = custom_exec_str({"service", + "-s", service, + "--reqtype", "gz_msgs.Int32", + "--reptype", "gz_msgs.Int32", + "--timeout", "1000", + "--req", "'data: " + value + "'"}); ASSERT_EQ(output, "data: " + value + "\n\n"); } @@ -399,24 +341,14 @@ TEST(gzTest, ServiceRequest) TEST(gzTest, TopicEcho) { // Launch a new publisher process that advertises a topic. - std::string publisher_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisher_path.c_str(), - g_partition.c_str()); + auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); - // Check the 'gz topic -e' command. - std::string gz = std::string(GZ_PATH); std::string output = custom_exec_str( - gz + " topic -e -t /foo -d 1.5 " + g_gzVersion); + {"topic", "-e", "-t", "/foo", "-d", "1.5"}); EXPECT_TRUE(output.find("x: 1") != std::string::npos); EXPECT_TRUE(output.find("y: 2") != std::string::npos); EXPECT_TRUE(output.find("z: 3") != std::string::npos); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -425,17 +357,10 @@ TEST(gzTest, TopicEcho) TEST(gzTest, TopicEchoNum) { // Launch a new publisher process that advertises a topic. - std::string publisher_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisher_path.c_str(), - g_partition.c_str()); + auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); - // Check the 'gz topic -e -n' command. - std::string gz = std::string(GZ_PATH); std::string output = custom_exec_str( - gz + " topic -e -t /foo -n 2 " + g_gzVersion); + {"topic", "-e", "-t", "/foo", "-n", "2"}); size_t pos = output.find("x: 1"); EXPECT_TRUE(pos != std::string::npos); @@ -457,78 +382,9 @@ TEST(gzTest, TopicEchoNum) EXPECT_TRUE(pos != std::string::npos); pos = output.find("z: 3", pos + 4); EXPECT_TRUE(pos == std::string::npos); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); -} - -////////////////////////////////////////////////// -/// \brief Check 'gz service --help' message and bash completion script for -/// consistent flags -TEST(gzTest, ServiceHelpVsCompletionFlags) -{ - // Flags in help message - std::string helpOutput = custom_exec_str("gz service --help"); - - // Call the output function in the bash completion script - std::filesystem::path scriptPath = PROJECT_SOURCE_DIR; - scriptPath = scriptPath / "src" / "cmd" / "transport.bash_completion.sh"; - - // Equivalent to: - // sh -c "bash -c \". /path/to/transport.bash_completion.sh; - // _gz_service_flags\"" - std::string cmd = "bash -c \". " + scriptPath.string() + - "; _gz_service_flags\""; - std::string scriptOutput = custom_exec_str(cmd); - - // Tokenize script output - std::istringstream iss(scriptOutput); - std::vector flags((std::istream_iterator(iss)), - std::istream_iterator()); - - EXPECT_GT(flags.size(), 0u); - - // Match each flag in script output with help message - for (const auto &flag : flags) - { - EXPECT_NE(std::string::npos, helpOutput.find(flag)) << helpOutput; - } } -////////////////////////////////////////////////// -/// \brief Check 'gz topic --help' message and bash completion script for -/// consistent flags -TEST(gzTest, TopicHelpVsCompletionFlags) -{ - // Flags in help message - std::string helpOutput = custom_exec_str("gz topic --help"); - - // Call the output function in the bash completion script - std::filesystem::path scriptPath = PROJECT_SOURCE_DIR; - scriptPath = scriptPath / "src" / "cmd" / "transport.bash_completion.sh"; - - // Equivalent to: - // sh -c "bash -c \". /path/to/transport.bash_completion.sh; - // _gz_topic_flags\"" - std::string cmd = "bash -c \". " + scriptPath.string() + - "; _gz_topic_flags\""; - std::string scriptOutput = custom_exec_str(cmd); - - // Tokenize script output - std::istringstream iss(scriptOutput); - std::vector flags((std::istream_iterator(iss)), - std::istream_iterator()); - EXPECT_GT(flags.size(), 0u); - - // Match each flag in script output with help message - for (const auto &flag : flags) - { - EXPECT_NE(std::string::npos, helpOutput.find(flag)) << helpOutput; - } -} - -///////////////////////////////////////////////// /// Main int main(int argc, char **argv) { @@ -536,16 +392,20 @@ int main(int argc, char **argv) g_partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", g_partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", g_partition); // Make sure that we load the library recently built and not the one installed // in your system. // Save the current value of LD_LIBRARY_PATH. - std::string value = ""; - transport::env("LD_LIBRARY_PATH", value); + std::string value; + gz::utils::env("LD_LIBRARY_PATH", value); // Add the directory where Gazebo Transport has been built. value = std::string(GZ_TEST_LIBRARY_PATH) + ":" + value; - setenv("LD_LIBRARY_PATH", value.c_str(), 1); + std::cout << value << std::endl; + if (!gz::utils::setenv("LD_LIBRARY_PATH", value)) + { + std::cerr << "Failed to set LD_LIBRARY_PATH" << std::endl; + } ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/src/cmd/gz_src_TEST.cc b/src/cmd/gz_src_TEST.cc index 57ef9661c..9e6deed45 100644 --- a/src/cmd/gz_src_TEST.cc +++ b/src/cmd/gz_src_TEST.cc @@ -28,10 +28,13 @@ #pragma warning(pop) #endif -#include "gtest/gtest.h" #include "gz.hh" #include "gz/transport/Node.hh" + +#include + #include "test_config.hh" +#include "gtest/gtest.h" using namespace gz; @@ -296,7 +299,7 @@ int main(int argc, char **argv) g_partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", g_partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", g_partition); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/CMakeLists.txt b/test/integration/CMakeLists.txt index 858962a0e..37b6d3df4 100644 --- a/test/integration/CMakeLists.txt +++ b/test/integration/CMakeLists.txt @@ -29,13 +29,11 @@ gz_build_tests(TYPE INTEGRATION SOURCES ${tests} LIB_DEPS ${EXTRA_TEST_LIB_DEPS}) foreach(test ${test_list}) - # Inform each test of its output directory so it knows where to call the # auxiliary files from. Using a generator expression here is useful for # multi-configuration generators, like Visual Studio. target_compile_definitions(${test} PRIVATE "DETAIL_GZ_TRANSPORT_TEST_DIR=\"$\"") - endforeach() set(auxiliary_files @@ -56,20 +54,33 @@ set(auxiliary_files # Build the auxiliary files. foreach(AUX_EXECUTABLE ${auxiliary_files}) - gz_add_executable(INTEGRATION_${AUX_EXECUTABLE} ${AUX_EXECUTABLE}.cc) + gz_add_executable(${AUX_EXECUTABLE} ${AUX_EXECUTABLE}.cc) # Link the libraries that we always need. - target_link_libraries(INTEGRATION_${AUX_EXECUTABLE} + target_link_libraries(${AUX_EXECUTABLE} PRIVATE ${PROJECT_LIBRARY_TARGET_NAME} gtest ${EXTRA_TEST_LIB_DEPS} ) +endforeach(AUX_EXECUTABLE) - if(UNIX) - # pthread is only available on Unix machines - target_link_libraries(INTEGRATION_${AUX_EXECUTABLE} - PRIVATE pthread) - endif() -endforeach(AUX_EXECUTABLE) +foreach(test ${test_list}) + target_compile_definitions(${test} PRIVATE + "AUTH_PUB_SUB_SUBSCRIBER_INVALID_EXE=\"$\"" + "FAST_PUB_EXE=\"$\"" + "PUB_EXE=\"$\"" + "PUB_THROTTLED_EXE=\"$\"" + "SCOPED_TOPIC_SUBSCRIBER_EXE=\"$\"" + + "TWO_PROCS_PUBLISHER_EXE=\"$\"" + "TWO_PROCS_PUB_SUB_SUBSCRIBER_EXE=\"$\"" + + "TWO_PROCS_SRV_CALL_REPLIER_EXE=\"$\"" + "TWO_PROCS_SRV_CALL_REPLIER_INC_EXE=\"$\"" + "TWO_PROCS_SRV_CALL_WITHOUT_INPUT_REPLIER_EXE=\"$\"" + "TWO_PROCS_SRV_CALL_WITHOUT_INPUT_REPLIER_INC_EXE=\"$\"" + "TWO_PROCS_SRV_CALL_WITHOUT_OUTPUT_REPLIER_EXE=\"$\"" + "TWO_PROCS_SRV_CALL_WITHOUT_OUTPUT_REPLIER_INC_EXE=\"$\"") +endforeach() diff --git a/test/integration/authPubSub.cc b/test/integration/authPubSub.cc index f0fd6eaf5..4b99d1a71 100644 --- a/test/integration/authPubSub.cc +++ b/test/integration/authPubSub.cc @@ -29,6 +29,10 @@ #include "gtest/gtest.h" #include "gz/transport/Node.hh" #include "gz/transport/TransportTypes.hh" + +#include +#include + #include "test_config.hh" using namespace gz; @@ -36,12 +40,15 @@ using namespace gz; static std::string partition; // NOLINT(*) static std::string g_topic = "/foo"; // NOLINT(*) +static constexpr const char * kAuthPubSubSubscriberInvalid = + AUTH_PUB_SUB_SUBSCRIBER_INVALID_EXE; + ////////////////////////////////////////////////// TEST(authPubSub, InvalidAuth) { // Setup the username and password for this test - setenv("GZ_TRANSPORT_USERNAME", "admin", 1); - setenv("GZ_TRANSPORT_PASSWORD", "test", 1); + ASSERT_TRUE(gz::utils::setenv("GZ_TRANSPORT_USERNAME", "admin")); + ASSERT_TRUE(gz::utils::setenv("GZ_TRANSPORT_PASSWORD", "test")); transport::Node node; auto pub = node.Advertise(g_topic); @@ -50,13 +57,8 @@ TEST(authPubSub, InvalidAuth) // No subscribers yet. EXPECT_FALSE(pub.HasConnections()); - std::string subscriberPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_authPubSubSubscriberInvalid_aux"); - - // Start the subscriber in another process with incorrect credentials. - testing::forkHandlerType pi = testing::forkAndRun(subscriberPath.c_str(), - partition.c_str(), "bad", "invalid"); + auto pi = gz::utils::Subprocess( + {kAuthPubSubSubscriberInvalid, partition, "bad", "invalid"}); msgs::Int32 msg; msg.set_data(1); @@ -74,9 +76,6 @@ TEST(authPubSub, InvalidAuth) EXPECT_TRUE(pub.Publish(msg)); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } - - // The other process should exit without receiving any of the messages. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -86,7 +85,7 @@ int main(int argc, char **argv) partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", partition); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/authPubSubSubscriberInvalid_aux.cc b/test/integration/authPubSubSubscriberInvalid_aux.cc index 9b8d2d4dd..39035728e 100644 --- a/test/integration/authPubSubSubscriberInvalid_aux.cc +++ b/test/integration/authPubSubSubscriberInvalid_aux.cc @@ -30,6 +30,9 @@ #endif #include "gz/transport/Node.hh" + +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -81,13 +84,13 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); // Set the username for this test. - setenv("GZ_TRANSPORT_USERNAME", argv[2], 1); + gz::utils::setenv("GZ_TRANSPORT_USERNAME", argv[2]); // Set the password for this test. - setenv("GZ_TRANSPORT_PASSWORD", argv[3], 1); + gz::utils::setenv("GZ_TRANSPORT_PASSWORD", argv[3]); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/fastPub_aux.cc b/test/integration/fastPub_aux.cc index bd04c41e7..d0df10cf0 100644 --- a/test/integration/fastPub_aux.cc +++ b/test/integration/fastPub_aux.cc @@ -26,6 +26,9 @@ #endif #include "gz/transport/Node.hh" + +#include + #include "test_config.hh" using namespace gz; @@ -58,7 +61,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); advertiseAndPublish(); } diff --git a/test/integration/pub_aux.cc b/test/integration/pub_aux.cc index c9ebebfb9..2737a3b84 100644 --- a/test/integration/pub_aux.cc +++ b/test/integration/pub_aux.cc @@ -22,6 +22,9 @@ #include "gtest/gtest.h" #include "gz/transport/Node.hh" + +#include + #include "test_config.hh" using namespace gz; @@ -59,7 +62,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); advertiseAndPublish(); } diff --git a/test/integration/pub_aux_throttled.cc b/test/integration/pub_aux_throttled.cc index e2040c4f2..0416523ca 100644 --- a/test/integration/pub_aux_throttled.cc +++ b/test/integration/pub_aux_throttled.cc @@ -20,8 +20,11 @@ #include #include -#include "gtest/gtest.h" #include "gz/transport/Node.hh" + +#include + +#include "gtest/gtest.h" #include "test_config.hh" using namespace gz; @@ -61,7 +64,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); advertiseAndPublish(); } diff --git a/test/integration/scopedTopic.cc b/test/integration/scopedTopic.cc index 9c36a935f..77294c158 100644 --- a/test/integration/scopedTopic.cc +++ b/test/integration/scopedTopic.cc @@ -21,6 +21,10 @@ #include "gz/transport/AdvertiseOptions.hh" #include "gz/transport/Node.hh" + +#include +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -30,18 +34,16 @@ static std::string partition; // NOLINT(*) static std::string g_topic = "/foo"; // NOLINT(*) static int data = 5; +static constexpr const char* kScopedTopicSubscriberExe = + SCOPED_TOPIC_SUBSCRIBER_EXE; + ////////////////////////////////////////////////// /// \brief Two different nodes, each one running in a different process. The /// publisher advertises the topic as "process". This test checks that the topic /// is not seen by the other node running in a different process. TEST(ScopedTopicTest, ProcessTest) { - std::string subscriber_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_scopedTopicSubscriber_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(subscriber_path.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kScopedTopicSubscriberExe, partition}); msgs::Int32 msg; msg.set_data(data); @@ -56,8 +58,6 @@ TEST(ScopedTopicTest, ProcessTest) EXPECT_TRUE(pub.Publish(msg)); std::this_thread::sleep_for(std::chrono::milliseconds(500)); EXPECT_TRUE(pub.Publish(msg)); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -67,7 +67,7 @@ int main(int argc, char **argv) partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", partition); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/scopedTopicSubscriber_aux.cc b/test/integration/scopedTopicSubscriber_aux.cc index 76c17d508..3bb44f16a 100644 --- a/test/integration/scopedTopicSubscriber_aux.cc +++ b/test/integration/scopedTopicSubscriber_aux.cc @@ -20,6 +20,9 @@ #include #include "gz/transport/Node.hh" + +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -73,7 +76,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/statistics.cc b/test/integration/statistics.cc index 771d054a3..628d248bf 100644 --- a/test/integration/statistics.cc +++ b/test/integration/statistics.cc @@ -23,6 +23,9 @@ #include "gtest/gtest.h" #include "gz/transport/Node.hh" #include "gz/transport/TransportTypes.hh" + +#include + #include "test_config.hh" using namespace gz; @@ -78,8 +81,8 @@ int main(int argc, char **argv) std::string partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); - setenv("GZ_TRANSPORT_TOPIC_STATISTICS", "1", 1); + gz::utils::setenv("GZ_PARTITION", partition); + gz::utils::setenv("GZ_TRANSPORT_TOPIC_STATISTICS", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsPubSub.cc b/test/integration/twoProcsPubSub.cc index a5a82f20f..05401f0e4 100644 --- a/test/integration/twoProcsPubSub.cc +++ b/test/integration/twoProcsPubSub.cc @@ -20,9 +20,13 @@ #include #include -#include "gtest/gtest.h" #include "gz/transport/Node.hh" #include "gz/transport/TransportTypes.hh" + +#include +#include + +#include "gtest/gtest.h" #include "test_config.hh" using namespace gz; @@ -38,6 +42,13 @@ static bool cbVectorExecuted = false; static bool cbRawExecuted = false; static int counter = 0; +static constexpr const char* kFastPubExe = FAST_PUB_EXE; +static constexpr const char* kPubExe = PUB_EXE; +static constexpr const char* kPubThrottledExe = PUB_THROTTLED_EXE; +static constexpr const char* kTwoProcsPublisherExe = TWO_PROCS_PUBLISHER_EXE; +static constexpr const char* kTwoProcsPubSubSubscriberExe = + TWO_PROCS_PUB_SUB_SUBSCRIBER_EXE; + ////////////////////////////////////////////////// /// \brief Initialize some global variables. void reset() @@ -109,12 +120,7 @@ TEST(twoProcPubSub, PubSubTwoProcsThreeNodes) // No subscribers yet. EXPECT_FALSE(pub.HasConnections()); - std::string subscriberPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPubSubSubscriber_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(subscriberPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsPubSubSubscriberExe, partition}); msgs::Vector3d msg; msg.set_x(1.0); @@ -132,8 +138,6 @@ TEST(twoProcPubSub, PubSubTwoProcsThreeNodes) EXPECT_TRUE(pub.Publish(msg)); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -148,12 +152,7 @@ TEST(twoProcPubSub, RawPubSubTwoProcsThreeNodes) // No subscribers yet. EXPECT_FALSE(pub.HasConnections()); - std::string subscriberPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPubSubSubscriber_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(subscriberPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsPubSubSubscriberExe, partition}); msgs::Vector3d msg; msg.set_x(1.0); @@ -174,8 +173,6 @@ TEST(twoProcPubSub, RawPubSubTwoProcsThreeNodes) EXPECT_TRUE(pub.PublishRaw(msg.SerializeAsString(), msg.GetTypeName())); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -183,12 +180,7 @@ TEST(twoProcPubSub, RawPubSubTwoProcsThreeNodes) /// the advertised types. TEST(twoProcPubSub, PubSubWrongTypesOnSubscription) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsPublisherExe, partition}); reset(); @@ -202,20 +194,13 @@ TEST(twoProcPubSub, PubSubWrongTypesOnSubscription) EXPECT_FALSE(cbExecuted); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// /// \brief Same as above, but using a raw subscription. TEST(twoProcPubSub, PubRawSubWrongTypesOnSubscription) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsPublisherExe, partition}); reset(); @@ -230,8 +215,6 @@ TEST(twoProcPubSub, PubRawSubWrongTypesOnSubscription) EXPECT_FALSE(cbRawExecuted); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -242,12 +225,7 @@ TEST(twoProcPubSub, PubRawSubWrongTypesOnSubscription) /// (correct and generic). TEST(twoProcPubSub, PubSubWrongTypesTwoSubscribers) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsPublisherExe, partition}); reset(); @@ -263,15 +241,12 @@ TEST(twoProcPubSub, PubSubWrongTypesTwoSubscribers) // Wait some time before publishing. std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - // Check that the message was not received. EXPECT_FALSE(cbExecuted); EXPECT_TRUE(cbVectorExecuted); EXPECT_TRUE(genericCbExecuted); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -282,12 +257,7 @@ TEST(twoProcPubSub, PubSubWrongTypesTwoSubscribers) /// callbacks are executed (correct and generic). TEST(twoProcPubSub, PubSubWrongTypesTwoRawSubscribers) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsPublisherExe, partition}); reset(); @@ -334,8 +304,6 @@ TEST(twoProcPubSub, PubSubWrongTypesTwoRawSubscribers) EXPECT_TRUE(genericRawCbExecuted); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -345,18 +313,13 @@ TEST(twoProcPubSub, PubSubWrongTypesTwoRawSubscribers) /// the prompt termination of the publisher. TEST(twoProcPubSub, FastPublisher) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, "INTEGRATION_fastPub_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kFastPubExe, partition}); reset(); transport::Node node; EXPECT_TRUE(node.Subscribe(g_topic, cbVector)); - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -365,11 +328,7 @@ TEST(twoProcPubSub, FastPublisher) /// by the subscriber. TEST(twoProcPubSub, SubThrottled) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, "INTEGRATION_pub_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kPubExe, partition}); reset(); @@ -387,8 +346,6 @@ TEST(twoProcPubSub, SubThrottled) EXPECT_LT(counter, 5); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -396,11 +353,7 @@ TEST(twoProcPubSub, SubThrottled) /// processes. The publisher publishes at a throttled frequency. TEST(twoProcPubSub, PubThrottled) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, "INTEGRATION_pub_aux_throttled"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kPubThrottledExe, partition}); reset(); @@ -416,8 +369,6 @@ TEST(twoProcPubSub, PubThrottled) EXPECT_LT(counter, 5); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -425,12 +376,7 @@ TEST(twoProcPubSub, PubThrottled) /// using a callback that accepts message information. TEST(twoProcPubSub, PubSubMessageInfo) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); - + auto pi = gz::utils::Subprocess({kTwoProcsPublisherExe, partition}); reset(); transport::Node node; @@ -443,8 +389,6 @@ TEST(twoProcPubSub, PubSubMessageInfo) EXPECT_FALSE(cbInfoExecuted); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -453,11 +397,7 @@ TEST(twoProcPubSub, PubSubMessageInfo) /// available topics. TEST(twoProcPubSub, TopicList) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsPublisherExe, partition}); reset(); @@ -494,8 +434,6 @@ TEST(twoProcPubSub, TopicList) EXPECT_LT(elapsed2, 2); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -504,11 +442,7 @@ TEST(twoProcPubSub, TopicList) /// about the topic. TEST(twoProcPubSub, TopicInfo) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, "INTEGRATION_twoProcsPublisher_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsPublisherExe, partition}); reset(); @@ -529,8 +463,6 @@ TEST(twoProcPubSub, TopicInfo) EXPECT_EQ(publishers.front().MsgTypeName(), "gz.msgs.Vector3d"); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -541,8 +473,8 @@ int main(int argc, char **argv) g_FQNPartition = std::string("/") + partition; // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); - setenv("GZ_TRANSPORT_TOPIC_STATISTICS", "1", 1); + gz::utils::setenv("GZ_PARTITION", partition); + gz::utils::setenv("GZ_TRANSPORT_TOPIC_STATISTICS", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsPubSubSubscriber_aux.cc b/test/integration/twoProcsPubSubSubscriber_aux.cc index ccd0f4ccd..49a360a02 100644 --- a/test/integration/twoProcsPubSubSubscriber_aux.cc +++ b/test/integration/twoProcsPubSubSubscriber_aux.cc @@ -21,6 +21,9 @@ #include #include "gz/transport/Node.hh" + +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -157,8 +160,8 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); - setenv("GZ_TRANSPORT_TOPIC_STATISTICS", "1", 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); + gz::utils::setenv("GZ_TRANSPORT_TOPIC_STATISTICS", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsPublisher_aux.cc b/test/integration/twoProcsPublisher_aux.cc index ee49964bd..ccb49c83f 100644 --- a/test/integration/twoProcsPublisher_aux.cc +++ b/test/integration/twoProcsPublisher_aux.cc @@ -20,6 +20,9 @@ #include #include "gz/transport/Node.hh" + +#include + #include "test_config.hh" using namespace gz; @@ -55,7 +58,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); advertiseAndPublish(); } diff --git a/test/integration/twoProcsSrvCall.cc b/test/integration/twoProcsSrvCall.cc index 059d3ab00..1226522fe 100644 --- a/test/integration/twoProcsSrvCall.cc +++ b/test/integration/twoProcsSrvCall.cc @@ -23,6 +23,10 @@ #include "gz/transport/Node.hh" #include "gz/transport/TopicUtils.hh" + +#include +#include "gz/utils/Subprocess.hh" + #include "gtest/gtest.h" #include "test_config.hh" @@ -36,6 +40,8 @@ static std::string g_topic = "/foo"; // NOLINT(*) static int data = 5; static int counter = 0; +static constexpr const char *kTwoProcsSrvCallReplierExe = TWO_PROCS_SRV_CALL_REPLIER_EXE; + ////////////////////////////////////////////////// /// \brief Initialize some global variables. void reset() @@ -68,12 +74,7 @@ void wrongResponse(const msgs::Vector3d &/*_rep*/, bool /*_result*/) /// advertises a service and the other requests a few service calls. TEST(twoProcSrvCall, SrvTwoProcs) { - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); reset(); @@ -111,9 +112,6 @@ TEST(twoProcSrvCall, SrvTwoProcs) EXPECT_EQ(counter, 1); reset(); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -127,12 +125,7 @@ TEST(twoProcSrvCall, SrvRequestWrongReq) bool result; unsigned int timeout = 1000; - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); wrongReq.set_x(1); wrongReq.set_y(2); @@ -151,9 +144,6 @@ TEST(twoProcSrvCall, SrvRequestWrongReq) EXPECT_FALSE(node.Request(g_topic, wrongReq, timeout, rep, result)); reset(); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -167,13 +157,7 @@ TEST(twoProcSrvCall, SrvRequestWrongRep) bool result; unsigned int timeout = 1000; - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplier_aux"); - - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); req.set_data(data); @@ -190,9 +174,6 @@ TEST(twoProcSrvCall, SrvRequestWrongRep) EXPECT_FALSE(node.Request(g_topic, req, timeout, wrongRep, result)); reset(); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -208,12 +189,7 @@ TEST(twoProcSrvCall, SrvTwoRequestsOneWrong) bool result; unsigned int timeout = 2000; - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); req.set_data(data); @@ -238,9 +214,6 @@ TEST(twoProcSrvCall, SrvTwoRequestsOneWrong) EXPECT_TRUE(responseExecuted); reset(); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -249,12 +222,7 @@ TEST(twoProcSrvCall, SrvTwoRequestsOneWrong) /// of available services. TEST(twoProcSrvCall, ServiceList) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); reset(); @@ -291,8 +259,6 @@ TEST(twoProcSrvCall, ServiceList) << "] Elapsed1[" << elapsed1.count() << "]"; reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -301,12 +267,7 @@ TEST(twoProcSrvCall, ServiceList) /// information about the service. TEST(twoProcSrvCall, ServiceInfo) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); reset(); @@ -328,8 +289,6 @@ TEST(twoProcSrvCall, ServiceInfo) EXPECT_EQ(publishers.front().RepTypeName(), "gz.msgs.Int32"); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -339,10 +298,10 @@ int main(int argc, char **argv) partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", partition); // Enable verbose mode. - // setenv("GZ_VERBOSE", "1", 1); + // gz::utils::setenv("GZ_VERBOSE", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallReplierInc_aux.cc b/test/integration/twoProcsSrvCallReplierInc_aux.cc index 8ef1c4b49..1f27e84fb 100644 --- a/test/integration/twoProcsSrvCallReplierInc_aux.cc +++ b/test/integration/twoProcsSrvCallReplierInc_aux.cc @@ -21,6 +21,9 @@ #include #include "gz/transport/Node.hh" + +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -63,7 +66,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallReplier_aux.cc b/test/integration/twoProcsSrvCallReplier_aux.cc index 6dacc1cb9..5b8523590 100644 --- a/test/integration/twoProcsSrvCallReplier_aux.cc +++ b/test/integration/twoProcsSrvCallReplier_aux.cc @@ -20,6 +20,9 @@ #include #include "gz/transport/Node.hh" + +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -53,7 +56,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); runReplier(); } diff --git a/test/integration/twoProcsSrvCallStress.cc b/test/integration/twoProcsSrvCallStress.cc index 2f9d71265..b231f2a01 100644 --- a/test/integration/twoProcsSrvCallStress.cc +++ b/test/integration/twoProcsSrvCallStress.cc @@ -21,6 +21,10 @@ #include #include "gz/transport/Node.hh" + +#include +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -29,15 +33,13 @@ using namespace gz; static std::string partition; // NOLINT(*) static std::string g_topic = "/foo"; // NOLINT(*) +static constexpr const char * kTwoProcsSrvReplierIncExe = + TWO_PROCS_SRV_CALL_REPLIER_INC_EXE; + ////////////////////////////////////////////////// TEST(twoProcSrvCall, ThousandCalls) { - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplierInc_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsSrvReplierIncExe, partition}); msgs::Int32 req; msgs::Int32 response; @@ -56,9 +58,6 @@ TEST(twoProcSrvCall, ThousandCalls) ASSERT_TRUE(result); EXPECT_EQ(i, response.data()); } - - // Need to kill the responser node running on an external process. - testing::killFork(pi); } ////////////////////////////////////////////////// @@ -68,7 +67,7 @@ int main(int argc, char **argv) partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", partition); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallSync1.cc b/test/integration/twoProcsSrvCallSync1.cc index ef93771da..edd69760f 100644 --- a/test/integration/twoProcsSrvCallSync1.cc +++ b/test/integration/twoProcsSrvCallSync1.cc @@ -21,6 +21,10 @@ #include #include "gz/transport/Node.hh" + +#include +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -30,6 +34,9 @@ static std::string partition; // NOLINT(*) static std::string g_topic = "/foo"; // NOLINT(*) static int data = 5; +static constexpr const char * kTwoProcsSrvCallReplierExe = + TWO_PROCS_SRV_CALL_REPLIER_EXE; + ////////////////////////////////////////////////// /// \brief This test spawns a service responser and a service requester. The /// synchronous requester uses a wrong service's name. The test should verify @@ -37,12 +44,7 @@ static int data = 5; /// the timeout. TEST(twoProcSrvCallSync1, SrvTwoProcs) { - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - partition.c_str()); + auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); int64_t timeout = 500; msgs::Int32 req; @@ -71,9 +73,6 @@ TEST(twoProcSrvCallSync1, SrvTwoProcs) // Check if the elapsed time was close to the timeout. auto diff = std::max(elapsed, timeout) - std::min(elapsed, timeout); EXPECT_LT(diff, 200); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -83,10 +82,10 @@ int main(int argc, char **argv) partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", partition); // Enable verbose mode. - setenv("GZ_VERBOSE", "1", 1); + gz::utils::setenv("GZ_VERBOSE", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallWithoutInput.cc b/test/integration/twoProcsSrvCallWithoutInput.cc index d98c112a0..8d7b1f69a 100644 --- a/test/integration/twoProcsSrvCallWithoutInput.cc +++ b/test/integration/twoProcsSrvCallWithoutInput.cc @@ -23,6 +23,10 @@ #include "gz/transport/Node.hh" #include "gz/transport/TopicUtils.hh" + +#include +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -36,6 +40,9 @@ static std::string g_topic = "/foo"; // NOLINT(*) static int g_data = 5; static int g_counter = 0; +static constexpr const char * kTwoProcsSrvCallWithoutInputReplierExe = + TWO_PROCS_SRV_CALL_WITHOUT_INPUT_REPLIER_EXE; + ////////////////////////////////////////////////// /// \brief Initialize some global variables. void reset() @@ -69,12 +76,8 @@ void wrongResponse(const msgs::Vector3d &/*_rep*/, bool /*_result*/) /// calls. TEST(twoProcSrvCallWithoutInput, SrvTwoProcs) { - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutInputReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); reset(); @@ -109,9 +112,6 @@ TEST(twoProcSrvCallWithoutInput, SrvTwoProcs) EXPECT_EQ(g_counter, 1); reset(); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -124,12 +124,8 @@ TEST(twoProcSrvCallWithoutInput, SrvRequestWrongRep) bool result; unsigned int timeout = 1000; - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutInputReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); reset(); @@ -144,9 +140,6 @@ TEST(twoProcSrvCallWithoutInput, SrvRequestWrongRep) EXPECT_FALSE(node.Request(g_topic, timeout, wrongRep, result)); reset(); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -161,12 +154,8 @@ TEST(twoProcSrvCallWithoutInput, SrvTwoRequestsOneWrong) bool result; unsigned int timeout = 2000; - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutInputReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); reset(); @@ -189,9 +178,6 @@ TEST(twoProcSrvCallWithoutInput, SrvTwoRequestsOneWrong) EXPECT_TRUE(g_responseExecuted); reset(); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -200,12 +186,8 @@ TEST(twoProcSrvCallWithoutInput, SrvTwoRequestsOneWrong) /// getting the list of available services. TEST(twoProcSrvCallWithoutInput, ServiceList) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutInputReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); reset(); @@ -241,8 +223,6 @@ TEST(twoProcSrvCallWithoutInput, ServiceList) EXPECT_LE(elapsed2, elapsed1); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -251,12 +231,8 @@ TEST(twoProcSrvCallWithoutInput, ServiceList) /// getting information about the service. TEST(twoProcSrvCallWithoutInput, ServiceInfo) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutInputReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); reset(); @@ -278,8 +254,6 @@ TEST(twoProcSrvCallWithoutInput, ServiceInfo) EXPECT_EQ(publishers.front().RepTypeName(), "gz.msgs.Int32"); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -289,10 +263,10 @@ int main(int argc, char **argv) g_partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", g_partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", g_partition); // Enable verbose mode. - // setenv("GZ_VERBOSE", "1", 1); + // gz::utils::setenv("GZ_VERBOSE", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallWithoutInputReplierInc_aux.cc b/test/integration/twoProcsSrvCallWithoutInputReplierInc_aux.cc index 195de0791..1cc15a893 100644 --- a/test/integration/twoProcsSrvCallWithoutInputReplierInc_aux.cc +++ b/test/integration/twoProcsSrvCallWithoutInputReplierInc_aux.cc @@ -21,6 +21,9 @@ #include #include "gz/transport/Node.hh" + +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -64,7 +67,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallWithoutInputReplier_aux.cc b/test/integration/twoProcsSrvCallWithoutInputReplier_aux.cc index 31eb1c13c..6ab90212d 100644 --- a/test/integration/twoProcsSrvCallWithoutInputReplier_aux.cc +++ b/test/integration/twoProcsSrvCallWithoutInputReplier_aux.cc @@ -20,6 +20,9 @@ #include #include "gz/transport/Node.hh" + +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -54,7 +57,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); runReplier(); } diff --git a/test/integration/twoProcsSrvCallWithoutInputStress.cc b/test/integration/twoProcsSrvCallWithoutInputStress.cc index 972cce3a5..5d89bd716 100644 --- a/test/integration/twoProcsSrvCallWithoutInputStress.cc +++ b/test/integration/twoProcsSrvCallWithoutInputStress.cc @@ -21,6 +21,10 @@ #include #include "gz/transport/Node.hh" + +#include +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -29,15 +33,14 @@ using namespace gz; static std::string g_partition; // NOLINT(*) static std::string g_topic = "/foo"; // NOLINT(*) +static constexpr const char * kTwoProcsSrvCallWithoutInputReplierIncExe = + TWO_PROCS_SRV_CALL_WITHOUT_INPUT_REPLIER_INC_EXE; + ////////////////////////////////////////////////// TEST(twoProcSrvCallWithoutInput, ThousandCalls) { - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutInputReplierInc_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutInputReplierIncExe, g_partition}); msgs::Int32 response; bool result; @@ -53,9 +56,6 @@ TEST(twoProcSrvCallWithoutInput, ThousandCalls) // Check the service response. ASSERT_TRUE(result); } - - // Need to kill the responser node running on an external process. - testing::killFork(pi); } ////////////////////////////////////////////////// @@ -65,7 +65,7 @@ int main(int argc, char **argv) g_partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", g_partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", g_partition); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallWithoutInputSync1.cc b/test/integration/twoProcsSrvCallWithoutInputSync1.cc index d2177b375..d01a734db 100644 --- a/test/integration/twoProcsSrvCallWithoutInputSync1.cc +++ b/test/integration/twoProcsSrvCallWithoutInputSync1.cc @@ -21,6 +21,10 @@ #include #include "gz/transport/Node.hh" + +#include +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -29,6 +33,9 @@ using namespace gz; static std::string g_partition; // NOLINT(*) static std::string g_topic = "/foo"; // NOLINT(*) +static constexpr const char * kTwoProcsSrvCallWithoutInputReplierExe = + TWO_PROCS_SRV_CALL_WITHOUT_INPUT_REPLIER_EXE; + ////////////////////////////////////////////////// /// \brief This test spawns a service that doesn't accept input parameters. The /// synchronous requester uses a wrong service's name. The test should verify @@ -36,12 +43,8 @@ static std::string g_topic = "/foo"; // NOLINT(*) /// the timeout. TEST(twoProcSrvCallWithoutInputSync1, SrvTwoProcs) { - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutInputReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); int64_t timeout = 500; msgs::Int32 rep; @@ -66,9 +69,6 @@ TEST(twoProcSrvCallWithoutInputSync1, SrvTwoProcs) // Check if the elapsed time was close to the timeout. auto diff = std::max(elapsed, timeout) - std::min(elapsed, timeout); EXPECT_LT(diff, 200); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -78,10 +78,10 @@ int main(int argc, char **argv) g_partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", g_partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", g_partition); // Enable verbose mode. - setenv("GZ_VERBOSE", "1", 1); + gz::utils::setenv("GZ_VERBOSE", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallWithoutOutput.cc b/test/integration/twoProcsSrvCallWithoutOutput.cc index 526e2283e..fe3302c77 100644 --- a/test/integration/twoProcsSrvCallWithoutOutput.cc +++ b/test/integration/twoProcsSrvCallWithoutOutput.cc @@ -22,6 +22,10 @@ #include "gz/transport/Node.hh" #include "gz/transport/TopicUtils.hh" + +#include +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -34,6 +38,9 @@ static std::string g_partition; // NOLINT(*) static std::string g_topic = "/foo"; // NOLINT(*) static int g_counter = 0; +static constexpr const char * kTwoProcsSrvCallWithoutOutputReplierExe = + TWO_PROCS_SRV_CALL_WITHOUT_OUTPUT_REPLIER_EXE; + ////////////////////////////////////////////////// /// \brief Initialize some global variables. void reset() @@ -51,12 +58,8 @@ TEST(twoProcSrvCallWithoutOutput, SrvRequestWrongReq) { msgs::Vector3d wrongReq; - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutOutputReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutOutputReplierExe, g_partition}); wrongReq.set_x(1); wrongReq.set_y(2); @@ -72,9 +75,6 @@ TEST(twoProcSrvCallWithoutOutput, SrvRequestWrongReq) EXPECT_FALSE(g_responseExecuted); reset(); - - // Wait for the child process to return. - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -83,12 +83,8 @@ TEST(twoProcSrvCallWithoutOutput, SrvRequestWrongReq) /// getting the list of available services. TEST(twoProcSrvCallWithoutOutput, ServiceList) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutOutputReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutOutputReplierExe, g_partition}); reset(); @@ -124,8 +120,6 @@ TEST(twoProcSrvCallWithoutOutput, ServiceList) EXPECT_LE(elapsed2, elapsed1); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -134,12 +128,8 @@ TEST(twoProcSrvCallWithoutOutput, ServiceList) /// getting information about the service. TEST(twoProcSrvCallWithoutOutput, ServiceInfo) { - std::string publisherPath = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutOutputReplier_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(publisherPath.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutOutputReplierExe, g_partition}); reset(); @@ -160,8 +150,6 @@ TEST(twoProcSrvCallWithoutOutput, ServiceInfo) EXPECT_EQ(publishers.front().ReqTypeName(), "gz.msgs.Int32"); reset(); - - testing::waitAndCleanupFork(pi); } ////////////////////////////////////////////////// @@ -171,10 +159,10 @@ int main(int argc, char **argv) g_partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", g_partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", g_partition); // Enable verbose mode. - // setenv("GZ_VERBOSE", "1", 1); + // gz::utils::setenv("GZ_VERBOSE", "1"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallWithoutOutputReplierInc_aux.cc b/test/integration/twoProcsSrvCallWithoutOutputReplierInc_aux.cc index 25dd7216e..8354ddb48 100644 --- a/test/integration/twoProcsSrvCallWithoutOutputReplierInc_aux.cc +++ b/test/integration/twoProcsSrvCallWithoutOutputReplierInc_aux.cc @@ -21,6 +21,9 @@ #include #include "gz/transport/Node.hh" + +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -62,7 +65,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/integration/twoProcsSrvCallWithoutOutputReplier_aux.cc b/test/integration/twoProcsSrvCallWithoutOutputReplier_aux.cc index 8eff1867f..285b06a60 100644 --- a/test/integration/twoProcsSrvCallWithoutOutputReplier_aux.cc +++ b/test/integration/twoProcsSrvCallWithoutOutputReplier_aux.cc @@ -20,6 +20,9 @@ #include #include "gz/transport/Node.hh" + +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -53,7 +56,7 @@ int main(int argc, char **argv) } // Set the partition name for this test. - setenv("GZ_PARTITION", argv[1], 1); + gz::utils::setenv("GZ_PARTITION", argv[1]); runReplier(); } diff --git a/test/integration/twoProcsSrvCallWithoutOutputStress.cc b/test/integration/twoProcsSrvCallWithoutOutputStress.cc index 3d76b95ec..dc4a7e595 100644 --- a/test/integration/twoProcsSrvCallWithoutOutputStress.cc +++ b/test/integration/twoProcsSrvCallWithoutOutputStress.cc @@ -21,6 +21,10 @@ #include #include "gz/transport/Node.hh" + +#include +#include + #include "gtest/gtest.h" #include "test_config.hh" @@ -29,15 +33,14 @@ using namespace gz; static std::string g_partition; // NOLINT(*) static std::string g_topic = "/foo"; // NOLINT(*) +static constexpr const char* kTwoProcsSrvCallWithoutOutputReplierInc = + TWO_PROCS_SRV_CALL_WITHOUT_OUTPUT_REPLIER_INC_EXE; + ////////////////////////////////////////////////// TEST(twoProcSrvCallWithoutOuput, ThousandCalls) { - std::string responser_path = testing::portablePathUnion( - GZ_TRANSPORT_TEST_DIR, - "INTEGRATION_twoProcsSrvCallWithoutOutputReplierInc_aux"); - - testing::forkHandlerType pi = testing::forkAndRun(responser_path.c_str(), - g_partition.c_str()); + auto pi = gz::utils::Subprocess( + {kTwoProcsSrvCallWithoutOutputReplierInc, g_partition}); msgs::Int32 req; transport::Node node; @@ -49,9 +52,6 @@ TEST(twoProcSrvCallWithoutOuput, ThousandCalls) req.set_data(i); ASSERT_TRUE(node.Request(g_topic, req)); } - - // Need to kill the responser node running on an external process. - testing::killFork(pi); } ////////////////////////////////////////////////// @@ -61,7 +61,7 @@ int main(int argc, char **argv) g_partition = testing::getRandomNumber(); // Set the partition name for this process. - setenv("GZ_PARTITION", g_partition.c_str(), 1); + gz::utils::setenv("GZ_PARTITION", g_partition); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/test_config.hh.in b/test/test_config.hh.in index bc7ea350a..df25a23f0 100644 --- a/test/test_config.hh.in +++ b/test/test_config.hh.in @@ -30,211 +30,14 @@ DETAIL_GZ_TRANSPORT_TEST_DIR #endif -#ifndef __APPLE__ - #if (!(defined(__clang__) || __unix__) || \ - (defined(__clang__) && __cplusplus >= 201703L) || \ - (__unix__ && __GNUC__ >= 8)) - #define GZ_HAVE_FILESYSTEM - #endif - - #ifdef GZ_HAVE_FILESYSTEM - #include - #else - #include - #endif -#endif - #include +#include #include #include #include -#ifdef _WIN32 - #include -#else - #include - #include - #include - #include -#endif - -#include "gz/transport/Helpers.hh" - -#if (_MSC_VER >= 1400) // Visual Studio 2005 - #include - - /// \brief setenv/unstenv are not present in Windows. Define them to make - /// the code portable. - /// \param[in] _name Variable name. - /// \param[in] _value Value. - /// \param[in] _rewrite If 'name' does exist in the environment, then its - /// value is changed to 'value' if 'rewrite' is nonzero. If overwrite is - /// zero, then the value of 'name' is not changed. - /// /return 0 on success or -1 on error. - int setenv(const char *_name, const char *_value, int /*_rewrite*/) - { - std::stringstream sstr; - std::string name = _name; - std::string value = _value; - sstr << name << '=' << value; - return _putenv(sstr.str().c_str()); - } - - /// \brief Deletes an environment variable. - /// \param[in] _name Variable name. - void unsetenv(const char *_name) - { - std::stringstream sstr; - std::string name = _name; - sstr << name << '='; - _putenv(sstr.str().c_str()); - } -#endif - namespace testing { - /// \brief Join _str1 and _str2 considering both as storing system paths. - /// \param[in] _str1 string containing a path. - /// \param[in] _str2 string containing a path. - /// \return The string representation of the union of two paths. - std::string portablePathUnion(const std::string &_str1, - const std::string &_str2) - { -#ifdef __APPLE__ - // Ugly as hell but trying to avoid boost::filesystem - return _str1 + "/" + _str2; -#else - #ifdef GZ_HAVE_FILESYSTEM - using namespace std::filesystem; - #else - using namespace std::experimental::filesystem; - #endif - return (path(_str1) / path(_str2)).string(); -#endif - } - -#ifdef _WIN32 - using forkHandlerType = PROCESS_INFORMATION; -#else - using forkHandlerType = pid_t; -#endif - - /// \brief create a new process and run command on it. This function is - /// implementing the creation of a new process on both Linux (fork) and - /// Windows (CreateProcess) and the execution of the command provided. - /// \param[in] _command The full system path to the binary to run into the - /// new process. - /// \param[in] _partition Name of the Gazebo partition (GZ_PARTITION) - /// \param[in] _username Username for authentication - /// (GZ_TRANSPORT_USERNAME) - /// \param[in] _password Password for authentication - /// (GZ_TRANSPORT_PASSWORD) - /// \return On success, the PID of the child process is returned in the - /// parent, an 0 is returned in the child. On failure, -1 is returned in the - /// parent and no child process is created. - forkHandlerType forkAndRun(const char *_command, const char *_partition, - const char *_username = nullptr, const char *_password = nullptr) - { -#ifdef _WIN32 - STARTUPINFO info= {sizeof(info)}; - PROCESS_INFORMATION processInfo; - - char cmd[500]; - // We should put quotes around the _command string to make sure we are - // robust to file paths that contain spaces. - gz_strcpy(cmd, "\""); - gz_strcat(cmd, _command); - gz_strcat(cmd, "\""); - gz_strcat(cmd, " "); - gz_strcat(cmd, _partition); - - if (_username && _password) - { - gz_strcat(cmd, " "); - gz_strcat(cmd, _username); - gz_strcat(cmd, " "); - gz_strcat(cmd, _password); - } - - // We set the first argument to NULL, because we want the behavior that - // CreateProcess exhibits when the first argument is NULL: i.e. Windows will - // automatically add the .exe extension onto the filename. When the first - // argument is non-NULL, it will not automatically add the extension, which - // makes more work for us. - // - // It should also be noted that the lookup behavior for the application is - // different when the first argument is non-NULL, so we should take that - // into consideration when determining what to put into the first and second - // arguments of CreateProcess. - if (!CreateProcess(NULL, const_cast(cmd), NULL, NULL, - TRUE, 0, NULL, NULL, &info, &processInfo)) - { - std::cerr << "CreateProcess call failed: " << cmd << std::endl; - } - - return processInfo; -#else - pid_t pid = fork(); - - if (pid == 0) - { - if (_username && _password) - { - if (execl(_command, _command, _partition, _username, _password, - reinterpret_cast(0)) == -1) - { - std::cerr << "Error running execl call: " << _command << std::endl; - } - } - else - { - if (execl(_command, _command, _partition, - reinterpret_cast(0)) == -1) - { - std::cerr << "Error running execl call: " << _command << std::endl; - } - } - } - - return pid; -#endif - } - - /// \brief Wait for the end of a process and handle the termination - /// \param[in] pi Process handler of the process to wait for - /// (PROCESS_INFORMATION in windows or forkHandlerType in UNIX). - void waitAndCleanupFork(const forkHandlerType pi) - { -#ifdef _WIN32 - // Wait until child process exits. - WaitForSingleObject(pi.hProcess, INFINITE); - - // Close process and thread handler. - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); -#else - // Wait for the child process to return. - int status; - waitpid(pi, &status, 0); - if (status == -1) - std::cerr << "Error while running waitpid" << std::endl; -#endif - } - - /// \brief Send a termination signal to the process handled by pi. - /// \param[in] pi Process handler of the process to stop - /// (PROCESS_INFORMATION in windows or forkHandlerType in UNIX). - void killFork(const forkHandlerType pi) - { -#ifdef _WIN32 - // TerminateProcess return 0 on error - if (TerminateProcess(pi.hProcess, 0) == 0) - std::cerr << "Error running TerminateProcess: " << GetLastError(); -#else - kill(pi, SIGTERM); -#endif - } - /// \brief Get a random number based on an integer converted to string. /// \return A random integer converted to string. std::string getRandomNumber() @@ -248,6 +51,6 @@ namespace testing return std::to_string(d(randGenerator)); } -} +} // namespace testing #endif // header guard From 03088cda9a09c51bb8710ff5448ac49048abf11d Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Thu, 2 Nov 2023 18:29:05 +0000 Subject: [PATCH 02/10] Add some more helper functions Signed-off-by: Michael Carroll --- src/cmd/gz_TEST.cc | 251 ++++++++++++++++++++------------------------- 1 file changed, 114 insertions(+), 137 deletions(-) diff --git a/src/cmd/gz_TEST.cc b/src/cmd/gz_TEST.cc index c443506a0..538627902 100644 --- a/src/cmd/gz_TEST.cc +++ b/src/cmd/gz_TEST.cc @@ -60,16 +60,42 @@ void topicCB(const msgs::StringMsg &_msg) } ////////////////////////////////////////////////// -std::string custom_exec_str(const std::vector &_args) +struct ProcessOutput +{ + int code {-1}; + std::string cout; + std::string cerr; +}; + +////////////////////////////////////////////////// +ProcessOutput custom_exec_str(const std::vector &_args) { auto fullArgs = std::vector{kGzExe}; std::copy(std::begin(_args), std::end(_args), std::back_inserter(fullArgs)); - fullArgs.push_back("--force-version"); - fullArgs.push_back(kGzVersion); + fullArgs.emplace_back("--force-version"); + fullArgs.emplace_back(kGzVersion); auto proc = gz::utils::Subprocess(fullArgs); - proc.Join(); + auto return_code = proc.Join(); + return {return_code, proc.Stdout(), proc.Stderr()}; +} + +////////////////////////////////////////////////// +std::optional +exec_with_retry(const std::vector &_args, + const std::function &_condition) +{ + bool success = false; + int retries = 0; - return proc.Stdout(); + while (!success && retries++ < 10) + { + auto output = custom_exec_str(_args); + success = _condition(output); + if (success) + return output; + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + } + return {}; } ////////////////////////////////////////////////// @@ -78,19 +104,12 @@ TEST(gzTest, GZ_UTILS_TEST_DISABLED_ON_MAC(TopicList)) { auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); - unsigned int retries = 0u; - bool topicFound = false; - std::string output; + auto output = exec_with_retry({"topic", "-l"}, + [](auto output){ + return output.cout == "/foo\n"; + }); - while (!topicFound && retries++ < 10u) - { - output = custom_exec_str({"topic", "-l"}); - topicFound = output == "/foo\n"; - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - break; - } - - EXPECT_TRUE(topicFound); + EXPECT_TRUE(output); } ////////////////////////////////////////////////// @@ -100,21 +119,16 @@ TEST(gzTest, TopicInfo) // Launch a new publisher process that advertises a topic. auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); - unsigned int retries = 0u; - bool infoFound = false; - std::string output; + auto output = exec_with_retry({"topic", "-t", "/foo", "-i"}, + [](auto output){ + return output.cout.size() > 50u; + }); - while (!infoFound && retries++ < 10u) - { - output = custom_exec_str({"topic", "-t", "/foo", "-i"}); - infoFound = output.size() > 50u; - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - } - EXPECT_TRUE(infoFound) << "OUTPUT[" - << output << "] Size[" << output.size() + ASSERT_TRUE(output) << "OUTPUT[" + << output->cout << "] Size[" << output->cout.size() << "]. Expected Size=50" << std::endl; - EXPECT_TRUE(output.find("gz.msgs.Vector3d") != std::string::npos); + EXPECT_TRUE(output->cout.find("gz.msgs.Vector3d") != std::string::npos); } ////////////////////////////////////////////////// @@ -125,17 +139,12 @@ TEST(gzTest, ServiceList) // Launch a new responser process that advertises a service. auto proc = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, g_partition}); - unsigned int retries = 0u; - bool serviceFound = false; + auto output = exec_with_retry({"service", "-l"}, + [](auto output){ + return output.cout == "/foo\n"; + }); - while (!serviceFound && retries++ < 10u) - { - std::string output = custom_exec_str({"service", "-l"}); - serviceFound = output == "/foo\n"; - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - } - - EXPECT_TRUE(serviceFound); + EXPECT_TRUE(output); } ////////////////////////////////////////////////// @@ -145,19 +154,13 @@ TEST(gzTest, ServiceInfo) // Launch a new responser process that advertises a service. auto proc = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, g_partition}); - unsigned int retries = 0u; - bool infoFound = false; - std::string output; + auto output = exec_with_retry({"service", "-s", "/foo", "-i"}, + [](auto output){ + return output.cout.size() > 50u; + }); - while (!infoFound && retries++ < 10u) - { - output = custom_exec_str({"service", "-s", "/foo", "-i"}); - infoFound = output.size() > 50u; - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - } - - EXPECT_TRUE(infoFound); - EXPECT_TRUE(output.find("gz.msgs.Int32") != std::string::npos); + ASSERT_TRUE(output); + EXPECT_TRUE(output->cout.find("gz.msgs.Int32") != std::string::npos); } ////////////////////////////////////////////////// @@ -175,17 +178,12 @@ TEST(gzTest, TopicListSameProc) EXPECT_TRUE(pub); EXPECT_TRUE(pub.Publish(msg)); - unsigned int retries = 0u; - bool topicFound = false; - - while (!topicFound && retries++ < 10u) - { - std::string output = custom_exec_str({"topic", "-l"}); - topicFound = output == "/foo\n"; - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - } + auto output = exec_with_retry({"topic", "-l"}, + [](auto output){ + return output.cout == "/foo\n"; + }); - EXPECT_TRUE(topicFound); + EXPECT_TRUE(output); } ////////////////////////////////////////////////// @@ -203,19 +201,13 @@ TEST(gzTest, TopicInfoSameProc) EXPECT_TRUE(pub); EXPECT_TRUE(pub.Publish(msg)); - unsigned int retries = 0u; - bool infoFound = false; - std::string output; + auto output = exec_with_retry({"topic", "-t", "/foo", "-i"}, + [](auto output){ + return output.cout.size() > 50u; + }); - while (!infoFound && retries++ < 10u) - { - output = custom_exec_str({"topic", "-t", "/foo", "-i"}); - infoFound = output.size() > 50u; - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - } - - EXPECT_TRUE(infoFound); - EXPECT_TRUE(output.find("gz.msgs.Vector3d") != std::string::npos); + ASSERT_TRUE(output); + EXPECT_TRUE(output->cout.find("gz.msgs.Vector3d") != std::string::npos); } ////////////////////////////////////////////////// @@ -225,17 +217,12 @@ TEST(gzTest, ServiceListSameProc) transport::Node node; EXPECT_TRUE(node.Advertise("/foo", srvEcho)); - unsigned int retries = 0u; - bool serviceFound = false; - - while (!serviceFound && retries++ < 10u) - { - std::string output = custom_exec_str({"service", "-l"}); - serviceFound = output == "/foo\n"; - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - } + auto output = exec_with_retry({"service", "-l"}, + [](auto output){ + return output.cout == "/foo\n"; + }); - EXPECT_TRUE(serviceFound); + EXPECT_TRUE(output); } ////////////////////////////////////////////////// @@ -245,22 +232,15 @@ TEST(gzTest, ServiceInfoSameProc) transport::Node node; EXPECT_TRUE(node.Advertise("/foo", srvEcho)); - unsigned int retries = 0u; - bool infoFound = false; - std::string output; + auto output = exec_with_retry({"service", "-s", "/foo", "-i"}, + [](auto output){ + return output.cout.size() > 50u; + }); - while (!infoFound && retries++ < 10u) - { - output = custom_exec_str({"service", "-s", "/foo", "-i"}); - infoFound = output.size() > 50u; - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - } - - EXPECT_TRUE(infoFound); - EXPECT_TRUE(output.find("gz.msgs.Int32") != std::string::npos); + ASSERT_TRUE(output); + EXPECT_TRUE(output->cout.find("gz.msgs.Int32") != std::string::npos); } - ////////////////////////////////////////////////// /// \brief Check 'gz topic -p' to send a message. TEST(gzTest, TopicPublish) @@ -269,47 +249,45 @@ TEST(gzTest, TopicPublish) g_topicCBStr = "bad_value"; EXPECT_TRUE(node.Subscribe("/bar", topicCB)); - std::string output; - unsigned int retries = 0; - while (g_topicCBStr != "good_value" && retries++ < 200u) + while (retries++ < 100u) { - // Send on alternating retries - if (retries % 2) - { - output = custom_exec_str({"topic", - "-t", "/bar", - "-m", "gz_msgs.StringMsg", - "-p", R"('data: "good_value"')"}); - EXPECT_TRUE(output.empty()) << output; - } - std::this_thread::sleep_for(std::chrono::milliseconds(30)); + auto output = custom_exec_str({"topic", + "-t", "/bar", + "-m", "gz.msgs.StringMsg", + "-p", "data: \"good_value\""}); + + EXPECT_TRUE(output.cout.empty()); + EXPECT_TRUE(output.cerr.empty()); + if (g_topicCBStr == "good_value") + break; + std::this_thread::sleep_for(std::chrono::milliseconds(60)); } EXPECT_EQ(g_topicCBStr, "good_value"); // Try to publish a message not included in Gazebo Messages. std::string error = "Unable to create message of type"; - output = custom_exec_str({"topic", + auto output = custom_exec_str({"topic", "-t", "/bar", - "-m", "gz_msgs.__bad_msg_type", - "-p", R"('data:"good_value"')"}); - EXPECT_EQ(output.compare(0, error.size(), error), 0); + "-m", "gz.msgs.__bad_msg_type", + "-p", R"(data: "good_value")"}); + EXPECT_EQ(output.cerr.compare(0, error.size(), error), 0); // Try to publish using an incorrect topic name. error = "Topic [/] is not valid"; output = custom_exec_str({"topic", "-t", "/", - "-m", "gz_msgs.StringMsg", - "-p", R"('data: "good_value"')"}); - EXPECT_EQ(output.compare(0, error.size(), error), 0) << output; + "-m", "gz.msgs.StringMsg", + "-p", R"(data: "good_value")"}); + EXPECT_EQ(output.cerr.compare(0, error.size(), error), 0); // Try to publish using an incorrect number of arguments. error = "The following argument was not expected: wrong_topic"; output = custom_exec_str({"topic", "-t", "/", "wrong_topic", - "-m", "gz_msgs.StringMsg", - "-p", R"('data: "good_value"')"}); - EXPECT_EQ(output.compare(0, error.size(), error), 0) << output; + "-m", "gz.msgs.StringMsg", + "-p", R"(data: "good_value")"}); + EXPECT_EQ(output.cerr.compare(0, error.size(), error), 0); } ////////////////////////////////////////////////// @@ -327,13 +305,13 @@ TEST(gzTest, ServiceRequest) msg.set_data(10); // Check the 'gz service -r' command. - std::string output = custom_exec_str({"service", + auto output = custom_exec_str({"service", "-s", service, "--reqtype", "gz_msgs.Int32", "--reptype", "gz_msgs.Int32", "--timeout", "1000", - "--req", "'data: " + value + "'"}); - ASSERT_EQ(output, "data: " + value + "\n\n"); + "--req", "data: " + value}); + ASSERT_EQ(output.cout, "data: " + value + "\n\n"); } ////////////////////////////////////////////////// @@ -343,12 +321,12 @@ TEST(gzTest, TopicEcho) // Launch a new publisher process that advertises a topic. auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); - std::string output = custom_exec_str( + auto output = custom_exec_str( {"topic", "-e", "-t", "/foo", "-d", "1.5"}); - EXPECT_TRUE(output.find("x: 1") != std::string::npos); - EXPECT_TRUE(output.find("y: 2") != std::string::npos); - EXPECT_TRUE(output.find("z: 3") != std::string::npos); + EXPECT_TRUE(output.cout.find("x: 1") != std::string::npos); + EXPECT_TRUE(output.cout.find("y: 2") != std::string::npos); + EXPECT_TRUE(output.cout.find("z: 3") != std::string::npos); } ////////////////////////////////////////////////// @@ -359,32 +337,31 @@ TEST(gzTest, TopicEchoNum) // Launch a new publisher process that advertises a topic. auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); - std::string output = custom_exec_str( + auto output = custom_exec_str( {"topic", "-e", "-t", "/foo", "-n", "2"}); - size_t pos = output.find("x: 1"); + size_t pos = output.cout.find("x: 1"); EXPECT_TRUE(pos != std::string::npos); - pos = output.find("x: 1", pos + 4); + pos = output.cout.find("x: 1", pos + 4); EXPECT_TRUE(pos != std::string::npos); - pos = output.find("x: 1", pos + 4); + pos = output.cout.find("x: 1", pos + 4); EXPECT_TRUE(pos == std::string::npos); - pos = output.find("y: 2"); + pos = output.cout.find("y: 2"); EXPECT_TRUE(pos != std::string::npos); - pos = output.find("y: 2", pos + 4); + pos = output.cout.find("y: 2", pos + 4); EXPECT_TRUE(pos != std::string::npos); - pos = output.find("y: 2", pos + 4); + pos = output.cout.find("y: 2", pos + 4); EXPECT_TRUE(pos == std::string::npos); - pos = output.find("z: 3"); + pos = output.cout.find("z: 3"); EXPECT_TRUE(pos != std::string::npos); - pos = output.find("z: 3", pos + 4); + pos = output.cout.find("z: 3", pos + 4); EXPECT_TRUE(pos != std::string::npos); - pos = output.find("z: 3", pos + 4); + pos = output.cout.find("z: 3", pos + 4); EXPECT_TRUE(pos == std::string::npos); } - /// Main int main(int argc, char **argv) { From 97cb1aefb53a4e410bad153c4e7691c345324d9b Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Thu, 2 Nov 2023 18:34:16 +0000 Subject: [PATCH 03/10] Lint Signed-off-by: Michael Carroll --- src/cmd/gz_TEST.cc | 3 ++- test/integration/twoProcsSrvCall.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cmd/gz_TEST.cc b/src/cmd/gz_TEST.cc index bce7876c2..6ba44ffb2 100644 --- a/src/cmd/gz_TEST.cc +++ b/src/cmd/gz_TEST.cc @@ -40,7 +40,8 @@ namespace { constexpr const char * kGzExe = GZ_EXE; constexpr const char * kTwoProcsPublisherExe = TWO_PROCS_PUBLISHER_EXE; -constexpr const char * kTwoProcsSrvCallReplierExe = TWO_PROCS_SRV_CALL_REPLIER_EXE; +constexpr const char * kTwoProcsSrvCallReplierExe = + TWO_PROCS_SRV_CALL_REPLIER_EXE; constexpr const char * kGzVersion = GZ_VERSION_FULL; } // namespace diff --git a/test/integration/twoProcsSrvCall.cc b/test/integration/twoProcsSrvCall.cc index 1226522fe..c9e254b6d 100644 --- a/test/integration/twoProcsSrvCall.cc +++ b/test/integration/twoProcsSrvCall.cc @@ -40,7 +40,8 @@ static std::string g_topic = "/foo"; // NOLINT(*) static int data = 5; static int counter = 0; -static constexpr const char *kTwoProcsSrvCallReplierExe = TWO_PROCS_SRV_CALL_REPLIER_EXE; +static constexpr const char *kTwoProcsSrvCallReplierExe = + TWO_PROCS_SRV_CALL_REPLIER_EXE; ////////////////////////////////////////////////// /// \brief Initialize some global variables. From a07d9f792bcd69dad6896350eaa35a261ec70a9e Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Mon, 27 Nov 2023 14:51:23 +0000 Subject: [PATCH 04/10] Clean up use of HAVE_GZ_TOOLS Signed-off-by: Michael Carroll --- src/CMakeLists.txt | 3 +-- src/cmd/CMakeLists.txt | 5 ++++- test/integration/CMakeLists.txt | 8 -------- test/test_config.hh.in | 8 -------- 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cfb71dd55..c984303ee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,7 +16,7 @@ target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME} ) target_include_directories(${PROJECT_LIBRARY_TARGET_NAME} - SYSTEM PUBLIC + SYSTEM PUBLIC $ $) @@ -39,7 +39,6 @@ foreach(test ${test_list}) # auxiliary files from. Using a generator expression here is useful for # multi-configuration generators, like Visual Studio. target_compile_definitions(${test} PRIVATE - "DETAIL_GZ_TRANSPORT_TEST_DIR=\"$\"" "GZ_TEST_LIBRARY_PATH=\"$\"") endforeach() diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt index f077906dc..9a559f1d7 100644 --- a/src/cmd/CMakeLists.txt +++ b/src/cmd/CMakeLists.txt @@ -8,6 +8,10 @@ if (MSVC) list(REMOVE_ITEM gtest_sources gz_TEST.cc) endif() +if (NOT HAVE_GZ_TOOLS) + list(REMOVE_ITEM gtest_sources gz_TEST.cc) +endif() + # Make a small static lib of command line functions add_library(gz STATIC gz.cc) target_link_libraries(gz @@ -50,7 +54,6 @@ foreach(test ${test_list}) "PROJECT_SOURCE_DIR=\"${PROJECT_SOURCE_DIR}\"" "TWO_PROCS_PUBLISHER_EXE=\"$\"" "TWO_PROCS_SRV_CALL_REPLIER_EXE=\"$\"" - "DETAIL_GZ_TRANSPORT_TEST_DIR=\"$\"" "GZ_EXE=\"${HAVE_GZ_TOOLS}\"" ) diff --git a/test/integration/CMakeLists.txt b/test/integration/CMakeLists.txt index 37b6d3df4..a60793e91 100644 --- a/test/integration/CMakeLists.txt +++ b/test/integration/CMakeLists.txt @@ -28,14 +28,6 @@ gz_build_tests(TYPE INTEGRATION SOURCES ${tests} TEST_LIST test_list LIB_DEPS ${EXTRA_TEST_LIB_DEPS}) -foreach(test ${test_list}) - # Inform each test of its output directory so it knows where to call the - # auxiliary files from. Using a generator expression here is useful for - # multi-configuration generators, like Visual Studio. - target_compile_definitions(${test} PRIVATE - "DETAIL_GZ_TRANSPORT_TEST_DIR=\"$\"") -endforeach() - set(auxiliary_files authPubSubSubscriberInvalid_aux fastPub_aux diff --git a/test/test_config.hh.in b/test/test_config.hh.in index df25a23f0..e71841b68 100644 --- a/test/test_config.hh.in +++ b/test/test_config.hh.in @@ -22,14 +22,6 @@ #define GZ_CONFIG_PATH "@CMAKE_BINARY_DIR@/test/conf" #define GZ_VERSION_FULL "@PROJECT_VERSION_FULL@" -#ifdef DETAIL_GZ_TRANSPORT_TEST_DIR -// The DETAIL_GZ_TRANSPORT_TEST_DIR macro is defined using generator -// expressions in CMakeLists.txt files. See test/integration/CMakeLists.txt for -// an example. -#define GZ_TRANSPORT_TEST_DIR \ - DETAIL_GZ_TRANSPORT_TEST_DIR -#endif - #include #include #include From 03d7a27cd52eadaad0a2407b30e41a371508ac32 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Mon, 27 Nov 2023 14:54:13 +0000 Subject: [PATCH 05/10] Address reviewer feedback Signed-off-by: Michael Carroll --- log/test/integration/ChirpParams.cc | 15 +++------------ log/test/integration/ChirpParams.hh | 5 +++-- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/log/test/integration/ChirpParams.cc b/log/test/integration/ChirpParams.cc index 1f606f1d6..ba0a517d5 100644 --- a/log/test/integration/ChirpParams.cc +++ b/log/test/integration/ChirpParams.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Open Source Robotics Foundation + * Copyright (C) 2023 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,22 +17,13 @@ #include "ChirpParams.hh" +#include +#include static constexpr const char* kTopicChirpExe = TOPIC_CHIRP_EXE; namespace gz::transport::log::test { - ////////////////////////////////////////////////// - /// \brief Similar to testing::forkAndRun(), except this function - /// specifically calls the INTEGRATION_topicChirp_aux process and passes - /// it arguments to determine how it should chirp out messages over its - /// topics. - /// \param _topics A list of topic names to chirp on - /// \param _chirps The number of messages to chirp out. Each message - /// will count up starting from the value 1 and ending with the value - /// _chirps. - /// \return A handle to the process. This can be used with - /// testing::waitAndCleanupFork(). gz::utils::Subprocess BeginChirps( const std::vector &_topics, const int _chirps, diff --git a/log/test/integration/ChirpParams.hh b/log/test/integration/ChirpParams.hh index e194cac84..5331df5ab 100644 --- a/log/test/integration/ChirpParams.hh +++ b/log/test/integration/ChirpParams.hh @@ -46,10 +46,11 @@ namespace gz::transport::log::test /// specifically calls the INTEGRATION_topicChirp_aux process and passes /// it arguments to determine how it should chirp out messages over its /// topics. - /// \param _topics A list of topic names to chirp on - /// \param _chirps The number of messages to chirp out. Each message + /// \param[in] _topics A list of topic names to chirp on + /// \param[in] _chirps The number of messages to chirp out. Each message /// will count up starting from the value 1 and ending with the value /// _chirps. + /// \param[in] _paritionName Gz transport partition to use for the test /// \return A handle to the process. This can be used with /// testing::waitAndCleanupFork(). gz::utils::Subprocess BeginChirps( From 87fd84698c526468a14d8c3ae28d5f0b8adbbc55 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Mon, 27 Nov 2023 16:03:32 +0000 Subject: [PATCH 06/10] Add test fixture to run service tests in their own partition Signed-off-by: Michael Carroll --- test/integration/twoProcsPubSub.cc | 12 ++-- test/integration/twoProcsSrvCall.cc | 71 ++++++++++--------- .../twoProcsSrvCallWithoutInput.cc | 71 +++++++++---------- .../twoProcsSrvCallWithoutOutput.cc | 61 ++++++++-------- 4 files changed, 111 insertions(+), 104 deletions(-) diff --git a/test/integration/twoProcsPubSub.cc b/test/integration/twoProcsPubSub.cc index 05401f0e4..2a508b888 100644 --- a/test/integration/twoProcsPubSub.cc +++ b/test/integration/twoProcsPubSub.cc @@ -42,12 +42,14 @@ static bool cbVectorExecuted = false; static bool cbRawExecuted = false; static int counter = 0; -static constexpr const char* kFastPubExe = FAST_PUB_EXE; -static constexpr const char* kPubExe = PUB_EXE; -static constexpr const char* kPubThrottledExe = PUB_THROTTLED_EXE; -static constexpr const char* kTwoProcsPublisherExe = TWO_PROCS_PUBLISHER_EXE; -static constexpr const char* kTwoProcsPubSubSubscriberExe = +namespace { +constexpr const char* kFastPubExe = FAST_PUB_EXE; +constexpr const char* kPubExe = PUB_EXE; +constexpr const char* kPubThrottledExe = PUB_THROTTLED_EXE; +constexpr const char* kTwoProcsPublisherExe = TWO_PROCS_PUBLISHER_EXE; +constexpr const char* kTwoProcsPubSubSubscriberExe = TWO_PROCS_PUB_SUB_SUBSCRIBER_EXE; +} // namespace ////////////////////////////////////////////////// /// \brief Initialize some global variables. diff --git a/test/integration/twoProcsSrvCall.cc b/test/integration/twoProcsSrvCall.cc index c9e254b6d..bca50b92f 100644 --- a/test/integration/twoProcsSrvCall.cc +++ b/test/integration/twoProcsSrvCall.cc @@ -35,7 +35,6 @@ using namespace gz; static bool responseExecuted; static bool wrongResponseExecuted; -static std::string partition; // NOLINT(*) static std::string g_topic = "/foo"; // NOLINT(*) static int data = 5; static int counter = 0; @@ -43,6 +42,36 @@ static int counter = 0; static constexpr const char *kTwoProcsSrvCallReplierExe = TWO_PROCS_SRV_CALL_REPLIER_EXE; +////////////////////////////////////////////////// +class twoProcSrvCall: public testing::Test { + protected: + void SetUp() override { + gz::utils::env("GZ_PARTITION", this->prevPartition); + + // Get a random partition name. + this->partition = testing::getRandomNumber(); + + // Set the partition name for this process. + gz::utils::setenv("GZ_PARTITION", this->partition); + + this->pi = std::make_unique( + std::vector({ + kTwoProcsSrvCallReplierExe, this->partition})); + } + + void TearDown() override { + gz::utils::setenv("GZ_PARTITION", this->prevPartition); + + this->pi->Terminate(); + this->pi->Join(); + } + + private: + std::string prevPartition; + std::string partition; + std::unique_ptr pi; +}; + ////////////////////////////////////////////////// /// \brief Initialize some global variables. void reset() @@ -73,10 +102,8 @@ void wrongResponse(const msgs::Vector3d &/*_rep*/, bool /*_result*/) ////////////////////////////////////////////////// /// \brief Two different nodes running in two different processes. One node /// advertises a service and the other requests a few service calls. -TEST(twoProcSrvCall, SrvTwoProcs) +TEST_F(twoProcSrvCall, SrvTwoProcs) { - auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); - reset(); msgs::Int32 req; @@ -119,15 +146,13 @@ TEST(twoProcSrvCall, SrvTwoProcs) /// \brief This test spawns a service responser and a service requester. The /// requester uses a wrong type for the request argument. The test should verify /// that the service call does not succeed. -TEST(twoProcSrvCall, SrvRequestWrongReq) +TEST_F(twoProcSrvCall, SrvRequestWrongReq) { msgs::Vector3d wrongReq; msgs::Int32 rep; bool result; unsigned int timeout = 1000; - auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); - wrongReq.set_x(1); wrongReq.set_y(2); wrongReq.set_z(3); @@ -151,15 +176,13 @@ TEST(twoProcSrvCall, SrvRequestWrongReq) /// \brief This test spawns a service responser and a service requester. The /// requester uses a wrong type for the response argument. The test should /// verify that the service call does not succeed. -TEST(twoProcSrvCall, SrvRequestWrongRep) +TEST_F(twoProcSrvCall, SrvRequestWrongRep) { msgs::Int32 req; msgs::Vector3d wrongRep; bool result; unsigned int timeout = 1000; - auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); - req.set_data(data); reset(); @@ -182,7 +205,7 @@ TEST(twoProcSrvCall, SrvRequestWrongRep) /// service requesters use incorrect types in some of the requests. The test /// should verify that a response is received only when the appropriate types /// are used. -TEST(twoProcSrvCall, SrvTwoRequestsOneWrong) +TEST_F(twoProcSrvCall, SrvTwoRequestsOneWrong) { msgs::Int32 req; msgs::Int32 goodRep; @@ -190,8 +213,6 @@ TEST(twoProcSrvCall, SrvTwoRequestsOneWrong) bool result; unsigned int timeout = 2000; - auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); - req.set_data(data); reset(); @@ -221,10 +242,8 @@ TEST(twoProcSrvCall, SrvTwoRequestsOneWrong) /// \brief This test spawns two nodes on different processes. One of the nodes /// advertises a service and the other uses ServiceList() for getting the list /// of available services. -TEST(twoProcSrvCall, ServiceList) +TEST_F(twoProcSrvCall, ServiceList) { - auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); - reset(); transport::Node node; @@ -266,10 +285,8 @@ TEST(twoProcSrvCall, ServiceList) /// \brief This test spawns two nodes on different processes. One of the nodes /// advertises a service and the other uses ServiceInfo() for getting /// information about the service. -TEST(twoProcSrvCall, ServiceInfo) +TEST_F(twoProcSrvCall, ServiceInfo) { - auto pi = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, partition}); - reset(); transport::Node node; @@ -291,19 +308,3 @@ TEST(twoProcSrvCall, ServiceInfo) reset(); } - -////////////////////////////////////////////////// -int main(int argc, char **argv) -{ - // Get a random partition name. - partition = testing::getRandomNumber(); - - // Set the partition name for this process. - gz::utils::setenv("GZ_PARTITION", partition); - - // Enable verbose mode. - // gz::utils::setenv("GZ_VERBOSE", "1"); - - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/test/integration/twoProcsSrvCallWithoutInput.cc b/test/integration/twoProcsSrvCallWithoutInput.cc index 8d7b1f69a..5dd7b5bd9 100644 --- a/test/integration/twoProcsSrvCallWithoutInput.cc +++ b/test/integration/twoProcsSrvCallWithoutInput.cc @@ -43,6 +43,36 @@ static int g_counter = 0; static constexpr const char * kTwoProcsSrvCallWithoutInputReplierExe = TWO_PROCS_SRV_CALL_WITHOUT_INPUT_REPLIER_EXE; +////////////////////////////////////////////////// +class twoProcSrvCallWithoutInput: public testing::Test { + protected: + void SetUp() override { + gz::utils::env("GZ_PARTITION", this->prevPartition); + + // Get a random partition name. + this->partition = testing::getRandomNumber(); + + // Set the partition name for this process. + gz::utils::setenv("GZ_PARTITION", this->partition); + + this->pi = std::make_unique( + std::vector({ + kTwoProcsSrvCallWithoutInputReplierExe, this->partition})); + } + + void TearDown() override { + gz::utils::setenv("GZ_PARTITION", this->prevPartition); + + this->pi->Terminate(); + this->pi->Join(); + } + + private: + std::string prevPartition; + std::string partition; + std::unique_ptr pi; +}; + ////////////////////////////////////////////////// /// \brief Initialize some global variables. void reset() @@ -74,11 +104,8 @@ void wrongResponse(const msgs::Vector3d &/*_rep*/, bool /*_result*/) /// \brief Two different nodes running in two different processes. One node /// advertises a service without input and the other requests a few service /// calls. -TEST(twoProcSrvCallWithoutInput, SrvTwoProcs) +TEST_F(twoProcSrvCallWithoutInput, SrvTwoProcs) { - auto pi = gz::utils::Subprocess( - {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); - reset(); transport::Node node; @@ -118,15 +145,12 @@ TEST(twoProcSrvCallWithoutInput, SrvTwoProcs) /// \brief This test spawns a service that doesn't accept input parameters. The /// service requester uses a wrong type for the response argument. The test /// should verify that the service call does not succeed. -TEST(twoProcSrvCallWithoutInput, SrvRequestWrongRep) +TEST_F(twoProcSrvCallWithoutInput, SrvRequestWrongRep) { msgs::Vector3d wrongRep; bool result; unsigned int timeout = 1000; - auto pi = gz::utils::Subprocess( - {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); - reset(); transport::Node node; @@ -147,16 +171,13 @@ TEST(twoProcSrvCallWithoutInput, SrvRequestWrongRep) /// service requesters use incorrect types in some of the requests. The test /// should verify that a response is received only when the appropriate types /// are used. -TEST(twoProcSrvCallWithoutInput, SrvTwoRequestsOneWrong) +TEST_F(twoProcSrvCallWithoutInput, SrvTwoRequestsOneWrong) { msgs::Int32 goodRep; msgs::Vector3d badRep; bool result; unsigned int timeout = 2000; - auto pi = gz::utils::Subprocess( - {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); - reset(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); @@ -184,11 +205,8 @@ TEST(twoProcSrvCallWithoutInput, SrvTwoRequestsOneWrong) /// \brief This test spawns two nodes on different processes. One of the nodes /// advertises a service without input and the other uses ServiceList() for /// getting the list of available services. -TEST(twoProcSrvCallWithoutInput, ServiceList) +TEST_F(twoProcSrvCallWithoutInput, ServiceList) { - auto pi = gz::utils::Subprocess( - {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); - reset(); transport::Node node; @@ -229,11 +247,8 @@ TEST(twoProcSrvCallWithoutInput, ServiceList) /// \brief This test spawns two nodes on different processes. One of the nodes /// advertises a service without input and the other uses ServiceInfo() for /// getting information about the service. -TEST(twoProcSrvCallWithoutInput, ServiceInfo) +TEST_F(twoProcSrvCallWithoutInput, ServiceInfo) { - auto pi = gz::utils::Subprocess( - {kTwoProcsSrvCallWithoutInputReplierExe, g_partition}); - reset(); transport::Node node; @@ -255,19 +270,3 @@ TEST(twoProcSrvCallWithoutInput, ServiceInfo) reset(); } - -////////////////////////////////////////////////// -int main(int argc, char **argv) -{ - // Get a random partition name. - g_partition = testing::getRandomNumber(); - - // Set the partition name for this process. - gz::utils::setenv("GZ_PARTITION", g_partition); - - // Enable verbose mode. - // gz::utils::setenv("GZ_VERBOSE", "1"); - - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/test/integration/twoProcsSrvCallWithoutOutput.cc b/test/integration/twoProcsSrvCallWithoutOutput.cc index fe3302c77..ead8b8677 100644 --- a/test/integration/twoProcsSrvCallWithoutOutput.cc +++ b/test/integration/twoProcsSrvCallWithoutOutput.cc @@ -41,6 +41,36 @@ static int g_counter = 0; static constexpr const char * kTwoProcsSrvCallWithoutOutputReplierExe = TWO_PROCS_SRV_CALL_WITHOUT_OUTPUT_REPLIER_EXE; +////////////////////////////////////////////////// +class twoProcSrvCallWithoutOutput: public testing::Test { + protected: + void SetUp() override { + gz::utils::env("GZ_PARTITION", this->prevPartition); + + // Get a random partition name. + this->partition = testing::getRandomNumber(); + + // Set the partition name for this process. + gz::utils::setenv("GZ_PARTITION", this->partition); + + this->pi = std::make_unique( + std::vector({ + kTwoProcsSrvCallWithoutOutputReplierExe, this->partition})); + } + + void TearDown() override { + gz::utils::setenv("GZ_PARTITION", this->prevPartition); + + this->pi->Terminate(); + this->pi->Join(); + } + + private: + std::string prevPartition; + std::string partition; + std::unique_ptr pi; +}; + ////////////////////////////////////////////////// /// \brief Initialize some global variables. void reset() @@ -54,13 +84,10 @@ void reset() /// \brief This test spawns a service that doesn't wait for ouput parameters. /// The requester uses a wrong type for the request argument. The test should /// verify that the service call does not succeed. -TEST(twoProcSrvCallWithoutOutput, SrvRequestWrongReq) +TEST_F(twoProcSrvCallWithoutOutput, SrvRequestWrongReq) { msgs::Vector3d wrongReq; - auto pi = gz::utils::Subprocess( - {kTwoProcsSrvCallWithoutOutputReplierExe, g_partition}); - wrongReq.set_x(1); wrongReq.set_y(2); wrongReq.set_z(3); @@ -81,11 +108,8 @@ TEST(twoProcSrvCallWithoutOutput, SrvRequestWrongReq) /// \brief This test spawns two nodes on different processes. One of the nodes /// advertises a service without output and the other uses ServiceList() for /// getting the list of available services. -TEST(twoProcSrvCallWithoutOutput, ServiceList) +TEST_F(twoProcSrvCallWithoutOutput, ServiceList) { - auto pi = gz::utils::Subprocess( - {kTwoProcsSrvCallWithoutOutputReplierExe, g_partition}); - reset(); transport::Node node; @@ -126,11 +150,8 @@ TEST(twoProcSrvCallWithoutOutput, ServiceList) /// \brief This test spawns two nodes on different processes. One of the nodes /// advertises a service without output and the other uses ServiceInfo() for /// getting information about the service. -TEST(twoProcSrvCallWithoutOutput, ServiceInfo) +TEST_F(twoProcSrvCallWithoutOutput, ServiceInfo) { - auto pi = gz::utils::Subprocess( - {kTwoProcsSrvCallWithoutOutputReplierExe, g_partition}); - reset(); transport::Node node; @@ -151,19 +172,3 @@ TEST(twoProcSrvCallWithoutOutput, ServiceInfo) reset(); } - -////////////////////////////////////////////////// -int main(int argc, char **argv) -{ - // Get a random partition name. - g_partition = testing::getRandomNumber(); - - // Set the partition name for this process. - gz::utils::setenv("GZ_PARTITION", g_partition); - - // Enable verbose mode. - // gz::utils::setenv("GZ_VERBOSE", "1"); - - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} From b94655700738254f6b8c4cdca32dbe0ef7b2878e Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Mon, 27 Nov 2023 18:46:05 +0000 Subject: [PATCH 07/10] Clear up shadowed variables Signed-off-by: Michael Carroll --- src/cmd/gz_TEST.cc | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/cmd/gz_TEST.cc b/src/cmd/gz_TEST.cc index 6ba44ffb2..3334f6722 100644 --- a/src/cmd/gz_TEST.cc +++ b/src/cmd/gz_TEST.cc @@ -106,8 +106,8 @@ TEST(gzTest, GZ_UTILS_TEST_DISABLED_ON_MAC(TopicList)) auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); auto output = exec_with_retry({"topic", "-l"}, - [](auto output){ - return output.cout == "/foo\n"; + [](auto proc){ + return proc.cout == "/foo\n"; }); EXPECT_TRUE(output); @@ -121,8 +121,8 @@ TEST(gzTest, TopicInfo) auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); auto output = exec_with_retry({"topic", "-t", "/foo", "-i"}, - [](auto output){ - return output.cout.size() > 50u; + [](auto proc){ + return proc.cout.size() > 50u; }); @@ -141,8 +141,8 @@ TEST(gzTest, ServiceList) auto proc = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, g_partition}); auto output = exec_with_retry({"service", "-l"}, - [](auto output){ - return output.cout == "/foo\n"; + [](auto proc){ + return proc.cout == "/foo\n"; }); EXPECT_TRUE(output); @@ -156,8 +156,8 @@ TEST(gzTest, ServiceInfo) auto proc = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, g_partition}); auto output = exec_with_retry({"service", "-s", "/foo", "-i"}, - [](auto output){ - return output.cout.size() > 50u; + [](auto proc){ + return proc.cout.size() > 50u; }); ASSERT_TRUE(output); @@ -180,8 +180,8 @@ TEST(gzTest, TopicListSameProc) EXPECT_TRUE(pub.Publish(msg)); auto output = exec_with_retry({"topic", "-l"}, - [](auto output){ - return output.cout == "/foo\n"; + [](auto proc){ + return proc.cout == "/foo\n"; }); EXPECT_TRUE(output); @@ -203,8 +203,8 @@ TEST(gzTest, TopicInfoSameProc) EXPECT_TRUE(pub.Publish(msg)); auto output = exec_with_retry({"topic", "-t", "/foo", "-i"}, - [](auto output){ - return output.cout.size() > 50u; + [](auto proc){ + return proc.cout.size() > 50u; }); ASSERT_TRUE(output); @@ -219,8 +219,8 @@ TEST(gzTest, ServiceListSameProc) EXPECT_TRUE(node.Advertise("/foo", srvEcho)); auto output = exec_with_retry({"service", "-l"}, - [](auto output){ - return output.cout == "/foo\n"; + [](auto proc){ + return proc.cout == "/foo\n"; }); EXPECT_TRUE(output); @@ -234,8 +234,8 @@ TEST(gzTest, ServiceInfoSameProc) EXPECT_TRUE(node.Advertise("/foo", srvEcho)); auto output = exec_with_retry({"service", "-s", "/foo", "-i"}, - [](auto output){ - return output.cout.size() > 50u; + [](auto proc){ + return proc.cout.size() > 50u; }); ASSERT_TRUE(output); From baa8dcd21b47a3bfce12b88e4254c15a249b15df Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Mon, 27 Nov 2023 19:44:48 +0000 Subject: [PATCH 08/10] Fix shadowed Signed-off-by: Michael Carroll --- src/cmd/gz_TEST.cc | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/cmd/gz_TEST.cc b/src/cmd/gz_TEST.cc index 3334f6722..5a6158e72 100644 --- a/src/cmd/gz_TEST.cc +++ b/src/cmd/gz_TEST.cc @@ -106,8 +106,8 @@ TEST(gzTest, GZ_UTILS_TEST_DISABLED_ON_MAC(TopicList)) auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); auto output = exec_with_retry({"topic", "-l"}, - [](auto proc){ - return proc.cout == "/foo\n"; + [](auto procOut){ + return procOut.cout == "/foo\n"; }); EXPECT_TRUE(output); @@ -121,8 +121,8 @@ TEST(gzTest, TopicInfo) auto proc = gz::utils::Subprocess({kTwoProcsPublisherExe, g_partition}); auto output = exec_with_retry({"topic", "-t", "/foo", "-i"}, - [](auto proc){ - return proc.cout.size() > 50u; + [](auto procOut){ + return procOut.cout.size() > 50u; }); @@ -141,8 +141,8 @@ TEST(gzTest, ServiceList) auto proc = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, g_partition}); auto output = exec_with_retry({"service", "-l"}, - [](auto proc){ - return proc.cout == "/foo\n"; + [](auto procOut){ + return procOut.cout == "/foo\n"; }); EXPECT_TRUE(output); @@ -156,8 +156,8 @@ TEST(gzTest, ServiceInfo) auto proc = gz::utils::Subprocess({kTwoProcsSrvCallReplierExe, g_partition}); auto output = exec_with_retry({"service", "-s", "/foo", "-i"}, - [](auto proc){ - return proc.cout.size() > 50u; + [](auto procOut){ + return procOut.cout.size() > 50u; }); ASSERT_TRUE(output); @@ -180,8 +180,8 @@ TEST(gzTest, TopicListSameProc) EXPECT_TRUE(pub.Publish(msg)); auto output = exec_with_retry({"topic", "-l"}, - [](auto proc){ - return proc.cout == "/foo\n"; + [](auto procOut){ + return procOut.cout == "/foo\n"; }); EXPECT_TRUE(output); @@ -203,8 +203,8 @@ TEST(gzTest, TopicInfoSameProc) EXPECT_TRUE(pub.Publish(msg)); auto output = exec_with_retry({"topic", "-t", "/foo", "-i"}, - [](auto proc){ - return proc.cout.size() > 50u; + [](auto procOut){ + return procOut.cout.size() > 50u; }); ASSERT_TRUE(output); @@ -219,8 +219,8 @@ TEST(gzTest, ServiceListSameProc) EXPECT_TRUE(node.Advertise("/foo", srvEcho)); auto output = exec_with_retry({"service", "-l"}, - [](auto proc){ - return proc.cout == "/foo\n"; + [](auto procOut){ + return procOut.cout == "/foo\n"; }); EXPECT_TRUE(output); @@ -234,8 +234,8 @@ TEST(gzTest, ServiceInfoSameProc) EXPECT_TRUE(node.Advertise("/foo", srvEcho)); auto output = exec_with_retry({"service", "-s", "/foo", "-i"}, - [](auto proc){ - return proc.cout.size() > 50u; + [](auto procOut){ + return procOut.cout.size() > 50u; }); ASSERT_TRUE(output); From ea0361c98fb6f43f6f9cae848357f71c05fa424a Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Mon, 27 Nov 2023 20:45:23 +0000 Subject: [PATCH 09/10] Allow verbose for coverage Signed-off-by: Michael Carroll --- src/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c984303ee..bed76c64d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,6 +41,8 @@ foreach(test ${test_list}) target_compile_definitions(${test} PRIVATE "GZ_TEST_LIBRARY_PATH=\"$\"") + set_property(TEST ${test} PROPERTY ENVIRONMENT "GZ_VERBOSE=1") + endforeach() if(MSVC) From 1c3d4b80b142f6cbccfc1063f02f012caf482a66 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Tue, 28 Nov 2023 18:18:37 +0000 Subject: [PATCH 10/10] Address reviewer feedback Signed-off-by: Michael Carroll --- src/cmd/cmdtransport.rb.in | 1 - test/integration/twoProcsSrvCall.cc | 2 ++ test/integration/twoProcsSrvCallWithoutInput.cc | 2 ++ test/integration/twoProcsSrvCallWithoutOutput.cc | 2 ++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cmd/cmdtransport.rb.in b/src/cmd/cmdtransport.rb.in index 671c65348..74d96000b 100644 --- a/src/cmd/cmdtransport.rb.in +++ b/src/cmd/cmdtransport.rb.in @@ -42,7 +42,6 @@ class Cmd conf_version = LIBRARY_VERSION exe_version = `#{exe_name} --version`.strip - # Sanity check: Verify that the version of the yaml file matches the version # of the library that we are using. unless exe_version.eql? conf_version diff --git a/test/integration/twoProcsSrvCall.cc b/test/integration/twoProcsSrvCall.cc index bca50b92f..e22b3d4bd 100644 --- a/test/integration/twoProcsSrvCall.cc +++ b/test/integration/twoProcsSrvCall.cc @@ -19,7 +19,9 @@ #include #include +#include #include +#include #include "gz/transport/Node.hh" #include "gz/transport/TopicUtils.hh" diff --git a/test/integration/twoProcsSrvCallWithoutInput.cc b/test/integration/twoProcsSrvCallWithoutInput.cc index 5dd7b5bd9..072df68b2 100644 --- a/test/integration/twoProcsSrvCallWithoutInput.cc +++ b/test/integration/twoProcsSrvCallWithoutInput.cc @@ -19,7 +19,9 @@ #include #include +#include #include +#include #include "gz/transport/Node.hh" #include "gz/transport/TopicUtils.hh" diff --git a/test/integration/twoProcsSrvCallWithoutOutput.cc b/test/integration/twoProcsSrvCallWithoutOutput.cc index ead8b8677..72995f35d 100644 --- a/test/integration/twoProcsSrvCallWithoutOutput.cc +++ b/test/integration/twoProcsSrvCallWithoutOutput.cc @@ -18,7 +18,9 @@ #include #include +#include #include +#include #include "gz/transport/Node.hh" #include "gz/transport/TopicUtils.hh"