Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libs/error_injector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ add_subdirectory(socket)
add_subdirectory(pthread)
add_subdirectory(unistd)
add_subdirectory(dirent)
add_subdirectory(uv)

celix_subproject(ERROR_INJECTOR_MDNSRESPONDER "Option to enable building the mdnsresponder error injector" OFF)
if (ERROR_INJECTOR_MDNSRESPONDER)
Expand Down
28 changes: 28 additions & 0 deletions libs/error_injector/uv/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 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.

find_package(libuv REQUIRED)

add_library(uv_ei STATIC src/uv_ei.cc)

target_include_directories(uv_ei PUBLIC include)
target_link_libraries(uv_ei PUBLIC Celix::error_injector libuv::uv)

target_link_options(uv_ei INTERFACE
LINKER:--wrap,uv_key_create
)
add_library(Celix::uv_ei ALIAS uv_ei)
36 changes: 36 additions & 0 deletions libs/error_injector/uv/include/uv_ei.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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.
*/

#ifndef CELIX_UV_THREADS_EI_H
#define CELIX_UV_THREADS_EI_H
#ifdef __cplusplus
extern "C" {
#endif

#include <uv.h>

#include "celix_error_injector.h"

CELIX_EI_DECLARE(uv_key_create, int);

#ifdef __cplusplus
}
#endif

#endif // CELIX_UV_THREADS_EI_H
32 changes: 32 additions & 0 deletions libs/error_injector/uv/src/uv_ei.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 "uv_ei.h"
#include "celix_error_injector.h"

extern "C" {

int __real_uv_key_create(uv_key_t* key);
CELIX_EI_DEFINE(uv_key_create, int)
int __wrap_uv_key_create(uv_key_t* key) {
CELIX_EI_IMPL(uv_key_create);
return __real_uv_key_create(key);
}

}
11 changes: 11 additions & 0 deletions libs/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ if (UTILS)
)
target_link_libraries(utils_cut PUBLIC ${UTILS_PUBLIC_DEPS} ${UTILS_PRIVATE_DEPS})

#Special test lib that disable the celix_err constructor/destructor attribute usage (for testing)
add_library(utils_err_no_ctor_dtor_cut STATIC src/celix_err.c)
target_include_directories(utils_err_no_ctor_dtor_cut PUBLIC
${CMAKE_CURRENT_LIST_DIR}/include
${CMAKE_BINARY_DIR}/celix/gen/includes/utils
${CMAKE_BINARY_DIR}/celix/gen/src/utils
src
)
target_compile_definitions(utils_err_no_ctor_dtor_cut PRIVATE CELIX_ERR_DISABLE_CONSTRUCTORS)
target_link_libraries(utils_err_no_ctor_dtor_cut PUBLIC ${UTILS_PUBLIC_DEPS} ${UTILS_PRIVATE_DEPS})

add_subdirectory(gtest)
endif ()

Expand Down
4 changes: 0 additions & 4 deletions libs/utils/error_injector/celix_threads/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,5 @@ target_link_options(threads_ei INTERFACE
LINKER:--wrap,celixThreadCondition_signal
LINKER:--wrap,celixThreadCondition_init
LINKER:--wrap,celixThreadRwlock_create
LINKER:--wrap,celix_tss_create
LINKER:--wrap,celix_tss_delete
LINKER:--wrap,celix_tss_set
LINKER:--wrap,celix_tss_get
)
add_library(Celix::threads_ei ALIAS threads_ei)
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ CELIX_EI_DECLARE(celixThreadCondition_signal, celix_status_t);
CELIX_EI_DECLARE(celixThreadCondition_init, celix_status_t);
CELIX_EI_DECLARE(celixThreadRwlock_create, celix_status_t);

CELIX_EI_DECLARE(celix_tss_create, celix_status_t);
CELIX_EI_DECLARE(celix_tss_delete, celix_status_t);
CELIX_EI_DECLARE(celix_tss_set, celix_status_t);
CELIX_EI_DECLARE(celix_tss_get, void*);

#ifdef __cplusplus
}
#endif
Expand Down
29 changes: 0 additions & 29 deletions libs/utils/error_injector/celix_threads/src/celix_threads_ei.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,33 +63,4 @@ celix_status_t __wrap_celixThreadRwlock_create(celix_thread_rwlock_t *__rwlock,
return __real_celixThreadRwlock_create(__rwlock, __attr);
}


celix_status_t __real_celix_tss_create(celix_tss_key_t* __key, void (*__destroyFunction)(void*));
CELIX_EI_DEFINE(celix_tss_create, celix_status_t)
celix_status_t __wrap_celix_tss_create(celix_tss_key_t* __key, void (*__destroyFunction)(void*)) {
CELIX_EI_IMPL(celix_tss_create);
return __real_celix_tss_create(__key, __destroyFunction);
}

