summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/syscalls/linux/cgroup.cc35
-rw-r--r--test/util/cgroup_util.cc13
-rw-r--r--test/util/cgroup_util.h8
3 files changed, 54 insertions, 2 deletions
diff --git a/test/syscalls/linux/cgroup.cc b/test/syscalls/linux/cgroup.cc
index a1006a978..862328f5b 100644
--- a/test/syscalls/linux/cgroup.cc
+++ b/test/syscalls/linux/cgroup.cc
@@ -15,6 +15,7 @@
// All tests in this file rely on being about to mount and unmount cgroupfs,
// which isn't expected to work, or be safe on a general linux system.
+#include <limits.h>
#include <sys/mount.h>
#include <unistd.h>
@@ -35,8 +36,9 @@ using ::testing::_;
using ::testing::Ge;
using ::testing::Gt;
-std::vector<std::string> known_controllers = {"cpu", "cpuset", "cpuacct",
- "memory"};
+std::vector<std::string> known_controllers = {
+ "cpu", "cpuset", "cpuacct", "job", "memory",
+};
bool CgroupsAvailable() {
return IsRunningOnGvisor() && !IsRunningWithVFS1() &&
@@ -257,6 +259,35 @@ TEST(CPUAcctCgroup, CPUAcctStat) {
EXPECT_THAT(Atoi<int64_t>(sys_tokens[1]), IsPosixErrorOkAndHolds(Ge(0)));
}
+// WriteAndVerifyControlValue attempts to write val to a cgroup file at path,
+// and verify the value by reading it afterwards.
+PosixError WriteAndVerifyControlValue(const Cgroup& c, std::string_view path,
+ int64_t val) {
+ RETURN_IF_ERRNO(c.WriteIntegerControlFile(path, val));
+ ASSIGN_OR_RETURN_ERRNO(int64_t newval, c.ReadIntegerControlFile(path));
+ if (newval != val) {
+ return PosixError(
+ EINVAL,
+ absl::StrFormat(
+ "Unexpected value for control file '%s': expected %d, got %d", path,
+ val, newval));
+ }
+ return NoError();
+}
+
+TEST(JobCgroup, ReadWriteRead) {
+ SKIP_IF(!CgroupsAvailable());
+
+ Mounter m(ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()));
+ Cgroup c = ASSERT_NO_ERRNO_AND_VALUE(m.MountCgroupfs("job"));
+
+ EXPECT_THAT(c.ReadIntegerControlFile("job.id"), IsPosixErrorOkAndHolds(0));
+ EXPECT_NO_ERRNO(WriteAndVerifyControlValue(c, "job.id", 1234));
+ EXPECT_NO_ERRNO(WriteAndVerifyControlValue(c, "job.id", -1));
+ EXPECT_NO_ERRNO(WriteAndVerifyControlValue(c, "job.id", LLONG_MIN));
+ EXPECT_NO_ERRNO(WriteAndVerifyControlValue(c, "job.id", LLONG_MAX));
+}
+
TEST(ProcCgroups, Empty) {
SKIP_IF(!CgroupsAvailable());
diff --git a/test/util/cgroup_util.cc b/test/util/cgroup_util.cc
index 65d9c4986..d8d3fe471 100644
--- a/test/util/cgroup_util.cc
+++ b/test/util/cgroup_util.cc
@@ -17,6 +17,7 @@
#include <sys/syscall.h>
#include <unistd.h>
+#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "test/util/fs_util.h"
#include "test/util/mount_util.h"
@@ -50,6 +51,18 @@ PosixErrorOr<int64_t> Cgroup::ReadIntegerControlFile(
return val;
}
+PosixError Cgroup::WriteControlFile(absl::string_view name,
+ const std::string& value) const {
+ ASSIGN_OR_RETURN_ERRNO(FileDescriptor fd, Open(Relpath(name), O_WRONLY));
+ RETURN_ERROR_IF_SYSCALL_FAIL(WriteFd(fd.get(), value.c_str(), value.size()));
+ return NoError();
+}
+
+PosixError Cgroup::WriteIntegerControlFile(absl::string_view name,
+ int64_t value) const {
+ return WriteControlFile(name, absl::StrCat(value));
+}
+
PosixErrorOr<absl::flat_hash_set<pid_t>> Cgroup::Procs() const {
ASSIGN_OR_RETURN_ERRNO(std::string buf, ReadControlFile("cgroup.procs"));
return ParsePIDList(buf);
diff --git a/test/util/cgroup_util.h b/test/util/cgroup_util.h
index b049559df..c6e4303e1 100644
--- a/test/util/cgroup_util.h
+++ b/test/util/cgroup_util.h
@@ -45,6 +45,14 @@ class Cgroup {
// to parse it as an integer.
PosixErrorOr<int64_t> ReadIntegerControlFile(absl::string_view name) const;
+ // Writes a string to a cgroup control file.
+ PosixError WriteControlFile(absl::string_view name,
+ const std::string& value) const;
+
+ // Writes an integer value to a cgroup control file.
+ PosixError WriteIntegerControlFile(absl::string_view name,
+ int64_t value) const;
+
// Returns the thread ids of the leaders of thread groups managed by this
// cgroup.
PosixErrorOr<absl::flat_hash_set<pid_t>> Procs() const;