This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a commit to branch feature/cap_req_model_lib
in repository https://gitbox.apache.org/repos/asf/celix.git

commit 5df30b1e6d66567650d6df6270cb4c311ab39d8e
Author: Pepijn Noltes <[email protected]>
AuthorDate: Sat Apr 8 20:42:32 2023 +0200

    Add celix array list ei and improve er test for librcm
---
 libs/CMakeLists.txt                                |  14 ++-
 libs/error_injector/CMakeLists.txt                 |   1 +
 .../error_injector/celix_array_list/CMakeLists.txt |  35 +++++++
 .../celix_array_list/include/celix_array_list_ei.h |  54 +++++++++++
 .../celix_array_list/src/celix_array_list_ei.cc    | 102 +++++++++++++++++++++
 libs/rcm/gtest/CMakeLists.txt                      |  17 ++--
 .../src/RequirementCapabilityModelTestSuite.cc     |   4 +
 ...ntCapabilityModelWithErrorInjectionTestSuite.cc |  54 ++++++++++-
 libs/rcm/src/celix_rcm_err.c                       |  13 +--
 libs/rcm/src/celix_rcm_err_private.h               |   1 -
 libs/rcm/src/celix_resource.c                      |  39 ++++++--
 libs/utils/include/celix_array_list.h              |  27 ++++--
 libs/utils/include_deprecated/array_list.h         |   2 +-
 libs/utils/src/array_list.c                        |  63 ++++++++-----
 14 files changed, 355 insertions(+), 71 deletions(-)

diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt
index 20b51203..d4be91e5 100644
--- a/libs/CMakeLists.txt
+++ b/libs/CMakeLists.txt
@@ -18,15 +18,18 @@
 #utils, dfi and etcdlib are standalone
 #(e.g. no dependency on celix framework
 add_subdirectory(utils)
+
+# Error Injectors
+if (ENABLE_TESTING AND LINKER_WRAP_SUPPORTED)
+    add_subdirectory(error_injector)
+endif ()
+
 add_subdirectory(dfi)
 add_subdirectory(etcdlib)
 add_subdirectory(promises)
 add_subdirectory(pushstreams)
 add_subdirectory(rcm)
-
 add_subdirectory(framework)
-
-#launcher
 add_subdirectory(launcher)
 
 #add_subdirectory(event_admin)# event_admin is unstable
@@ -35,8 +38,3 @@ if (CELIX_CXX14)
     add_subdirectory(dependency_manager_cxx)
 endif ()
 
-# Error Injectors
-if (ENABLE_TESTING AND LINKER_WRAP_SUPPORTED)
-    add_subdirectory(error_injector)
-endif ()
-
diff --git a/libs/error_injector/CMakeLists.txt 
b/libs/error_injector/CMakeLists.txt
index 37f78c57..3092c26a 100644
--- a/libs/error_injector/CMakeLists.txt
+++ b/libs/error_injector/CMakeLists.txt
@@ -26,6 +26,7 @@ add_library(Celix::error_injector ALIAS error_injector)
 add_subdirectory(malloc)
 add_subdirectory(asprintf)
 add_subdirectory(celix_properties)
+add_subdirectory(celix_array_list)
 add_subdirectory(celix_utils)
 add_subdirectory(zip)
 add_subdirectory(stdio)
