From 25df868ea92780bbe0322d8c6b6f6163e2832202 Mon Sep 17 00:00:00 2001 From: Pepijn Noltes Date: Sun, 2 Jun 2024 23:06:37 +0200 Subject: [PATCH] gh-685: Add celix launcher test suite with error injection --- libs/framework/gtest/CMakeLists.txt | 1 + .../CelixLauncherErrorInjectionTestSuite.cc | 81 +++++++++++++++++++ libs/framework/src/celix_launcher.c | 13 +-- libs/framework/src/celix_launcher_private.h | 9 +++ .../celix_properties/CMakeLists.txt | 1 + .../include/celix_properties_ei.h | 1 + .../src/celix_properties_ei.cc | 11 +++ libs/utils/src/properties.c | 2 +- 8 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 libs/framework/gtest/src/CelixLauncherErrorInjectionTestSuite.cc diff --git a/libs/framework/gtest/CMakeLists.txt b/libs/framework/gtest/CMakeLists.txt index 9e65e430a..af3f60c0a 100644 --- a/libs/framework/gtest/CMakeLists.txt +++ b/libs/framework/gtest/CMakeLists.txt @@ -141,6 +141,7 @@ if (EI_TESTS) src/FrameworkBundleWithErrorInjectionTestSuite.cc src/FrameworkFactoryWithErrorInjectionTestSuite.cc src/ManifestErrorInjectionTestSuite.cc + src/CelixLauncherErrorInjectionTestSuite.cc ) target_compile_definitions(test_framework_with_ei PRIVATE SIMPLE_TEST_BUNDLE1_LOCATION="${SIMPLE_TEST_BUNDLE1}" diff --git a/libs/framework/gtest/src/CelixLauncherErrorInjectionTestSuite.cc b/libs/framework/gtest/src/CelixLauncherErrorInjectionTestSuite.cc new file mode 100644 index 000000000..6b448f013 --- /dev/null +++ b/libs/framework/gtest/src/CelixLauncherErrorInjectionTestSuite.cc @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +#include "celix_launcher.h" +#include "celix_stdlib_cleanup.h" +#include "celix_utils.h" +#include "framework.h" +#include "celix_launcher_private.h" + +#include "celix_properties_ei.h" +#include "malloc_ei.h" + +#define LAUNCH_WAIT_TIMEOUT 100 + +class CelixLauncherErrorInjectionTestSuite : public ::testing::Test { + public: + CelixLauncherErrorInjectionTestSuite() { + celix_ei_expect_calloc(nullptr, 0, nullptr); + celix_ei_expect_celix_properties_setEntry(nullptr, 0, CELIX_SUCCESS); + } + + static int launch(const std::vector& args, celix_properties_t* props) { + celix_autofree char* str = nullptr; + if (props) { + EXPECT_EQ(CELIX_SUCCESS, celix_properties_saveToString(props, 0, &str)); + } + + char** argv = new char*[args.size()]; + for (size_t i = 0; i < args.size(); ++i) { + argv[i] = celix_utils_strdup(args[i].c_str()); + } + + auto rc = celix_launcher_launchAndWait((int)args.size(), argv, str); + + for (size_t i = 0; i < args.size(); ++i) { + free(argv[i]); + } + delete [] argv; + return rc; + } +}; + +TEST_F(CelixLauncherErrorInjectionTestSuite, CreateBundleCacheErrorTest) { + //Given an error injection for calloc is primed when called from framework_create + celix_ei_expect_calloc((void*)framework_create, 0, nullptr); + + //When calling celix_launcher_launchAndWait + auto rc = launch({"programName", "-c"}, nullptr); + + //Then an exception is expected + EXPECT_EQ(1, rc); +} + +TEST_F(CelixLauncherErrorInjectionTestSuite, CombinePropertiesErrorTest) { + //Given an error injection for celix_properties_setEntry is primed when called from celix_launcher_combineProperties + celix_ei_expect_celix_properties_setEntry((void*)celix_launcher_combineProperties, 0, ENOMEM); + + //When calling celix_launcher_launchAndWait with configuration properties + auto rc = launch({"programName"}, nullptr); + + //Then an exception is expected + EXPECT_EQ(1, rc); +} diff --git a/libs/framework/src/celix_launcher.c b/libs/framework/src/celix_launcher.c index 4a8fe95eb..a6572be28 100644 --- a/libs/framework/src/celix_launcher.c +++ b/libs/framework/src/celix_launcher.c @@ -78,13 +78,6 @@ static celix_status_t celix_launcher_createFramework(celix_properties_t* embedde */ static celix_status_t celix_launcher_parseOptions(int argc, char* argv[], celix_launcher_options_t* opts); -/** - * @brief Create a combined configuration properties set by combining the embedded properties with the runtime properties. - * @param[in,out] embeddedProps The embedded properties to use and extend with the runtime properties. - * @param[in] configFile The optional runtime properties file to load and use. - */ -static celix_status_t celix_launcher_combineProperties(celix_properties_t* embeddedProps, const celix_properties_t* runtimeProps); - /** * @brief Print the usage of the Celix launcher command arguments. */ @@ -170,7 +163,7 @@ int celix_launcher_launchAndWait(int argc, char* argv[], const char* embeddedCon curl_global_cleanup(); #endif } - return CELIX_LAUNCHER_OK_EXIT_CODE; + return status == CELIX_SUCCESS ? CELIX_LAUNCHER_OK_EXIT_CODE : CELIX_LAUNCHER_ERROR_EXIT_CODE; } static celix_status_t celix_launcher_setGlobalFramework(celix_framework_t* fw) { @@ -247,7 +240,7 @@ static celix_status_t celix_launcher_createFramework(celix_properties_t* embedde #endif *frameworkOut = celix_frameworkFactory_createFramework(embeddedProps); - return *frameworkOut != NULL ? CELIX_SUCCESS : CELIX_ENOMEM; + return *frameworkOut != NULL ? CELIX_SUCCESS : CELIX_FRAMEWORK_EXCEPTION; } /** @@ -334,7 +327,7 @@ static celix_status_t celix_launcher_createBundleCache(celix_properties_t* embed return CELIX_SUCCESS; } -static celix_status_t celix_launcher_combineProperties(celix_properties_t* embeddedProps, +celix_status_t celix_launcher_combineProperties(celix_properties_t* embeddedProps, const celix_properties_t* runtimeProps) { if (embeddedProps && runtimeProps) { CELIX_PROPERTIES_ITERATE(runtimeProps, visit) { diff --git a/libs/framework/src/celix_launcher_private.h b/libs/framework/src/celix_launcher_private.h index ebfedeba0..d35bd197d 100644 --- a/libs/framework/src/celix_launcher_private.h +++ b/libs/framework/src/celix_launcher_private.h @@ -33,6 +33,15 @@ extern "C" { */ void celix_launcher_stopInternal(const int* signal); +/** + * @brief Create a combined configuration properties set by combining the embedded properties with the runtime + * properties. + * @param[in,out] embeddedProps The embedded properties to use and extend with the runtime properties. + * @param[in] configFile The optional runtime properties file to load and use. + */ +celix_status_t celix_launcher_combineProperties(celix_properties_t* embeddedProps, + const celix_properties_t* runtimeProps); + #ifdef __cplusplus } #endif diff --git a/libs/utils/error_injector/celix_properties/CMakeLists.txt b/libs/utils/error_injector/celix_properties/CMakeLists.txt index 445c544ea..aa177a63f 100644 --- a/libs/utils/error_injector/celix_properties/CMakeLists.txt +++ b/libs/utils/error_injector/celix_properties/CMakeLists.txt @@ -26,6 +26,7 @@ target_link_options(properties_ei INTERFACE LINKER:--wrap,celix_properties_set LINKER:--wrap,celix_properties_setLong LINKER:--wrap,celix_properties_setVersion + LINKER:--wrap,celix_properties_setEntry LINKER:--wrap,celix_properties_save LINKER:--wrap,celix_properties_load ) diff --git a/libs/utils/error_injector/celix_properties/include/celix_properties_ei.h b/libs/utils/error_injector/celix_properties/include/celix_properties_ei.h index 4c7d54ee5..9291d0c5e 100644 --- a/libs/utils/error_injector/celix_properties/include/celix_properties_ei.h +++ b/libs/utils/error_injector/celix_properties/include/celix_properties_ei.h @@ -31,6 +31,7 @@ CELIX_EI_DECLARE(celix_properties_copy, celix_properties_t*); CELIX_EI_DECLARE(celix_properties_set, celix_status_t); CELIX_EI_DECLARE(celix_properties_setLong, celix_status_t); CELIX_EI_DECLARE(celix_properties_setVersion, celix_status_t); +CELIX_EI_DECLARE(celix_properties_setEntry, celix_status_t); CELIX_EI_DECLARE(celix_properties_save, celix_status_t); CELIX_EI_DECLARE(celix_properties_load, celix_status_t); diff --git a/libs/utils/error_injector/celix_properties/src/celix_properties_ei.cc b/libs/utils/error_injector/celix_properties/src/celix_properties_ei.cc index c6616ee00..1ba0903ca 100644 --- a/libs/utils/error_injector/celix_properties/src/celix_properties_ei.cc +++ b/libs/utils/error_injector/celix_properties/src/celix_properties_ei.cc @@ -55,6 +55,17 @@ celix_status_t __wrap_celix_properties_setVersion(celix_properties_t *properties return __real_celix_properties_setVersion(properties, key, version); } +celix_status_t __real_celix_properties_setEntry(celix_properties_t* properties, + const char* key, + const celix_properties_entry_t* entry); +CELIX_EI_DEFINE(celix_properties_setEntry, celix_status_t) +celix_status_t __wrap_celix_properties_setEntry(celix_properties_t* properties, + const char* key, + const celix_properties_entry_t* entry) { + CELIX_EI_IMPL(celix_properties_setEntry); + return __real_celix_properties_setEntry(properties, key, entry); +} + celix_status_t __real_celix_properties_save(const celix_properties_t* properties, const char* filename, int encodeFlags); CELIX_EI_DEFINE(celix_properties_save, celix_status_t) diff --git a/libs/utils/src/properties.c b/libs/utils/src/properties.c index 53f84fff1..3ec19a2f7 100644 --- a/libs/utils/src/properties.c +++ b/libs/utils/src/properties.c @@ -495,7 +495,7 @@ const char* celix_properties_getAsString(const celix_properties_t* properties, celix_status_t celix_properties_setString(celix_properties_t* properties, const char* key, const char* value) { - if (!properties) { + if (!properties) { return CELIX_SUCCESS; // silently ignore NULL properties } char* copy = celix_properties_createString(properties, value);