From f986c26c22c5c23f34da4d5189221719fd13b220 Mon Sep 17 00:00:00 2001 From: jikai Date: Wed, 22 Nov 2023 22:05:04 +0800 Subject: [PATCH 172/181] add ut for devicemapper Signed-off-by: jikai --- test/image/oci/storage/layers/CMakeLists.txt | 2 + .../storage/layers/devmapper/CMakeLists.txt | 75 ++++ ...9702e4bd316dd50ae85467b0378a419b23b60ba73d | 6 + ...a9fb83febf6dc0b1548dfe896161533668281c9f4f | 6 + ...0a625721fdbea5c94ca6da897acdd814d710149770 | 6 + .../devmapper/data/devicemapper/metadata/base | 7 + .../devicemapper/metadata/deviceset-metadata | 5 + .../metadata/transaction-metadata | 5 + .../id | 1 + .../layers/devmapper/driver_devmapper_ut.cc | 390 ++++++++++++++++++ test/mocks/libdevmapper_mock.cc | 191 +++++++++ test/mocks/libdevmapper_mock.h | 52 +++ 12 files changed, 746 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/data/devicemapper/mnt/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d/id 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 330a8306..df1ef7d3 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..e6ba0307 --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/CMakeLists.txt @@ -0,0 +1,75 @@ +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/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/driver.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}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/remote_layer_support/ro_symlink_maintain.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/quota/project_quota.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../mocks/libdevmapper_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../mocks/isulad_config_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 -Wl,--wrap,archive_unpack") + +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/data/devicemapper/mnt/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d/id b/test/image/oci/storage/layers/devmapper/data/devicemapper/mnt/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d/id new file mode 100644 index 00000000..5e6b1b2a --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/mnt/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d/id @@ -0,0 +1 @@ +3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f \ No newline at end of file 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..088aa4d4 --- /dev/null +++ b/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc @@ -0,0 +1,390 @@ +/****************************************************************************** + * 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.h" +#include "driver_devmapper.h" +#include "driver_overlay2.h" +#include "mock.h" +#include "path.h" +#include "utils.h" +#include "util_archive.h" +#include "libdevmapper_mock.h" +#include "isulad_config_mock.h" +#include "wrapper_devmapper.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)); + + DECLARE_WRAPPER(archive_unpack, int, (const io_read_wrapper *content, const char *dstdir, const archive_options *options, + const char *root_dir, char **errmsg)); + DEFINE_WRAPPER(archive_unpack, int, (const io_read_wrapper *content, const char *dstdir, const archive_options *options, + const char *root_dir, char **errmsg), + (content, dstdir, options, root_dir, errmsg)); +} + +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); + MockIsuladConf_SetMock(&m_isulad_conf_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); + + opts = (struct storage_module_init_options *)util_common_calloc_s(sizeof(struct storage_module_init_options)); + opts->storage_root = strdup(root_dir.c_str()); + opts->storage_run_root = strdup(run_dir.c_str()); + opts->driver_name = strdup("devicemapper"); + opts->driver_opts = (char **)util_common_calloc_s(6 * sizeof(char *)); + opts->driver_opts[0] = strdup("dm.thinpooldev=/dev/mapper/isulad0-thinpool"); + opts->driver_opts[1] = strdup("dm.fs=ext4"); + opts->driver_opts[2] = strdup("dm.min_free_space=10%"); + opts->driver_opts[3] = strdup("dm.basesize=12G"); + opts->driver_opts[4] = strdup("dm.mkfsarg=-q"); + opts->driver_opts[5] = strdup("dm.mountopt=rw"); + opts->driver_opts_len = 6; + + 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); + MOCK_SET(util_mount, 0); + MOCK_SET(umount2, 0); + ASSERT_EQ(graphdriver_init(opts), 0); + MOCK_CLEAR(util_exec_cmd); + MOCK_CLEAR(util_mount); + MOCK_CLEAR(umount2); + } + + void TearDown() override + { + MOCK_SET(umount2, 0); + ASSERT_EQ(graphdriver_cleanup(), 0); + MOCK_CLEAR(umount2); + + MockLibdevmapper_SetMock(nullptr); + MockIsuladConf_SetMock(nullptr); + std::string rm_command = "rm -rf /tmp/isulad/"; + ASSERT_EQ(system(rm_command.c_str()), 0); + + if (opts != NULL) { + free(opts->storage_root); + free(opts->storage_run_root); + free(opts->driver_name); + util_free_array_by_len(opts->driver_opts, opts->driver_opts_len); + free(opts); + } + } + + NiceMock m_libdevmapper_mock; + NiceMock m_isulad_conf_mock; + char data_path[PATH_MAX] = { 0x00 }; + struct storage_module_init_options *opts = NULL; +}; + +TEST_F(DriverDevmapperUnitTest, test_devmapper_init) +{ + // cleanup before + MOCK_SET(umount2, 0); + ASSERT_EQ(graphdriver_cleanup(), 0); + MOCK_CLEAR(umount2); + + std::string rm_command = "rm -rf /tmp/isulad/"; + ASSERT_EQ(system(rm_command.c_str()), 0); + std::string mk_command = "mkdir -p /tmp/isulad/data/devicemapper/mnt"; + ASSERT_EQ(system(mk_command.c_str()), 0); + 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); + MOCK_SET(util_mount, 0); + MOCK_SET(umount2, 0); + ASSERT_EQ(graphdriver_init(opts), 0); + MOCK_CLEAR(util_exec_cmd); + MOCK_CLEAR(util_mount); + MOCK_CLEAR(umount2); +} + +TEST_F(DriverDevmapperUnitTest, test_devmapper_layer_exists) +{ + std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; + std::string incorrectId { "eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8" }; + ASSERT_TRUE(graphdriver_layer_exists(id.c_str())); + ASSERT_FALSE(graphdriver_layer_exists(incorrectId.c_str())); +} + +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("12G"); + create_opts->storage_opt->len = 1; + + ASSERT_EQ(graphdriver_create_rw(id.c_str(), nullptr, create_opts), 0); + ASSERT_TRUE(graphdriver_layer_exists(id.c_str())); + free_driver_create_opts(create_opts); +} + +TEST_F(DriverDevmapperUnitTest, test_devmapper_create_ro) +{ + 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("12G"); + create_opts->storage_opt->len = 1; + + ASSERT_EQ(graphdriver_create_ro(id.c_str(), nullptr, create_opts), 0); + ASSERT_TRUE(graphdriver_layer_exists(id.c_str())); + free_driver_create_opts(create_opts); +} + +TEST_F(DriverDevmapperUnitTest, test_devmapper_rm_layer) +{ + std::string existed_id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; + std::string not_existed_id { "eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8" }; + + ASSERT_EQ(graphdriver_rm_layer(existed_id.c_str()), 0); + ASSERT_EQ(graphdriver_rm_layer(not_existed_id.c_str()), 0); +} + +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 = graphdriver_mount_layer(id.c_str(), mount_opts); + ASSERT_STREQ(mount_dir, merged_dir.c_str()); + MOCK_CLEAR(util_mount); + + MOCK_SET(umount2, 0); + ASSERT_EQ(graphdriver_umount_layer(id.c_str()), 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 = graphdriver_mount_layer(id.c_str(), mount_opts); + ASSERT_STREQ(mount_dir, merged_dir.c_str()); + MOCK_CLEAR(util_mount); + + MOCK_SET(umount2, 0); + ASSERT_EQ(graphdriver_umount_layer(id.c_str()), 0); + MOCK_CLEAR(umount2); + free_driver_mount_opts(mount_opts); +} + +TEST_F(DriverDevmapperUnitTest, test_devmapper_get_data) +{ + std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; + + container_inspect_graph_driver *inspect = graphdriver_get_metadata(id.c_str()); + ASSERT_NE(inspect, nullptr); + ASSERT_STREQ(inspect->data->device_id, "4"); + ASSERT_STREQ(inspect->data->device_size, "10737418240"); + ASSERT_STREQ(inspect->data->merged_dir, "/tmp/isulad/data/devicemapper/mnt/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f/rootfs"); + free_container_inspect_graph_driver(inspect); + + EXPECT_CALL(m_libdevmapper_mock, DMUdevGetSyncSupport()).WillOnce(Return(1)); + + struct graphdriver_status *status = graphdriver_get_status(); + ASSERT_NE(status, nullptr); + ASSERT_STREQ(status->driver_name, "devicemapper"); + free_graphdriver_status(status); + + ASSERT_EQ(devmapper_repair_lowers(nullptr, nullptr, nullptr), 0); + ASSERT_EQ(devmapper_get_layer_fs_info(nullptr, nullptr, nullptr), 0); +} + +TEST_F(DriverDevmapperUnitTest, test_devmapper_apply_diff) +{ + struct io_read_wrapper reader = {0}; + std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; + MOCK_SET(util_mount, 0); + MOCK_SET(archive_unpack, 0); + MOCK_SET(umount2, 0); + EXPECT_CALL(m_isulad_conf_mock, ConfGetISuladRootDir()).WillOnce(Return(util_strdup_s("/tmp/isulad"))); + ASSERT_EQ(graphdriver_apply_diff(id.c_str(), &reader), 0); + MOCK_CLEAR(archive_unpack); + MOCK_CLEAR(util_mount); + MOCK_CLEAR(umount2); +} + +TEST_F(DriverDevmapperUnitTest, test_wrapper_devmapper) +{ + ASSERT_STREQ(dev_strerror(ERR_TASK_RUN), "Task run error"); + ASSERT_STREQ(dev_strerror(ERR_TASK_SET_COOKIE), "Task set cookie error"); + ASSERT_STREQ(dev_strerror(ERR_NIL_COOKIE), "cookie ptr can't be nil"); + ASSERT_STREQ(dev_strerror(ERR_TASK_SET_ADD_NODE), "Task add dm node failed"); + ASSERT_STREQ(dev_strerror(ERR_BUSY), "Device busy"); + ASSERT_STREQ(dev_strerror(ERR_DEVICE_ID_EXISTS), "Device exists already"); + ASSERT_STREQ(dev_strerror(ERR_ENXIO), "No such device of address"); + ASSERT_STREQ(dev_strerror(ERR_TASK_ADD_TARGET), "Task add target device error"); + ASSERT_STREQ(dev_strerror(ERR_TASK_DEFERRED_REMOVE), "dm_task_deferred_remove failed"); + ASSERT_STREQ(dev_strerror(100), "Unknown error"); +} \ No newline at end of file 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