The following tests are in this commit: NotAnIgnore() - Test that non-ignore rules are not processed
SimpleMatch() - Test that an ignore rule with a matching cgroup and controller match CgroupsDontMatch() - Test that cgroups with similar but not matching names do not match ControllersDontMatch() - Test that controllers with non-matching names do not match CombinedControllers() - Test that controllers that have been mounted on the same path, e.g. cpu,cpuacct, can be matched by a rule MatchChildFolder() - Compares a rule with a single-level hierarchy with a rule that matches that hierarchy MatchGrandchildFolder() - Compares a rule with a multi-level hierarchy with a process that matches that hierachy MatchSimilarChildFolder() - Compares a child folder that is similar to the rule. This mimics a misconfiguration that a user could make RealWorldMatch() - Test that a realistic cgroup proc file matches a new process RealWorldNoMatch() - Test that a realistic cgroup proc file will not match a new process SimilarFolderNoMatch() - Compares a rule with a folder name that is similar to the process' cgroup, but not a match RootDestinationMatch() - Compares a rule with the root as the destination and a process also running in the root cgroup RootDestinationNoMatch() - Compares a rule with the root as the destination and a process in another cgroup folder The results from googletest are reported below: [----------] 13 tests from CgroupCompareIgnoreRuleTest [ RUN ] CgroupCompareIgnoreRuleTest.NotAnIgnore [ OK ] CgroupCompareIgnoreRuleTest.NotAnIgnore (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.SimpleMatch [ OK ] CgroupCompareIgnoreRuleTest.SimpleMatch (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.CgroupsDontMatch [ OK ] CgroupCompareIgnoreRuleTest.CgroupsDontMatch (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.ControllersDontMatch [ OK ] CgroupCompareIgnoreRuleTest.ControllersDontMatch (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.CombinedControllers [ OK ] CgroupCompareIgnoreRuleTest.CombinedControllers (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.MatchChildFolder [ OK ] CgroupCompareIgnoreRuleTest.MatchChildFolder (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.MatchGrandchildFolder [ OK ] CgroupCompareIgnoreRuleTest.MatchGrandchildFolder (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.MatchSimilarChildFolder [ OK ] CgroupCompareIgnoreRuleTest.MatchSimilarChildFolder (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.RealWorldMatch [ OK ] CgroupCompareIgnoreRuleTest.RealWorldMatch (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.RealWorldNoMatch [ OK ] CgroupCompareIgnoreRuleTest.RealWorldNoMatch (1 ms) [ RUN ] CgroupCompareIgnoreRuleTest.SimilarFolderNoMatch [ OK ] CgroupCompareIgnoreRuleTest.SimilarFolderNoMatch (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.RootDestinationMatch [ OK ] CgroupCompareIgnoreRuleTest.RootDestinationMatch (0 ms) [ RUN ] CgroupCompareIgnoreRuleTest.RootDestinationNoMatch [ OK ] CgroupCompareIgnoreRuleTest.RootDestinationNoMatch (0 ms) [----------] 13 tests from CgroupCompareIgnoreRuleTest (3 ms total) Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com> --- src/api.c | 2 +- src/libcgroup-internal.h | 3 + tests/gunit/004-cgroup_compare_ignore_rule.cpp | 340 +++++++++++++++++++++++++ tests/gunit/Makefile.am | 3 +- 4 files changed, 346 insertions(+), 2 deletions(-) create mode 100644 tests/gunit/004-cgroup_compare_ignore_rule.cpp diff --git a/src/api.c b/src/api.c index 0cdd2a8c316f..3fbe1ed28e2f 100644 --- a/src/api.c +++ b/src/api.c @@ -2879,7 +2879,7 @@ static int cgroup_find_matching_controller(char * const *rule_controllers, * @return True if the rule is an ignore rule and this pid/procname * match the rule. False otherwise */ -static bool cgroup_compare_ignore_rule(const struct cgroup_rule * const rule, +STATIC bool cgroup_compare_ignore_rule(const struct cgroup_rule * const rule, pid_t pid, const char * const procname) { char *controller_list[MAX_MNT_ELEMENTS] = { '\0' }; diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index efe9b36fe052..c827fea28d35 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -303,6 +303,9 @@ int cg_get_cgroups_from_proc_cgroups(pid_t pid, char *cgroup_list[], char *controller_list[], int list_len); +bool cgroup_compare_ignore_rule(const struct cgroup_rule * const rule, + pid_t pid, const char * const procname); + #endif /* UNIT_TEST */ __END_DECLS diff --git a/tests/gunit/004-cgroup_compare_ignore_rule.cpp b/tests/gunit/004-cgroup_compare_ignore_rule.cpp new file mode 100644 index 000000000000..f50f523d18d8 --- /dev/null +++ b/tests/gunit/004-cgroup_compare_ignore_rule.cpp @@ -0,0 +1,340 @@ +/** + * libcgroup googletest for cgroup_compare_ignore_rule() + * + * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. + * Author: Tom Hromatka <tom.hroma...@oracle.com> + */ + +/* + * This library is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see <http://www.gnu.org/licenses>. + */ + +#include "gtest/gtest.h" + +#include "libcgroup-internal.h" + +class CgroupCompareIgnoreRuleTest : public ::testing::Test { +}; + +static void CreateCgroupProcFile(const char * const contents) +{ + FILE *f; + + f = fopen(TEST_PROC_PID_CGROUP_FILE, "w"); + ASSERT_NE(f, nullptr); + + fprintf(f, "%s", contents); + fclose(f); +} + +TEST_F(CgroupCompareIgnoreRuleTest, NotAnIgnore) +{ + char procname[] = "myprocess"; + struct cgroup_rule rule; + pid_t pid = 1234; + bool ret; + + rule.is_ignore = false; + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, false); +} + +TEST_F(CgroupCompareIgnoreRuleTest, SimpleMatch) +{ + char proc_file_contents[] = + "7:cpuacct:/SimpleMatchCgroup"; + char rule_controller[] = "cpuacct"; + char procname[] = "procfoo"; + struct cgroup_rule rule; + pid_t pid = 2345; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.procname = NULL; + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "SimpleMatchCgroup"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, true); +} + +TEST_F(CgroupCompareIgnoreRuleTest, CgroupsDontMatch) +{ + char proc_file_contents[] = + "2:cpuacct:CloseButNotQuite"; + char rule_controller[] = "cpuacct"; + char procname[] = "procfoo2"; + struct cgroup_rule rule; + pid_t pid = 4567; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "CloseButNotQuit"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, false); +} + +TEST_F(CgroupCompareIgnoreRuleTest, ControllersDontMatch) +{ + char proc_file_contents[] = + "5:memory:MyCgroup"; + char rule_controller[] = "cpuacct"; + char procname[] = "procfoo3"; + struct cgroup_rule rule; + pid_t pid = 5678; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "MyCgroup"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, false); +} + +TEST_F(CgroupCompareIgnoreRuleTest, CombinedControllers) +{ + char proc_file_contents[] = + "13:cpu,cpuacct:/containercg"; + char rule_controller[] = "cpuacct"; + char procname[] = "docker"; + struct cgroup_rule rule; + pid_t pid = 6789; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + rule.controllers[1] = NULL; + sprintf(rule.destination, "containercg"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, true); +} + +TEST_F(CgroupCompareIgnoreRuleTest, MatchChildFolder) +{ + char proc_file_contents[] = + "7:cpuset:/parentcg/childcg/grandchildcg"; + char rule_controller[] = "cpuset"; + char procname[] = "childprocess"; + struct cgroup_rule rule; + pid_t pid = 7890; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.procname = procname; + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "parentcg/"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, true); +} + +TEST_F(CgroupCompareIgnoreRuleTest, MatchGrandchildFolder) +{ + char proc_file_contents[] = + "1:hugetlb:/parentcg/childcg/grandchildcg"; + char rule_controller[] = "hugetlb"; + char procname[] = "granchildprocess"; + struct cgroup_rule rule; + pid_t pid = 8901; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.procname = NULL; + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "parentcg/childcg/"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, true); +} + +/** + * This test is designed to highlight the case where the user has not put a + * trailing slash at the end of the rule's destination. By design, this will + * cause the rule to match a wide variety of cases. + * + * For example, given the rule destination of "Folder". The following + * behavior would be observed: + * Process Location Matches the rule? + * Folder Yes + * Folders Yes + * Folder/AnotherFolder Yes + * Folder2 Yes + * Folder3/ChildFolder Yes + * Folde No + */ +TEST_F(CgroupCompareIgnoreRuleTest, MatchSimilarChildFolder) +{ + char proc_file_contents[] = + "1:hugetlb:/parentcg/childcg2"; + char rule_controller[] = "hugetlb"; + char procname[] = "granchildprocess"; + struct cgroup_rule rule; + pid_t pid = 8901; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.procname = NULL; + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "parentcg/childcg"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, true); +} + +TEST_F(CgroupCompareIgnoreRuleTest, RealWorldMatch) +{ + char proc_file_contents[] = + "12:memory:/user/johndoe/0\n" + "11:perf_event:/\n" + "10:rdma:/\n" + "9:blkio:/user.slice\n" + "8:cpu,cpuacct:/myCgroup\n" + "7:freezer:/user/johndoe/0\n" + "6:net_cls,net_prio:/\n" + "5:pids:/user.slice/user-1000.slice/session-1.scope\n" + "4:devices:/user.slice\n" + "3:cpuset:/\n" + "2:hugetlb:/\n" + "1:name=systemd:/user.slice/user-1000.slice/session-1.scope\n" + "0::/user.slice/user-1000.slice/session-1.scope\n"; + char rule_controller[] = "cpu"; + char procname[] = "granchildprocess"; + struct cgroup_rule rule; + pid_t pid = 8901; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.procname = NULL; + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "myCgroup/"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, true); +} + +TEST_F(CgroupCompareIgnoreRuleTest, RealWorldNoMatch) +{ + char proc_file_contents[] = + "12:memory:/user/johndoe/0\n" + "11:perf_event:/\n" + "10:rdma:/\n" + "9:blkio:/user.slice\n" + "8:cpu,cpuacct:/myCgroup\n" + "7:freezer:/user/johndoe/0\n" + "6:net_cls,net_prio:/NetCgroup\n" + "5:pids:/user.slice/user-1000.slice/session-1.scope\n" + "4:devices:/user.slice\n" + "3:cpuset:/\n" + "2:hugetlb:/\n" + "1:name=systemd:/user.slice/user-1000.slice/session-1.scope\n" + "0::/user.slice/user-1000.slice/session-1.scope\n"; + char rule_controller[] = "net_cls"; + char procname[] = "NotMatching"; + struct cgroup_rule rule; + pid_t pid = 9012; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.procname = NULL; + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "NetCgroup2"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, false); +} + +TEST_F(CgroupCompareIgnoreRuleTest, SimilarFolderNoMatch) +{ + char proc_file_contents[] = + "4:memory:/folder1"; + char rule_controller[] = "memory"; + char procname[] = "childprocess"; + struct cgroup_rule rule; + pid_t pid = 2345; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.procname = procname; + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "folder/"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, false); +} + +TEST_F(CgroupCompareIgnoreRuleTest, RootDestinationMatch) +{ + char proc_file_contents[] = + "2:freezer:/"; + char rule_controller[] = "freezer"; + char procname[] = "ANewProcess"; + struct cgroup_rule rule; + pid_t pid = 3456; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.procname = procname; + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "/"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, true); +} + +TEST_F(CgroupCompareIgnoreRuleTest, RootDestinationNoMatch) +{ + char proc_file_contents[] = + "2:freezer:/somerandomcg"; + char rule_controller[] = "freezer"; + char procname[] = "ANewProcess"; + struct cgroup_rule rule; + pid_t pid = 3456; + bool ret; + + CreateCgroupProcFile(proc_file_contents); + + rule.procname = procname; + rule.is_ignore = true; + rule.controllers[0] = rule_controller; + sprintf(rule.destination, "/"); + + ret = cgroup_compare_ignore_rule(&rule, pid, procname); + ASSERT_EQ(ret, false); +} diff --git a/tests/gunit/Makefile.am b/tests/gunit/Makefile.am index 85050d2b7cff..ff2630644044 100644 --- a/tests/gunit/Makefile.am +++ b/tests/gunit/Makefile.am @@ -41,4 +41,5 @@ TESTS = gtest gtest_SOURCES = gtest.cpp \ 001-path.cpp \ 002-cgroup_parse_rules_options.cpp \ - 003-cg_get_cgroups_from_proc_cgroups.cpp + 003-cg_get_cgroups_from_proc_cgroups.cpp \ + 004-cgroup_compare_ignore_rule.cpp -- 1.8.3.1 _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel