// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include "util/cgroup_util.h" #include #include #include #include #include "common/cgroup_memory_ctl.h" #include "gtest/gtest_pred_impl.h" #include "testutil/test_util.h" #include "util/cgroup_util.h" namespace doris { class CGroupUtilTest : public ::testing::Test { protected: CGroupUtilTest() {} ~CGroupUtilTest() override = default; }; TEST_F(CGroupUtilTest, ReadMetrics) { std::string dir_path = GetCurrentRunningDir(); std::string memory_limit_in_bytes_path(dir_path); memory_limit_in_bytes_path += "/util/test_data/memory.limit_in_bytes"; int64_t value; auto st = CGroupUtil::read_int_line_from_cgroup_file(memory_limit_in_bytes_path, &value); EXPECT_TRUE(st.ok()); EXPECT_EQ(6291456000, value); std::string memory_stat_path(dir_path); memory_stat_path += "/util/test_data/memory.stat"; std::unordered_map metrics_map; CGroupUtil::read_int_metric_from_cgroup_file(memory_stat_path, metrics_map); EXPECT_EQ(5443584, metrics_map["inactive_file"]); EXPECT_EQ(0, metrics_map["rss"]); std::string error_memory_limit_in_bytes_path(dir_path); error_memory_limit_in_bytes_path += "/util/test_data/Zzz/memory.limit_in_bytes"; int64_t error_value; auto st2 = CGroupUtil::read_int_line_from_cgroup_file(error_memory_limit_in_bytes_path, &error_value); EXPECT_FALSE(st2.ok()); std::string error_memory_stat_path(dir_path); error_memory_stat_path += "/util/test_data/Zzz/memory.stat"; std::unordered_map error_metrics_map; CGroupUtil::read_int_metric_from_cgroup_file(error_memory_stat_path, error_metrics_map); EXPECT_TRUE(error_metrics_map.empty()); } TEST_F(CGroupUtilTest, memlimit) { LOG(INFO) << CGroupMemoryCtl::debug_string(); int64_t mem_limit; int64_t mem_usage; auto status1 = CGroupMemoryCtl::find_cgroup_mem_limit(&mem_limit); auto status2 = CGroupMemoryCtl::find_cgroup_mem_usage(&mem_usage); if (CGroupUtil::cgroupsv1_enable() || CGroupUtil::cgroupsv2_enable()) { std::ifstream file("/proc/self/cgroup"); if (file.peek() == std::ifstream::traits_type::eof()) { EXPECT_FALSE(status1.ok()); EXPECT_FALSE(status2.ok()); } else { EXPECT_TRUE(status1.ok()); EXPECT_TRUE(status2.ok()); } } else { EXPECT_FALSE(status1.ok()); EXPECT_FALSE(status2.ok()); } } TEST_F(CGroupUtilTest, readcpu) { std::string dir_path = GetCurrentRunningDir(); std::string cpuset_1_path(dir_path + "/util/test_data/cgroup_cpu_data/cpuset1"); std::string cpuset_1_str = ""; Status ret1 = CGroupUtil::read_string_line_from_cgroup_file(cpuset_1_path, &cpuset_1_str); EXPECT_TRUE(ret1.ok()); int cpu_count1 = 0; static_cast(CGroupUtil::parse_cpuset_line(cpuset_1_str, &cpu_count1)); EXPECT_TRUE(cpu_count1 == 3); std::string cpuset_2_path(dir_path + "/util/test_data/cgroup_cpu_data/cpuset2"); std::string cpuset_2_str = ""; Status ret2 = CGroupUtil::read_string_line_from_cgroup_file(cpuset_2_path, &cpuset_2_str); EXPECT_TRUE(ret2.ok()); int cpu_count2 = 0; static_cast(CGroupUtil::parse_cpuset_line(cpuset_2_str, &cpu_count2)); EXPECT_TRUE(cpu_count2 == 11); std::string cpuset_3_path(dir_path + "/util/test_data/cgroup_cpu_data/cpuset3"); std::string cpuset_3_str = ""; Status ret3 = CGroupUtil::read_string_line_from_cgroup_file(cpuset_3_path, &cpuset_3_str); EXPECT_TRUE(ret3.ok()); int cpu_count3 = 0; static_cast(CGroupUtil::parse_cpuset_line(cpuset_3_str, &cpu_count3)); EXPECT_TRUE(cpu_count3 == 10); int ret = CGroupUtil::get_cgroup_limited_cpu_number(16); EXPECT_TRUE(ret > 0); // 1 read cgroup v2 quota // 1.1 read default value std::filesystem::path path11 = dir_path + "/util/test_data/cgroup_cpu_data/test11/child"; std::filesystem::path default_path_11 = dir_path + "/util/test_data/cgroup_cpu_data/test11"; int ret11 = CGroupUtil::get_cgroup_v2_cpu_quota_number(path11, default_path_11, 96); EXPECT_TRUE(ret11 == 96); // 1.2 read from child to parent std::filesystem::path path12 = dir_path + "/util/test_data/cgroup_cpu_data/test12/child"; std::filesystem::path default_path_12 = dir_path + "/util/test_data/cgroup_cpu_data/test12"; int ret12 = CGroupUtil::get_cgroup_v2_cpu_quota_number(path12, default_path_12, 96); EXPECT_TRUE(ret12 == 2); // 1.3 read parent std::filesystem::path path13 = dir_path + "/util/test_data/cgroup_cpu_data/test13/child"; std::filesystem::path default_path_13 = dir_path + "/util/test_data/cgroup_cpu_data/test13"; int ret13 = CGroupUtil::get_cgroup_v2_cpu_quota_number(path13, default_path_13, 96); EXPECT_TRUE(ret13 == 2); // 1.4 read child std::filesystem::path path14 = dir_path + "/util/test_data/cgroup_cpu_data/test14/child"; std::filesystem::path default_path_14 = dir_path + "/util/test_data/cgroup_cpu_data/test14"; int ret14 = CGroupUtil::get_cgroup_v2_cpu_quota_number(path14, default_path_14, 96); EXPECT_TRUE(ret14 == 3); // 2 read cgroup v2 cpuset // 2.1 read child std::filesystem::path path21 = dir_path + "/util/test_data/cgroup_cpu_data/test21/child"; std::filesystem::path default_path_21 = dir_path + "/util/test_data/cgroup_cpu_data/test21"; int ret21 = CGroupUtil::get_cgroup_v2_cpuset_number(path21, default_path_21, 96); EXPECT_TRUE(ret21 == 2); // 2.2 read parent std::filesystem::path path22 = dir_path + "/util/test_data/cgroup_cpu_data/test22/child"; std::filesystem::path default_path_22 = dir_path + "/util/test_data/cgroup_cpu_data/test22"; int ret22 = CGroupUtil::get_cgroup_v2_cpuset_number(path22, default_path_22, 96); EXPECT_TRUE(ret22 == 7); // 3 read cgroup v1 quota // 3.1 read child std::filesystem::path path31 = dir_path + "/util/test_data/cgroup_cpu_data/test31/child"; std::filesystem::path default_path_31 = dir_path + "/util/test_data/cgroup_cpu_data/test31"; int ret31 = CGroupUtil::get_cgroup_v1_cpu_quota_number(path31, default_path_31, 96); EXPECT_TRUE(ret31 == 5); // 3.2 read parent std::filesystem::path path32 = dir_path + "/util/test_data/cgroup_cpu_data/test32/child"; std::filesystem::path default_path_32 = dir_path + "/util/test_data/cgroup_cpu_data/test32"; int ret32 = CGroupUtil::get_cgroup_v1_cpu_quota_number(path32, default_path_32, 96); EXPECT_TRUE(ret32 == 6); // 3.3 read default std::filesystem::path path33 = dir_path + "/util/test_data/cgroup_cpu_data/test33/child"; std::filesystem::path default_path_33 = dir_path + "/util/test_data/cgroup_cpu_data/test33"; int ret33 = CGroupUtil::get_cgroup_v1_cpu_quota_number(path33, default_path_33, 96); EXPECT_TRUE(ret33 == 96); // 4 read cgroup v1 cpuset std::filesystem::path path41 = dir_path + "/util/test_data/cgroup_cpu_data/test41"; int ret41 = CGroupUtil::get_cgroup_v1_cpuset_number(path41, 96); EXPECT_TRUE(ret41 == 3); } } // namespace doris