celix_status_t __real_celix_tss_delete(celix_tss_key_t __key);
CELIX_EI_DEFINE(celix_tss_delete, celix_status_t)
celix_status_t __wrap_celix_tss_delete(celix_tss_key_t __key) {
CELIX_EI_IMPL(celix_tss_delete);
return __real_celix_tss_delete(__key);
}

celix_status_t __real_celix_tss_set(celix_tss_key_t __key, void* __value);
CELIX_EI_DEFINE(celix_tss_set, celix_status_t)
celix_status_t __wrap_celix_tss_set(celix_tss_key_t __key, void* __value) {
CELIX_EI_IMPL(celix_tss_set);
return __real_celix_tss_set(__key, __value);
}

void* __real_celix_tss_get(celix_tss_key_t __key);
CELIX_EI_DEFINE(celix_tss_get, void*)
void* __wrap_celix_tss_get(celix_tss_key_t __key) {
CELIX_EI_IMPL(celix_tss_get);
return __real_celix_tss_get(__key);
}

}
15 changes: 12 additions & 3 deletions libs/utils/gtest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,23 @@ if (EI_TESTS)
target_link_libraries(test_utils_celix_err_with_ei PRIVATE
utils_cut
Celix::malloc_ei
Celix::threads_ei
GTest::gtest GTest::gtest_main
)
add_test(NAME test_utils_celix_err_with_ei COMMAND test_utils_celix_err_with_ei)
setup_target_for_coverage(test_utils_celix_err_with_ei SCAN_DIR ..)

#Note testing version seperated, otherwise version calls are already wrapped
add_executable(test_utils_celix_err_key_create_with_ei
src/ErrKeyCreateErrorInjectionTestSuite.cc
)
target_link_libraries(test_utils_celix_err_key_create_with_ei PRIVATE
utils_err_no_ctor_dtor_cut
Celix::uv_ei
GTest::gtest GTest::gtest_main
)
add_test(NAME test_utils_celix_err_key_create_with_ei COMMAND test_utils_celix_err_key_create_with_ei)
setup_target_for_coverage(test_utils_celix_err_key_create_with_ei SCAN_DIR ..)

#Note testing version separated, otherwise version calls are already wrapped
add_executable(test_utils_version_with_ei
src/VersionErrorInjectionTestSuite.cc
)
Expand Down Expand Up @@ -154,7 +164,6 @@ if (EI_TESTS)
Celix::fts_ei
utils_cut
Celix::utils_ei
Celix::ifaddrs_ei
Celix::threads_ei
Celix::malloc_ei
Celix::asprintf_ei
Expand Down
20 changes: 1 addition & 19 deletions libs/utils/gtest/src/ErrErrorInjectionTestSuite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include <fstream>

#include "celix_err.h"
#include "celix_threads_ei.h"
#include "celix_errno.h"
#include "malloc_ei.h"

class ErrErrorInjectionTestSuite : public ::testing::Test {
Expand All @@ -34,28 +34,10 @@ class ErrErrorInjectionTestSuite : public ::testing::Test {
freopen(CAPTURE_FILENAME, "w", stderr);
}
~ErrErrorInjectionTestSuite() noexcept override {
celix_ei_expect_celix_tss_set(nullptr, 0, CELIX_SUCCESS);
celix_ei_expect_malloc(nullptr, 0, CELIX_SUCCESS);
}
};

TEST_F(ErrErrorInjectionTestSuite, PushErrorWithTssSetFailingTest) {
//Given a primed error injection for celix_tss_set
celix_ei_expect_celix_tss_set((void*)celix_err_push, 1, CELIX_ILLEGAL_STATE);

//When an error is pushed
celix_err_push("error message");

fclose(stderr);
std::ifstream tempFile{CAPTURE_FILENAME};
std::string fileContents((std::istreambuf_iterator<char>(tempFile)),
std::istreambuf_iterator<char>());
tempFile.close();

EXPECT_TRUE(strstr(fileContents.c_str(), "Failed to set thread specific storage for celix_err") != nullptr) <<
"Expected error message not found in: " << fileContents;
}