diff --git a/libs/error_injector/celix_array_list/CMakeLists.txt 
b/libs/error_injector/celix_array_list/CMakeLists.txt
new file mode 100644
index 00000000..9954bf00
--- /dev/null
+++ b/libs/error_injector/celix_array_list/CMakeLists.txt
@@ -0,0 +1,35 @@
+# 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.
+
+add_library(array_list_ei STATIC src/celix_array_list_ei.cc)
+
+target_include_directories(array_list_ei PUBLIC 
${CMAKE_CURRENT_LIST_DIR}/include)
+target_link_libraries(array_list_ei PUBLIC Celix::error_injector Celix::utils)
+target_link_options(array_list_ei INTERFACE
+        LINKER:--wrap,celix_arrayList_create
+        LINKER:--wrap,celix_arrayList_createWithOptions
+        LINKER:--wrap,celix_arrayList_add
+        LINKER:--wrap,celix_arrayList_addInt
+        LINKER:--wrap,celix_arrayList_addLong
+        LINKER:--wrap,celix_arrayList_addUInt
+        LINKER:--wrap,celix_arrayList_addULong
+        LINKER:--wrap,celix_arrayList_addFloat
+        LINKER:--wrap,celix_arrayList_addDouble
+        LINKER:--wrap,celix_arrayList_addBool
+        LINKER:--wrap,celix_arrayList_addSize
+)
+add_library(Celix::array_list_ei ALIAS array_list_ei)
diff --git a/libs/error_injector/celix_array_list/include/celix_array_list_ei.h 
b/libs/error_injector/celix_array_list/include/celix_array_list_ei.h
new file mode 100644
index 00000000..0184c128
--- /dev/null
+++ b/libs/error_injector/celix_array_list/include/celix_array_list_ei.h
@@ -0,0 +1,54 @@
+/*
+ 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_CELIX_ARRAY_LIST_EI_H
+#define CELIX_CELIX_ARRAY_LIST_EI_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "celix_array_list.h"
+#include "celix_error_injector.h"
+
+CELIX_EI_DECLARE(celix_arrayList_create, celix_array_list_t*);
+
+CELIX_EI_DECLARE(celix_arrayList_createWithOptions, celix_array_list_t*);
+
+CELIX_EI_DECLARE(celix_arrayList_add, celix_status_t);
+
+CELIX_EI_DECLARE(celix_arrayList_addInt, celix_status_t);
+
+CELIX_EI_DECLARE(celix_arrayList_addLong, celix_status_t);
+
+CELIX_EI_DECLARE(celix_arrayList_addUInt, celix_status_t);
+
+CELIX_EI_DECLARE(celix_arrayList_addULong, celix_status_t);
+
+CELIX_EI_DECLARE(celix_arrayList_addFloat, celix_status_t);
+
+CELIX_EI_DECLARE(celix_arrayList_addDouble, celix_status_t);
+
+//CELIX_EI_DECLARE(celix_arrayList_addBool, celix_status_t);
+
+CELIX_EI_DECLARE(celix_arrayList_addSize, celix_status_t);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //CELIX_CELIX_ARRAY_LIST_EI_H
diff --git a/libs/error_injector/celix_array_list/src/celix_array_list_ei.cc 
b/libs/error_injector/celix_array_list/src/celix_array_list_ei.cc
new file mode 100644
index 00000000..6916b5f8
--- /dev/null
+++ b/libs/error_injector/celix_array_list/src/celix_array_list_ei.cc
@@ -0,0 +1,102 @@
+/*
+ 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 "celix_array_list_ei.h"
+
+extern "C" {
+
+void *__real_celix_arrayList_create(void);
+CELIX_EI_DEFINE(celix_arrayList_create, celix_array_list_t*)
+void *__wrap_celix_arrayList_create(void) {
+    CELIX_EI_IMPL(celix_arrayList_create);
+    return __real_celix_arrayList_create();
+}
+
+void *__real_celix_arrayList_createWithOptions(const 
celix_array_list_create_options_t* opts);
+CELIX_EI_DEFINE(celix_arrayList_createWithOptions, celix_array_list_t*)
+void *__wrap_celix_arrayList_createWithOptions(const 
celix_array_list_create_options_t* opts) {
+    CELIX_EI_IMPL(celix_arrayList_createWithOptions);
+    return __real_celix_arrayList_createWithOptions(opts);
+}
+
+celix_status_t __real_celix_arrayList_add(celix_array_list_t* list, void* 
value);
+CELIX_EI_DEFINE(celix_arrayList_add, celix_status_t)
+celix_status_t __wrap_celix_arrayList_add(celix_array_list_t* list, void* 
value) {
+    CELIX_EI_IMPL_POSITIVE(celix_arrayList_add);
+    return __real_celix_arrayList_add(list, value);
+}
+
+celix_status_t __real_celix_arrayList_addInt(celix_array_list_t* list, int 
value);
+CELIX_EI_DEFINE(celix_arrayList_addInt, celix_status_t)
+celix_status_t __wrap_celix_arrayList_addInt(celix_array_list_t* list, int 
value) {
+    CELIX_EI_IMPL_POSITIVE(celix_arrayList_addInt);
+    return __real_celix_arrayList_addInt(list, value);
+}
+
+celix_status_t __real_celix_arrayList_addLong(celix_array_list_t* list, long 
value);
+CELIX_EI_DEFINE(celix_arrayList_addLong, celix_status_t)
+celix_status_t __wrap_celix_arrayList_addLong(celix_array_list_t* list, long 
value) {
+    CELIX_EI_IMPL_POSITIVE(celix_arrayList_addLong);
+    return __real_celix_arrayList_addLong(list, value);
+}
+
+celix_status_t __real_celix_arrayList_addUInt(celix_array_list_t* list, 
unsigned int value);
+CELIX_EI_DEFINE(celix_arrayList_addUInt, celix_status_t)
+celix_status_t __wrap_celix_arrayList_addUInt(celix_array_list_t* list, 
unsigned int value) {
+    CELIX_EI_IMPL_POSITIVE(celix_arrayList_addUInt);
+    return __real_celix_arrayList_addUInt(list, value);
+}
+
+celix_status_t __real_celix_arrayList_addULong(celix_array_list_t* list, 
unsigned long value);
+CELIX_EI_DEFINE(celix_arrayList_addULong, celix_status_t)
+celix_status_t __wrap_celix_arrayList_addULong(celix_array_list_t* list, 
unsigned long value) {
+    CELIX_EI_IMPL_POSITIVE(celix_arrayList_addULong);
+    return __real_celix_arrayList_addULong(list, value);
+}
+
+celix_status_t __real_celix_arrayList_addFloat(celix_array_list_t* list, float 
value);
+CELIX_EI_DEFINE(celix_arrayList_addFloat, celix_status_t)
+celix_status_t __wrap_celix_arrayList_addFloat(celix_array_list_t* list, float 
value) {
+    CELIX_EI_IMPL_POSITIVE(celix_arrayList_addFloat);
+    return __real_celix_arrayList_addFloat(list, value);
+}
+
+celix_status_t __real_celix_arrayList_addDouble(celix_array_list_t* list, 
double value);
+CELIX_EI_DEFINE(celix_arrayList_addDouble, celix_status_t)
+celix_status_t __wrap_celix_arrayList_addDouble(celix_array_list_t* list, 
double value) {
+    CELIX_EI_IMPL_POSITIVE(celix_arrayList_addDouble);
+    return __real_celix_arrayList_addDouble(list, value);
+}
+
+//TODO
+//celix_status_t __real_celix_arrayList_addBool(celix_array_list_t* list, bool 
value);
+//CELIX_EI_DEFINE(celix_arrayList_addBool, celix_status_t)
+//celix_status_t __wrap_celix_arrayList_addBool(celix_array_list_t* list, bool 
value)
+//    CELIX_EI_IMPL_POSITIVE(celix_arrayList_addBool);
+//    return __real_celix_arrayList_addBool(list, value);
+//}
+
+celix_status_t __real_celix_arrayList_addSize(celix_array_list_t* list, size_t 
value);
+CELIX_EI_DEFINE(celix_arrayList_addSize, celix_status_t)
+celix_status_t __wrap_celix_arrayList_addSize(celix_array_list_t* list, size_t 
value) {
+    CELIX_EI_IMPL_POSITIVE(celix_arrayList_addSize);
+    return __real_celix_arrayList_addSize(list, value);
+}
+
+}
diff --git a/libs/rcm/gtest/CMakeLists.txt b/libs/rcm/gtest/CMakeLists.txt
index baa924f3..52d3b485 100644
--- a/libs/rcm/gtest/CMakeLists.txt
+++ b/libs/rcm/gtest/CMakeLists.txt
@@ -25,10 +25,13 @@ target_link_libraries(test_rcm PRIVATE Celix::rcm 
GTest::gtest GTest::gtest_main
 add_test(NAME test_rcm COMMAND test_rcm)
 setup_target_for_coverage(test_rcm SCAN_DIR ..)
 
-add_executable(test_rcm_with_error_injection
-    src/RequirementCapabilityModelWithErrorInjectionTestSuite.cc
-)
-target_link_libraries(test_rcm_with_error_injection PRIVATE Celix::rcm 
GTest::gtest GTest::gtest_main)
-target_link_libraries(test_rcm_with_error_injection PRIVATE Celix::malloc_ei 
Celix::utils_ei)
-add_test(NAME test_rcm_with_error_injection COMMAND 
test_rcm_with_error_injection)
-setup_target_for_coverage(test_rcm_with_error_injection SCAN_DIR ..)
+if (LINKER_WRAP_SUPPORTED)
+    add_executable(test_rcm_with_error_injection
+        src/RequirementCapabilityModelWithErrorInjectionTestSuite.cc
+    )
+    target_link_libraries(test_rcm_with_error_injection PRIVATE Celix::rcm 
GTest::gtest GTest::gtest_main)
+    target_link_libraries(test_rcm_with_error_injection PRIVATE 
Celix::malloc_ei Celix::utils_ei Celix::array_list_ei)
+    add_test(NAME test_rcm_with_error_injection COMMAND 
test_rcm_with_error_injection)
+    setup_target_for_coverage(test_rcm_with_error_injection SCAN_DIR ..)
+endif ()
+
diff --git a/libs/rcm/gtest/src/RequirementCapabilityModelTestSuite.cc 
b/libs/rcm/gtest/src/RequirementCapabilityModelTestSuite.cc
index b9c7d555..50db0e5e 100644
--- a/libs/rcm/gtest/src/RequirementCapabilityModelTestSuite.cc
+++ b/libs/rcm/gtest/src/RequirementCapabilityModelTestSuite.cc
@@ -25,11 +25,14 @@
 #include "celix_resource.h"
 #include "celix_rcm_err.h"
 
+extern void celix_rcm_deinitThreadSpecificStorageKey(); //private function, 
used to ensure coverage
+
 class RequirementCapabilityModelTestSuite : public ::testing::Test {};
 
 TEST_F(RequirementCapabilityModelTestSuite, TestRequirement) {
     celix_requirement_t* req = celix_requirement_create(nullptr, 
"test-namespace", "(&(capability.attribute1=foo)(capability.attribute2=bar))");
     ASSERT_TRUE(req != nullptr);
+    EXPECT_TRUE(celix_requirement_equals(req, req));
     EXPECT_STREQ("test-namespace", celix_requirement_getNamespace(req));
     EXPECT_STREQ("(&(capability.attribute1=foo)(capability.attribute2=bar))", 
celix_requirement_getFilter(req));
 
@@ -77,6 +80,7 @@ TEST_F(RequirementCapabilityModelTestSuite, TestRequirement) {
 TEST_F(RequirementCapabilityModelTestSuite, TestCapability) {
     celix_capability_t* cap = celix_capability_create(nullptr, 
"test-namespace");
     ASSERT_TRUE(cap != nullptr);
+    EXPECT_TRUE(celix_capability_equals(cap, cap));
     EXPECT_STREQ("test-namespace", celix_capability_getNamespace(cap));
 
     celix_capability_t* cap2 = celix_capability_create(nullptr, 
"test-namespace");
diff --git 
a/libs/rcm/gtest/src/RequirementCapabilityModelWithErrorInjectionTestSuite.cc 
b/libs/rcm/gtest/src/RequirementCapabilityModelWithErrorInjectionTestSuite.cc
index 40c08741..33bec6e9 100644
--- 
a/libs/rcm/gtest/src/RequirementCapabilityModelWithErrorInjectionTestSuite.cc
+++ 
b/libs/rcm/gtest/src/RequirementCapabilityModelWithErrorInjectionTestSuite.cc
@@ -19,8 +19,11 @@
 
 #include <gtest/gtest.h>
 
+#include <memory>
+
 #include "malloc_ei.h"
 #include "celix_utils_ei.h"
+#include "celix_array_list_ei.h"
 
 #include "celix/Properties.h"
 #include "celix_capability.h"
@@ -35,7 +38,9 @@ public:
     ~RequirementCapabilityModelWithErrorInjectionTestSuite() override {
         celix_ei_expect_malloc(nullptr, 0, nullptr);
         celix_ei_expect_celix_utils_strdup(nullptr, 0, nullptr);
-        //TODO add celix_ei_expect_celix_arrayList_create(nullptr, 0, nullptr);
+        celix_ei_expect_celix_arrayList_createWithOptions(nullptr, 0, nullptr);
+        celix_ei_expect_celix_arrayList_create(nullptr, 0, nullptr);
+        celix_ei_expect_celix_arrayList_add(nullptr, 0, CELIX_SUCCESS);
         celix_rcmErr_resetErrors();
     }
 };
@@ -77,9 +82,50 @@ 
TEST_F(RequirementCapabilityModelWithErrorInjectionTestSuite, TestResourceErrorH
     EXPECT_EQ(nullptr, res);
     EXPECT_EQ(1, celix_rcmErr_getErrorCount());
 
-    //TODO inject error on first celix_arrayList_create call from 
celix_resource_create
+    //inject error on first celix_arrayList_createWithOptions call from 
celix_resource_create
+    
celix_ei_expect_celix_arrayList_createWithOptions((void*)celix_resource_create, 
0, nullptr);
+    res = celix_resource_create();
+    EXPECT_EQ(nullptr, res);
+    EXPECT_EQ(2, celix_rcmErr_getErrorCount());
+
+    res = celix_resource_create();
+    EXPECT_NE(nullptr, res);
+    celix_capability_t* cap = celix_capability_create(res, "test");
+    EXPECT_NE(nullptr, cap);
+    celix_requirement_t* req = celix_requirement_create(res, "test", nullptr);
+    EXPECT_NE(nullptr, req);
+
+    //inject error on first celix_arrayList_create call from 
celix_resource_addCapability
+    
celix_ei_expect_celix_arrayList_create((void*)celix_resource_addCapability, 0, 
nullptr);
+    EXPECT_FALSE(celix_resource_addCapability(res, cap));
+    EXPECT_EQ(3, celix_rcmErr_getErrorCount());
+
+    //inject error on first celix_arrayList_add call from 
celix_resource_addCapability
+    celix_ei_expect_celix_arrayList_add((void*)celix_resource_addCapability, 
0, CELIX_ENOMEM);
+    EXPECT_FALSE(celix_resource_addCapability(res, cap));
+    EXPECT_EQ(4, celix_rcmErr_getErrorCount());
+
+    //inject error on second celix_arrayList_add call from 
celix_resource_addCapability
+    celix_ei_expect_celix_arrayList_add((void*)celix_resource_addCapability, 
0, CELIX_ENOMEM, 2);
+    EXPECT_FALSE(celix_resource_addCapability(res, cap));
+    EXPECT_EQ(5, celix_rcmErr_getErrorCount());
+
+    //inject error on first celix_arrayList_create call from 
celix_resource_addRequirement
+    
celix_ei_expect_celix_arrayList_create((void*)celix_resource_addRequirement, 0, 
nullptr);
+    EXPECT_FALSE(celix_resource_addRequirement(res, req));
+    EXPECT_EQ(6, celix_rcmErr_getErrorCount());
+
+    //inject error on first celix_arrayList_add call from 
celix_resource_addRequirement
+    celix_ei_expect_celix_arrayList_add((void*)celix_resource_addRequirement, 
0, CELIX_ENOMEM);
+    EXPECT_FALSE(celix_resource_addRequirement(res, req));
+    EXPECT_EQ(7, celix_rcmErr_getErrorCount());
 
-    //TODO inject error on first celix_arrayList_create call from 
celix_resource_addCapability
+    //inject error on second celix_arrayList_add call from 
celix_resource_addRequirement
+    celix_ei_expect_celix_arrayList_add((void*)celix_resource_addRequirement, 
0, CELIX_ENOMEM, 2);
+    EXPECT_FALSE(celix_resource_addRequirement(res, req));
+    EXPECT_EQ(8, celix_rcmErr_getErrorCount());
 
-    //TODO inject error on first celix_arrayList_create call from 
celix_resource_addRequirement
+    celix_capability_destroy(cap);
+    celix_requirement_destroy(req);
+    celix_resource_destroy(res);
 }
\ No newline at end of file
diff --git a/libs/rcm/src/celix_rcm_err.c b/libs/rcm/src/celix_rcm_err.c
index 8938726e..f3a32ab5 100644
--- a/libs/rcm/src/celix_rcm_err.c
+++ b/libs/rcm/src/celix_rcm_err.c
@@ -42,12 +42,12 @@ static void celix_rcm_destroyTssErrors(void* data) {
     celix_arrayList_destroy(errors);
 }
 
-__attribute__((constructor)) static void 
celix_rcm_initThreadSpecificStorageKey() {
+__attribute__((constructor)) void celix_rcm_initThreadSpecificStorageKey() {
     //tss_create(&celix_rcm_tssErrorsKey, celix_rcm_destroyTssErrors);
     pthread_key_create(&celix_rcm_tssErrorsKey, celix_rcm_destroyTssErrors);
 }
 
-__attribute__((destructor)) static void 
celix_rcm_deinitThreadSpecificStorageKey() {
+__attribute__((destructor)) void celix_rcm_deinitThreadSpecificStorageKey() {
     //tss_delete(celix_rcm_tssErrorsKey);
     pthread_key_delete(celix_rcm_tssErrorsKey);
 }
@@ -76,13 +76,8 @@ int celix_rcmErr_getErrorCount() {
 void celix_rcmErr_resetErrors() {
     //celix_array_list_t* errors = tss_get(celix_rcm_tssErrorsKey);
     celix_array_list_t* errors = pthread_getspecific(celix_rcm_tssErrorsKey);
-    if (errors != NULL) {
-        for (int i = 0; i < celix_arrayList_size(errors); ++i) {
-            char* msg = celix_arrayList_get(errors, i);
-            free(msg);
-        }
-        celix_arrayList_clear(errors);
-    }
+    celix_rcm_destroyTssErrors(errors);
+    pthread_setspecific(celix_rcm_tssErrorsKey, NULL);
 }
 
 static void celix_rcm_pushMsg(char* msg) {
diff --git a/libs/rcm/src/celix_rcm_err_private.h 
b/libs/rcm/src/celix_rcm_err_private.h
index 83b353be..b6bce443 100644
--- a/libs/rcm/src/celix_rcm_err_private.h
+++ b/libs/rcm/src/celix_rcm_err_private.h
@@ -34,7 +34,6 @@ void celix_rcmErr_pushf(char* format, ...) 
__attribute__((format(printf, 1, 2)))
  */
 void celix_rcmErr_push(const char* msg);
 
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/rcm/src/celix_resource.c b/libs/rcm/src/celix_resource.c
index fbe51083..3dd25782 100644
--- a/libs/rcm/src/celix_resource.c
+++ b/libs/rcm/src/celix_resource.c
@@ -168,19 +168,30 @@ bool celix_resource_addCapability(celix_resource_t* res, 
celix_capability_t* cap
         return false;
     }
 
