From db7f3da393c29ef4da570e78c268eebf86ae7bb7 Mon Sep 17 00:00:00 2001 From: khromenokroman Date: Sun, 1 Sep 2024 19:17:43 +0200 Subject: [PATCH] iox-#2330 Refactor func for platform --- .github/workflows/build-test.yml | 39 ++----- .../cmake/IceoryxPackageHelper.cmake | 7 +- .../iceoryx_posh/internal/roudi/roudi.hpp | 56 +++++++--- iceoryx_posh/source/roudi/roudi.cpp | 1 + .../moduletests/test_roudi_system_manager.cpp | 100 +++++++++++++++--- ...est-ubuntu-support-systemd-integrations.sh | 62 +++++++++++ .../build-test-ubuntu-support-systemd-unit.sh | 48 +++++++++ tools/iceoryx_build_test.sh | 8 ++ 8 files changed, 257 insertions(+), 64 deletions(-) create mode 100755 tools/ci/build-test-ubuntu-support-systemd-integrations.sh create mode 100755 tools/ci/build-test-ubuntu-support-systemd-unit.sh diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index e2387562b4..7ad01213b2 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -205,45 +205,20 @@ jobs: - run: ./tools/ci/build-test-ubuntu-bazel.sh # Check run systemd - build-and-run-roudi-with-systemd-ubuntu: + build-and-run-roudi-with-systemd-and-build-test-and-run-ubuntu: # prevent stuck jobs consuming runners for 6 hours timeout-minutes: 60 runs-on: ubuntu-latest needs: pre-flight-check steps: - - name: Update - run: sudo apt update - - name: Install depends - run: sudo apt install -y gcc g++ cmake libacl1-dev libncurses5-dev pkg-config libsystemd-dev - name: Checkout uses: actions/checkout@v4 - - name: Cmake cache - run: cmake -Bbuild -Hiceoryx_meta -DBUILD_SHARED_LIBS=ON -DUSE_SYSTEMD=ON - - name: build - run: cmake --build build -j 16 - - name: Install - run: sudo cmake --build build --target install - - name: Ldconfig run - run: sudo ldconfig - - name: Create unit file - run: echo -e "[Unit]\nDescription=Test application roudi\n\n[Service]\nType=notify\nRestartSec=10\nRestart=always\nExecStart=/usr/local/bin/iox-roudi\nTimeoutStartSec=10\nWatchdogSec=5\n\n[Install]\nWantedBy=multi-user.target" | sudo tee /usr/lib/systemd/system/test_iox.service > /dev/null - - name: Show unit - run: cat /usr/lib/systemd/system/test_iox.service - - name: Daemon reload - run: sudo systemctl daemon-reload - - name: Check status - run: sudo systemctl status test_iox || true - - name: Start roudi - run: | - sudo systemctl start test_iox || (echo "Failed to start service"; sudo journalctl -u test_iox -n 50; exit 1) - - name: Wait for 30 seconds - run: sleep 30 - - name: Check roudi - run: sudo systemctl status test_iox || (echo "Failed to start service"; sudo journalctl -u test_iox -n 50; exit 1) - - name: Stop roudi - run: sudo systemctl stop test_iox - - name: Show journal - run: sudo journalctl -u test_iox -n 100 + - name: Install iceoryx dependencies and clang-tidy + uses: ./.github/actions/install-iceoryx-deps-and-clang + - name: Build project and test and run unit test + run: sudo ./tools/ci/build-test-ubuntu-support-systemd-unit.sh + - name: Start integration test + run: sudo ./tools/ci/build-test-ubuntu-support-systemd-integrations.sh coverage-and-docs: # prevent stuck jobs consuming runners for 6 hours diff --git a/iceoryx_platform/cmake/IceoryxPackageHelper.cmake b/iceoryx_platform/cmake/IceoryxPackageHelper.cmake index 0858a27b35..fcfdc69ef3 100644 --- a/iceoryx_platform/cmake/IceoryxPackageHelper.cmake +++ b/iceoryx_platform/cmake/IceoryxPackageHelper.cmake @@ -237,6 +237,11 @@ Macro(iox_add_executable) target_compile_options(${IOX_TARGET} PRIVATE ${ICEORYX_CXX_FLAGS} ${ICEORYX_CXX_WARNINGS} ${ICEORYX_SANITIZER_FLAGS} ${ICEORYX_GRCOV_FLAGS}) endif() + if(USE_SYSTEMD AND ("${IOX_TARGET}" STREQUAL "posh_moduletests")) + target_compile_definitions(${IOX_TARGET} PRIVATE USE_SYSTEMD_TEST=1) + message(STATUS "[i] Configuring ${IOX_TARGET} with systemd support.") + endif () + if ( IOX_STACK_SIZE ) if(APPLE) # @todo iox-#1287 not yet supported @@ -341,7 +346,7 @@ Macro(iox_add_library) if ( LINUX ) if(USE_SYSTEMD AND ("${IOX_TARGET}" STREQUAL "iceoryx_posh_roudi")) - message(STATUS "[i] Configuring iceoryx_posh_roudi with systemd support.") + message(STATUS "[i] Configuring ${IOX_TARGET} with systemd support.") target_compile_definitions(${IOX_TARGET} PRIVATE USE_SYSTEMD=1) target_link_libraries(${IOX_TARGET} PUBLIC ${IOX_PUBLIC_LIBS_LINUX} PRIVATE ${IOX_PRIVATE_LIBS_LINUX} systemd) else() diff --git a/iceoryx_posh/include/iceoryx_posh/internal/roudi/roudi.hpp b/iceoryx_posh/include/iceoryx_posh/internal/roudi/roudi.hpp index e748d5d773..268123d6b6 100644 --- a/iceoryx_posh/include/iceoryx_posh/internal/roudi/roudi.hpp +++ b/iceoryx_posh/include/iceoryx_posh/internal/roudi/roudi.hpp @@ -78,10 +78,15 @@ class ServiceManagement ServiceManagement& operator=(ServiceManagement const& other) = delete; ServiceManagement& operator=(ServiceManagement&& other) = default; - /// dbus signal handler - virtual void processNotify() = 0; - /// Sets a shutdown flag - virtual void shutdown() = 0; + static constexpr const uint16_t SIZE_STRING = 4096; ///< maximum size of string // 2 + static constexpr const uint8_t SIZE_THREAD_NAME = 15; ///< max size for thread name // 1 + + + virtual void processNotify() = 0; /// dbus signal handler + virtual void shutdown() = 0; /// Sets a shutdown flag + virtual bool setThreadNameHelper(iox::string& threadName) = 0; /// Sets a thread name + virtual std::string getEnvironmentVariable(const char* const env_var) = 0; /// Get environment variable + virtual bool sendSDNotifySignalHelper(const std::string_view state) = 0; /// Send notify protected: ServiceManagement() = default; @@ -97,11 +102,7 @@ class ServiceManagementSystemd final : public ServiceManagement std::condition_variable watchdogNotifyCondition; ///< watch dog notification condition // 48 std::mutex watchdogMutex; ///< watch dog mutex // 40 std::thread m_listenThreadWatchdog; ///< thread that listens to systemd watchdog signals // 8 - public: - static constexpr const uint16_t SIZE_STRING = 4096; ///< maximum size of string // 2 - static constexpr const uint8_t SIZE_THREAD_NAME = 15; ///< max size for thread name // 1 - private: - std::atomic_bool m_shutdown{false}; ///< indicates if service is being shutdown // 1 + std::atomic_bool m_shutdown{false}; ///< indicates if service is being shutdown // 1 public: ServiceManagementSystemd() = default; @@ -125,22 +126,22 @@ class ServiceManagementSystemd final : public ServiceManagement * @param env_var Pointer to environment variable * @return Environment variable as std::string **/ - static std::string getEnvironmentVariable(const char* const env_var); + std::string getEnvironmentVariable(const char* const env_var) final; /** * @brief Helper function to set thread name * @param threadName Thread name to be set * @return True if successfully set, otherwise false **/ - static bool setThreadNameHelper(iox::string& threadName); + bool setThreadNameHelper(iox::string& threadName) final; -#ifdef USE_SYSTEMD /** * @brief Helper function to send SDNotify signals * @param state SDNotify state to be sent * @return True if signal sending is successful, otherwise false **/ - static bool sendSDNotifySignalHelper(const std::string_view state) +#ifdef USE_SYSTEMD + bool sendSDNotifySignalHelper(const std::string_view state) final { auto result = IOX_POSIX_CALL(sd_notify)(0, state.data()).successReturnValue(1).evaluate(); if (result.has_error()) @@ -153,7 +154,7 @@ class ServiceManagementSystemd final : public ServiceManagement return true; } #else - static bool sendSDNotifySignalHelper([[maybe_unused]] const std::string_view state) + bool sendSDNotifySignalHelper([[maybe_unused]] const std::string_view state) final { // empty implementation return true; @@ -203,6 +204,33 @@ class NoServiceManagementSystemd final : public ServiceManagement { // empty implementation } + + /** + * @brief Empty implementation of get environment variable + **/ + std::string getEnvironmentVariable([[maybe_unused]] const char* const env_var) final + { + // empty implementation + return "no implement"; + } + + /** + * @brief Empty implementation set thread name + **/ + bool setThreadNameHelper([[maybe_unused]] iox::string& threadName) final + { + // empty implementation + return true; + } + + /** + * @brief Empty implementation send SDNotify signals + **/ + bool sendSDNotifySignalHelper([[maybe_unused]] const std::string_view state) final + { + // empty implementation + return true; + } }; } // namespace service_management diff --git a/iceoryx_posh/source/roudi/roudi.cpp b/iceoryx_posh/source/roudi/roudi.cpp index 2e41ee1245..400c0396dc 100644 --- a/iceoryx_posh/source/roudi/roudi.cpp +++ b/iceoryx_posh/source/roudi/roudi.cpp @@ -681,6 +681,7 @@ void ServiceManagementSystemd::processNotify() } } + } // namespace service_management } // namespace roudi } // namespace iox diff --git a/iceoryx_posh/test/moduletests/test_roudi_system_manager.cpp b/iceoryx_posh/test/moduletests/test_roudi_system_manager.cpp index 5e9ed715db..5c585bde3f 100644 --- a/iceoryx_posh/test/moduletests/test_roudi_system_manager.cpp +++ b/iceoryx_posh/test/moduletests/test_roudi_system_manager.cpp @@ -1,63 +1,129 @@ +// Copyright (c) 2019 - 2020 by Robert Bosch GmbH. All rights reserved. +// Copyright (c) 2020 - 2021 by Apex.AI Inc. All rights reserved. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + #include "iceoryx_posh/internal/roudi/roudi.hpp" #include +#if defined(_WIN32) || defined(_WIN64) +#define GTEST_SKIP_FOR_WINDOWS() GTEST_SKIP() << "Skipping this test on Windows." +#else +#define GTEST_SKIP_FOR_WINDOWS() (void)0 +#endif + +#ifdef USE_SYSTEMD_TEST +#define GTEST_SKIP_NOT_SUPPORT_SYSTEMD() (void)0 +#else +#define GTEST_SKIP_NOT_SUPPORT_SYSTEMD() GTEST_SKIP() << "Skipping this test when systemd is not use." +#endif + + TEST(RoudiSystemD, CreateObject) { ::testing::Test::RecordProperty("TEST_ID", "aa77b5f6-ffb3-4267-982d-dfe85da384ca"); - std::unique_ptr roudiSendMessage; - ASSERT_NO_THROW(std::make_unique()); + GTEST_SKIP_NOT_SUPPORT_SYSTEMD(); + std::unique_ptr roudiSendMessage; + ASSERT_NO_THROW(roudiSendMessage = std::make_unique()); } TEST(RoudiSystemD, CheckConstantsSizeThreadName) { ::testing::Test::RecordProperty("TEST_ID", "9c39f45c-a63c-43ec-9606-e50c33247b3f"); - std::unique_ptr roudiSendMessage; - ASSERT_NO_THROW(std::make_unique()); + GTEST_SKIP_NOT_SUPPORT_SYSTEMD(); + std::unique_ptr roudiSendMessage; + ASSERT_NO_THROW(roudiSendMessage = std::make_unique()); ASSERT_EQ(roudiSendMessage->SIZE_THREAD_NAME, 15) << "Size thread must equal 15 simbols"; } TEST(RoudiSystemD, CheckConstantsSizeString) { ::testing::Test::RecordProperty("TEST_ID", "0b3e3058-6052-49cc-8a67-723f3775a745"); - std::unique_ptr roudiSendMessage; - ASSERT_NO_THROW(std::make_unique()); + GTEST_SKIP_NOT_SUPPORT_SYSTEMD(); + std::unique_ptr roudiSendMessage; + ASSERT_NO_THROW(roudiSendMessage = std::make_unique()); ASSERT_EQ(roudiSendMessage->SIZE_STRING, 4096) << "Size string must equal 4096 simbols"; } TEST(RoudiSystemD, SetThreadNameHelper) { ::testing::Test::RecordProperty("TEST_ID", "b9ff9e83-9dde-4221-bd1e-c1016ec2d5ff"); - std::unique_ptr roudiSendMessage; - bool result = false; + GTEST_SKIP_FOR_WINDOWS(); + GTEST_SKIP_NOT_SUPPORT_SYSTEMD(); +#ifdef USE_SYSTEMD_TEST + std::unique_ptr roudiSendMessage; + bool result = true; - ASSERT_NO_THROW(std::make_unique()); - iox::string nameThread = "test"; + ASSERT_NO_THROW(roudiSendMessage = std::make_unique()); + iox::string nameThread = "test"; ASSERT_NO_THROW(result = roudiSendMessage->setThreadNameHelper(nameThread)); ASSERT_EQ(result, true) << "Can not change name thread"; +#else + /* need add test (other OS) */ + ASSERT_EQ(true, true); +#endif } TEST(RoudiSystemD, GetEnvironmentVariableReturnsCorrectValue) { ::testing::Test::RecordProperty("TEST_ID", "12dfa746-d1f1-4b4e-864d-2cb28ee49f70"); + GTEST_SKIP_FOR_WINDOWS(); + GTEST_SKIP_NOT_SUPPORT_SYSTEMD(); +#ifdef USE_SYSTEMD_TEST const char* const env_var_name = "TEST_ENV_VAR"; const char* const env_var_value = "test_value"; auto set_env = IOX_POSIX_CALL(setenv)(env_var_name, env_var_value, 1).failureReturnValue(-1).evaluate(); EXPECT_FALSE(set_env.has_error()) << "setenv failed with error: " << set_env.get_error().errnum; - iox::roudi::service_management::ServiceManagementSystemd sut; + SendMessageServiceManagement sut; std::string result = sut.getEnvironmentVariable(env_var_name); - - EXPECT_EQ(result, env_var_value); + if (result != "no implement") + { + EXPECT_EQ(result, env_var_value); + } + else + { + EXPECT_EQ(result, "no implement"); + } +#else + /* need add test (other OS) */ + ASSERT_EQ(true, true); +#endif } TEST(RoudiSystemD, GetEnvironmentVariableHandlesNonExistentVar) { ::testing::Test::RecordProperty("TEST_ID", "9595728f-a504-46e3-8672-b074696326a4"); - iox::roudi::service_management::ServiceManagementSystemd sut; + GTEST_SKIP_FOR_WINDOWS(); + GTEST_SKIP_NOT_SUPPORT_SYSTEMD(); +#ifdef USE_SYSTEMD_TEST + SendMessageServiceManagement sut; std::string result = sut.getEnvironmentVariable("NON_EXISTENT_VAR"); - - EXPECT_TRUE(result.empty()); -} + if (result != "no implement") + { + EXPECT_TRUE(result.empty()); + } + else + { + EXPECT_EQ(result, "no implement"); + } +#else + /* need add test (other OS) */ + ASSERT_EQ(true, true); +#endif +} \ No newline at end of file diff --git a/tools/ci/build-test-ubuntu-support-systemd-integrations.sh b/tools/ci/build-test-ubuntu-support-systemd-integrations.sh new file mode 100755 index 0000000000..1d57a03043 --- /dev/null +++ b/tools/ci/build-test-ubuntu-support-systemd-integrations.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# Copyright (c) 2021 by Apex.AI Inc. All rights reserved. +# +# 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. +# +# SPDX-License-Identifier: Apache-2.0 + +# This script builds iceoryx_hoofs und iceoryx_posh and executes all tests + +set -e + +if [ "$USER" != "root" ]; then + echo "Please run this as root or with sudo" + exit 1 +fi + +msg() { + printf "\033[1;32m%s: %s\033[0m\n" ${FUNCNAME[1]} "$1" +} + +msg "Create unit file" +echo -e "[Unit]\nDescription=Test application roudi\n\n[Service]\nType=notify\nRestartSec=10\nRestart=always\nExecStart=/usr/local/bin/iox-roudi\nTimeoutStartSec=10\nWatchdogSec=5\n\n[Install]\nWantedBy=multi-user.target" | tee /usr/lib/systemd/system/test_iox.service > /dev/null + +msg "Show unit" +cat /usr/lib/systemd/system/test_iox.service + +msg "Daemon reload" +systemctl daemon-reload + +msg "Check status" +systemctl status test_iox || true + +msg "Start roudi" +systemctl start test_iox || (echo "Failed to start service"; sudo journalctl -u test_iox -n 50; exit 1) + +msg "Wait for 30 seconds" +sleep 30 + +msg "Check roudi" +systemctl status test_iox || (echo "Failed to start service"; sudo journalctl -u test_iox -n 50; exit 1) + +msg "Stop roudi" +systemctl stop test_iox + +msg "Show journal" +journalctl -u test_iox -n 100 + +msg "Start test (integration) posh with systemd" +cd build/posh/test && ./posh_integrationtests + +msg "Start test (module) posh with systemd" +cd build/posh/test && ./posh_moduletests diff --git a/tools/ci/build-test-ubuntu-support-systemd-unit.sh b/tools/ci/build-test-ubuntu-support-systemd-unit.sh new file mode 100755 index 0000000000..84f8affe86 --- /dev/null +++ b/tools/ci/build-test-ubuntu-support-systemd-unit.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Copyright (c) 2021 by Apex.AI Inc. All rights reserved. +# +# 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. +# +# SPDX-License-Identifier: Apache-2.0 + +# This script builds iceoryx_hoofs und iceoryx_posh and executes all tests + +set -e + +if [ "$USER" != "root" ]; then + echo "Please run this as root or with sudo" + exit 1 +fi + +msg() { + printf "\033[1;32m%s: %s\033[0m\n" ${FUNCNAME[1]} "$1" +} + +WORKSPACE=$(git rev-parse --show-toplevel) +cd ${WORKSPACE} + +msg "Install libsystemd-dev" +apt install -y libsystemd-dev + +msg "compiler versions: +$(gcc --version) +$(clang --version)" + +msg "building sources" +./tools/iceoryx_build_test.sh systemd build-shared build-test + +msg "running all tests" +cd ./build +./tools/run_tests.sh all +cd - + diff --git a/tools/iceoryx_build_test.sh b/tools/iceoryx_build_test.sh index b0e4ad278c..823868c670 100755 --- a/tools/iceoryx_build_test.sh +++ b/tools/iceoryx_build_test.sh @@ -58,6 +58,7 @@ COMPONENTS="iceoryx_platform iceoryx_hoofs iceoryx_posh iceoryx_introspection ic TOOLCHAIN_FILE="" CMAKE_C_FLAGS="" CMAKE_CXX_FLAGS="" +USE_SYSTEMD_FLAGS="" while (( "$#" )); do case "$1" in @@ -228,6 +229,11 @@ while (( "$#" )); do CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -malign-double" shift 1 ;; + "systemd") + echo " [i] Build with support systemd" + USE_SYSTEMD_FLAGS="ON" + shift 1 + ;; "help") echo "Build script for iceoryx." echo "By default, iceoryx with C-Binding and TOML-config is built." @@ -266,6 +272,7 @@ while (( "$#" )); do echo " roudi-env Build the roudi environment" echo " 32-bit-x86 Build as 32 bit library for x64" echo " 32-bit-arm Build as 32 bit library for arm" + echo " systemd Build with support systemd" echo "" echo "e.g. iceoryx_build_test.sh -b ./build-scripted clean test" echo "for gcov report: iceoryx_build_test.sh clean -c unit" @@ -342,6 +349,7 @@ if [ "$NO_BUILD" == false ]; then -DTEST_WITH_HUGE_PAYLOAD=$TEST_HUGE_PAYLOAD \ -DCMAKE_C_FLAGS="$CMAKE_C_FLAGS" \ -DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS" \ + -DUSE_SYSTEMD="$USE_SYSTEMD_FLAGS" \ "$WORKSPACE"/iceoryx_meta cmake --build . --target install -- -j$NUM_JOBS