diff --git a/interfaces/innerkits/fs_manager/BUILD.gn b/interfaces/innerkits/fs_manager/BUILD.gn index 1722527e5..af22a6d89 100755 --- a/interfaces/innerkits/fs_manager/BUILD.gn +++ b/interfaces/innerkits/fs_manager/BUILD.gn @@ -33,6 +33,7 @@ ohos_static_library("libfsmanager_static") { "//base/startup/init/interfaces/innerkits/include", "//third_party/bounds_checking_function/include", "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", "//base/startup/init/services/log", "//base/startup/init/services/param/include", ] diff --git a/interfaces/innerkits/fs_manager/fstab_mount.c b/interfaces/innerkits/fs_manager/fstab_mount.c index 36cf64b3a..7a5e19ae7 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 33e5b4030..eceaff307 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" }, @@ -15,6 +16,7 @@ { "name": "InitAddPostCfgLoadHook" }, { "name": "InitModuleMgrInstall" }, { "name": "InitModuleMgrUnInstall" }, + { "name": "InitSetExtendedFileSystems" }, { "name": "AutorunModuleMgrUnInstall" }, { "name": "StartupLog" }, { "name": "DoJobNow" }, @@ -82,5 +84,10 @@ { "name": "InitAddServiceParseHook" }, { "name": "InitAddJobParseHook" }, { "name": "InitAddPostPersistParamLoadHook"}, - { "name": "InitServiceRestartHook" } + { "name": "InitServiceRestartHook" }, + { "name": "OH_StrArrayGetIndex" }, + { "name": "OH_ExtendableStrArrayGetIndex" }, + { "name": "OH_StrDictGet" }, + { "name": "OH_ExtendableStrDictGet" }, + { "name": "GetUptimeInMicroSeconds" } ] diff --git a/interfaces/innerkits/libbegetutil.versionscript b/interfaces/innerkits/libbegetutil.versionscript index 3b32a5c45..4f1d947ab 100644 --- a/interfaces/innerkits/libbegetutil.versionscript +++ b/interfaces/innerkits/libbegetutil.versionscript @@ -148,6 +148,10 @@ GetDistributionOSApiVersion; GetDistributionOSReleaseType; SaveParameters; + 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..8871de374 100644 --- a/services/utils/init_utils.c +++ b/services/utils/init_utils.c @@ -711,31 +711,86 @@ 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 dea00104a..43097261e 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -211,6 +211,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