From 2ad7ecf5adbd75f1ba4678e69d768d4b807ae08d Mon Sep 17 00:00:00 2001 From: jikai Date: Wed, 29 Nov 2023 17:08:31 +0800 Subject: [PATCH 45/64] improve ut for devicemapper Signed-off-by: jikai --- .../storage/layers/devmapper/CMakeLists.txt | 8 +- .../id | 1 + .../layers/devmapper/driver_devmapper_ut.cc | 209 +++++++++++++----- 3 files changed, 165 insertions(+), 53 deletions(-) create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/mnt/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d/id diff --git a/test/image/oci/storage/layers/devmapper/CMakeLists.txt b/test/image/oci/storage/layers/devmapper/CMakeLists.txt index f98de1a8..e6ba0307 100644 --- a/test/image/oci/storage/layers/devmapper/CMakeLists.txt +++ b/test/image/oci/storage/layers/devmapper/CMakeLists.txt @@ -23,14 +23,18 @@ add_executable(${DRIVER_DEVMAPPER_EXE} ${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/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 @@ -56,7 +60,7 @@ target_include_directories(${DRIVER_DEVMAPPER_EXE} PUBLIC ${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") +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} 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 index 59e53f97..088aa4d4 100644 --- a/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc +++ b/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc @@ -16,11 +16,16 @@ #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; @@ -29,13 +34,20 @@ 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)); + 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() @@ -118,6 +130,7 @@ 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"; @@ -129,13 +142,18 @@ protected: 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); + 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)); @@ -152,7 +170,6 @@ protected: 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; @@ -164,32 +181,76 @@ protected: 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_SET(util_mount, 0); + MOCK_SET(umount2, 0); + ASSERT_EQ(graphdriver_init(opts), 0); MOCK_CLEAR(util_exec_cmd); - - util_free_array_by_len(driver_opts, driver_opts_len); - free(names); + 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 }; - graphdriver driver = {.ops = nullptr, .name = "devicemapper", }; + 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(devmapper_layer_exist(id.c_str(), &driver)); - ASSERT_FALSE(devmapper_layer_exist(incorrectId.c_str(), &driver)); + ASSERT_TRUE(graphdriver_layer_exists(id.c_str())); + ASSERT_FALSE(graphdriver_layer_exists(incorrectId.c_str())); } TEST_F(DriverDevmapperUnitTest, test_devmapper_create_rw) @@ -205,11 +266,42 @@ TEST_F(DriverDevmapperUnitTest, test_devmapper_create_rw) 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->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(devmapper_create_rw(id.c_str(), nullptr, &driver, create_opts), 0); - ASSERT_TRUE(devmapper_layer_exist(id.c_str(), &driver)); + 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) @@ -220,12 +312,12 @@ TEST_F(DriverDevmapperUnitTest, test_devmapper_mount_layer) char* mount_dir = nullptr; MOCK_SET(util_mount, 0); - mount_dir = devmapper_mount_layer(id.c_str(), &driver, mount_opts); + 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(devmapper_umount_layer(id.c_str(), &driver), 0); + ASSERT_EQ(graphdriver_umount_layer(id.c_str()), 0); MOCK_CLEAR(umount2); free(mount_dir); mount_dir = nullptr; @@ -237,47 +329,62 @@ TEST_F(DriverDevmapperUnitTest, test_devmapper_mount_layer) mount_opts->options_len = 1; MOCK_SET(util_mount, 0); - mount_dir = devmapper_mount_layer(id.c_str(), &driver, mount_opts); + 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(devmapper_umount_layer(id.c_str(), &driver), 0); + ASSERT_EQ(graphdriver_umount_layer(id.c_str()), 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); + free_driver_mount_opts(mount_opts); } -TEST_F(DriverDevmapperUnitTest, test_devmapper_get_layer_metadata) +TEST_F(DriverDevmapperUnitTest, test_devmapper_get_data) { 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))); + 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)); - ASSERT_EQ(devmapper_get_driver_status(&driver, status), 0); + struct graphdriver_status *status = graphdriver_get_status(); + ASSERT_NE(status, nullptr); ASSERT_STREQ(status->driver_name, "devicemapper"); - free(status->driver_name); - free(status->backing_fs); - free(status->status); - free(status); + 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 -- 2.42.0