From 7ae418b6472a0e216bd14e8ea3e421c3ef89aa97 Mon Sep 17 00:00:00 2001 From: handyohos Date: Sat, 21 Oct 2023 13:58:58 +0800 Subject: [PATCH] Feat: extend supported file systems by adding StrArray and StrDict utility api 1) Add StrArray and StrDict utility api and add corresponding unittests 2) Extend supported file systems by the utility api Signed-off-by: handyohos Change-Id: I8b14ec85f6efbcb3be96a50314f7fb949f937605 #I899SK --- interfaces/innerkits/fs_manager/BUILD.gn | 1 + interfaces/innerkits/fs_manager/fstab_mount.c | 52 ++- interfaces/innerkits/include/init_utils.h | 64 ++- .../include/init_filesystems.h | 36 ++ .../include/init_module_engine.h | 1 + .../init_module_engine/stub/libinit.stub.json | 9 +- .../innerkits/libbegetutil.versionscript | 4 + services/utils/init_utils.c | 74 +++- test/unittest/BUILD.gn | 1 + test/unittest/innerkits/strutil_unittest.cpp | 416 ++++++++++++++++++ 10 files changed, 634 insertions(+), 24 deletions(-) create mode 100755 interfaces/innerkits/init_module_engine/include/init_filesystems.h create mode 100755 test/unittest/innerkits/strutil_unittest.cpp diff --git a/interfaces/innerkits/fs_manager/BUILD.gn b/interfaces/innerkits/fs_manager/BUILD.gn index 6d1c0f72e..5d7ef8b30 100755 --- a/interfaces/innerkits/fs_manager/BUILD.gn +++ b/interfaces/innerkits/fs_manager/BUILD.gn @@ -34,6 +34,7 @@ ohos_static_library("libfsmanager_static") { "//base/startup/init/interfaces/innerkits/include/param", "//base/startup/init/services/log", "//base/startup/init/services/param/include", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", ] if (defined(global_parts_info.startup_hvb)) { sources += [ diff --git a/interfaces/innerkits/fs_manager/fstab_mount.c b/interfaces/innerkits/fs_manager/fstab_mount.c index ef426bff9..e8c0b2af4 100755 --- a/interfaces/innerkits/fs_manager/fstab_mount.c +++ b/interfaces/innerkits/fs_manager/fstab_mount.c @@ -30,6 +30,7 @@ #ifdef SUPPORT_HVB #include "dm_verity.h" #endif +#include "init_filesystems.h" #ifdef __cplusplus #if __cplusplus @@ -58,20 +59,45 @@ __attribute__((weak)) void InitPostMount(const char *mountPoint, int rc) { } +static const SUPPORTED_FILE_SYSTEM supportedFileSystems[] = { + { "ext4", 0 }, + { "f2fs", 1 }, + { "overlay", 0 }, + { NULL, 0 } +}; + +static void **extendedFileSystems_ = NULL; + +void InitSetExtendedFileSystems(const SUPPORTED_FILE_SYSTEM *extendedFileSystems[]) +{ + extendedFileSystems_ = (void **)extendedFileSystems; +} + +static const SUPPORTED_FILE_SYSTEM *GetSupportedFileSystemInfo(const char *fsType) +{ + return (const SUPPORTED_FILE_SYSTEM *)OH_ExtendableStrDictGet((void **)supportedFileSystems, + sizeof(SUPPORTED_FILE_SYSTEM), fsType, 0, extendedFileSystems_); +} + +static bool IsSupportedDataType(const char *fsType) +{ + const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType); + if (item == NULL) { + return false; + } + if (item->for_userdata) { + return true; + } + return false; +} + bool IsSupportedFilesystem(const char *fsType) { - bool supported = false; - if (fsType != NULL) { - static const char *supportedFilesystem[] = {"ext4", "f2fs", "overlay", NULL}; - int index = 0; - while (supportedFilesystem[index] != NULL) { - if (strcmp(supportedFilesystem[index++], fsType) == 0) { - supported = true; - break; - } - } + const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType); + if (item == NULL) { + return false; } - return supported; + return true; } static int ExecCommand(int argc, char **argv) @@ -118,7 +144,7 @@ int DoFormat(const char *devPath, const char *fsType) int argc = ARRAY_LENGTH(formatCmds); char **argv = (char **)formatCmds; ret = ExecCommand(argc, argv); - } else if (strcmp(fsType, "f2fs") == 0) { + } else if (IsSupportedDataType(fsType)) { #ifdef __MUSL__ char *formatCmds[] = { "/bin/mkfs.f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr", @@ -356,7 +382,7 @@ int MountOneItem(FstabItem *item) WaitForFile(item->deviceName, WAIT_MAX_SECOND); } - if (strcmp(item->fsType, "f2fs") == 0 && strcmp(item->mountPoint, "/data") == 0) { + if (strcmp(item->mountPoint, "/data") == 0 && IsSupportedDataType(item->fsType)) { int ret = DoResizeF2fs(item->deviceName, 0, item->fsManagerFlags); if (ret != 0) { BEGET_LOGE("Failed to resize.f2fs dir %s , ret = %d", item->deviceName, ret); diff --git a/interfaces/innerkits/include/init_utils.h b/interfaces/innerkits/include/init_utils.h index 842364071..754b42523 100644 --- a/interfaces/innerkits/include/init_utils.h +++ b/interfaces/innerkits/include/init_utils.h @@ -103,7 +103,69 @@ int GetParameterFromCmdLine(const char *paramName, char *value, size_t valueLen) * @param ignoreCase 0 means exact match, others mean ignore case * @return return 0 if succeed; other values if failed. */ -int StrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase); +int OH_StrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase); + +/** + * @brief Get string index from a string array with extended strings + * + * @param strArray string array + * Attension: last item in the array must be NULL, for example: + * const char *strArray[] = { "val1", "val2", NULL } + * @param target string to be matched + * @param ignoreCase 0 means exact match, others mean ignore case + * @param extend optional extended strings array, last string must be NULL + * @return return 0 if succeed; other values if failed. + */ +int OH_ExtendableStrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase, const char *extend[]); + +/** + * @brief Get string dictionary from a string dictionary array + * + * @param strDict string dictionary array + * Attension: last item in the array must be NULL, for example: + * Each item must be a structure with "const char *" as the first element + * For example: + * typedef { + * const char *key; // First element must be "const char *" + * const char *value; // Arbitrary elements + * // Optionally add more elements + * } STRING_DICT_ST; + * @param target string to be matched + * @param ignoreCase 0 means exact match, others mean ignore case + * @return return item pointer if succeed; NULL if failed + * @example + * // Define a name-value pair as dictionary item + * typedef struct { + * const char *name; + * const char *value; + * } NAME_VALUE_ST; + + * // Fill the dictionary values + * NAME_VALUE_ST dict[] = { { "key1", "val1" }, { "key2", "val2" }}; + + * // Find by key name + * NAME_VALUE_ST *found = (NAME_VALUE_ST *)StrDictGetIndex((void **)dict, sizeof(NAME_VALUE_ST), "key1", FALSE); + */ +void *OH_StrDictGet(void **strDict, int dictSize, const char *target, int ignoreCase); + +/** + * @brief Get string dictionary from a string dictionary array and extended string dictionary + * + * @param strDict string dictionary array + * Attension: last item in the array must be NULL, for example: + * Each item must be a structure with "const char *" as the first element + * For example: + * typedef { + * const char *key; // First element must be "const char *" + * const char *value; // Arbitrary elements + * // Optionally add more elements + * } STRING_DICT_ST; + * @param target string to be matched + * @param ignoreCase 0 means exact match, others mean ignore case + * @param extendStrDict optional extended strings dictionary array, last item must be NULL + * @return return item pointer if succeed; NULL if failed. + */ +void *OH_ExtendableStrDictGet(void **strDict, int dictSize, const char *target, int ignoreCase, void **extendStrDict); long long GetUptimeInMicroSeconds(const struct timespec *uptime); diff --git a/interfaces/innerkits/init_module_engine/include/init_filesystems.h b/interfaces/innerkits/init_module_engine/include/init_filesystems.h new file mode 100755 index 000000000..f79b7c372 --- /dev/null +++ b/interfaces/innerkits/init_module_engine/include/init_filesystems.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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. + */ +#ifndef STARTUP_INIT_SUPPORTED_FILE_SYSTEMS_H +#define STARTUP_INIT_SUPPORTED_FILE_SYSTEMS_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct tagSUPPORTED_FILE_SYSTEM { + const char *fs_name; + int for_userdata; +} SUPPORTED_FILE_SYSTEM; + +void InitSetExtendedFileSystems(const SUPPORTED_FILE_SYSTEM *extendedFileSystems[]); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/init_module_engine/include/init_module_engine.h b/interfaces/innerkits/init_module_engine/include/init_module_engine.h index 64e29dbb1..8a1bd582f 100755 --- a/interfaces/innerkits/init_module_engine/include/init_module_engine.h +++ b/interfaces/innerkits/init_module_engine/include/init_module_engine.h @@ -23,6 +23,7 @@ #include "init_modulemgr.h" #include "init_cmdexecutor.h" #include "init_running_hooks.h" +#include "init_filesystems.h" #ifdef __cplusplus #if __cplusplus diff --git a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json index bce06074a..a2a3d4201 100644 --- a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json +++ b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json @@ -6,6 +6,7 @@ { "name": "AddCmdExecutor" }, { "name": "RemoveCmdExecutor" }, { "name": "HookMgrAdd" }, + { "name": "HookMgrAddEx" }, { "name": "HookMgrDel" }, { "name": "GetBootStageHookMgr"}, { "name": "InitAddGlobalInitHook" }, @@ -76,9 +77,15 @@ { "name": "OH_HashMapIsEmpty" }, { "name": "OH_HashMapRemove" }, { "name": "OH_HashMapTraverse" }, + { "name": "OH_StrArrayGetIndex" }, + { "name": "OH_ExtendableStrArrayGetIndex" }, + { "name": "OH_StrDictGet" }, + { "name": "OH_ExtendableStrDictGet" }, + { "name": "GetUptimeInMicroSeconds" }, { "name": "InitAddServiceHook" }, { "name": "InitAddRebootHook" }, { "name": "InitAddServiceParseHook" }, { "name": "InitAddJobParseHook" }, - { "name": "InitAddPostPersistParamLoadHook"} + { "name": "InitAddPostPersistParamLoadHook"}, + { "name": "InitSetExtendedFileSystems" } ] diff --git a/interfaces/innerkits/libbegetutil.versionscript b/interfaces/innerkits/libbegetutil.versionscript index d1e7d9874..d54e0897c 100644 --- a/interfaces/innerkits/libbegetutil.versionscript +++ b/interfaces/innerkits/libbegetutil.versionscript @@ -147,6 +147,10 @@ GetDistributionOSVersion; GetDistributionOSApiVersion; GetDistributionOSReleaseType; + OH_StrArrayGetIndex; + OH_ExtendableStrArrayGetIndex; + OH_StrDictGet; + OH_ExtendableStrDictGet; local: *; }; \ No newline at end of file diff --git a/services/utils/init_utils.c b/services/utils/init_utils.c index 678d5931f..ecaa61226 100644 --- a/services/utils/init_utils.c +++ b/services/utils/init_utils.c @@ -711,31 +711,87 @@ uint32_t IntervalTime(struct timespec *startTime, struct timespec *endTime) return diff; } -int StrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase) +typedef int (*str_compare)(const char *s1, const char *s2); + +int OH_ExtendableStrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase, const char *extend[]) { int i; + int idx; + str_compare cmp = strcmp; - if ((target == NULL) || (target[0] == '\0')) { + if ((strArray == NULL) || (target == NULL) || (target[0] == '\0')) { return -1; } if (ignoreCase) { - for (i = 0; strArray[i] != NULL; i++) { - if (strcasecmp(strArray[i], target) == 0) { - return i; - } - } - return -1; + cmp = strcasecmp; } for (i = 0; strArray[i] != NULL; i++) { - if (strcmp(strArray[i], target) == 0) { + if (cmp(strArray[i], target) == 0) { return i; } } + if (extend == NULL) { + return -1; + } + idx = 0; + while (extend[idx] != NULL) { + if (cmp(extend[idx], target) == 0) { + return i + idx; + } + idx++; + } return -1; } +int OH_StrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase) +{ + return OH_ExtendableStrArrayGetIndex(strArray, target, ignoreCase, NULL); +} + +void *OH_ExtendableStrDictGet(void **strDict, int dictSize, const char *target, int ignoreCase, void **extendStrDict) +{ + int i; + const char *pos; + str_compare cmp = strcmp; + + if ((strDict == NULL) || (dictSize < sizeof(const char *)) || (target == NULL) || (target[0] == '\0')) { + return NULL; + } + + if (ignoreCase) { + cmp = strcasecmp; + } + + i = 0; + pos = (const char *)strDict; + while (*pos != '\0') { + if (cmp(*(const char **)pos, target) == 0) { + return (void *)pos; + } + i++; + pos = pos + dictSize; + } + if (extendStrDict == NULL) { + return NULL; + } + pos = (const char *)extendStrDict; + while (*pos != '\0') { + if (cmp(*(const char **)pos, target) == 0) { + return (void *)pos; + } + i++; + pos = pos + dictSize; + } + return NULL; +} + +void *OH_StrDictGet(void **strDict, int dictSize, const char *target, int ignoreCase) +{ + return OH_ExtendableStrDictGet(strDict, dictSize, target, ignoreCase, NULL); +} + long long GetUptimeInMicroSeconds(const struct timespec *uptime) { struct timespec now; diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 773288049..431b6a154 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -210,6 +210,7 @@ ohos_unittest("init_unittest") { "//base/startup/init/interfaces/innerkits/syspara/param_wrapper.cpp", "innerkits/hookmgr_unittest.cpp", "innerkits/modulemgr_unittest.cpp", + "innerkits/strutil_unittest.cpp", ] configs = [ "//base/startup/init/test/unittest:utest_config" ] diff --git a/test/unittest/innerkits/strutil_unittest.cpp b/test/unittest/innerkits/strutil_unittest.cpp new file mode 100755 index 000000000..a0adf7908 --- /dev/null +++ b/test/unittest/innerkits/strutil_unittest.cpp @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ + +#include +#include +#include "init_utils.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class StrUtilUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(StrUtilUnitTest, StrArrayGetIndex_unit_test, TestSize.Level1) +{ + int ret; + const char *strArray[] = { "a1", "a2", "a3", NULL}; + + // Invalid arguments test + ret = OH_StrArrayGetIndex(NULL, "test", 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(NULL, NULL, 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(strArray, NULL, 0); + EXPECT_EQ(ret, -1); + + // Matched + ret = OH_StrArrayGetIndex(strArray, "a1", 0); + EXPECT_EQ(ret, 0); + ret = OH_StrArrayGetIndex(strArray, "a2", 0); + EXPECT_EQ(ret, 1); + ret = OH_StrArrayGetIndex(strArray, "a3", 0); + EXPECT_EQ(ret, 2); + + // Not matched + ret = OH_StrArrayGetIndex(strArray, "aa1", 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(strArray, "A1", 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(strArray, "A2", 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(strArray, "A3", 0); + EXPECT_EQ(ret, -1); + + // Ignore case + ret = OH_StrArrayGetIndex(strArray, "A1", 1); + EXPECT_EQ(ret, 0); + ret = OH_StrArrayGetIndex(strArray, "A2", 2); + EXPECT_EQ(ret, 1); + ret = OH_StrArrayGetIndex(strArray, "A3", 3); + EXPECT_EQ(ret, 2); +} + +HWTEST_F(StrUtilUnitTest, OH_ExtendableStrArrayGetIndex_unitest, TestSize.Level1) +{ + int ret; + const char *strArray[] = { "a1", "a2", "a3", NULL}; + const char *extendStrArray[] = { "a4", "a5", "a6", NULL}; + + // Matched + ret = OH_ExtendableStrArrayGetIndex(strArray, "a4", 0, extendStrArray); + EXPECT_EQ(ret, 3); + ret = OH_ExtendableStrArrayGetIndex(strArray, "a5", 0, extendStrArray); + EXPECT_EQ(ret, 4); + ret = OH_ExtendableStrArrayGetIndex(strArray, "a6", 0, extendStrArray); + EXPECT_EQ(ret, 5); + + // Not matched + ret = OH_ExtendableStrArrayGetIndex(strArray, "aa1", 0, extendStrArray); + EXPECT_EQ(ret, -1); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A4", 0, extendStrArray); + EXPECT_EQ(ret, -1); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A5", 0, extendStrArray); + EXPECT_EQ(ret, -1); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A6", 0, extendStrArray); + EXPECT_EQ(ret, -1); + + // Ignore case + ret = OH_ExtendableStrArrayGetIndex(strArray, "A4", 1, extendStrArray); + EXPECT_EQ(ret, 3); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A5", 2, extendStrArray); + EXPECT_EQ(ret, 4); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A6", 3, extendStrArray); + EXPECT_EQ(ret, 5); +} + +HWTEST_F(StrUtilUnitTest, StrDictGet_unit_test_str_array, TestSize.Level1) +{ + int ret; + void *res; + const char *strArray[] = { "a1", "a2", "a3", NULL}; + + // Invalid arguments test + res = OH_StrDictGet(NULL, 0, "test", 0); + EXPECT_EQ(res, NULL); + res = OH_StrDictGet(NULL, 0, NULL, 0); + EXPECT_EQ(res, NULL); + res = OH_StrDictGet((void **)strArray, 1, NULL, 0); + EXPECT_EQ(res, NULL); + res = OH_StrDictGet((void **)strArray, 3, NULL, 0); + EXPECT_EQ(res, NULL); + + // Matched + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "a1", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a1"); + EXPECT_EQ(ret, 0); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "a2", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a2"); + EXPECT_EQ(ret, 0); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "a3", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a3"); + EXPECT_EQ(ret, 0); + + // Not matched + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "aa1", 0); + EXPECT_EQ(res, nullptr); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A1", 0); + EXPECT_EQ(res, nullptr); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A2", 0); + EXPECT_EQ(res, nullptr); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A3", 0); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A1", 1); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a1"); + EXPECT_EQ(ret, 0); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A2", 2); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a2"); + EXPECT_EQ(ret, 0); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A3", 3); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a3"); + EXPECT_EQ(ret, 0); +} + +using STRING_INT_DICT = struct { + const char *key; + int val; +}; + +HWTEST_F(StrUtilUnitTest, StrDictGet_unit_test_str_int_dict, TestSize.Level1) +{ + const STRING_INT_DICT *res; + const STRING_INT_DICT strIntDict[] = { + {"a1", 1}, + {"a2", 2}, + {"a3", 3}, + {NULL, 0} + }; + + // Matched + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "a1", 0); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 1); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "a2", 0); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 2); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "a3", 0); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 3); + + // Not matched + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "aa1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A2", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A3", 0); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A1", 3); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 1); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A2", 2); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 2); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A3", 1); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 3); +} + +using STRING_STRING_DICT = struct { + const char *key; + const char *val; +}; + +HWTEST_F(StrUtilUnitTest, StrDictGet_unit_test_str_str_dict, TestSize.Level1) +{ + int ret; + const STRING_STRING_DICT *res; + const STRING_STRING_DICT strStrDict[] = { + {"a1", "val1"}, + {"a2", "val2"}, + {"a3", "val3"}, + {NULL, NULL} + }; + + // Matched + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "a1", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val1"); + EXPECT_EQ(ret, 0); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "a2", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val2"); + EXPECT_EQ(ret, 0); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "a3", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val3"); + EXPECT_EQ(ret, 0); + + // Not matched + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "aa1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A2", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A3", 0); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A1", 3); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val1"); + EXPECT_EQ(ret, 0); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A2", 2); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val2"); + EXPECT_EQ(ret, 0); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A3", 1); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val3"); + EXPECT_EQ(ret, 0); +} + +using STRING_HYBRID_DICT = struct { + const char *key; + int cnt; + const char *val; +}; + +HWTEST_F(StrUtilUnitTest, StrDictGet_unit_test_str_hybrid_dict, TestSize.Level1) +{ + int ret; + const STRING_HYBRID_DICT *res; + const STRING_HYBRID_DICT strHybridDict[] = { + {"a1", 1, "val1"}, + {"a2", 2, "val2"}, + {"a3", 3, "val3"}, + {NULL, 0, NULL} + }; + + // string array Matched + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a1", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val1"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 1); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a2", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val2"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 2); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a3", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val3"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 3); + + // Not matched + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "aa1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A2", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A3", 0); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A1", 3); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val1"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 1); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A2", 2); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val2"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 2); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A3", 1); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val3"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 3); +} + +HWTEST_F(StrUtilUnitTest, ExtendableStrDictGet_unit_test, TestSize.Level1) +{ + int ret; + const STRING_HYBRID_DICT *res; + const STRING_HYBRID_DICT strHybridDict[] = { + {"a1", 1, "val1"}, + {"a2", 2, "val2"}, + {"a3", 3, "val3"}, + {NULL, 0, NULL} + }; + const STRING_HYBRID_DICT extendHybridDict[] = { + {"a4", 4, "val4"}, + {"a5", 5, "val5"}, + {"a6", 6, "val6"}, + {NULL, 0, NULL} + }; + + // string array Matched + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a4", 0, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val4"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 4); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a5", 0, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val5"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 5); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a6", 0, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val6"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 6); + + // Not matched + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "aa1", 0, (void **)extendHybridDict); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A4", 0, (void **)extendHybridDict); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A5", 0, (void **)extendHybridDict); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A6", 0, (void **)extendHybridDict); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A4", 3, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val4"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 4); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A5", 2, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val5"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 5); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A6", 1, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val6"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 6); +} +} // namespace init_ut -- Gitee