Skip to content

Commit

Permalink
gh-674: Add missing array list support to several celix_properties fu…
Browse files Browse the repository at this point in the history
…nctions, add more tests.
  • Loading branch information
PengZheng committed Apr 2, 2024
1 parent 10473c5 commit 3437c04
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 40 deletions.
45 changes: 44 additions & 1 deletion libs/utils/gtest/src/PropertiesErrorInjectionTestSuite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@
*/

#include <gtest/gtest.h>
#include <string>

#include "celix/Properties.h"
#include "celix_cleanup.h"
#include "celix_convert_utils.h"
#include "celix_err.h"
#include "celix_properties.h"
#include "celix_properties_private.h"
#include "celix_utils_private_constants.h"
#include "celix_version.h"

#include "asprintf_ei.h"
#include "celix_array_list_ei.h"
#include "celix_string_hash_map_ei.h"
#include "celix_utils_ei.h"
Expand All @@ -40,6 +43,8 @@ class PropertiesErrorInjectionTestSuite : public ::testing::Test {
PropertiesErrorInjectionTestSuite() = default;
~PropertiesErrorInjectionTestSuite() override {
celix_err_resetErrors();
celix_ei_expect_open_memstream(nullptr, 0, nullptr);
celix_ei_expect_asprintf(nullptr, 0, -1);
celix_ei_expect_malloc(nullptr, 0, nullptr);
celix_ei_expect_celix_stringHashMap_createWithOptions(nullptr, 0, nullptr);
celix_ei_expect_celix_arrayList_copy(nullptr, 0, nullptr);
Expand Down Expand Up @@ -140,6 +145,20 @@ TEST_F(PropertiesErrorInjectionTestSuite, SetFailureTest) {
// Then the celix_properties_set call fails
ASSERT_EQ(celix_properties_set(props, "key", "value"), CELIX_ENOMEM);

celix_ei_expect_celix_utils_strdup((void*)celix_properties_createString, 0, nullptr);
ASSERT_EQ(CELIX_ENOMEM, celix_properties_setLong(props, "key", 1000));

celix_ei_expect_celix_utils_strdup((void*)celix_properties_createString, 0, nullptr);
ASSERT_EQ(CELIX_ENOMEM, celix_properties_setDouble(props, "key", 1.2));

double largeNumber = 123456789012345.0;
celix_ei_expect_asprintf((void*)celix_properties_setDouble, 3, -1);
ASSERT_EQ(CELIX_ENOMEM, celix_properties_setDouble(props, "key", largeNumber));

celix_autoptr(celix_array_list_t) list = celix_arrayList_createLongArray();
celix_ei_expect_open_memstream((void*)celix_utils_arrayListToString, 1, nullptr);
ASSERT_EQ(CELIX_ENOMEM, celix_properties_setArrayList(props, "key", list));

// C++ API
// Given a celix properties object with a filled optimization cache
celix::Properties cxxProps{};
Expand Down Expand Up @@ -309,6 +328,7 @@ TEST_F(PropertiesErrorInjectionTestSuite, GetAsArrayWithArrayListCopyFailedTest)
celix_properties_setArrayList(props, "doubleArray", doubleList);
celix_properties_setArrayList(props, "boolArray", boolList);
celix_properties_setArrayList(props, "versionArray", versionList);
celix_properties_setString(props, "string", "Hello world");

// When a celix_arrayList_createWithOptions error injection is set for celix_properties_getAsStringArrayList
celix_ei_expect_celix_arrayList_copy((void*)celix_properties_getAsStringArrayList, 1, nullptr);
Expand Down Expand Up @@ -354,6 +374,13 @@ TEST_F(PropertiesErrorInjectionTestSuite, GetAsArrayWithArrayListCopyFailedTest)
status = celix_properties_getAsVersionArrayList(props, "versionArray", nullptr, &versions);
ASSERT_EQ(status, CELIX_ENOMEM);
ASSERT_EQ(nullptr, versions);


celix_ei_expect_open_memstream((void*)celix_utils_convertStringToVersionArrayList, 1, nullptr);
versions = nullptr;
status = celix_properties_getAsVersionArrayList(props, "string", nullptr, &versions);
ASSERT_EQ(status, CELIX_ENOMEM);
ASSERT_EQ(nullptr, versions);
}

TEST_F(PropertiesErrorInjectionTestSuite, SetArrayWithArrayListCopyFailedTest) {
Expand Down Expand Up @@ -411,7 +438,7 @@ TEST_F(PropertiesErrorInjectionTestSuite, LoadFromStringFailureTest) {
celix_err_resetErrors();
}

TEST_F(PropertiesErrorInjectionTestSuite, LoadSetVersionFailureTest) {
TEST_F(PropertiesErrorInjectionTestSuite, SetVersionFailureTest) {
// Given a celix properties object
celix_autoptr(celix_properties_t) props = celix_properties_create();
// And a version object
Expand All @@ -424,4 +451,20 @@ TEST_F(PropertiesErrorInjectionTestSuite, LoadSetVersionFailureTest) {
//And a celix err msg is pushed
ASSERT_EQ(1, celix_err_getErrorCount());
celix_err_resetErrors();

celix_autoptr(celix_version_t) version2 = celix_version_create(1, 2, 3, "aaaaaaaaaaaaaaaaaaaaaaaaaa");
celix_ei_expect_asprintf((void*) celix_version_toString, 0, -1);
status = celix_properties_setVersion(props, "key", version2);
ASSERT_EQ(status, CELIX_ENOMEM);
ASSERT_STREQ("Cannot fill property entry", celix_err_popLastError());
ASSERT_STREQ("Failed to allocate memory for celix_version_toString", celix_err_popLastError());
celix_err_resetErrors();

fillOptimizationCache(props);
celix_ei_expect_celix_utils_strdup((void*)celix_properties_createString, 0, nullptr);
status = celix_properties_setVersion(props, "key1", version);
ASSERT_EQ(status, CELIX_ENOMEM);
//And a celix err msg is pushed
ASSERT_EQ(1, celix_err_getErrorCount());
celix_err_resetErrors();
}
58 changes: 52 additions & 6 deletions libs/utils/gtest/src/PropertiesTestSuite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,23 @@ TEST_F(PropertiesTestSuite, GetSetTest) {
char keyA[] = "x";
char keyB[] = "y";
char keyC[] = "z";
char *keyD = strndup("a", 1);
char* keyD = strndup("a", 1);
const char* keyE = "e";
char valueA[] = "1";
char valueB[] = "2";
char valueC[] = "3";
char *valueD = strndup("4", 1);
char *valueE = strdup("5");
celix_properties_set(properties, keyA, valueA);
celix_properties_set(properties, keyB, valueB);
celix_properties_assign(properties, keyD, valueD);
celix_properties_assignString(properties, keyE, valueE);

EXPECT_STREQ(valueA, celix_properties_get(properties, keyA, nullptr));
EXPECT_STREQ(valueB, celix_properties_get(properties, keyB, nullptr));
EXPECT_STREQ(valueC, celix_properties_get(properties, keyC, valueC));
EXPECT_STREQ(valueD, celix_properties_get(properties, keyD, nullptr));
EXPECT_STREQ(valueE, celix_properties_get(properties, keyE, nullptr));

celix_properties_destroy(properties);
}
Expand Down Expand Up @@ -368,22 +372,31 @@ TEST_F(PropertiesTestSuite, GetTypeAndCopyTest) {
celix_properties_setBool(props, "bool", true);
auto* version = celix_version_create(1, 2, 3, nullptr);
celix_properties_setVersion(props, "version", version);
celix_autoptr(celix_array_list_t) longList = celix_arrayList_createLongArray();
celix_arrayList_addLong(longList, 1);
celix_arrayList_addLong(longList, 2);
celix_arrayList_addLong(longList, 3);
celix_properties_setArrayList(props, "array", longList);

EXPECT_EQ(5, celix_properties_size(props));
EXPECT_EQ(6, celix_properties_size(props));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_STRING, celix_properties_getType(props, "string"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_LONG, celix_properties_getType(props, "long"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_DOUBLE, celix_properties_getType(props, "double"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_BOOL, celix_properties_getType(props, "bool"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_VERSION, celix_properties_getType(props, "version"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_UNSET, celix_properties_getType(props, "missing"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_ARRAY_LIST, celix_properties_getType(props, "array"));
EXPECT_TRUE(celix_arrayList_equals(longList, celix_properties_getArrayList(props, "array")));

auto* copy = celix_properties_copy(props);
EXPECT_EQ(5, celix_properties_size(copy));
EXPECT_EQ(6, celix_properties_size(copy));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_STRING, celix_properties_getType(copy, "string"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_LONG, celix_properties_getType(copy, "long"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_DOUBLE, celix_properties_getType(copy, "double"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_BOOL, celix_properties_getType(copy, "bool"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_VERSION, celix_properties_getType(copy, "version"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_ARRAY_LIST, celix_properties_getType(copy, "array"));
EXPECT_TRUE(celix_arrayList_equals(longList, celix_properties_getArrayList(copy, "array")));

celix_version_destroy(version);
celix_properties_destroy(props);
Expand Down Expand Up @@ -572,6 +585,8 @@ TEST_F(PropertiesTestSuite, SetWithCopyTest) {
celix_properties_assign(props, celix_utils_strdup("key"), celix_utils_strdup("value2"));
EXPECT_EQ(1, celix_properties_size(props));
celix_properties_destroy(props);

EXPECT_EQ(CELIX_SUCCESS, celix_properties_assign(nullptr, celix_utils_strdup("key"), celix_utils_strdup("value2")));
}

TEST_F(PropertiesTestSuite, HasKeyTest) {
Expand Down Expand Up @@ -600,17 +615,25 @@ TEST_F(PropertiesTestSuite, SetEntryTest) {
auto* version = celix_version_create(1, 2, 3, nullptr);
celix_properties_setVersion(props1, "key5", version);
celix_version_destroy(version);
celix_autoptr(celix_array_list_t) longList = celix_arrayList_createLongArray();
celix_arrayList_addLong(longList, 1);
celix_arrayList_addLong(longList, 2);
celix_arrayList_addLong(longList, 3);
celix_properties_setArrayList(props1, "key6", longList);

CELIX_PROPERTIES_ITERATE(props1, visit) {
celix_properties_setEntry(props2, visit.key, &visit.entry);
celix_properties_setEntry(nullptr, visit.key, &visit.entry);
}

EXPECT_EQ(5, celix_properties_size(props2));
EXPECT_EQ(6, celix_properties_size(props2));
EXPECT_STREQ("value1", celix_properties_getAsString(props2, "key1", nullptr));
EXPECT_EQ(123, celix_properties_getAsLong(props2, "key2", -1L));
EXPECT_EQ(true, celix_properties_getAsBool(props2, "key3", false));
EXPECT_EQ(3.14, celix_properties_getAsDouble(props2, "key4", -1.0));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_VERSION, celix_properties_getType(props2, "key5"));
EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_ARRAY_LIST, celix_properties_getType(props2, "key6"));
EXPECT_TRUE(celix_properties_equals(props1, props2));

celix_properties_destroy(props1);
celix_properties_destroy(props2);
Expand Down Expand Up @@ -708,6 +731,22 @@ TEST_F(PropertiesTestSuite, InvalidArgumentsTest) {
EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_assign(props, nullptr, strdup("value")));
EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_assign(props, strdup("key"), nullptr));
EXPECT_EQ(2, celix_err_getErrorCount());

EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_assignString(props, nullptr, strdup("value")));

celix_autoptr(celix_array_list_t) list1 = celix_arrayList_create();
celix_autoptr(celix_array_list_t) list2 = celix_arrayList_createStringArray();
celix_autoptr(celix_array_list_t) list3 = celix_arrayList_createPointerArray();

EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_setArrayList(props, nullptr, list2));
EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_setArrayList(props, "list", nullptr));
EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_setArrayList(props, "list", list1));
EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_setArrayList(props, "list", list3));

EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_assignArrayList(props, nullptr, celix_steal_ptr(list2)));
EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_assignArrayList(props, "list", nullptr));
EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_assignArrayList(props, "list", celix_steal_ptr(list1)));
EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, celix_properties_assignArrayList(props, "list", celix_steal_ptr(list3)));
}

TEST_F(PropertiesTestSuite, GetStatsTest) {
Expand Down Expand Up @@ -867,6 +906,7 @@ TEST_F(PropertiesTestSuite, GetTypedArrayListTest) {
celix_properties_assignArrayList(props, "doubleList", doubleList);
celix_properties_assignArrayList(props, "boolList", boolList);
celix_properties_assignArrayList(props, "versionList", versionList);
celix_properties_setString(props, "string", "Hello world");

//When the celix_properties_getAs<Type>ArrayList is called with the array lists
celix_autoptr(celix_array_list_t) retrievedStringList = nullptr;
Expand All @@ -887,8 +927,7 @@ TEST_F(PropertiesTestSuite, GetTypedArrayListTest) {
EXPECT_TRUE(celix_arrayList_equals(boolList, retrievedBoolList));
EXPECT_TRUE(celix_arrayList_equals(versionList, retrievedVersionList));


///When the celix_properties_get<Type>ArrayList is called with the array lists
//When the celix_properties_get<Type>ArrayList is called with the array lists
const auto* retrievedStringList2 = celix_properties_getStringArrayList(props, "stringList");
const auto* retrievedLongList2 = celix_properties_getLongArrayList(props, "longList");
const auto* retrievedDoubleList2 = celix_properties_getDoubleArrayList(props, "doubleList");
Expand All @@ -908,13 +947,20 @@ TEST_F(PropertiesTestSuite, GetTypedArrayListTest) {
const auto* retrievedDoubleList3 = celix_properties_getArrayList(props, "doubleList");
const auto* retrievedBoolList3 = celix_properties_getArrayList(props, "boolList");
const auto* retrievedVersionList3 = celix_properties_getArrayList(props, "versionList");
EXPECT_EQ(nullptr, celix_properties_getArrayList(props, "missing"));

//Then the retrieved array lists should be the same as the original array lists
EXPECT_TRUE(celix_arrayList_equals(stringList, retrievedStringList3));
EXPECT_TRUE(celix_arrayList_equals(longList, retrievedLongList3));
EXPECT_TRUE(celix_arrayList_equals(doubleList, retrievedDoubleList3));
EXPECT_TRUE(celix_arrayList_equals(boolList, retrievedBoolList3));
EXPECT_TRUE(celix_arrayList_equals(versionList, retrievedVersionList3));

celix_autoptr(celix_array_list_t) longList4 = celix_arrayList_copy(longList);
celix_autoptr(celix_array_list_t) retrievedLongList4 = nullptr;
EXPECT_EQ(CELIX_SUCCESS, celix_properties_getAsLongArrayList(props, "string", longList4, &retrievedLongList4));
EXPECT_TRUE(celix_arrayList_equals(longList, retrievedLongList4));

}

TEST_F(PropertiesTestSuite, GetAsTypedArrayListWithInvalidDefault) {
Expand Down
13 changes: 6 additions & 7 deletions libs/utils/include/celix_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -526,8 +526,7 @@ CELIX_UTILS_EXPORT celix_status_t celix_properties_getAsVersion(const celix_prop
*
* This function will make a copy of the provided celix_array_list_t object, using the celix_arrayList_copy function.
*
* If an error occurs, the error status is returned and a message is logged to
* celix_err.
* If an error occurs, the error status is returned and a message is logged to celix_err.
*
* @param[in] properties The property set to modify.
* @param[in] key The key of the property to set.
Expand Down Expand Up @@ -556,7 +555,7 @@ CELIX_UTILS_EXPORT celix_status_t celix_properties_setArrayList(celix_properties
* to the properties set. Cannot be NULL.
* @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if there was not enough memory to set the entry,
* and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL, values is NULL or the array list type is
* valid. On error, the provided array list is destroyed.
* invalid. On error, the provided array list is destroyed.
*/
CELIX_UTILS_EXPORT celix_status_t celix_properties_assignArrayList(celix_properties_t* properties,
const char* key,
Expand Down Expand Up @@ -616,7 +615,7 @@ CELIX_UTILS_EXPORT celix_status_t celix_properties_getAsLongArrayList(const celi
/**
* @brief Get the property value as an array of longs without copying.
*
* This function provides a non-owning, read-only access to a array of longs property value.
* This function provides a non-owning, read-only access to an array of longs property value.
* It returns a const pointer to the array. If the property is not set or its value is not an array of longs,
* NULL is returned.
*
Expand Down Expand Up @@ -658,7 +657,7 @@ CELIX_UTILS_EXPORT celix_status_t celix_properties_getAsDoubleArrayList(const ce
/**
* @brief Get the property value as an array of doubles without copying.
*
* This function provides a non-owning, read-only access to a array of doubles property value.
* This function provides a non-owning, read-only access to an array of doubles property value.
* It returns a const pointer to the array. If the property is not set or its value is not an array of doubles,
* NULL is returned.
*
Expand Down Expand Up @@ -748,7 +747,7 @@ CELIX_UTILS_EXPORT celix_status_t celix_properties_getAsStringArrayList(const ce
/**
* @brief Get the property value as an array of strings without copying.
*
* This function provides a non-owning, read-only access to a array of string property value.
* This function provides a non-owning, read-only access to an array of string property value.
* It returns a const pointer to the array. If the property is not set or its value is not an array of strings,
* NULL is returned.
*
Expand Down Expand Up @@ -796,7 +795,7 @@ CELIX_UTILS_EXPORT celix_status_t celix_properties_getAsVersionArrayList(const c
/**
* @brief Get the property value as an array of celix_version_t entries without copying.
*
* This function provides a non-owning, read-only access to a array of celix_version_t property value.
* This function provides a non-owning, read-only access to an array of celix_version_t property value.
* entries. It returns a const pointer to the array. If the property is not set or its value is not an array of
* celix_version_t entries, NULL is returned.
*
Expand Down
Loading

0 comments on commit 3437c04

Please sign in to comment.