From ca297d26dc1e7b47d6987c6bbbd92dd2e3d78670 Mon Sep 17 00:00:00 2001 From: jikai Date: Wed, 22 Nov 2023 22:05:04 +0800 Subject: [PATCH 32/64] add ut for devicemapper Signed-off-by: jikai --- test/image/oci/storage/layers/CMakeLists.txt | 2 + .../storage/layers/devmapper/CMakeLists.txt | 71 +++++ ...9702e4bd316dd50ae85467b0378a419b23b60ba73d | 6 + ...a9fb83febf6dc0b1548dfe896161533668281c9f4f | 6 + ...0a625721fdbea5c94ca6da897acdd814d710149770 | 6 + .../devmapper/data/devicemapper/metadata/base | 7 + .../devicemapper/metadata/deviceset-metadata | 5 + .../metadata/transaction-metadata | 5 + .../layers/devmapper/driver_devmapper_ut.cc | 283 ++++++++++++++++++ test/mocks/libdevmapper_mock.cc | 191 ++++++++++++ test/mocks/libdevmapper_mock.h | 52 ++++ 11 files changed, 634 insertions(+) create mode 100644 test/image/oci/storage/layers/devmapper/CMakeLists.txt create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770 create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/base create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/deviceset-metadata create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/transaction-metadata create mode 100644 test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc create mode 100644 test/mocks/libdevmapper_mock.cc create mode 100644 test/mocks/libdevmapper_mock.h diff --git a/test/image/oci/storage/layers/CMakeLists.txt b/test/image/oci/storage/layers/CMakeLists.txt index 413a8b38..e1c76453 100644 --- a/test/image/oci/storage/layers/CMakeLists.txt +++ b/test/image/oci/storage/layers/CMakeLists.txt @@ -1,5 +1,7 @@ project(iSulad_UT) +add_subdirectory(devmapper) + # storage_driver_ut SET(DRIVER_EXE storage_driver_ut) diff --git a/test/image/oci/storage/layers/devmapper/CMakeLists.txt b/test/image/oci/storage/layers/devmapper/CMakeLists.txt new file mode 100644 index 00000000..f98de1a8 --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/CMakeLists.txt @@ -0,0 +1,71 @@ +project(iSulad_UT) + +# driver_devmapper_ut +SET(DRIVER_DEVMAPPER_EXE driver_devmapper_ut) + +add_executable(${DRIVER_DEVMAPPER_EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_regex.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_verify.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_string.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_convert.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_fs.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/util_atomic.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_base64.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_timestamp.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/path.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/map/map.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/map/rb_tree.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/buffer/buffer.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/tar/util_archive.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/tar/util_gzip.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/sha256/sha256.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/config/daemon_arguments.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/config/isulad_config.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/common/err_msg.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/common/selinux_label.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/metadata_store.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../mocks/libdevmapper_mock.cc + driver_devmapper_ut.cc) + +target_include_directories(${DRIVER_DEVMAPPER_EXE} PUBLIC + ${GTEST_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../include + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/common + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/tar + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/map + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/sha256 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/console + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/buffer + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/config + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/common + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/api + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/remote_layer_support + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/quota + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../mocks + ) + +set_target_properties(${DRIVER_DEVMAPPER_EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,util_exec_cmd -Wl,--wrap,util_mount -Wl,--wrap,umount2") + +target_link_libraries(${DRIVER_DEVMAPPER_EXE} + ${GTEST_BOTH_LIBRARIES} + ${GMOCK_LIBRARY} + ${GMOCK_MAIN_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${ISULA_LIBUTILS_LIBRARY} + ${LIBTAR_LIBRARY} + -lcrypto -lyajl -larchive ${SELINUX_LIBRARY} -lz -lcap) + +add_test(NAME ${DRIVER_DEVMAPPER_EXE} COMMAND ${DRIVER_DEVMAPPER_EXE} --gtest_output=xml:${DRIVER_DEVMAPPER_EXE}-Results.xml) +set_tests_properties(${DRIVER_DEVMAPPER_EXE} PROPERTIES TIMEOUT 120) diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d new file mode 100644 index 00000000..f51ae926 --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d @@ -0,0 +1,6 @@ +{ + "hash": "068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d", + "device_id": 6, + "size": 10737418240, + "transaction_id": 8 +} diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f new file mode 100644 index 00000000..de727a79 --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f @@ -0,0 +1,6 @@ +{ + "hash": "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f", + "device_id": 4, + "size": 10737418240, + "transaction_id": 4 +} diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770 b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770 new file mode 100644 index 00000000..e1e8988e --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770 @@ -0,0 +1,6 @@ +{ + "hash": "ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770", + "device_id": 2, + "size": 10737418240, + "transaction_id": 2 +} diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/base b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/base new file mode 100644 index 00000000..2412113d --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/base @@ -0,0 +1,7 @@ +{ + "hash": "base", + "device_id": 1, + "size": 10737418240, + "transaction_id": 1, + "initialized": true +} diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/deviceset-metadata b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/deviceset-metadata new file mode 100644 index 00000000..94f7a6a3 --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/deviceset-metadata @@ -0,0 +1,5 @@ +{ + "next_device_id": 7, + "BaseDeviceFilesystem": "ext4", + "BaseDeviceUUID": "4fa22307-0c88-4fa4-8f16-a9459e9cbc4a" +} diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/transaction-metadata b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/transaction-metadata new file mode 100644 index 00000000..a011249a --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/transaction-metadata @@ -0,0 +1,5 @@ +{ + "open_transaction_id": 8, + "device_hash": "068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d", + "device_id": 6 +} diff --git a/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc b/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc new file mode 100644 index 00000000..59e53f97 --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc @@ -0,0 +1,283 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: jikai + * Create: 2023-11-22 + * Description: provide oci storage driver unit test for devmapper + ******************************************************************************/ + +#include +#include + +#include "driver_devmapper.h" +#include "mock.h" +#include "path.h" +#include "utils.h" +#include "libdevmapper_mock.h" + +using ::testing::Invoke; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::_; + +extern "C" { + DECLARE_WRAPPER_V(util_exec_cmd, bool, (exec_func_t cb_func, void *args, const char *stdin_msg, char **stdout_msg, char **stderr_msg)); + DEFINE_WRAPPER_V(util_exec_cmd, bool, (exec_func_t cb_func, void *args, const char *stdin_msg, char **stdout_msg, char **stderr_msg), (cb_func, args, stdin_msg, stdout_msg, stderr_msg)); + + DECLARE_WRAPPER(util_mount, int, (const char *src, const char *dst, const char *mtype, const char *mntopts)); + DEFINE_WRAPPER(util_mount, int, (const char *src, const char *dst, const char *mtype, const char *mntopts), (src, dst, mtype, mntopts)); + + DECLARE_WRAPPER(umount2, int, (const char *__special_file, int __flags)); + DEFINE_WRAPPER(umount2, int, (const char *__special_file, int __flags), (__special_file, __flags)); +} + +static std::string GetDirectory() +{ + char abs_path[PATH_MAX] { 0x00 }; + int ret = readlink("/proc/self/exe", abs_path, sizeof(abs_path)); + if (ret < 0 || static_cast(ret) >= sizeof(abs_path)) { + return ""; + } + + for (int i { ret }; i >= 0; --i) { + if (abs_path[i] == '/') { + abs_path[i + 1] = '\0'; + break; + } + } + + return static_cast(abs_path) + "../../../../../../../test/image/oci/storage/layers/devmapper"; +} + +static bool invokeUtilExecCmd(exec_func_t cb_func, void *args, const char *stdin_msg, char **stdout_msg, char **stderr_msg) +{ + if (cb_func == nullptr || args == nullptr || stdout_msg == nullptr || stderr_msg == nullptr) { + return false; + } + + char **tmp_args = static_cast(args); + + if (util_array_len((const char **)tmp_args) < 1) { + return false; + } + + if (strcmp(tmp_args[0], "blkid") == 0) { + *stdout_msg = util_strdup_s("4fa22307-0c88-4fa4-8f16-a9459e9cbc4a"); + } + return true; +} + +static struct dm_task *invokeDMTaskCreate(int type) { + return static_cast(util_common_calloc_s(sizeof(0))); +} + +static void invokeDMTaskDestroy(struct dm_task *task) { + free(task); + return; +} + +static int invokeDMTaskGetDriverVersion(struct dm_task *task, char *version, size_t size) { + if (task == nullptr || version == nullptr || strncpy(version, "4.27.0", size) == NULL) { + return 0; + } + + return 1; +} + +static int invokeDMTaskGetInfo(struct dm_task *task, struct dm_info *dmi) { + if (task == nullptr || dmi == nullptr) { + return 0; + } + + dmi->exists = 1; + return 1; +} + +static void *invokeDMGetNextTarget(struct dm_task *task, void *next, uint64_t *start, uint64_t *length, + char **target_type, char **params) { + static char type[] = "thin-pool"; + static char par[] = "0 0/1024 0/1024"; + if (target_type) { + *target_type = type; + } + if (params) { + *params = par; + } + return nullptr; +} + +class DriverDevmapperUnitTest : public testing::Test { +protected: + void SetUp() override + { + MockLibdevmapper_SetMock(&m_libdevmapper_mock); + std::string isulad_dir { "/tmp/isulad/" }; + mkdir(isulad_dir.c_str(), 0755); + std::string root_dir = isulad_dir + "data"; + std::string run_dir = isulad_dir + "data/run"; + std::string data_dir = GetDirectory() + "/data"; + std::string driver_home = root_dir + "/devicemapper"; + + ASSERT_STRNE(util_clean_path(data_dir.c_str(), data_path, sizeof(data_path)), nullptr); + std::string cp_command = "cp -r " + std::string(data_path) + " " + isulad_dir; + ASSERT_EQ(system(cp_command.c_str()), 0); + + char **driver_opts = static_cast(util_common_calloc_s(3 * sizeof(char *))); + driver_opts[0] = strdup("dm.thinpooldev=/dev/mapper/isulad0-thinpool"); + driver_opts[1] = strdup("dm.fs=ext4"); + driver_opts[2] = strdup("dm.min_free_space=10%"); + int driver_opts_len = 3; + + ASSERT_EQ(devmapper_init(&driver, nullptr, (const char **)driver_opts, driver_opts_len), -1); + + EXPECT_CALL(m_libdevmapper_mock, DMTaskCreate(_)).WillRepeatedly(Invoke(invokeDMTaskCreate)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskSetMessage(_, _)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskSetSector(_, _)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskSetAddNode(_, _)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskAddTarget(_, _, _, _, _)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskSetName(_, _)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskRun(_)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskDestroy(_)).WillRepeatedly(Invoke(invokeDMTaskDestroy)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskGetInfo(_, _)).WillRepeatedly(Invoke(invokeDMTaskGetInfo)); + EXPECT_CALL(m_libdevmapper_mock, DMGetNextTarget(_, _, _, _, _, _)).WillRepeatedly(Invoke(invokeDMGetNextTarget)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskSetCookie(_, _, _)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMUdevWait(_)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMUdevComplete(_)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskDeferredRemove(_)).WillRepeatedly(Return(1)); + + + char *names = static_cast(util_common_calloc_s(sizeof(struct dm_names) + strlen("isulad0-pool") + 1)); + struct dm_names *dname = (struct dm_names *)names; + dname->dev = 1; + dname->next = 0; + strcpy(names + sizeof(struct dm_names), "isulad0-pool"); + EXPECT_CALL(m_libdevmapper_mock, DMTaskGetNames(_)).WillOnce(Return(dname)); + EXPECT_CALL(m_libdevmapper_mock, DMSetDevDir(_)).WillOnce(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskGetDriverVersion(_, _, _)).WillOnce(Invoke(invokeDMTaskGetDriverVersion)); + EXPECT_CALL(m_libdevmapper_mock, DMUdevGetSyncSupport()).WillOnce(Return(1)); + + MOCK_SET_V(util_exec_cmd, invokeUtilExecCmd); + + ASSERT_EQ(devmapper_init(&driver, driver_home.c_str(), (const char **)driver_opts, driver_opts_len), 0); + MOCK_CLEAR(util_exec_cmd); + + util_free_array_by_len(driver_opts, driver_opts_len); + free(names); + } + + void TearDown() override + { + MockLibdevmapper_SetMock(nullptr); + std::string rm_command = "rm -rf /tmp/isulad/"; + ASSERT_EQ(system(rm_command.c_str()), 0); + } + + NiceMock m_libdevmapper_mock; + char data_path[PATH_MAX] = { 0x00 }; + graphdriver driver = {.ops = nullptr, .name = "devicemapper", }; +}; + +TEST_F(DriverDevmapperUnitTest, test_devmapper_layer_exists) +{ + std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; + std::string incorrectId { "eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8" }; + ASSERT_TRUE(devmapper_layer_exist(id.c_str(), &driver)); + ASSERT_FALSE(devmapper_layer_exist(incorrectId.c_str(), &driver)); +} + +TEST_F(DriverDevmapperUnitTest, test_devmapper_create_rw) +{ + std::string id { "eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8" }; + struct driver_create_opts *create_opts; + + create_opts = (struct driver_create_opts *)util_common_calloc_s(sizeof(struct driver_create_opts)); + ASSERT_NE(create_opts, nullptr); + + create_opts->storage_opt = static_cast(util_common_calloc_s(sizeof(json_map_string_string))); + ASSERT_NE(create_opts->storage_opt, nullptr); + create_opts->storage_opt->keys = static_cast(util_common_calloc_s(sizeof(char *))); + create_opts->storage_opt->values = static_cast(util_common_calloc_s(sizeof(char *))); + create_opts->storage_opt->keys[0] = strdup("size"); + create_opts->storage_opt->values[0] = strdup("10G"); + create_opts->storage_opt->len = 1; + + ASSERT_EQ(devmapper_create_rw(id.c_str(), nullptr, &driver, create_opts), 0); + ASSERT_TRUE(devmapper_layer_exist(id.c_str(), &driver)); +} + +TEST_F(DriverDevmapperUnitTest, test_devmapper_mount_layer) +{ + std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; + std::string merged_dir = "/tmp/isulad/data/devicemapper/mnt/" + id + "/rootfs"; + struct driver_mount_opts *mount_opts = nullptr; + char* mount_dir = nullptr; + + MOCK_SET(util_mount, 0); + mount_dir = devmapper_mount_layer(id.c_str(), &driver, mount_opts); + ASSERT_STREQ(mount_dir, merged_dir.c_str()); + MOCK_CLEAR(util_mount); + + MOCK_SET(umount2, 0); + ASSERT_EQ(devmapper_umount_layer(id.c_str(), &driver), 0); + MOCK_CLEAR(umount2); + free(mount_dir); + mount_dir = nullptr; + + mount_opts = static_cast(util_common_calloc_s(sizeof(struct driver_mount_opts))); + ASSERT_NE(mount_opts, nullptr); + mount_opts->options = static_cast(util_common_calloc_s(1 * sizeof(char *))); + mount_opts->options[0] = strdup("ro"); + mount_opts->options_len = 1; + + MOCK_SET(util_mount, 0); + mount_dir = devmapper_mount_layer(id.c_str(), &driver, mount_opts); + ASSERT_STREQ(mount_dir, merged_dir.c_str()); + MOCK_CLEAR(util_mount); + + MOCK_SET(umount2, 0); + ASSERT_EQ(devmapper_umount_layer(id.c_str(), &driver), 0); + MOCK_CLEAR(umount2); + free(mount_opts->mount_label); + util_free_array_by_len(mount_opts->options, mount_opts->options_len); + free(mount_opts); + free(mount_dir); +} + +TEST_F(DriverDevmapperUnitTest, test_devmapper_get_layer_metadata) +{ + std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; + json_map_string_string *map_info = static_cast(util_common_calloc_s(sizeof(json_map_string_string))); + + ASSERT_EQ(devmapper_get_layer_metadata(id.c_str(), &driver, map_info), 0); + ASSERT_EQ(map_info->len, 4); + ASSERT_STREQ(map_info->keys[0], "DeviceId"); + ASSERT_STREQ(map_info->values[0], "4"); + ASSERT_STREQ(map_info->keys[1], "DeviceSize"); + ASSERT_STREQ(map_info->values[1], "10737418240"); + ASSERT_STREQ(map_info->keys[2], "DeviceName"); + ASSERT_STREQ(map_info->keys[3], "MergedDir"); + ASSERT_STREQ(map_info->values[3], "/tmp/isulad/data/devicemapper/mnt/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f/rootfs"); + + free_json_map_string_string(map_info); +} + +TEST_F(DriverDevmapperUnitTest, test_devmapper_get_driver_status) +{ + struct graphdriver_status *status = static_cast(util_common_calloc_s(sizeof(struct graphdriver_status))); + + EXPECT_CALL(m_libdevmapper_mock, DMUdevGetSyncSupport()).WillOnce(Return(1)); + + ASSERT_EQ(devmapper_get_driver_status(&driver, status), 0); + ASSERT_STREQ(status->driver_name, "devicemapper"); + free(status->driver_name); + free(status->backing_fs); + free(status->status); + free(status); +} diff --git a/test/mocks/libdevmapper_mock.cc b/test/mocks/libdevmapper_mock.cc new file mode 100644 index 00000000..7d6c8024 --- /dev/null +++ b/test/mocks/libdevmapper_mock.cc @@ -0,0 +1,191 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: jikai + * Create: 2023-11-22 + * Description: provide lib device mapper mock + ******************************************************************************/ + +#include "libdevmapper_mock.h" + +namespace { +MockLibdevmapper *g_libdevmapper_mock = nullptr; +} + +void MockLibdevmapper_SetMock(MockLibdevmapper* mock) +{ + g_libdevmapper_mock = mock; +} + +struct dm_task *dm_task_create(int type) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskCreate(type); + } + return nullptr; +} + +int dm_task_set_message(struct dm_task *dmt, const char *msg) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskSetMessage(dmt, msg); + } + return 0; +} + +int dm_task_set_sector(struct dm_task *dmt, uint64_t sector) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskSetSector(dmt, sector); + } + return 0; +} + +int dm_task_set_add_node(struct dm_task *dmt, dm_add_node_t add_node) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskSetAddNode(dmt, add_node); + } + return 0; +} + +int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size, const char *ttype, const char *params) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskAddTarget(dmt, start, size, ttype, params); + } + return 0; +} + +int dm_set_dev_dir(const char *dir) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMSetDevDir(dir); + } + return 0; +} + +int dm_task_set_name(struct dm_task *dmt, const char *name) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskSetName(dmt, name); + } + return 0; +} + +int dm_task_run(struct dm_task *dmt) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskRun(dmt); + } + return 0; +} + +int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskGetDriverVersion(dmt, version, size); + } + return 0; +} + +void dm_task_destroy(struct dm_task *dmt) +{ + if (g_libdevmapper_mock != nullptr) { + g_libdevmapper_mock->DMTaskDestroy(dmt); + } +} + +int dm_get_library_version(char *version, size_t size) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMGetLibraryVersion(version, size); + } + return 0; +} + +int dm_task_get_info(struct dm_task *dmt, struct dm_info *info) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskGetInfo(dmt, info); + } + return 0; +} + +void *dm_get_next_target(struct dm_task *dmt, void *next, uint64_t *start, uint64_t *length, + char **target_type, char **params) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMGetNextTarget(dmt, next, start, length, target_type, params); + } + return nullptr; +} + +int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskSetCookie(dmt, cookie, flags); + } + return 0; +} + +int dm_udev_wait(uint32_t cookie) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMUdevWait(cookie); + } + return 0; +} + +int dm_udev_complete(uint32_t cookie) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMUdevComplete(cookie); + } + return 0; +} + +int dm_task_deferred_remove(struct dm_task *dmt) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskDeferredRemove(dmt); + } + return 0; +} + +struct dm_names *dm_task_get_names(struct dm_task *dmt) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMTaskGetNames(dmt); + } + return nullptr; +} + +int dm_udev_get_sync_support(void) +{ + if (g_libdevmapper_mock != nullptr) { + return g_libdevmapper_mock->DMUdevGetSyncSupport(); + } + return 0; +} + +void dm_udev_set_sync_support(int sync_with_udev) +{ + if (g_libdevmapper_mock != nullptr) { + g_libdevmapper_mock->DMUdevSetSyncSupport(sync_with_udev); + } +} + +void dm_log_with_errno_init(void log_cb(int level, const char *file, int line, int dm_errno_or_class, const char *f, ...)) +{ + if (g_libdevmapper_mock != nullptr) { + g_libdevmapper_mock->DMLogWithErrnoInit(log_cb); + } +} diff --git a/test/mocks/libdevmapper_mock.h b/test/mocks/libdevmapper_mock.h new file mode 100644 index 00000000..53c5ad4b --- /dev/null +++ b/test/mocks/libdevmapper_mock.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: jikai + * Create: 2023-11-22 + * Description: provide lib device mapper mock + ******************************************************************************/ + +#ifndef _ISULAD_TEST_MOCKS_DEVMAPPER_MOCK_H +#define _ISULAD_TEST_MOCKS_DEVMAPPER_MOCK_H + +#include + +#include + +class MockLibdevmapper { +public: + virtual ~MockLibdevmapper() = default; + MOCK_METHOD1(DMTaskCreate, struct dm_task*(int type)); + MOCK_METHOD2(DMTaskSetMessage, int(struct dm_task *dmt, const char *msg)); + MOCK_METHOD2(DMTaskSetSector, int(struct dm_task *dmt, uint64_t sector)); + MOCK_METHOD2(DMTaskSetAddNode, int(struct dm_task *dmt, dm_add_node_t add_node)); + MOCK_METHOD5(DMTaskAddTarget, int(struct dm_task *dmt, uint64_t start, uint64_t size, const char *ttype, const char *params)); + MOCK_METHOD1(DMSetDevDir, int(const char *dir)); + MOCK_METHOD2(DMTaskSetName, int(struct dm_task *dmt, const char *name)); + MOCK_METHOD1(DMTaskRun, int(struct dm_task *dmt)); + MOCK_METHOD3(DMTaskGetDriverVersion, int(struct dm_task *dmt, char *version, size_t size)); + MOCK_METHOD1(DMTaskDestroy, void(struct dm_task *dmt)); + MOCK_METHOD2(DMGetLibraryVersion, int(char *version, size_t size)); + MOCK_METHOD2(DMTaskGetInfo, int(struct dm_task *dmt, struct dm_info *info)); + MOCK_METHOD6(DMGetNextTarget, void*(struct dm_task *dmt, void *next, uint64_t *start, uint64_t *length, + char **target_type, char **params)); + MOCK_METHOD3(DMTaskSetCookie, int(struct dm_task *dmt, uint32_t *cookie, uint16_t flags)); + MOCK_METHOD1(DMUdevWait, int(uint32_t cookie)); + MOCK_METHOD1(DMUdevComplete, int(uint32_t cookie)); + MOCK_METHOD1(DMTaskDeferredRemove, int(struct dm_task *dmt)); + MOCK_METHOD1(DMTaskGetNames, struct dm_names *(struct dm_task *dmt)); + MOCK_METHOD0(DMUdevGetSyncSupport, int(void)); + MOCK_METHOD1(DMUdevSetSyncSupport, void(int sync_with_udev)); + MOCK_METHOD1(DMLogWithErrnoInit, void(void log_cb(int level, const char *file, int line, int dm_errno_or_class, const char *f, ...))); +}; + +void MockLibdevmapper_SetMock(MockLibdevmapper* mock); + +#endif -- 2.42.0