TEST_F(ErrErrorInjectionTestSuite, PushErrorWithMallocFailingTest) {
//Given a primed error injection for malloc
celix_ei_expect_malloc(CELIX_EI_UNKNOWN_CALLER, 1, nullptr);
Expand Down
48 changes: 48 additions & 0 deletions libs/utils/gtest/src/ErrKeyCreateErrorInjectionTestSuite.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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 <gtest/gtest.h>

#include "celix_err.h"
#include "celix_err_private.h"
#include "uv_ei.h"

class ErrKeyCreateErrorInjectionTestSuite : public ::testing::Test {
public:
ErrKeyCreateErrorInjectionTestSuite() = default;

~ErrKeyCreateErrorInjectionTestSuite() noexcept override {
celix_ei_expect_uv_key_create(nullptr, 0, 0);
}
};

TEST_F(ErrKeyCreateErrorInjectionTestSuite, InitThreadStorageKeyFailureAndSuccess) {
celix_ei_expect_uv_key_create((void*)celix_err_initThreadSpecificStorageKey, 0, -1);
celix_err_initThreadSpecificStorageKey();

celix_err_push("error message");
EXPECT_EQ(0, celix_err_getErrorCount());

celix_ei_expect_uv_key_create(nullptr, 0, 0);
celix_err_initThreadSpecificStorageKey();
celix_err_resetErrors();
celix_err_push("error message");
EXPECT_EQ(1, celix_err_getErrorCount());
celix_err_deinitThreadSpecificStorageKey();
}
17 changes: 0 additions & 17 deletions libs/utils/gtest/src/ThreadsTestSuite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -371,23 +371,6 @@ TEST_F(ThreadsTestSuite, RwLockAttrTest) {
celixThreadRwlockAttr_destroy(&attr);
}

TEST_F(ThreadsTestSuite, TssTest) {
celix_tss_key_t key;
celix_status_t status = celix_tss_create(&key, [](void* ptr) { free(ptr); });
EXPECT_EQ(CELIX_SUCCESS, status);

int* value = (int*)malloc(sizeof(int));
*value = 123;
status = celix_tss_set(key, value);
EXPECT_EQ(CELIX_SUCCESS, status);

value = (int*)celix_tss_get(key);
EXPECT_EQ(123, *value);

status = celix_tss_delete(key);
EXPECT_EQ(CELIX_SUCCESS, status);
}

static void * thread_test_func_create(void * arg) {
char ** test_str = (char**) arg;
*test_str = strdup("SUCCESS");
Expand Down
59 changes: 0 additions & 59 deletions libs/utils/include/celix_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,65 +359,6 @@ CELIX_UTILS_EXPORT celix_status_t celixThreadCondition_signal(celix_thread_cond_

CELIX_UTILS_EXPORT celix_status_t celixThread_once(celix_thread_once_t *once_control, void (*init_routine)(void));

//Thread Specific Storage (TSS) Abstraction
typedef pthread_key_t celix_tss_key_t;

/**
* @brief Create a thread specific storage key visible for all threads.
*
*
* Upon creation, the value NULL shall be associated with
* the new key in all active threads of the process. Upon thread creation,
* the value NULL shall be associated with all defined keys in the new thread
*
* An optional destructor function may be associated with each key value. At thread exit, if a key value has a
* non-NULL destructor pointer, and the thread has a non-NULL value associated with that key, the value of the key is
* set to NULL, and then the function pointed to is called with the previously associated value as its sole argument.
* The order of destructor calls is unspecified if more than one destructor exists for a thread when it exits.
*
* @param key The key to create.
* @param destroyFunction The function to call when the key is destroyed.
* @return CELIX_SUCCESS if the key is created successfully.
*
* @retval CELIX_ENOMEM if there was insufficient memory for the key creation.
* @retval CELIX_EAGAIN if the system lacked the necessary resources to create another thread specific data key.
*/
CELIX_UTILS_EXPORT celix_status_t celix_tss_create(celix_tss_key_t* key, void (*destroyFunction)(void*));

/**
* @brief Delete a thread specific storage key previously created by celix_tss_create.
*
* @param key The key to delete.
* @return CELIX_SUCCESS if the key is deleted successfully.
*
* @retval CELIX_ILLEGAL_ARGUMENT if the key is invalid.
* @retval CELIX_ILLEGAL_STATE if the key is otherwise not deleted successfully.
*/
CELIX_UTILS_EXPORT celix_status_t celix_tss_delete(celix_tss_key_t key);

/**
* @brief Set a thread-specific value for the provide thread specific storage key.
*
* @param key The key to set the value for.
* @param value The thread-specific value to set.
* @return CELIX_SUCCESS if the value is set successfully.
*
* @retval CELIX_ILLEGAL_ARGUMENT if the key is invalid.
* @retval CELIX_ENOMEM if there was insufficient memory to set the value.
* @retval CELIX_ILLEGAL_STATE if the value is not set successfully.
*/
CELIX_UTILS_EXPORT celix_status_t celix_tss_set(celix_tss_key_t key, void* value);

/**
* @brief Get the thread-specific value for the provided thread specific storage key.
*
* @param key The key to get the value for.
* @return The thread-specific value.
*
* @retval NULL if the key is invalid or there is no thread-specific value set for the key.
*/
CELIX_UTILS_EXPORT void* celix_tss_get(celix_tss_key_t key);

#ifdef __cplusplus
}
#endif
Expand Down
Loading
Loading