55a7cf1445
Reviewed-by: stuefe, asmehra
558 lines
23 KiB
C++
558 lines
23 KiB
C++
/*
|
|
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code 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 General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
#include "precompiled.hpp"
|
|
|
|
#ifdef LINUX
|
|
|
|
#include "runtime/os.hpp"
|
|
#include "cgroupSubsystem_linux.hpp"
|
|
#include "cgroupV1Subsystem_linux.hpp"
|
|
#include "cgroupV2Subsystem_linux.hpp"
|
|
#include "unittest.hpp"
|
|
#include "utilities/globalDefinitions.hpp"
|
|
|
|
#include <stdio.h>
|
|
|
|
// for basename
|
|
#include <libgen.h>
|
|
|
|
typedef struct {
|
|
const char* mount_path;
|
|
const char* root_path;
|
|
const char* cgroup_path;
|
|
const char* expected_path;
|
|
} TestCase;
|
|
|
|
// Utilities
|
|
static bool file_exists(const char* filename) {
|
|
struct stat st;
|
|
return os::stat(filename, &st) == 0;
|
|
}
|
|
|
|
// we rely on temp_file returning modifiable memory in resource area.
|
|
static char* temp_file(const char* prefix) {
|
|
const testing::TestInfo* test_info = ::testing::UnitTest::GetInstance()->current_test_info();
|
|
stringStream path;
|
|
path.print_raw(os::get_temp_directory());
|
|
path.print_raw(os::file_separator());
|
|
path.print("%s-test-jdk.pid%d.%s.%s", prefix, os::current_process_id(),
|
|
test_info->test_case_name(), test_info->name());
|
|
return path.as_string(true);
|
|
}
|
|
|
|
static void delete_file(const char* filename) {
|
|
if (!file_exists(filename)) {
|
|
return;
|
|
}
|
|
int ret = remove(filename);
|
|
EXPECT_TRUE(ret == 0 || errno == ENOENT) << "failed to remove file '" << filename << "': "
|
|
<< os::strerror(errno) << " (" << errno << ")";
|
|
}
|
|
|
|
class TestController : public CgroupController {
|
|
private:
|
|
char* _path;
|
|
public:
|
|
TestController(char* p): _path(p) {}
|
|
const char* subsystem_path() override {
|
|
return _path;
|
|
};
|
|
bool is_read_only() override {
|
|
return true; // doesn't matter
|
|
}
|
|
};
|
|
|
|
static void fill_file(const char* path, const char* content) {
|
|
delete_file(path);
|
|
FILE* fp = os::fopen(path, "w");
|
|
if (fp == nullptr) {
|
|
return;
|
|
}
|
|
if (content != nullptr) {
|
|
fprintf(fp, "%s", content);
|
|
}
|
|
fclose(fp);
|
|
}
|
|
|
|
TEST(cgroupTest, read_numerical_key_value_failure_cases) {
|
|
char* test_file = temp_file("cgroups");
|
|
const char* b = basename(test_file);
|
|
EXPECT_TRUE(b != nullptr) << "basename was null";
|
|
stringStream path;
|
|
path.print_raw(os::file_separator());
|
|
path.print_raw(b);
|
|
const char* base_with_slash = path.as_string(true);
|
|
|
|
TestController* controller = new TestController((char*)os::get_temp_directory());
|
|
constexpr julong bad = 0xBAD;
|
|
julong x = bad;
|
|
|
|
fill_file(test_file, "foo ");
|
|
bool is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_FALSE(is_ok) << "Value is missing in key/value case, expecting false";
|
|
EXPECT_EQ(bad, x) << "x must be unchanged";
|
|
|
|
x = bad;
|
|
fill_file(test_file, "faulty_start foo 101");
|
|
is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_FALSE(is_ok) << "key must be at the start";
|
|
EXPECT_EQ(bad, x) << "x must be unchanged";
|
|
|
|
x = bad;
|
|
fill_file(test_file, nullptr);
|
|
is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_FALSE(is_ok) << "key not in empty file";
|
|
EXPECT_EQ(bad, x) << "x must be unchanged";
|
|
|
|
x = bad;
|
|
fill_file(test_file, "foo\n");
|
|
is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_FALSE(is_ok) << "key must have a value";
|
|
EXPECT_EQ(bad, x) << "x must be unchanged";
|
|
|
|
x = bad;
|
|
fill_file(test_file, "foof 1002");
|
|
is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_FALSE(is_ok) << "key must be exact match";
|
|
EXPECT_EQ(bad, x) << "x must be unchanged";
|
|
|
|
// Cleanup
|
|
delete_file(test_file);
|
|
}
|
|
|
|
TEST(cgroupTest, read_numerical_key_value_success_cases) {
|
|
char* test_file = temp_file("cgroups");
|
|
const char* b = basename(test_file);
|
|
EXPECT_TRUE(b != nullptr) << "basename was null";
|
|
stringStream path;
|
|
path.print_raw(os::file_separator());
|
|
path.print_raw(b);
|
|
const char* base_with_slash = path.as_string(true);
|
|
|
|
TestController* controller = new TestController((char*)os::get_temp_directory());
|
|
constexpr julong bad = 0xBAD;
|
|
julong x = bad;
|
|
|
|
fill_file(test_file, "foo 100");
|
|
bool is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_TRUE(is_ok);
|
|
EXPECT_EQ((julong)100, x);
|
|
|
|
x = bad;
|
|
fill_file(test_file, "foo\t111");
|
|
is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_TRUE(is_ok);
|
|
EXPECT_EQ((julong)111, x);
|
|
|
|
x = bad;
|
|
fill_file(test_file, "foo\nbar 333\nfoo\t111");
|
|
is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_TRUE(is_ok);
|
|
EXPECT_EQ((julong)111, x);
|
|
|
|
x = bad;
|
|
fill_file(test_file, "foof 100\nfoo 133");
|
|
is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_TRUE(is_ok);
|
|
EXPECT_EQ((julong)133, x);
|
|
|
|
x = bad;
|
|
fill_file(test_file, "foo\t333\nfoot 999");
|
|
is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_TRUE(is_ok);
|
|
EXPECT_EQ((julong)333, x);
|
|
|
|
x = bad;
|
|
fill_file(test_file, "foo 1\nfoo car");
|
|
is_ok = controller->read_numerical_key_value(base_with_slash, "foo", &x);
|
|
EXPECT_TRUE(is_ok);
|
|
EXPECT_EQ((julong)1, x);
|
|
|
|
// Cleanup
|
|
delete_file(test_file);
|
|
}
|
|
|
|
TEST(cgroupTest, read_number_null) {
|
|
TestController* null_path_controller = new TestController((char*)nullptr);
|
|
const char* test_file_path = "/not-used";
|
|
constexpr julong bad = 0xBAD;
|
|
julong a = bad;
|
|
// null subsystem_path() case
|
|
bool is_ok = null_path_controller->read_number(test_file_path, &a);
|
|
EXPECT_FALSE(is_ok) << "Null subsystem path should be an error";
|
|
EXPECT_EQ(bad, a) << "Expected untouched scan value";
|
|
}
|
|
|
|
TEST(cgroupTest, read_string_beyond_max_path) {
|
|
char larger_than_max[MAXPATHLEN + 1];
|
|
for (int i = 0; i < (MAXPATHLEN); i++) {
|
|
larger_than_max[i] = 'A' + (i % 26);
|
|
}
|
|
larger_than_max[MAXPATHLEN] = '\0';
|
|
TestController* too_large_path_controller = new TestController(larger_than_max);
|
|
const char* test_file_path = "/file-not-found";
|
|
char foo[1024];
|
|
foo[0] = '\0';
|
|
bool is_ok = too_large_path_controller->read_string(test_file_path, foo, 1024);
|
|
EXPECT_FALSE(is_ok) << "Too long path should be an error";
|
|
EXPECT_STREQ("", foo) << "Expected untouched scan value";
|
|
}
|
|
|
|
TEST(cgroupTest, read_number_file_not_exist) {
|
|
TestController* unknown_path_ctrl = new TestController((char*)"/do/not/exist");
|
|
const char* test_file_path = "/file-not-found";
|
|
constexpr julong bad = 0xBAD;
|
|
julong result = bad;
|
|
bool is_ok = unknown_path_ctrl->read_number(test_file_path, &result);
|
|
EXPECT_FALSE(is_ok) << "File not found should be an error";
|
|
EXPECT_EQ(bad, result) << "Expected untouched scan value";
|
|
}
|
|
|
|
TEST(cgroupTest, read_numerical_key_value_null) {
|
|
TestController* null_path_controller = new TestController((char*)nullptr);
|
|
const char* test_file_path = "/not-used";
|
|
const char* key = "something";
|
|
constexpr julong bad = 0xBAD;
|
|
julong a = bad;
|
|
// null subsystem_path() case
|
|
bool is_ok = null_path_controller->read_numerical_key_value(test_file_path, key, &a);
|
|
EXPECT_FALSE(is_ok) << "Null subsystem path should be an error";
|
|
EXPECT_EQ(bad, a) << "Expected untouched scan value";
|
|
}
|
|
|
|
TEST(cgroupTest, read_number_tests) {
|
|
char* test_file = temp_file("cgroups");
|
|
const char* b = basename(test_file);
|
|
constexpr julong bad = 0xBAD;
|
|
EXPECT_TRUE(b != nullptr) << "basename was null";
|
|
stringStream path;
|
|
path.print_raw(os::file_separator());
|
|
path.print_raw(b);
|
|
const char* base_with_slash = path.as_string(true);
|
|
fill_file(test_file, "8888");
|
|
|
|
TestController* controller = new TestController((char*)os::get_temp_directory());
|
|
julong foo = bad;
|
|
bool ok = controller->read_number(base_with_slash, &foo);
|
|
EXPECT_TRUE(ok) << "Number parsing should have been successful";
|
|
EXPECT_EQ((julong)8888, foo) << "Wrong value for 'foo' (NOTE: 0xBAD == " << 0xBAD << ")";
|
|
|
|
// Some interface files might have negative values, ensure we can read
|
|
// them and manually cast them as needed.
|
|
fill_file(test_file, "-1");
|
|
foo = bad;
|
|
ok = controller->read_number(base_with_slash, &foo);
|
|
EXPECT_TRUE(ok) << "Number parsing should have been successful";
|
|
EXPECT_EQ((jlong)-1, (jlong)foo) << "Wrong value for 'foo' (NOTE: 0xBAD == " << 0xBAD << ")";
|
|
|
|
foo = bad;
|
|
fill_file(test_file, nullptr);
|
|
ok = controller->read_number(base_with_slash, &foo);
|
|
EXPECT_FALSE(ok) << "Empty file should have failed";
|
|
EXPECT_EQ(bad, foo) << "foo was altered";
|
|
|
|
// Some interface files have numbers as well as the string
|
|
// 'max', which means unlimited.
|
|
jlong result = -10;
|
|
fill_file(test_file, "max\n");
|
|
ok = controller->read_number_handle_max(base_with_slash, &result);
|
|
EXPECT_TRUE(ok) << "Number parsing for 'max' string should have been successful";
|
|
EXPECT_EQ((jlong)-1, result) << "'max' means unlimited (-1)";
|
|
|
|
result = -10;
|
|
fill_file(test_file, "11114\n");
|
|
ok = controller->read_number_handle_max(base_with_slash, &result);
|
|
EXPECT_TRUE(ok) << "Number parsing for should have been successful";
|
|
EXPECT_EQ((jlong)11114, result) << "Incorrect result";
|
|
|
|
result = -10;
|
|
fill_file(test_file, "-51114\n");
|
|
ok = controller->read_number_handle_max(base_with_slash, &result);
|
|
EXPECT_TRUE(ok) << "Number parsing for should have been successful";
|
|
EXPECT_EQ((jlong)-51114, result) << "Incorrect result";
|
|
|
|
delete_file(test_file);
|
|
}
|
|
|
|
TEST(cgroupTest, read_string_tests) {
|
|
char* test_file = temp_file("cgroups");
|
|
const char* b = basename(test_file);
|
|
EXPECT_TRUE(b != nullptr) << "basename was null";
|
|
stringStream path;
|
|
path.print_raw(os::file_separator());
|
|
path.print_raw(b);
|
|
const char* base_with_slash = path.as_string(true);
|
|
fill_file(test_file, "foo-bar");
|
|
|
|
TestController* controller = new TestController((char*)os::get_temp_directory());
|
|
char result[1024];
|
|
bool ok = controller->read_string(base_with_slash, result, 1024);
|
|
EXPECT_TRUE(ok) << "String parsing should have been successful";
|
|
EXPECT_STREQ("foo-bar", result);
|
|
|
|
result[0] = '\0';
|
|
fill_file(test_file, "1234");
|
|
ok = controller->read_string(base_with_slash, result, 1024);
|
|
EXPECT_TRUE(ok) << "String parsing should have been successful";
|
|
EXPECT_STREQ("1234", result);
|
|
|
|
// values with a space
|
|
result[0] = '\0';
|
|
fill_file(test_file, "abc def");
|
|
ok = controller->read_string(base_with_slash, result, 1024);
|
|
EXPECT_TRUE(ok) << "String parsing should have been successful";
|
|
EXPECT_STREQ("abc def", result);
|
|
|
|
result[0] = '\0';
|
|
fill_file(test_file, " \na");
|
|
ok = controller->read_string(base_with_slash, result, 1024);
|
|
EXPECT_TRUE(ok) << "String parsing should have been successful";
|
|
EXPECT_STREQ(" ", result);
|
|
|
|
// only the first line are being returned
|
|
result[0] = '\0';
|
|
fill_file(test_file, "test\nabc");
|
|
ok = controller->read_string(base_with_slash, result, 1024);
|
|
EXPECT_TRUE(ok) << "String parsing should have been successful";
|
|
EXPECT_STREQ("test", result);
|
|
|
|
result[0] = '\0';
|
|
fill_file(test_file, nullptr);
|
|
ok = controller->read_string(base_with_slash, result, 1024);
|
|
EXPECT_FALSE(ok) << "Empty file should have failed";
|
|
EXPECT_STREQ("", result) << "Expected untouched result";
|
|
delete_file(test_file);
|
|
|
|
// File contents larger than 1K
|
|
// We only read in the first 1K - 1 bytes
|
|
const size_t large_len = 2 * 1024;
|
|
char too_large[large_len];
|
|
for (size_t i = 0; i < large_len; i++) {
|
|
too_large[i] = 'A' + (i % 26);
|
|
}
|
|
too_large[large_len - 1] = '\0';
|
|
result[0] = '\0';
|
|
fill_file(test_file, too_large);
|
|
ok = controller->read_string(base_with_slash, result, 1024);
|
|
EXPECT_TRUE(ok) << "String parsing should have been successful";
|
|
EXPECT_TRUE(1023 == strlen(result)) << "Expected only the first 1023 chars to be read in";
|
|
EXPECT_EQ(0, strncmp(too_large, result, 1023));
|
|
EXPECT_EQ(result[1023], '\0') << "The last character must be the null character";
|
|
}
|
|
|
|
TEST(cgroupTest, read_number_tuple_test) {
|
|
char* test_file = temp_file("cgroups");
|
|
const char* b = basename(test_file);
|
|
EXPECT_TRUE(b != nullptr) << "basename was null";
|
|
stringStream path;
|
|
path.print_raw(os::file_separator());
|
|
path.print_raw(b);
|
|
const char* base_with_slash = path.as_string(true);
|
|
fill_file(test_file, "max 10000");
|
|
|
|
TestController* controller = new TestController((char*)os::get_temp_directory());
|
|
jlong result = -10;
|
|
bool ok = controller->read_numerical_tuple_value(base_with_slash, true /* use_first */, &result);
|
|
EXPECT_TRUE(ok) << "Should be OK to read value";
|
|
EXPECT_EQ((jlong)-1, result) << "max should be unlimited (-1)";
|
|
|
|
result = -10;
|
|
ok = controller->read_numerical_tuple_value(base_with_slash, false /* use_first */, &result);
|
|
EXPECT_TRUE(ok) << "Should be OK to read the value";
|
|
EXPECT_EQ((jlong)10000, result);
|
|
|
|
// non-max strings
|
|
fill_file(test_file, "abc 10000");
|
|
result = -10;
|
|
ok = controller->read_numerical_tuple_value(base_with_slash, true /* use_first */, &result);
|
|
EXPECT_FALSE(ok) << "abc should not be parsable";
|
|
EXPECT_EQ((jlong)-10, result) << "result value should be unchanged";
|
|
|
|
fill_file(test_file, nullptr);
|
|
result = -10;
|
|
ok = controller->read_numerical_tuple_value(base_with_slash, true /* use_first */, &result);
|
|
EXPECT_FALSE(ok) << "Empty file should be an error";
|
|
EXPECT_EQ((jlong)-10, result) << "result value should be unchanged";
|
|
}
|
|
|
|
TEST(cgroupTest, read_numerical_key_beyond_max_path) {
|
|
char larger_than_max[MAXPATHLEN + 1];
|
|
for (int i = 0; i < (MAXPATHLEN); i++) {
|
|
larger_than_max[i] = 'A' + (i % 26);
|
|
}
|
|
larger_than_max[MAXPATHLEN] = '\0';
|
|
TestController* too_large_path_controller = new TestController(larger_than_max);
|
|
const char* test_file_path = "/file-not-found";
|
|
const char* key = "something";
|
|
julong a = 0xBAD;
|
|
bool is_ok = too_large_path_controller->read_numerical_key_value(test_file_path, key, &a);
|
|
EXPECT_FALSE(is_ok) << "Too long path should be an error";
|
|
EXPECT_EQ((julong)0xBAD, a) << "Expected untouched scan value";
|
|
}
|
|
|
|
TEST(cgroupTest, read_numerical_key_file_not_exist) {
|
|
TestController* unknown_path_ctrl = new TestController((char*)"/do/not/exist");
|
|
const char* test_file_path = "/file-not-found";
|
|
const char* key = "something";
|
|
julong a = 0xBAD;
|
|
bool is_ok = unknown_path_ctrl->read_numerical_key_value(test_file_path, key, &a);
|
|
EXPECT_FALSE(is_ok) << "File not found should be an error";
|
|
EXPECT_EQ((julong)0xBAD, a) << "Expected untouched scan value";
|
|
}
|
|
|
|
TEST(cgroupTest, set_cgroupv1_subsystem_path) {
|
|
TestCase host = {
|
|
"/sys/fs/cgroup/memory", // mount_path
|
|
"/", // root_path
|
|
"/user.slice/user-1000.slice/user@1000.service", // cgroup_path
|
|
"/sys/fs/cgroup/memory/user.slice/user-1000.slice/user@1000.service" // expected_path
|
|
};
|
|
TestCase container_engine = {
|
|
"/sys/fs/cgroup/mem", // mount_path
|
|
"/user.slice/user-1000.slice/user@1000.service", // root_path
|
|
"/user.slice/user-1000.slice/user@1000.service", // cgroup_path
|
|
"/sys/fs/cgroup/mem" // expected_path
|
|
};
|
|
int length = 2;
|
|
TestCase* testCases[] = { &host,
|
|
&container_engine };
|
|
for (int i = 0; i < length; i++) {
|
|
CgroupV1Controller* ctrl = new CgroupV1Controller( (char*)testCases[i]->root_path,
|
|
(char*)testCases[i]->mount_path,
|
|
true /* read-only mount */);
|
|
ctrl->set_subsystem_path((char*)testCases[i]->cgroup_path);
|
|
ASSERT_STREQ(testCases[i]->expected_path, ctrl->subsystem_path());
|
|
}
|
|
}
|
|
|
|
TEST(cgroupTest, set_cgroupv2_subsystem_path) {
|
|
TestCase at_mount_root = {
|
|
"/sys/fs/cgroup", // mount_path
|
|
nullptr, // root_path, ignored
|
|
"/", // cgroup_path
|
|
"/sys/fs/cgroup" // expected_path
|
|
};
|
|
TestCase sub_path = {
|
|
"/sys/fs/cgroup", // mount_path
|
|
nullptr, // root_path, ignored
|
|
"/foobar", // cgroup_path
|
|
"/sys/fs/cgroup/foobar" // expected_path
|
|
};
|
|
int length = 2;
|
|
TestCase* testCases[] = { &at_mount_root,
|
|
&sub_path };
|
|
for (int i = 0; i < length; i++) {
|
|
CgroupV2Controller* ctrl = new CgroupV2Controller( (char*)testCases[i]->mount_path,
|
|
(char*)testCases[i]->cgroup_path,
|
|
true /* read-only mount */);
|
|
ASSERT_STREQ(testCases[i]->expected_path, ctrl->subsystem_path());
|
|
}
|
|
}
|
|
|
|
TEST(cgroupTest, cgroupv2_is_hierarchy_walk_needed) {
|
|
bool controller_read_only = false; // value irrelevant;
|
|
CgroupV2Controller* test = new CgroupV2Controller((char*)"/sys/fs/cgroup",
|
|
(char*)"/" /* cgroup_path */,
|
|
controller_read_only);
|
|
EXPECT_FALSE(test->needs_hierarchy_adjustment());
|
|
test = new CgroupV2Controller((char*)"/sys/fs/cgroup",
|
|
(char*)"/bar" /* cgroup_path */,
|
|
controller_read_only);
|
|
EXPECT_TRUE(test->needs_hierarchy_adjustment());
|
|
test = new CgroupV2Controller((char*)"/sys/fs/cgroup/b",
|
|
(char*)"/a/b" /* cgroup_path */,
|
|
controller_read_only);
|
|
EXPECT_TRUE(test->needs_hierarchy_adjustment());
|
|
|
|
CgroupCpuController* test2 = new CgroupV2CpuController(CgroupV2Controller((char*)"/sys/fs/cgroup",
|
|
(char*)"/" /* cgroup_path */,
|
|
controller_read_only));
|
|
EXPECT_FALSE(test2->needs_hierarchy_adjustment());
|
|
test2 = new CgroupV2CpuController(CgroupV2Controller((char*)"/sys/fs/cgroup",
|
|
(char*)"/bar" /* cgroup_path */,
|
|
controller_read_only));
|
|
EXPECT_TRUE(test2->needs_hierarchy_adjustment());
|
|
test2 = new CgroupV2CpuController(CgroupV2Controller((char*)"/sys/fs/cgroup/b",
|
|
(char*)"/a/b" /* cgroup_path */,
|
|
controller_read_only));
|
|
EXPECT_TRUE(test2->needs_hierarchy_adjustment());
|
|
|
|
CgroupMemoryController* test3 = new CgroupV2MemoryController(CgroupV2Controller((char*)"/sys/fs/cgroup",
|
|
(char*)"/" /* cgroup_path */,
|
|
controller_read_only));
|
|
EXPECT_FALSE(test3->needs_hierarchy_adjustment());
|
|
test3 = new CgroupV2MemoryController(CgroupV2Controller((char*)"/sys/fs/cgroup",
|
|
(char*)"/bar" /* cgroup_path */,
|
|
controller_read_only));
|
|
EXPECT_TRUE(test3->needs_hierarchy_adjustment());
|
|
test3 = new CgroupV2MemoryController(CgroupV2Controller((char*)"/sys/fs/cgroup/b",
|
|
(char*)"/a/b" /* cgroup_path */,
|
|
controller_read_only));
|
|
EXPECT_TRUE(test3->needs_hierarchy_adjustment());
|
|
}
|
|
|
|
TEST(cgroupTest, cgroupv1_is_hierarchy_walk_needed) {
|
|
bool controller_read_only = true; // shouldn't matter;
|
|
CgroupV1Controller* test = new CgroupV1Controller((char*)"/a/b/c" /* root */,
|
|
(char*)"/sys/fs/cgroup/memory" /* mount_path */,
|
|
controller_read_only);
|
|
test->set_subsystem_path((char*)"/a/b/c");
|
|
EXPECT_FALSE(test->needs_hierarchy_adjustment());
|
|
test->set_subsystem_path((char*)"/");
|
|
EXPECT_TRUE(test->needs_hierarchy_adjustment());
|
|
test = new CgroupV1Controller((char*)"/a/b/c" /* root */,
|
|
(char*)"/"/* mount_path */,
|
|
controller_read_only);
|
|
test->set_subsystem_path((char*)"/");
|
|
EXPECT_TRUE(test->needs_hierarchy_adjustment());
|
|
|
|
CgroupCpuController* test2 = new CgroupV1CpuController(CgroupV1Controller((char*)"/a/b/c" /* root */,
|
|
(char*)"/sys/fs/cgroup/memory" /* mount_path */,
|
|
controller_read_only));
|
|
static_cast<CgroupV1CpuController*>(test2)->set_subsystem_path((char*)"/a/b/c");
|
|
EXPECT_FALSE(test2->needs_hierarchy_adjustment());
|
|
static_cast<CgroupV1CpuController*>(test2)->set_subsystem_path((char*)"/");
|
|
EXPECT_TRUE(test2->needs_hierarchy_adjustment());
|
|
test2 = new CgroupV1CpuController(CgroupV1Controller((char*)"/a/b/c" /* root */,
|
|
(char*)"/"/* mount_path */,
|
|
controller_read_only));
|
|
static_cast<CgroupV1CpuController*>(test2)->set_subsystem_path((char*)"/");
|
|
EXPECT_TRUE(test2->needs_hierarchy_adjustment());
|
|
|
|
CgroupMemoryController* test3 = new CgroupV1MemoryController(CgroupV1Controller((char*)"/a/b/c" /* root */,
|
|
(char*)"/sys/fs/cgroup/memory" /* mount_path */,
|
|
controller_read_only));
|
|
static_cast<CgroupV1MemoryController*>(test3)->set_subsystem_path((char*)"/a/b/c");
|
|
EXPECT_FALSE(test3->needs_hierarchy_adjustment());
|
|
static_cast<CgroupV1MemoryController*>(test3)->set_subsystem_path((char*)"/");
|
|
EXPECT_TRUE(test3->needs_hierarchy_adjustment());
|
|
test3 = new CgroupV1MemoryController(CgroupV1Controller((char*)"/a/b/c" /* root */,
|
|
(char*)"/"/* mount_path */,
|
|
controller_read_only));
|
|
static_cast<CgroupV1MemoryController*>(test3)->set_subsystem_path((char*)"/");
|
|
EXPECT_TRUE(test3->needs_hierarchy_adjustment());
|
|
}
|
|
|
|
#endif // LINUX
|