-    celix_arrayList_add(res->allCapabilities, cap);
     const char* ns = celix_capability_getNamespace(cap);
     celix_array_list_t* caps = 
celix_stringHashMap_get(res->capabilitiesByNamespace, ns);
     if (caps == NULL) {
         caps = celix_arrayList_create();
         if (caps == NULL) {
-            celix_rcmErr_push("Failed to allocate capabilities list. Out of 
memory.");
-            return false;
+            goto err_handling;
         }
         celix_stringHashMap_put(res->capabilitiesByNamespace, ns, caps);
     }
-    celix_arrayList_add(caps, cap);
+    celix_status_t status = celix_arrayList_add(caps, cap);
+    if (status != CELIX_SUCCESS) {
+        goto err_handling;
+    }
+    status = celix_arrayList_add(res->allCapabilities, cap);
+    if (status != CELIX_SUCCESS) {
+        goto err_handling;
+    }
     return true;
+err_handling:
+    celix_rcmErr_push("Failed to add capability to resource. Out of memory.");
+    if (caps != NULL) {
+        celix_arrayList_remove(caps, cap);
+    }
+    return false;
 }
 
 bool celix_resource_addRequirement(celix_resource_t* res, celix_requirement_t* 
req) {
@@ -191,17 +202,29 @@ bool celix_resource_addRequirement(celix_resource_t* res, 
celix_requirement_t* r
         return false;
     }
 
-    celix_arrayList_add(res->allRequirements, req);
     const char* ns = celix_requirement_getNamespace(req);
     celix_array_list_t* reqs = 
celix_stringHashMap_get(res->requirementsByNamespace, ns);
     if (reqs == NULL) {
         reqs = celix_arrayList_create();
         if (reqs == NULL) {
-            celix_rcmErr_push("Failed to allocate requirement list. Out of 
memory.");
-            return false;
+            goto err_handling;
         }
         celix_stringHashMap_put(res->requirementsByNamespace, ns, reqs);
     }
-    celix_arrayList_add(reqs, req);
+    celix_status_t status = celix_arrayList_add(reqs, req);
+    if (status != CELIX_SUCCESS) {
+        goto err_handling;
+    }
+    status = celix_arrayList_add(res->allRequirements, req);
+    if (status != CELIX_SUCCESS) {
+        goto err_handling;
+    }
+
     return true;
+err_handling:
+    celix_rcmErr_push("Failed to add requirement to resource. Out of memory.");
+    if (reqs != NULL) {
+        celix_arrayList_remove(reqs, req);
+    }
+    return false;
 }
diff --git a/libs/utils/include/celix_array_list.h 
b/libs/utils/include/celix_array_list.h
index 77e174ec..28c48ec4 100644
--- a/libs/utils/include/celix_array_list.h
+++ b/libs/utils/include/celix_array_list.h
@@ -230,72 +230,81 @@ size_t celix_arrayList_getSize(const celix_array_list_t 
*list, int index);
  *
  * @param map The array list.
  * @param value The pointer value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
-void celix_arrayList_add(celix_array_list_t *list, void* value);
+celix_status_t celix_arrayList_add(celix_array_list_t *list, void* value);
 
 /**
  * @brief add pointer entry to the back of the array list.
  *
  * @param map The array list.
  * @param value The int value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
-void celix_arrayList_addInt(celix_array_list_t *list, int value);
+celix_status_t celix_arrayList_addInt(celix_array_list_t *list, int value);
 
 /**
  * @brief add pointer entry to the back of the array list.
  *
  * @param map The array list.
  * @param value The long value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
-void celix_arrayList_addLong(celix_array_list_t *list, long value);
+celix_status_t celix_arrayList_addLong(celix_array_list_t *list, long value);
 
 /**
  * @brief add pointer entry to the back of the array list.
  *
  * @param map The array list.
  * @param value The unsigned int value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
-void celix_arrayList_addUInt(celix_array_list_t *list, unsigned int value);
+celix_status_t celix_arrayList_addUInt(celix_array_list_t *list, unsigned int 
value);
 
 /**
  * @brief add pointer entry to the back of the array list.
  *
  * @param map The array list.
  * @param value The unsigned long value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
-void celix_arrayList_addULong(celix_array_list_t *list, unsigned long value);
+celix_status_t celix_arrayList_addULong(celix_array_list_t *list, unsigned 
long value);
 
 /**
  * @brief add pointer entry to the back of the array list.
  *
  * @param map The array list.
  * @param value The float value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
-void celix_arrayList_addFloat(celix_array_list_t *list, float value);
+celix_status_t celix_arrayList_addFloat(celix_array_list_t *list, float value);
 
 /**
  * @brief add pointer entry to the back of the array list.
  *
  * @param map The array list.
  * @param value The double value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
-void celix_arrayList_addDouble(celix_array_list_t *list, double value);
+celix_status_t celix_arrayList_addDouble(celix_array_list_t *list, double 
value);
 
 /**
  * @brief add pointer entry to the back of the array list.
  *
  * @param map The array list.
  * @param value The bool value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
-void celix_arrayList_addBool(celix_array_list_t *list, bool value);
+celix_status_t celix_arrayList_addBool(celix_array_list_t *list, bool value);
 
 /**
  * @brief add pointer entry to the back of the array list.
  *
  * @param map The array list.
  * @param value The size_t value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
-void celix_arrayList_addSize(celix_array_list_t *list, size_t value);
+celix_status_t celix_arrayList_addSize(celix_array_list_t *list, size_t value);
 
 /**
  * @brief Returns the index of the provided entry, if found.
diff --git a/libs/utils/include_deprecated/array_list.h 
b/libs/utils/include_deprecated/array_list.h
index cde701da..ca4c23f7 100644
--- a/libs/utils/include_deprecated/array_list.h
+++ b/libs/utils/include_deprecated/array_list.h
@@ -47,7 +47,7 @@ UTILS_EXPORT void arrayList_destroy(celix_array_list_t *list);
 
 UTILS_EXPORT void arrayList_trimToSize(celix_array_list_t *list);
 
-UTILS_EXPORT void arrayList_ensureCapacity(celix_array_list_t *list, int 
capacity);
+UTILS_EXPORT celix_status_t arrayList_ensureCapacity(celix_array_list_t *list, 
int capacity);
 
 UTILS_EXPORT unsigned int arrayList_size(celix_array_list_t *list);
 
diff --git a/libs/utils/src/array_list.c b/libs/utils/src/array_list.c
index 27c32010..746f4dcd 100644
--- a/libs/utils/src/array_list.c
+++ b/libs/utils/src/array_list.c
@@ -90,7 +90,8 @@ void arrayList_trimToSize(array_list_pt list) {
     }
 }
 
-void arrayList_ensureCapacity(array_list_pt list, int capacity) {
+celix_status_t arrayList_ensureCapacity(array_list_pt list, int capacity) {
+    celix_status_t status = CELIX_SUCCESS;
     celix_array_list_entry_t *newList;
     list->modCount++;
     size_t oldCapacity = list->capacity;
@@ -100,9 +101,13 @@ void arrayList_ensureCapacity(array_list_pt list, int 
capacity) {
             newCapacity = capacity;
         }
         newList = realloc(list->elementData, sizeof(celix_array_list_entry_t) 
* newCapacity);
-        list->capacity = newCapacity;
-        list->elementData = newList;
+        if (newList != NULL) {
+            list->capacity = newCapacity;
+            list->elementData = newList;
+        }
+        status = newList == NULL ? CELIX_ENOMEM : CELIX_SUCCESS;
     }
+    return status;
 }
 
 unsigned int arrayList_size(array_list_pt list) {
@@ -420,65 +425,75 @@ double celix_arrayList_getDouble(const celix_array_list_t 
*list, int index) { re
 bool celix_arrayList_getBool(const celix_array_list_t *list, int index) { 
return arrayList_getEntry(list, index).boolVal; }
 size_t celix_arrayList_getSize(const celix_array_list_t *list, int index) { 
return arrayList_getEntry(list, index).sizeVal; }
 
-static void arrayList_addEntry(celix_array_list_t *list, 
celix_array_list_entry_t entry) {
-    arrayList_ensureCapacity(list, (int)list->size + 1);
-    list->elementData[list->size++] = entry;
+static celix_status_t celix_arrayList_addEntry(celix_array_list_t *list, 
celix_array_list_entry_t entry) {
+    celix_status_t status = arrayList_ensureCapacity(list, (int)list->size + 
1);
+    if (status == CELIX_SUCCESS) {
+        list->elementData[list->size++] = entry;
+    }
+    return status;
 }
 
-void celix_arrayList_add(celix_array_list_t *list, void * element) {
+celix_status_t celix_arrayList_add(celix_array_list_t *list, void * element) {
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.voidPtrVal = element;
-    arrayList_addEntry(list, entry);
+    return celix_arrayList_addEntry(list, entry);
 }
 
-void celix_arrayList_addInt(celix_array_list_t *list, int val) { 
+celix_status_t celix_arrayList_addInt(celix_array_list_t *list, int val) {
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.intVal = val;
-    arrayList_addEntry(list, entry);
+    return celix_arrayList_addEntry(list, entry);
 }
-void celix_arrayList_addLong(celix_array_list_t *list, long val) { 
+
+celix_status_t celix_arrayList_addLong(celix_array_list_t *list, long val) {
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.longVal = val;
-    arrayList_addEntry(list, entry);
+    return celix_arrayList_addEntry(list, entry);
 }
-void celix_arrayList_addUInt(celix_array_list_t *list, unsigned int val) { 
+
+celix_status_t celix_arrayList_addUInt(celix_array_list_t *list, unsigned int 
val) {
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.uintVal = val;
-    arrayList_addEntry(list, entry);
+    return celix_arrayList_addEntry(list, entry);
 }
-void celix_arrayList_addULong(celix_array_list_t *list, unsigned long val) { 
+
+celix_status_t celix_arrayList_addULong(celix_array_list_t *list, unsigned 
long val) {
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.ulongVal = val;
-    arrayList_addEntry(list, entry);
+    return celix_arrayList_addEntry(list, entry);
 }
-void celix_arrayList_addDouble(celix_array_list_t *list, double val) { 
+
+celix_status_t celix_arrayList_addDouble(celix_array_list_t *list, double val) 
{
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.doubleVal = val;
-    arrayList_addEntry(list, entry);
+    return celix_arrayList_addEntry(list, entry);
 }
-void celix_arrayList_addFloat(celix_array_list_t *list, float val) { 
+
+celix_status_t celix_arrayList_addFloat(celix_array_list_t *list, float val) {
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.floatVal = val;
-    arrayList_addEntry(list, entry);
+    return celix_arrayList_addEntry(list, entry);
 }
-void celix_arrayList_addBool(celix_array_list_t *list, bool val) { 
+
+celix_status_t celix_arrayList_addBool(celix_array_list_t *list, bool val) {
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.boolVal = val;
-    arrayList_addEntry(list, entry);
+    return celix_arrayList_addEntry(list, entry);
 }
-void celix_arrayList_addSize(celix_array_list_t *list, size_t val) { 
+
+celix_status_t celix_arrayList_addSize(celix_array_list_t *list, size_t val) {
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.sizeVal = val;
-    arrayList_addEntry(list, entry);
+    return celix_arrayList_addEntry(list, entry);
 }
 
 int celix_arrayList_indexOf(celix_array_list_t *list, celix_array_list_entry_t 
entry) {

Reply via email to