From 82dd5a1db70fdb3f4934a3f9c0ee290ce5bee1b2 Mon Sep 17 00:00:00 2001 From: jikai Date: Sat, 27 Jan 2024 15:30:05 +0800 Subject: [PATCH 09/43] improve dt for oci spec update Signed-off-by: jikai --- .../container_cases/dev_cgroup_rule.sh | 4 +- CI/test_cases/container_cases/ulimit.sh | 19 ++ test/specs/specs/CMakeLists.txt | 1 + test/specs/specs/specs_ut.cc | 168 ++++++++++++++++++ 4 files changed, 190 insertions(+), 2 deletions(-) diff --git a/CI/test_cases/container_cases/dev_cgroup_rule.sh b/CI/test_cases/container_cases/dev_cgroup_rule.sh index 5616d37a..33a839c5 100755 --- a/CI/test_cases/container_cases/dev_cgroup_rule.sh +++ b/CI/test_cases/container_cases/dev_cgroup_rule.sh @@ -60,13 +60,13 @@ function test_cpu_dev_cgoup_rule_spec() def_cid=$(isula run -tid --runtime $runtime -m 10m $image /bin/sh) [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - run container failed" && ((ret++)) cp $default_config $default_config_bak - sed -i '/"linux": {/a \ \t\t"devices": [\n\t\t{\n\t\t\t"type": "c",\n\t\t\t"path": "\/dev\/testABC",\n\t\t\t"major": 88,\n\t\t\t"minor": 88\n\t\t}\n\t\t],' $default_config + sed -i '/"linux": {/a \ \t\t"devices": [\n\t\t{\n\t\t\t"type": "c",\n\t\t\t"path": "\/dev\/testA",\n\t\t\t"major": 88,\n\t\t\t"minor": 88\n\t\t}\n\t\t],' $default_config stop_isulad_without_valgrind start_isulad_with_valgrind --cgroup-parent $test_cgroup_parent [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - start isulad failed" && ((ret++)) isula restart -t 0 $def_cid [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - restart container failed" && ((ret++)) - cat /sys/fs/cgroup/memory/$test_cgroup_parent/$def_cid/memory.limit_in_bytes | grep ^10485760$ + isula exec -it $def_cid sh -c "cat /sys/fs/cgroup/memory/memory.limit_in_bytes | grep ^10485760$" [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - --cgroup-parent cannot work" && ((ret++)) cnt=$(cat ${RUNTIME_ROOT_PATH}/${runtime}/$def_cid/config.json | grep "major\": 88" | wc -l) [[ $? -ne 0 ]]&& [[ $cnt -ne 2 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - check device major failed" && ((ret++)) diff --git a/CI/test_cases/container_cases/ulimit.sh b/CI/test_cases/container_cases/ulimit.sh index f823dc1c..41cdcece 100755 --- a/CI/test_cases/container_cases/ulimit.sh +++ b/CI/test_cases/container_cases/ulimit.sh @@ -49,9 +49,28 @@ function test_ulimit() [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - restart failed" && ((ret++)) cat ${RUNTIME_ROOT_PATH}/${runtime}/$cid/config.json | grep "RLIMIT_" [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - check rlimit failed after restart" && ((ret++)) + + check_valgrind_log + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - stop isulad failed" && ((ret++)) + + start_isulad_with_valgrind + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - start isulad failed" && ((ret++)) + + # if default ulimit of isulad changed, isula start should do update ulimit of oci spec + isula restart -t 0 $cid + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - restart failed" && ((ret++)) + cat ${RUNTIME_ROOT_PATH}/${runtime}/$cid/config.json | grep "RLIMIT_" + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - check rlimit failed after restart" && ((ret++)) + isula rm -f $cid [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - rm container failed" && ((ret++)) + check_valgrind_log + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - stop isulad failed" && ((ret++)) + + start_isulad_with_valgrind --default-ulimit nproc=2048:4096 --default-ulimit nproc=2048:8192 --default-ulimit nofile=1024:4096 + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - start isulad failed" && ((ret++)) + isula run --ulimit nproc= $image --runtime $runtime /bin/sh > $ulimitlog 2>&1 cat $ulimitlog | grep "delimiter '=' can't be the first or the last character" [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - check failed" && ((ret++)) diff --git a/test/specs/specs/CMakeLists.txt b/test/specs/specs/CMakeLists.txt index a9dbc52c..508123fa 100644 --- a/test/specs/specs/CMakeLists.txt +++ b/test/specs/specs/CMakeLists.txt @@ -84,6 +84,7 @@ target_include_directories(${EXE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks ) +set_target_properties(${EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,util_common_calloc_s -Wl,--wrap,util_smart_calloc_s -Wl,--wrap,get_readonly_default_oci_spec") target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) diff --git a/test/specs/specs/specs_ut.cc b/test/specs/specs/specs_ut.cc index ad903a3f..47e4ca6e 100644 --- a/test/specs/specs/specs_ut.cc +++ b/test/specs/specs/specs_ut.cc @@ -19,6 +19,7 @@ #include "mock.h" #include "isula_libutils/oci_runtime_spec.h" #include "specs_api.h" +#include "specs_mount.h" #include "specs_namespace.h" #include "specs_security.h" #include "isula_libutils/host_config.h" @@ -43,6 +44,46 @@ using ::testing::_; using namespace std; +static int g_malloc_count = 0; +static int g_malloc_match = 1; + +extern "C" { + DECLARE_WRAPPER_V(util_common_calloc_s, void *, (size_t size)); + DEFINE_WRAPPER_V(util_common_calloc_s, void *, (size_t size), (size)); + + DECLARE_WRAPPER_V(util_smart_calloc_s, void *, (size_t size, size_t len)); + DEFINE_WRAPPER_V(util_smart_calloc_s, void *, (size_t size, size_t len), (size, len)); + + DECLARE_WRAPPER(get_readonly_default_oci_spec, const oci_runtime_spec *, (bool system_container)); + DEFINE_WRAPPER(get_readonly_default_oci_spec, const oci_runtime_spec *, (bool system_container), (system_container)); +} + +void *util_common_calloc_s_fail(size_t size) +{ + g_malloc_count++; + + if (g_malloc_count == g_malloc_match) { + g_malloc_match++; + g_malloc_count = 0; + return nullptr; + } else { + return __real_util_common_calloc_s(size); + } +} + +void *util_smart_calloc_s_fail(size_t size, size_t len) +{ + g_malloc_count++; + + if (g_malloc_count == g_malloc_match) { + g_malloc_match++; + g_malloc_count = 0; + return nullptr; + } else { + return __real_util_smart_calloc_s(size, len); + } +} + class SpecsUnitTest : public testing::Test { public: void SetUp() override @@ -234,6 +275,32 @@ char *invoke_conf_get_isulad_cgroup_parent() return util_strdup_s("/var/lib/isulad/engines/lcr"); } +int invoke_conf_get_isulad_default_ulimit_empty(host_config_ulimits_element ***ulimit) +{ + if (ulimit == nullptr) { + return -1; + } + return 0; +} + +int invoke_conf_get_isulad_default_ulimit(host_config_ulimits_element ***ulimit) +{ + if (ulimit == nullptr) { + return -1; + } + host_config_ulimits_element *ele = static_cast(util_common_calloc_s(sizeof(host_config_ulimits_element))); + if (ele == nullptr) { + return -1; + } + ele->hard = 8192; + ele->soft = 2048; + ele->name = util_strdup_s("NPROC"); + + int ret = ulimit_array_append(ulimit, ele, ulimit_array_len(*ulimit)); + free_host_config_ulimits_element(ele); + return ret; +} + TEST_F(SpecsUnitTest, test_merge_container_cgroups_path_1) { ASSERT_EQ(merge_container_cgroups_path(nullptr, nullptr), nullptr); @@ -347,6 +414,107 @@ TEST_F(SpecsUnitTest, test_merge_container_cgroups_path_5) testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); } +TEST_F(SpecsUnitTest, test_update_oci_container_cgroups_path) +{ + parser_error err = nullptr; + host_config *hostspec = static_cast(util_common_calloc_s(sizeof(host_config))); + ASSERT_NE(hostspec, nullptr); + + oci_runtime_spec *ocispec = oci_runtime_spec_parse_data("{\"ociVersion\": \"1.0.1\", \"linux\": \ + {} }", nullptr, &err); + ASSERT_NE(ocispec, nullptr); + + ocispec->linux->cgroups_path = util_strdup_s("/isulad"); + ASSERT_EQ(update_oci_container_cgroups_path("abcdef", nullptr, nullptr), -1); + EXPECT_CALL(m_isulad_conf, GetCgroupParent()).WillRepeatedly(Invoke(invoke_conf_get_isulad_cgroup_parent)); + ASSERT_EQ(update_oci_container_cgroups_path("abcdef", ocispec, hostspec), 0); + ASSERT_STREQ(ocispec->linux->cgroups_path, "/var/lib/isulad/engines/lcr/abcdef"); + + free(err); + free_host_config(hostspec); + free_oci_runtime_spec(ocispec); + + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(SpecsUnitTest, test_update_oci_ulimit) +{ + parser_error err = nullptr; + host_config *hostspec = static_cast(util_common_calloc_s(sizeof(host_config))); + ASSERT_NE(hostspec, nullptr); + + char *oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); + ASSERT_TRUE(oci_config_file != nullptr); + oci_runtime_spec *ocispec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); + ASSERT_NE(ocispec, nullptr); + + ASSERT_EQ(update_oci_ulimit(nullptr, nullptr), -1); + EXPECT_CALL(m_isulad_conf, GetUlimit(_)).WillRepeatedly(Invoke(invoke_conf_get_isulad_default_ulimit)); + ASSERT_EQ(update_oci_ulimit(ocispec, hostspec), 0); + ASSERT_EQ(ocispec->process->rlimits_len, 1); + ASSERT_EQ(ocispec->process->rlimits[0]->hard, 8192); + ASSERT_EQ(ocispec->process->rlimits[0]->soft, 2048); + ASSERT_STREQ(ocispec->process->rlimits[0]->type, "RLIMIT_NPROC"); + EXPECT_CALL(m_isulad_conf, GetUlimit(_)).WillRepeatedly(Invoke(invoke_conf_get_isulad_default_ulimit_empty)); + ASSERT_EQ(update_oci_ulimit(ocispec, hostspec), 0); + ASSERT_EQ(ocispec->process->rlimits_len, 0); + + free(err); + free(oci_config_file); + free_host_config(hostspec); + free_oci_runtime_spec(ocispec); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(SpecsUnitTest, test_update_devcies_for_oci_spec) +{ + parser_error err = nullptr; + oci_runtime_spec *readonly_spec = oci_runtime_spec_parse_data("{\"ociVersion\": \"1.0.1\", \"linux\": \ + { \"devices\": \ + [ { \"type\": \"c\", \"path\": \"/dev/testA\", \ + \"fileMode\": 8612, \"major\": 99, \"minor\": 99} ], \ + \"resources\": { \"devices\": [ { \"allow\": false, \ + \"type\": \"a\", \"major\": -1, \ + \"minor\": -1, \"access\": \"rwm\" } ] } } }", nullptr, &err); + ASSERT_NE(readonly_spec, nullptr); + free(err); + err = nullptr; + host_config *hostspec = static_cast(util_common_calloc_s(sizeof(host_config))); + ASSERT_NE(hostspec, nullptr); + + oci_runtime_spec *ocispec = oci_runtime_spec_parse_data("{\"ociVersion\": \"1.0.1\", \"linux\": \ + { \"devices\": [ ], \ + \"resources\": { \"devices\": [ ] } } }", nullptr, &err); + ASSERT_NE(ocispec, nullptr); + + MOCK_SET(get_readonly_default_oci_spec, readonly_spec); + MOCK_SET_V(util_smart_calloc_s, util_smart_calloc_s_fail); + MOCK_SET_V(util_common_calloc_s, util_common_calloc_s_fail); + + ASSERT_EQ(update_devcies_for_oci_spec(ocispec, hostspec), -1); + ASSERT_EQ(update_devcies_for_oci_spec(ocispec, hostspec), -1); + ASSERT_EQ(update_devcies_for_oci_spec(ocispec, hostspec), -1); + free(ocispec->linux->devices[0]); + free(ocispec->linux->devices); + ocispec->linux->devices = NULL; + ocispec->linux->devices_len = 0; + ASSERT_EQ(update_devcies_for_oci_spec(ocispec, hostspec), -1); + free(ocispec->linux->devices[0]); + free(ocispec->linux->devices); + ocispec->linux->devices = NULL; + ocispec->linux->devices_len = 0; + ASSERT_EQ(update_devcies_for_oci_spec(ocispec, hostspec), 0); + + MOCK_CLEAR(get_readonly_default_oci_spec); + MOCK_CLEAR(util_smart_calloc_s); + MOCK_CLEAR(util_common_calloc_s); + + free_oci_runtime_spec(readonly_spec); + free_oci_runtime_spec(ocispec); + free_host_config(hostspec); + free(err); +} + /********************************* UT for merge caps *******************************************/ struct capabilities_lens { size_t bounding_len; -- 2.34.1