summaryrefslogtreecommitdiff
path: root/0032-add-ut-for-devicemapper.patch
diff options
context:
space:
mode:
Diffstat (limited to '0032-add-ut-for-devicemapper.patch')
-rw-r--r--0032-add-ut-for-devicemapper.patch737
1 files changed, 737 insertions, 0 deletions
diff --git a/0032-add-ut-for-devicemapper.patch b/0032-add-ut-for-devicemapper.patch
new file mode 100644
index 0000000..e28c5fa
--- /dev/null
+++ b/0032-add-ut-for-devicemapper.patch
@@ -0,0 +1,737 @@
+From ca297d26dc1e7b47d6987c6bbbd92dd2e3d78670 Mon Sep 17 00:00:00 2001
+From: jikai <jikai11@huawei.com>
+Date: Wed, 22 Nov 2023 22:05:04 +0800
+Subject: [PATCH 32/64] add ut for devicemapper
+
+Signed-off-by: jikai <jikai11@huawei.com>
+---
+ 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 <gtest/gtest.h>
++#include <gmock/gmock.h>
++
++#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<size_t>(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<std::string>(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<char **>(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<struct dm_task *>(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<char **>(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<char *>(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<MockLibdevmapper> 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<json_map_string_string *>(util_common_calloc_s(sizeof(json_map_string_string)));
++ ASSERT_NE(create_opts->storage_opt, nullptr);
++ create_opts->storage_opt->keys = static_cast<char **>(util_common_calloc_s(sizeof(char *)));
++ create_opts->storage_opt->values = static_cast<char **>(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<struct driver_mount_opts *>(util_common_calloc_s(sizeof(struct driver_mount_opts)));
++ ASSERT_NE(mount_opts, nullptr);
++ mount_opts->options = static_cast<char **>(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<json_map_string_string *>(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<struct graphdriver_status *>(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 <gmock/gmock.h>
++
++#include <libdevmapper.h>
++
++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
+