summaryrefslogtreecommitdiffhomepage
path: root/test/util
diff options
context:
space:
mode:
Diffstat (limited to 'test/util')
-rw-r--r--test/util/BUILD459
-rw-r--r--test/util/capability_util.h46
-rw-r--r--test/util/cgroup_util.cc264
-rw-r--r--test/util/cgroup_util.h135
-rw-r--r--test/util/cleanup.h61
-rw-r--r--test/util/epoll_util.cc52
-rw-r--r--test/util/epoll_util.h36
-rw-r--r--test/util/eventfd_util.h43
-rw-r--r--test/util/file_descriptor.h134
-rw-r--r--test/util/fs_util.cc728
-rw-r--r--test/util/fs_util.h237
-rw-r--r--test/util/fs_util_test.cc105
-rw-r--r--test/util/fuchsia_capability_util.cc73
-rw-r--r--test/util/fuse_util.cc63
-rw-r--r--test/util/fuse_util.h75
-rw-r--r--test/util/linux_capability_util.cc93
-rw-r--r--test/util/linux_capability_util.h128
-rw-r--r--test/util/logging.cc95
-rw-r--r--test/util/logging.h117
-rw-r--r--test/util/memory_util.h147
-rw-r--r--test/util/mount_util.cc176
-rw-r--r--test/util/mount_util.h99
-rw-r--r--test/util/mount_util_test.cc47
-rw-r--r--test/util/multiprocess_util.cc176
-rw-r--r--test/util/multiprocess_util.h133
-rw-r--r--test/util/platform_util.cc48
-rw-r--r--test/util/platform_util.h56
-rw-r--r--test/util/posix_error.cc98
-rw-r--r--test/util/posix_error.h459
-rw-r--r--test/util/posix_error_test.cc46
-rw-r--r--test/util/proc_util.cc107
-rw-r--r--test/util/proc_util.h150
-rw-r--r--test/util/proc_util_test.cc81
-rw-r--r--test/util/pty_util.cc58
-rw-r--r--test/util/pty_util.h39
-rw-r--r--test/util/rlimit_util.cc45
-rw-r--r--test/util/rlimit_util.h32
-rw-r--r--test/util/save_util.cc65
-rw-r--r--test/util/save_util.h60
-rw-r--r--test/util/save_util_linux.cc49
-rw-r--r--test/util/save_util_other.cc31
-rw-r--r--test/util/signal_util.cc104
-rw-r--r--test/util/signal_util.h107
-rw-r--r--test/util/socket_util.cc1129
-rw-r--r--test/util/socket_util.h591
-rw-r--r--test/util/socket_util_impl.cc28
-rw-r--r--test/util/temp_path.cc164
-rw-r--r--test/util/temp_path.h135
-rw-r--r--test/util/temp_umask.h39
-rw-r--r--test/util/test_main.cc20
-rw-r--r--test/util/test_util.cc239
-rw-r--r--test/util/test_util.h816
-rw-r--r--test/util/test_util_impl.cc59
-rw-r--r--test/util/test_util_runfiles.cc46
-rw-r--r--test/util/test_util_test.cc251
-rw-r--r--test/util/thread_util.h93
-rw-r--r--test/util/time_util.cc41
-rw-r--r--test/util/time_util.h29
-rw-r--r--test/util/timer_util.cc45
-rw-r--r--test/util/timer_util.h169
-rw-r--r--test/util/uid_util.cc44
-rw-r--r--test/util/uid_util.h29
-rw-r--r--test/util/verity_util.cc97
-rw-r--r--test/util/verity_util.h84
64 files changed, 0 insertions, 9505 deletions
diff --git a/test/util/BUILD b/test/util/BUILD
deleted file mode 100644
index 5b6bcb32c..000000000
--- a/test/util/BUILD
+++ /dev/null
@@ -1,459 +0,0 @@
-load("//tools:defs.bzl", "cc_library", "cc_test", "coreutil", "default_net_util", "gbenchmark_internal", "gtest", "select_system")
-
-package(
- default_visibility = ["//:sandbox"],
- licenses = ["notice"],
-)
-
-cc_library(
- name = "capability_util",
- testonly = 1,
- srcs = [
- "fuchsia_capability_util.cc",
- "linux_capability_util.cc",
- ],
- hdrs = [
- "capability_util.h",
- "linux_capability_util.h",
- ],
- deps = [
- ":cleanup",
- ":memory_util",
- ":posix_error",
- ":save_util",
- ":socket_util",
- ":test_util",
- "@com_google_absl//absl/strings",
- ],
-)
-
-cc_library(
- name = "eventfd_util",
- testonly = 1,
- hdrs = ["eventfd_util.h"],
- deps = [
- ":file_descriptor",
- ":posix_error",
- ":save_util",
- ],
-)
-
-cc_library(
- name = "file_descriptor",
- testonly = 1,
- hdrs = ["file_descriptor.h"],
- deps = [
- ":logging",
- ":posix_error",
- ":save_util",
- "@com_google_absl//absl/strings",
- "@com_google_absl//absl/strings:str_format",
- gtest,
- ],
-)
-
-cc_library(
- name = "fuse_util",
- testonly = 1,
- srcs = ["fuse_util.cc"],
- hdrs = ["fuse_util.h"],
-)
-
-cc_library(
- name = "proc_util",
- testonly = 1,
- srcs = ["proc_util.cc"],
- hdrs = ["proc_util.h"],
- deps = [
- ":fs_util",
- ":posix_error",
- ":test_util",
- "@com_google_absl//absl/strings",
- gtest,
- ],
-)
-
-cc_test(
- name = "proc_util_test",
- size = "small",
- srcs = ["proc_util_test.cc"],
- deps = [
- ":proc_util",
- ":test_main",
- ":test_util",
- gtest,
- ],
-)
-
-cc_library(
- name = "cleanup",
- testonly = 1,
- hdrs = ["cleanup.h"],
-)
-
-cc_library(
- name = "fs_util",
- testonly = 1,
- srcs = ["fs_util.cc"],
- hdrs = ["fs_util.h"],
- deps = [
- ":cleanup",
- ":file_descriptor",
- ":posix_error",
- "@com_google_absl//absl/strings",
- "@com_google_absl//absl/time",
- gtest,
- ],
-)
-
-cc_test(
- name = "fs_util_test",
- size = "small",
- srcs = ["fs_util_test.cc"],
- deps = [
- ":fs_util",
- ":posix_error",
- ":temp_path",
- ":test_main",
- ":test_util",
- gtest,
- ],
-)
-
-cc_library(
- name = "logging",
- testonly = 1,
- srcs = ["logging.cc"],
- hdrs = ["logging.h"],
-)
-
-cc_library(
- name = "memory_util",
- testonly = 1,
- hdrs = ["memory_util.h"],
- deps = [
- ":logging",
- ":posix_error",
- ":save_util",
- ":test_util",
- "@com_google_absl//absl/strings",
- "@com_google_absl//absl/strings:str_format",
- ],
-)
-
-cc_library(
- name = "mount_util",
- testonly = 1,
- srcs = ["mount_util.cc"],
- hdrs = ["mount_util.h"],
- deps = [
- ":cleanup",
- ":posix_error",
- ":test_util",
- "@com_google_absl//absl/container:flat_hash_map",
- "@com_google_absl//absl/strings",
- gtest,
- ],
-)
-
-cc_test(
- name = "mount_util_test",
- size = "small",
- srcs = ["mount_util_test.cc"],
- deps = [
- ":mount_util",
- ":test_main",
- ":test_util",
- gtest,
- ],
-)
-
-cc_library(
- name = "save_util",
- testonly = 1,
- srcs = [
- "save_util.cc",
- "save_util_linux.cc",
- "save_util_other.cc",
- ],
- hdrs = ["save_util.h"],
- defines = select_system(),
- deps = [
- ":logging",
- "@com_google_absl//absl/types:optional",
- ],
-)
-
-cc_library(
- name = "multiprocess_util",
- testonly = 1,
- srcs = ["multiprocess_util.cc"],
- hdrs = ["multiprocess_util.h"],
- deps = [
- ":cleanup",
- ":file_descriptor",
- ":posix_error",
- ":save_util",
- ":test_util",
- gtest,
- "@com_google_absl//absl/strings",
- ],
-)
-
-cc_library(
- name = "platform_util",
- testonly = 1,
- srcs = ["platform_util.cc"],
- hdrs = ["platform_util.h"],
- deps = [":test_util"],
-)
-
-cc_library(
- name = "posix_error",
- testonly = 1,
- srcs = ["posix_error.cc"],
- hdrs = ["posix_error.h"],
- deps = [
- ":logging",
- "@com_google_absl//absl/base:core_headers",
- "@com_google_absl//absl/strings",
- "@com_google_absl//absl/types:variant",
- gtest,
- ],
-)
-
-cc_test(
- name = "posix_error_test",
- size = "small",
- srcs = ["posix_error_test.cc"],
- deps = [
- ":posix_error",
- ":test_main",
- gtest,
- ],
-)
-
-cc_library(
- name = "pty_util",
- testonly = 1,
- srcs = ["pty_util.cc"],
- hdrs = ["pty_util.h"],
- deps = [
- ":file_descriptor",
- ":posix_error",
- ],
-)
-
-cc_library(
- name = "signal_util",
- testonly = 1,
- srcs = ["signal_util.cc"],
- hdrs = ["signal_util.h"],
- deps = [
- ":cleanup",
- ":posix_error",
- ":test_util",
- gtest,
- ],
-)
-
-cc_library(
- name = "temp_path",
- testonly = 1,
- srcs = ["temp_path.cc"],
- hdrs = ["temp_path.h"],
- deps = [
- ":fs_util",
- ":posix_error",
- ":test_util",
- "@com_google_absl//absl/strings",
- "@com_google_absl//absl/time",
- gtest,
- ],
-)
-
-cc_library(
- name = "test_util",
- testonly = 1,
- srcs = [
- "test_util.cc",
- "test_util_impl.cc",
- "test_util_runfiles.cc",
- ],
- hdrs = ["test_util.h"],
- defines = select_system(),
- deps = coreutil() + [
- ":fs_util",
- ":logging",
- ":posix_error",
- ":save_util",
- "@bazel_tools//tools/cpp/runfiles",
- "@com_google_absl//absl/base:core_headers",
- "@com_google_absl//absl/flags:flag",
- "@com_google_absl//absl/flags:parse",
- "@com_google_absl//absl/strings",
- "@com_google_absl//absl/strings:str_format",
- "@com_google_absl//absl/time",
- gtest,
- gbenchmark_internal,
- ],
-)
-
-cc_library(
- name = "thread_util",
- testonly = 1,
- hdrs = ["thread_util.h"],
- deps = [":logging"],
-)
-
-cc_library(
- name = "time_util",
- testonly = 1,
- srcs = ["time_util.cc"],
- hdrs = ["time_util.h"],
- deps = [
- "@com_google_absl//absl/time",
- ],
-)
-
-cc_library(
- name = "timer_util",
- testonly = 1,
- srcs = ["timer_util.cc"],
- hdrs = ["timer_util.h"],
- deps = [
- ":cleanup",
- ":logging",
- ":posix_error",
- ":test_util",
- "@com_google_absl//absl/time",
- gtest,
- ],
-)
-
-cc_test(
- name = "test_util_test",
- size = "small",
- srcs = ["test_util_test.cc"],
- deps = [
- ":test_main",
- ":test_util",
- gtest,
- ],
-)
-
-cc_library(
- name = "test_main",
- testonly = 1,
- srcs = ["test_main.cc"],
- deps = [":test_util"],
-)
-
-cc_library(
- name = "benchmark_main",
- testonly = 1,
- linkstatic = 1,
- deps = [
- ":test_util",
- "@com_google_absl//absl/flags:flag",
- gtest,
- gbenchmark_internal,
- ],
-)
-
-cc_library(
- name = "epoll_util",
- testonly = 1,
- srcs = ["epoll_util.cc"],
- hdrs = ["epoll_util.h"],
- deps = [
- ":file_descriptor",
- ":posix_error",
- ":save_util",
- gtest,
- ],
-)
-
-cc_library(
- name = "rlimit_util",
- testonly = 1,
- srcs = ["rlimit_util.cc"],
- hdrs = ["rlimit_util.h"],
- deps = [
- ":cleanup",
- ":logging",
- ":posix_error",
- ":test_util",
- ],
-)
-
-cc_library(
- name = "uid_util",
- testonly = 1,
- srcs = ["uid_util.cc"],
- hdrs = ["uid_util.h"],
- deps = [
- ":posix_error",
- ":save_util",
- ],
-)
-
-cc_library(
- name = "temp_umask",
- testonly = 1,
- hdrs = ["temp_umask.h"],
-)
-
-cc_library(
- name = "cgroup_util",
- testonly = 1,
- srcs = ["cgroup_util.cc"],
- hdrs = ["cgroup_util.h"],
- deps = [
- ":cleanup",
- ":fs_util",
- ":mount_util",
- ":posix_error",
- ":temp_path",
- "@com_google_absl//absl/container:flat_hash_map",
- "@com_google_absl//absl/container:flat_hash_set",
- "@com_google_absl//absl/strings",
- ],
-)
-
-cc_library(
- name = "verity_util",
- testonly = 1,
- srcs = ["verity_util.cc"],
- hdrs = ["verity_util.h"],
- deps = [
- ":fs_util",
- ":mount_util",
- ":posix_error",
- ":temp_path",
- ],
-)
-
-cc_library(
- name = "socket_util",
- testonly = 1,
- srcs = [
- "socket_util.cc",
- "socket_util_impl.cc",
- ],
- hdrs = ["socket_util.h"],
- defines = select_system(),
- deps = default_net_util() + [
- gtest,
- "@com_google_absl//absl/memory",
- "@com_google_absl//absl/strings",
- "@com_google_absl//absl/strings:str_format",
- "@com_google_absl//absl/time",
- "@com_google_absl//absl/types:optional",
- "//test/util:file_descriptor",
- "//test/util:posix_error",
- "//test/util:temp_path",
- "//test/util:test_util",
- "//test/util:thread_util",
- ],
-)
diff --git a/test/util/capability_util.h b/test/util/capability_util.h
deleted file mode 100644
index 318a43feb..000000000
--- a/test/util/capability_util.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-// Utilities for testing capabilities.
-
-#ifndef GVISOR_TEST_UTIL_CAPABILITY_UTIL_H_
-#define GVISOR_TEST_UTIL_CAPABILITY_UTIL_H_
-
-#if defined(__Fuchsia__)
-// Nothing to include.
-#elif defined(__linux__)
-#include "test/util/linux_capability_util.h"
-#else
-#error "Unhandled platform"
-#endif
-
-namespace gvisor {
-namespace testing {
-
-// HaveRawIPSocketCapability returns whether or not the process has access to
-// raw IP sockets.
-//
-// Returns an error when raw IP socket access cannot be determined.
-PosixErrorOr<bool> HaveRawIPSocketCapability();
-
-// HavePacketSocketCapability returns whether or not the process has access to
-// packet sockets.
-//
-// Returns an error when packet socket access cannot be determined.
-PosixErrorOr<bool> HavePacketSocketCapability();
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_CAPABILITY_UTIL_H_
diff --git a/test/util/cgroup_util.cc b/test/util/cgroup_util.cc
deleted file mode 100644
index df3c57b87..000000000
--- a/test/util/cgroup_util.cc
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright 2021 The gVisor Authors.
-//
-// Licensed 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 "test/util/cgroup_util.h"
-
-#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"
-
-namespace gvisor {
-namespace testing {
-
-Cgroup::Cgroup(absl::string_view path) : cgroup_path_(path) {
- id_ = ++Cgroup::next_id_;
- std::cerr << absl::StreamFormat("[cg#%d] <= %s", id_, cgroup_path_)
- << std::endl;
-}
-
-PosixErrorOr<Cgroup> Cgroup::RecursivelyCreate(absl::string_view path) {
- RETURN_IF_ERRNO(RecursivelyCreateDir(path));
- return Cgroup(path);
-}
-
-PosixErrorOr<Cgroup> Cgroup::Create(absl::string_view path) {
- RETURN_IF_ERRNO(Mkdir(path));
- return Cgroup(path);
-}
-
-PosixErrorOr<Cgroup> Cgroup::CreateChild(absl::string_view name) const {
- return Cgroup::Create(JoinPath(Path(), name));
-}
-
-PosixErrorOr<std::string> Cgroup::ReadControlFile(
- absl::string_view name) const {
- std::string buf;
- RETURN_IF_ERRNO(GetContents(Relpath(name), &buf));
-
- const std::string alias_path = absl::StrFormat("[cg#%d]/%s", id_, name);
- std::cerr << absl::StreamFormat("<contents of %s>", alias_path) << std::endl;
- std::cerr << buf;
- std::cerr << absl::StreamFormat("<end of %s>", alias_path) << std::endl;
-
- return buf;
-}
-
-PosixErrorOr<int64_t> Cgroup::ReadIntegerControlFile(
- absl::string_view name) const {
- ASSIGN_OR_RETURN_ERRNO(const std::string buf, ReadControlFile(name));
- ASSIGN_OR_RETURN_ERRNO(const int64_t val, Atoi<int64_t>(buf));
- 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);
-}
-
-PosixErrorOr<absl::flat_hash_set<pid_t>> Cgroup::Tasks() const {
- ASSIGN_OR_RETURN_ERRNO(std::string buf, ReadControlFile("tasks"));
- return ParsePIDList(buf);
-}
-
-PosixError Cgroup::ContainsCallingProcess() const {
- ASSIGN_OR_RETURN_ERRNO(const absl::flat_hash_set<pid_t> procs, Procs());
- ASSIGN_OR_RETURN_ERRNO(const absl::flat_hash_set<pid_t> tasks, Tasks());
- const pid_t pid = getpid();
- const pid_t tid = syscall(SYS_gettid);
- if (!procs.contains(pid)) {
- return PosixError(
- ENOENT, absl::StrFormat("Cgroup doesn't contain process %d", pid));
- }
- if (!tasks.contains(tid)) {
- return PosixError(ENOENT,
- absl::StrFormat("Cgroup doesn't contain task %d", tid));
- }
- return NoError();
-}
-
-PosixErrorOr<absl::flat_hash_set<pid_t>> Cgroup::ParsePIDList(
- absl::string_view data) const {
- absl::flat_hash_set<pid_t> res;
- std::vector<absl::string_view> lines = absl::StrSplit(data, '\n');
- for (const absl::string_view& line : lines) {
- if (line.empty()) {
- continue;
- }
- ASSIGN_OR_RETURN_ERRNO(const int32_t pid, Atoi<int32_t>(line));
- res.insert(static_cast<pid_t>(pid));
- }
- return res;
-}
-
-int64_t Cgroup::next_id_ = 0;
-
-PosixErrorOr<Cgroup> Mounter::MountCgroupfs(std::string mopts) {
- ASSIGN_OR_RETURN_ERRNO(TempPath mountpoint,
- TempPath::CreateDirIn(root_.path()));
- ASSIGN_OR_RETURN_ERRNO(
- Cleanup mount, Mount("none", mountpoint.path(), "cgroup", 0, mopts, 0));
- const std::string mountpath = mountpoint.path();
- std::cerr << absl::StreamFormat(
- "Mount(\"none\", \"%s\", \"cgroup\", 0, \"%s\", 0) => OK",
- mountpath, mopts)
- << std::endl;
- Cgroup cg = Cgroup(mountpath);
- mountpoints_[cg.id()] = std::move(mountpoint);
- mounts_[cg.id()] = std::move(mount);
- return cg;
-}
-
-PosixError Mounter::Unmount(const Cgroup& c) {
- auto mount = mounts_.find(c.id());
- auto mountpoint = mountpoints_.find(c.id());
-
- if (mount == mounts_.end() || mountpoint == mountpoints_.end()) {
- return PosixError(
- ESRCH, absl::StrFormat("No mount found for cgroupfs containing cg#%d",
- c.id()));
- }
-
- std::cerr << absl::StreamFormat("Unmount([cg#%d])", c.id()) << std::endl;
-
- // Simply delete the entries, their destructors will unmount and delete the
- // mountpoint. Note the order is important to avoid errors: mount then
- // mountpoint.
- mounts_.erase(mount);
- mountpoints_.erase(mountpoint);
-
- return NoError();
-}
-
-void Mounter::release(const Cgroup& c) {
- auto mp = mountpoints_.find(c.id());
- if (mp != mountpoints_.end()) {
- mp->second.release();
- mountpoints_.erase(mp);
- }
-
- auto m = mounts_.find(c.id());
- if (m != mounts_.end()) {
- m->second.Release();
- mounts_.erase(m);
- }
-}
-
-constexpr char kProcCgroupsHeader[] =
- "#subsys_name\thierarchy\tnum_cgroups\tenabled";
-
-PosixErrorOr<absl::flat_hash_map<std::string, CgroupsEntry>>
-ProcCgroupsEntries() {
- std::string content;
- RETURN_IF_ERRNO(GetContents("/proc/cgroups", &content));
-
- bool found_header = false;
- absl::flat_hash_map<std::string, CgroupsEntry> entries;
- std::vector<std::string> lines = absl::StrSplit(content, '\n');
- std::cerr << "<contents of /proc/cgroups>" << std::endl;
- for (const std::string& line : lines) {
- std::cerr << line << std::endl;
-
- if (!found_header) {
- EXPECT_EQ(line, kProcCgroupsHeader);
- found_header = true;
- continue;
- }
- if (line.empty()) {
- continue;
- }
-
- // Parse a single entry from /proc/cgroups.
- //
- // Example entries, fields are tab separated in the real file:
- //
- // #subsys_name hierarchy num_cgroups enabled
- // cpuset 12 35 1
- // cpu 3 222 1
- // ^ ^ ^ ^
- // 0 1 2 3
-
- CgroupsEntry entry;
- std::vector<std::string> fields =
- StrSplit(line, absl::ByAnyChar(": \t"), absl::SkipEmpty());
-
- entry.subsys_name = fields[0];
- ASSIGN_OR_RETURN_ERRNO(entry.hierarchy, Atoi<uint32_t>(fields[1]));
- ASSIGN_OR_RETURN_ERRNO(entry.num_cgroups, Atoi<uint64_t>(fields[2]));
- ASSIGN_OR_RETURN_ERRNO(const int enabled, Atoi<int>(fields[3]));
- entry.enabled = enabled != 0;
-
- entries[entry.subsys_name] = entry;
- }
- std::cerr << "<end of /proc/cgroups>" << std::endl;
-
- return entries;
-}
-
-PosixErrorOr<absl::flat_hash_map<std::string, PIDCgroupEntry>>
-ProcPIDCgroupEntries(pid_t pid) {
- const std::string path = absl::StrFormat("/proc/%d/cgroup", pid);
- std::string content;
- RETURN_IF_ERRNO(GetContents(path, &content));
-
- absl::flat_hash_map<std::string, PIDCgroupEntry> entries;
- std::vector<std::string> lines = absl::StrSplit(content, '\n');
-
- std::cerr << absl::StreamFormat("<contents of %s>", path) << std::endl;
- for (const std::string& line : lines) {
- std::cerr << line << std::endl;
-
- if (line.empty()) {
- continue;
- }
-
- // Parse a single entry from /proc/<pid>/cgroup.
- //
- // Example entries:
- //
- // 2:cpu:/path/to/cgroup
- // 1:memory:/
-
- PIDCgroupEntry entry;
- std::vector<std::string> fields =
- absl::StrSplit(line, absl::ByChar(':'), absl::SkipEmpty());
-
- ASSIGN_OR_RETURN_ERRNO(entry.hierarchy, Atoi<uint32_t>(fields[0]));
- entry.controllers = fields[1];
- entry.path = fields[2];
-
- entries[entry.controllers] = entry;
- }
- std::cerr << absl::StreamFormat("<end of %s>", path) << std::endl;
-
- return entries;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/cgroup_util.h b/test/util/cgroup_util.h
deleted file mode 100644
index ccc7219e3..000000000
--- a/test/util/cgroup_util.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2021 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_CGROUP_UTIL_H_
-#define GVISOR_TEST_UTIL_CGROUP_UTIL_H_
-
-#include <unistd.h>
-
-#include "absl/container/flat_hash_map.h"
-#include "absl/container/flat_hash_set.h"
-#include "absl/strings/string_view.h"
-#include "test/util/cleanup.h"
-#include "test/util/fs_util.h"
-#include "test/util/temp_path.h"
-
-namespace gvisor {
-namespace testing {
-
-// Cgroup represents a cgroup directory on a mounted cgroupfs.
-class Cgroup {
- public:
- Cgroup(std::string_view path);
-
- uint64_t id() const { return id_; }
-
- // RecursivelyCreate creates cgroup specified by path, including all
- // components leading up to path. Path should end inside a cgroupfs mount. If
- // path already exists, RecursivelyCreate does nothing and silently succeeds.
- static PosixErrorOr<Cgroup> RecursivelyCreate(std::string_view path);
-
- // Creates a new cgroup at path. The parent directory must exist and be a
- // cgroupfs directory.
- static PosixErrorOr<Cgroup> Create(std::string_view path);
-
- const std::string& Path() const { return cgroup_path_; }
-
- // Creates a child cgroup under this cgroup with the given name.
- PosixErrorOr<Cgroup> CreateChild(std::string_view name) const;
-
- std::string Relpath(absl::string_view leaf) const {
- return JoinPath(cgroup_path_, leaf);
- }
-
- // Returns the contents of a cgroup control file with the given name.
- PosixErrorOr<std::string> ReadControlFile(absl::string_view name) const;
-
- // Reads the contents of a cgroup control with the given name, and attempts
- // 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;
-
- PosixErrorOr<absl::flat_hash_set<pid_t>> Tasks() const;
-
- // ContainsCallingProcess checks whether the calling process is part of the
- PosixError ContainsCallingProcess() const;
-
- private:
- PosixErrorOr<absl::flat_hash_set<pid_t>> ParsePIDList(
- absl::string_view data) const;
-
- static int64_t next_id_;
- int64_t id_;
- const std::string cgroup_path_;
-};
-
-// Mounter is a utility for creating cgroupfs mounts. It automatically manages
-// the lifetime of created mounts.
-class Mounter {
- public:
- Mounter(TempPath root) : root_(std::move(root)) {}
-
- PosixErrorOr<Cgroup> MountCgroupfs(std::string mopts);
-
- PosixError Unmount(const Cgroup& c);
-
- void release(const Cgroup& c);
-
- private:
- // The destruction order of these members avoids errors during cleanup. We
- // first unmount (by executing the mounts_ cleanups), then delete the
- // mountpoint subdirs, then delete the root.
- TempPath root_;
- absl::flat_hash_map<int64_t, TempPath> mountpoints_;
- absl::flat_hash_map<int64_t, Cleanup> mounts_;
-};
-
-// Represents a line from /proc/cgroups.
-struct CgroupsEntry {
- std::string subsys_name;
- uint32_t hierarchy;
- uint64_t num_cgroups;
- bool enabled;
-};
-
-// Returns a parsed representation of /proc/cgroups.
-PosixErrorOr<absl::flat_hash_map<std::string, CgroupsEntry>>
-ProcCgroupsEntries();
-
-// Represents a line from /proc/<pid>/cgroup.
-struct PIDCgroupEntry {
- uint32_t hierarchy;
- std::string controllers;
- std::string path;
-};
-
-// Returns a parsed representation of /proc/<pid>/cgroup.
-PosixErrorOr<absl::flat_hash_map<std::string, PIDCgroupEntry>>
-ProcPIDCgroupEntries(pid_t pid);
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_CGROUP_UTIL_H_
diff --git a/test/util/cleanup.h b/test/util/cleanup.h
deleted file mode 100644
index c76482ef4..000000000
--- a/test/util/cleanup.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_CLEANUP_H_
-#define GVISOR_TEST_UTIL_CLEANUP_H_
-
-#include <functional>
-#include <utility>
-
-namespace gvisor {
-namespace testing {
-
-class Cleanup {
- public:
- Cleanup() : released_(true) {}
- explicit Cleanup(std::function<void()>&& callback) : cb_(callback) {}
-
- Cleanup(Cleanup&& other) {
- released_ = other.released_;
- cb_ = other.Release();
- }
-
- Cleanup& operator=(Cleanup&& other) {
- released_ = other.released_;
- cb_ = other.Release();
- return *this;
- }
-
- ~Cleanup() {
- if (!released_) {
- cb_();
- }
- }
-
- std::function<void()>&& Release() {
- released_ = true;
- return std::move(cb_);
- }
-
- private:
- Cleanup(Cleanup const& other) = delete;
-
- bool released_ = false;
- std::function<void(void)> cb_;
-};
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_CLEANUP_H_
diff --git a/test/util/epoll_util.cc b/test/util/epoll_util.cc
deleted file mode 100644
index 2e5051468..000000000
--- a/test/util/epoll_util.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/epoll_util.h"
-
-#include <sys/epoll.h>
-
-#include "gmock/gmock.h"
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-#include "test/util/save_util.h"
-
-namespace gvisor {
-namespace testing {
-
-PosixErrorOr<FileDescriptor> NewEpollFD(int size) {
- // "Since Linux 2.6.8, the size argument is ignored, but must be greater than
- // zero." - epoll_create(2)
- int fd = epoll_create(size);
- MaybeSave();
- if (fd < 0) {
- return PosixError(errno, "epoll_create");
- }
- return FileDescriptor(fd);
-}
-
-PosixError RegisterEpollFD(int epoll_fd, int target_fd, int events,
- uint64_t data) {
- struct epoll_event event;
- event.events = events;
- event.data.u64 = data;
- int rc = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, target_fd, &event);
- MaybeSave();
- if (rc < 0) {
- return PosixError(errno, "epoll_ctl");
- }
- return NoError();
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/epoll_util.h b/test/util/epoll_util.h
deleted file mode 100644
index f233b37d5..000000000
--- a/test/util/epoll_util.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_EPOLL_UTIL_H_
-#define GVISOR_TEST_UTIL_EPOLL_UTIL_H_
-
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-// Returns a new epoll file descriptor.
-PosixErrorOr<FileDescriptor> NewEpollFD(int size = 1);
-
-// Registers `target_fd` with the epoll instance represented by `epoll_fd` for
-// the epoll events `events`. Events on `target_fd` will be indicated by setting
-// data.u64 to `data` in the returned epoll_event.
-PosixError RegisterEpollFD(int epoll_fd, int target_fd, int events,
- uint64_t data);
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_EPOLL_UTIL_H_
diff --git a/test/util/eventfd_util.h b/test/util/eventfd_util.h
deleted file mode 100644
index cb9ce829c..000000000
--- a/test/util/eventfd_util.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_EVENTFD_UTIL_H_
-#define GVISOR_TEST_UTIL_EVENTFD_UTIL_H_
-
-#include <sys/eventfd.h>
-
-#include <cerrno>
-
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-#include "test/util/save_util.h"
-
-namespace gvisor {
-namespace testing {
-
-// Returns a new eventfd with the given initial value and flags.
-inline PosixErrorOr<FileDescriptor> NewEventFD(unsigned int initval = 0,
- int flags = 0) {
- int fd = eventfd(initval, flags);
- MaybeSave();
- if (fd < 0) {
- return PosixError(errno, "eventfd");
- }
- return FileDescriptor(fd);
-}
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_EVENTFD_UTIL_H_
diff --git a/test/util/file_descriptor.h b/test/util/file_descriptor.h
deleted file mode 100644
index fc5caa55b..000000000
--- a/test/util/file_descriptor.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_FILE_DESCRIPTOR_H_
-#define GVISOR_TEST_UTIL_FILE_DESCRIPTOR_H_
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <string>
-
-#include "gmock/gmock.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/str_format.h"
-#include "test/util/logging.h"
-#include "test/util/posix_error.h"
-#include "test/util/save_util.h"
-
-namespace gvisor {
-namespace testing {
-
-// FileDescriptor is an RAII type class which takes ownership of a file
-// descriptor. It will close the FD when this object goes out of scope.
-class FileDescriptor {
- public:
- // Constructs an empty FileDescriptor (one that does not own a file
- // descriptor).
- FileDescriptor() = default;
-
- // Constructs a FileDescriptor that owns fd. If fd is negative, constructs an
- // empty FileDescriptor.
- explicit FileDescriptor(int fd) { set_fd(fd); }
-
- FileDescriptor(FileDescriptor&& orig) : fd_(orig.release()) {}
-
- FileDescriptor& operator=(FileDescriptor&& orig) {
- reset(orig.release());
- return *this;
- }
-
- PosixErrorOr<FileDescriptor> Dup() const {
- if (fd_ < 0) {
- return PosixError(EINVAL, "Attempting to Dup unset fd");
- }
-
- int fd = dup(fd_);
- if (fd < 0) {
- return PosixError(errno, absl::StrCat("dup ", fd_));
- }
- MaybeSave();
- return FileDescriptor(fd);
- }
-
- FileDescriptor(FileDescriptor const& other) = delete;
- FileDescriptor& operator=(FileDescriptor const& other) = delete;
-
- ~FileDescriptor() { reset(); }
-
- // If this object is non-empty, returns the owned file descriptor. (Ownership
- // is retained by the FileDescriptor.) Otherwise returns -1.
- int get() const { return fd_; }
-
- // If this object is non-empty, transfers ownership of the file descriptor to
- // the caller and returns it. Otherwise returns -1.
- int release() {
- int const fd = fd_;
- fd_ = -1;
- return fd;
- }
-
- // If this object is non-empty, closes the owned file descriptor (recording a
- // test failure if the close fails).
- void reset() { reset(-1); }
-
- // Like no-arg reset(), but the FileDescriptor takes ownership of fd after
- // closing its existing file descriptor.
- void reset(int fd) {
- if (fd_ >= 0) {
- TEST_PCHECK(close(fd_) == 0);
- MaybeSave();
- }
- set_fd(fd);
- }
-
- private:
- // Wrapper that coerces negative fd values other than -1 to -1 so that get()
- // etc. return -1.
- void set_fd(int fd) { fd_ = std::max(fd, -1); }
-
- int fd_ = -1;
-};
-
-// Wrapper around open(2) that returns a FileDescriptor.
-inline PosixErrorOr<FileDescriptor> Open(std::string const& path, int flags,
- mode_t mode = 0) {
- int fd = open(path.c_str(), flags, mode);
- if (fd < 0) {
- return PosixError(errno, absl::StrFormat("open(%s, %#x, %#o)", path.c_str(),
- flags, mode));
- }
- MaybeSave();
- return FileDescriptor(fd);
-}
-
-// Wrapper around openat(2) that returns a FileDescriptor.
-inline PosixErrorOr<FileDescriptor> OpenAt(int dirfd, std::string const& path,
- int flags, mode_t mode = 0) {
- int fd = openat(dirfd, path.c_str(), flags, mode);
- if (fd < 0) {
- return PosixError(errno, absl::StrFormat("openat(%d, %s, %#x, %#o)", dirfd,
- path, flags, mode));
- }
- MaybeSave();
- return FileDescriptor(fd);
-}
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_FILE_DESCRIPTOR_H_
diff --git a/test/util/fs_util.cc b/test/util/fs_util.cc
deleted file mode 100644
index 253411858..000000000
--- a/test/util/fs_util.cc
+++ /dev/null
@@ -1,728 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/fs_util.h"
-
-#include <dirent.h>
-#ifdef __linux__
-#include <linux/magic.h>
-#endif // __linux__
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "gmock/gmock.h"
-#include "absl/strings/match.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/str_split.h"
-#include "absl/strings/string_view.h"
-#include "absl/time/clock.h"
-#include "absl/time/time.h"
-#include "test/util/cleanup.h"
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-namespace {
-PosixError WriteContentsToFD(int fd, absl::string_view contents) {
- int written = 0;
- while (static_cast<absl::string_view::size_type>(written) < contents.size()) {
- int wrote = write(fd, contents.data() + written, contents.size() - written);
- if (wrote < 0) {
- if (errno == EINTR) {
- continue;
- }
- return PosixError(
- errno, absl::StrCat("WriteContentsToFD fd: ", fd, " write failure."));
- }
- written += wrote;
- }
- return NoError();
-}
-} // namespace
-
-namespace internal {
-
-// Given a collection of file paths, append them all together,
-// ensuring that the proper path separators are inserted between them.
-std::string JoinPathImpl(std::initializer_list<absl::string_view> paths) {
- std::string result;
-
- if (paths.size() != 0) {
- // This size calculation is worst-case: it assumes one extra "/" for every
- // path other than the first.
- size_t total_size = paths.size() - 1;
- for (const absl::string_view path : paths) total_size += path.size();
- result.resize(total_size);
-
- auto begin = result.begin();
- auto out = begin;
- bool trailing_slash = false;
- for (absl::string_view path : paths) {
- if (path.empty()) continue;
- if (path.front() == '/') {
- if (trailing_slash) {
- path.remove_prefix(1);
- }
- } else {
- if (!trailing_slash && out != begin) *out++ = '/';
- }
- const size_t this_size = path.size();
- memcpy(&*out, path.data(), this_size);
- out += this_size;
- trailing_slash = out[-1] == '/';
- }
- result.erase(out - begin);
- }
- return result;
-}
-} // namespace internal
-
-// Returns a status or the current working directory.
-PosixErrorOr<std::string> GetCWD() {
- char buffer[PATH_MAX + 1] = {};
- if (getcwd(buffer, PATH_MAX) == nullptr) {
- return PosixError(errno, "GetCWD() failed");
- }
-
- return std::string(buffer);
-}
-
-PosixErrorOr<struct stat> Stat(absl::string_view path) {
- struct stat stat_buf;
- int res = stat(std::string(path).c_str(), &stat_buf);
- if (res < 0) {
- return PosixError(errno, absl::StrCat("stat ", path));
- }
- return stat_buf;
-}
-
-PosixErrorOr<struct stat> Lstat(absl::string_view path) {
- struct stat stat_buf;
- int res = lstat(std::string(path).c_str(), &stat_buf);
- if (res < 0) {
- return PosixError(errno, absl::StrCat("lstat ", path));
- }
- return stat_buf;
-}
-
-PosixErrorOr<struct stat> Fstat(int fd) {
- struct stat stat_buf;
- int res = fstat(fd, &stat_buf);
- if (res < 0) {
- return PosixError(errno, absl::StrCat("fstat ", fd));
- }
- return stat_buf;
-}
-
-PosixErrorOr<bool> Exists(absl::string_view path) {
- struct stat stat_buf;
- int res = lstat(std::string(path).c_str(), &stat_buf);
- if (res < 0) {
- if (errno == ENOENT) {
- return false;
- }
- return PosixError(errno, absl::StrCat("lstat ", path));
- }
- return true;
-}
-
-PosixErrorOr<bool> IsDirectory(absl::string_view path) {
- ASSIGN_OR_RETURN_ERRNO(struct stat stat_buf, Lstat(path));
- if (S_ISDIR(stat_buf.st_mode)) {
- return true;
- }
-
- return false;
-}
-
-PosixError Delete(absl::string_view path) {
- int res = unlink(std::string(path).c_str());
- if (res < 0) {
- return PosixError(errno, absl::StrCat("unlink ", path));
- }
-
- return NoError();
-}
-
-PosixError Truncate(absl::string_view path, int length) {
- int res = truncate(std::string(path).c_str(), length);
- if (res < 0) {
- return PosixError(errno,
- absl::StrCat("truncate ", path, " to length ", length));
- }
-
- return NoError();
-}
-
-PosixError Chmod(absl::string_view path, int mode) {
- int res = chmod(std::string(path).c_str(), mode);
- if (res < 0) {
- return PosixError(errno, absl::StrCat("chmod ", path));
- }
-
- return NoError();
-}
-
-PosixError MknodAt(const FileDescriptor& dfd, absl::string_view path, int mode,
- dev_t dev) {
- int res = mknodat(dfd.get(), std::string(path).c_str(), mode, dev);
- if (res < 0) {
- return PosixError(errno, absl::StrCat("mknod ", path));
- }
-
- return NoError();
-}
-
-PosixError UnlinkAt(const FileDescriptor& dfd, absl::string_view path,
- int flags) {
- int res = unlinkat(dfd.get(), std::string(path).c_str(), flags);
- if (res < 0) {
- return PosixError(errno, absl::StrCat("unlink ", path));
- }
-
- return NoError();
-}
-
-PosixError Mkdir(absl::string_view path, int mode) {
- int res = mkdir(std::string(path).c_str(), mode);
- if (res < 0) {
- return PosixError(errno,
- absl::StrFormat("mkdir \"%s\" mode %#o", path, mode));
- }
-
- return NoError();
-}
-
-PosixError Rmdir(absl::string_view path) {
- int res = rmdir(std::string(path).c_str());
- if (res < 0) {
- return PosixError(errno, absl::StrCat("rmdir ", path));
- }
-
- return NoError();
-}
-
-PosixError SetContents(absl::string_view path, absl::string_view contents) {
- ASSIGN_OR_RETURN_ERRNO(bool exists, Exists(path));
- if (!exists) {
- return PosixError(
- ENOENT, absl::StrCat("SetContents file ", path, " doesn't exist."));
- }
-
- ASSIGN_OR_RETURN_ERRNO(auto fd, Open(std::string(path), O_WRONLY | O_TRUNC));
- return WriteContentsToFD(fd.get(), contents);
-}
-
-// Create a file with the given contents (if it does not already exist with the
-// given mode) and then set the contents.
-PosixError CreateWithContents(absl::string_view path,
- absl::string_view contents, int mode) {
- ASSIGN_OR_RETURN_ERRNO(
- auto fd, Open(std::string(path), O_WRONLY | O_CREAT | O_TRUNC, mode));
- return WriteContentsToFD(fd.get(), contents);
-}
-
-PosixError GetContents(absl::string_view path, std::string* output) {
- ASSIGN_OR_RETURN_ERRNO(auto fd, Open(std::string(path), O_RDONLY));
- output->clear();
-
- // Keep reading until we hit an EOF or an error.
- return GetContentsFD(fd.get(), output);
-}
-
-PosixErrorOr<std::string> GetContents(absl::string_view path) {
- std::string ret;
- RETURN_IF_ERRNO(GetContents(path, &ret));
- return ret;
-}
-
-PosixErrorOr<std::string> GetContentsFD(int fd) {
- std::string ret;
- RETURN_IF_ERRNO(GetContentsFD(fd, &ret));
- return ret;
-}
-
-PosixError GetContentsFD(int fd, std::string* output) {
- // Keep reading until we hit an EOF or an error.
- while (true) {
- char buf[16 * 1024] = {}; // Read in 16KB chunks.
- int bytes_read = read(fd, buf, sizeof(buf));
- if (bytes_read < 0) {
- if (errno == EINTR) {
- continue;
- }
- return PosixError(errno, "GetContentsFD read failure.");
- }
-
- if (bytes_read == 0) {
- break; // EOF.
- }
-
- output->append(buf, bytes_read);
- }
- return NoError();
-}
-
-PosixErrorOr<std::string> ReadLink(absl::string_view path) {
- char buf[PATH_MAX + 1] = {};
- int ret = readlink(std::string(path).c_str(), buf, PATH_MAX);
- if (ret < 0) {
- return PosixError(errno, absl::StrCat("readlink ", path));
- }
-
- return std::string(buf, ret);
-}
-
-PosixError WalkTree(
- absl::string_view path, bool recursive,
- const std::function<void(absl::string_view, const struct stat&)>& cb) {
- DIR* dir = opendir(std::string(path).c_str());
- if (dir == nullptr) {
- return PosixError(errno, absl::StrCat("opendir ", path));
- }
- auto dir_closer = Cleanup([&dir]() { closedir(dir); });
- while (true) {
- // Readdir(3): If the end of the directory stream is reached, NULL is
- // returned and errno is not changed. If an error occurs, NULL is returned
- // and errno is set appropriately. To distinguish end of stream and from an
- // error, set errno to zero before calling readdir() and then check the
- // value of errno if NULL is returned.
- errno = 0;
- struct dirent* dp = readdir(dir);
- if (dp == nullptr) {
- if (errno != 0) {
- return PosixError(errno, absl::StrCat("readdir ", path));
- }
- break; // We're done.
- }
-
- if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) {
- // Skip dots.
- continue;
- }
-
- auto full_path = JoinPath(path, dp->d_name);
- ASSIGN_OR_RETURN_ERRNO(struct stat s, Stat(full_path));
- if (S_ISDIR(s.st_mode) && recursive) {
- RETURN_IF_ERRNO(WalkTree(full_path, recursive, cb));
- } else {
- cb(full_path, s);
- }
- }
- // We're done walking so let's invoke our cleanup callback now.
- dir_closer.Release()();
-
- // And we have to dispatch the callback on the base directory.
- ASSIGN_OR_RETURN_ERRNO(struct stat s, Stat(path));
- cb(path, s);
-
- return NoError();
-}
-
-PosixErrorOr<std::vector<std::string>> ListDir(absl::string_view abspath,
- bool skipdots) {
- std::vector<std::string> files;
-
- DIR* dir = opendir(std::string(abspath).c_str());
- if (dir == nullptr) {
- return PosixError(errno, absl::StrCat("opendir ", abspath));
- }
- auto dir_closer = Cleanup([&dir]() { closedir(dir); });
- while (true) {
- // Readdir(3): If the end of the directory stream is reached, NULL is
- // returned and errno is not changed. If an error occurs, NULL is returned
- // and errno is set appropriately. To distinguish end of stream and from an
- // error, set errno to zero before calling readdir() and then check the
- // value of errno if NULL is returned.
- errno = 0;
- struct dirent* dp = readdir(dir);
- if (dp == nullptr) {
- if (errno != 0) {
- return PosixError(errno, absl::StrCat("readdir ", abspath));
- }
- break; // We're done.
- }
-
- if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) {
- if (skipdots) {
- continue;
- }
- }
- files.push_back(std::string(dp->d_name));
- }
-
- return files;
-}
-
-PosixError DirContains(absl::string_view path,
- const std::vector<std::string>& expect,
- const std::vector<std::string>& exclude) {
- ASSIGN_OR_RETURN_ERRNO(auto listing, ListDir(path, false));
-
- for (auto& expected_entry : expect) {
- auto cursor = std::find(listing.begin(), listing.end(), expected_entry);
- if (cursor == listing.end()) {
- return PosixError(ENOENT, absl::StrFormat("Failed to find '%s' in '%s'",
- expected_entry, path));
- }
- }
- for (auto& excluded_entry : exclude) {
- auto cursor = std::find(listing.begin(), listing.end(), excluded_entry);
- if (cursor != listing.end()) {
- return PosixError(ENOENT, absl::StrCat("File '", excluded_entry,
- "' found in path '", path, "'"));
- }
- }
- return NoError();
-}
-
-PosixError EventuallyDirContains(absl::string_view path,
- const std::vector<std::string>& expect,
- const std::vector<std::string>& exclude) {
- constexpr int kRetryCount = 100;
- const absl::Duration kRetryDelay = absl::Milliseconds(100);
-
- for (int i = 0; i < kRetryCount; ++i) {
- auto res = DirContains(path, expect, exclude);
- if (res.ok()) {
- return res;
- }
- if (i < kRetryCount - 1) {
- // Sleep if this isn't the final iteration.
- absl::SleepFor(kRetryDelay);
- }
- }
- return PosixError(ETIMEDOUT,
- "Timed out while waiting for directory to contain files ");
-}
-
-PosixError RecursivelyDelete(absl::string_view path, int* undeleted_dirs,
- int* undeleted_files) {
- ASSIGN_OR_RETURN_ERRNO(bool exists, Exists(path));
- if (!exists) {
- return PosixError(ENOENT, absl::StrCat(path, " does not exist"));
- }
-
- ASSIGN_OR_RETURN_ERRNO(bool dir, IsDirectory(path));
- if (!dir) {
- // Nothing recursive needs to happen we can just call Delete.
- auto status = Delete(path);
- if (!status.ok() && undeleted_files) {
- (*undeleted_files)++;
- }
- return status;
- }
-
- return WalkTree(path, /*recursive=*/true,
- [&](absl::string_view absolute_path, const struct stat& s) {
- if (S_ISDIR(s.st_mode)) {
- auto rm_status = Rmdir(absolute_path);
- if (!rm_status.ok() && undeleted_dirs) {
- (*undeleted_dirs)++;
- }
- } else {
- auto delete_status = Delete(absolute_path);
- if (!delete_status.ok() && undeleted_files) {
- (*undeleted_files)++;
- }
- }
- });
-}
-
-PosixError RecursivelyCreateDir(absl::string_view path) {
- if (path.empty() || path == "/") {
- return PosixError(EINVAL, "Cannot create root!");
- }
-
- // Does it already exist, if so we're done.
- ASSIGN_OR_RETURN_ERRNO(bool exists, Exists(path));
- if (exists) {
- return NoError();
- }
-
- // Do we need to create directories under us?
- auto dirname = Dirname(path);
- ASSIGN_OR_RETURN_ERRNO(exists, Exists(dirname));
- if (!exists) {
- RETURN_IF_ERRNO(RecursivelyCreateDir(dirname));
- }
-
- return Mkdir(path);
-}
-
-// Makes a path absolute with respect to an optional base. If no base is
-// provided it will use the current working directory.
-PosixErrorOr<std::string> MakeAbsolute(absl::string_view filename,
- absl::string_view base) {
- if (filename.empty()) {
- return PosixError(EINVAL, "filename cannot be empty.");
- }
-
- if (filename[0] == '/') {
- // This path is already absolute.
- return std::string(filename);
- }
-
- std::string actual_base;
- if (!base.empty()) {
- actual_base = std::string(base);
- } else {
- auto cwd_or = GetCWD();
- RETURN_IF_ERRNO(cwd_or.error());
- actual_base = cwd_or.ValueOrDie();
- }
-
- // Reverse iterate removing trailing slashes, effectively right trim '/'.
- for (int i = actual_base.size() - 1; i >= 0 && actual_base[i] == '/'; --i) {
- actual_base.erase(i, 1);
- }
-
- if (filename == ".") {
- return actual_base.empty() ? "/" : actual_base;
- }
-
- return absl::StrCat(actual_base, "/", filename);
-}
-
-std::string CleanPath(const absl::string_view unclean_path) {
- std::string path = std::string(unclean_path);
- const char* src = path.c_str();
- std::string::iterator dst = path.begin();
-
- // Check for absolute path and determine initial backtrack limit.
- const bool is_absolute_path = *src == '/';
- if (is_absolute_path) {
- *dst++ = *src++;
- while (*src == '/') ++src;
- }
- std::string::const_iterator backtrack_limit = dst;
-
- // Process all parts
- while (*src) {
- bool parsed = false;
-
- if (src[0] == '.') {
- // 1dot ".<whateverisnext>", check for END or SEP.
- if (src[1] == '/' || !src[1]) {
- if (*++src) {
- ++src;
- }
- parsed = true;
- } else if (src[1] == '.' && (src[2] == '/' || !src[2])) {
- // 2dot END or SEP (".." | "../<whateverisnext>").
- src += 2;
- if (dst != backtrack_limit) {
- // We can backtrack the previous part
- for (--dst; dst != backtrack_limit && dst[-1] != '/'; --dst) {
- // Empty.
- }
- } else if (!is_absolute_path) {
- // Failed to backtrack and we can't skip it either. Rewind and copy.
- src -= 2;
- *dst++ = *src++;
- *dst++ = *src++;
- if (*src) {
- *dst++ = *src;
- }
- // We can never backtrack over a copied "../" part so set new limit.
- backtrack_limit = dst;
- }
- if (*src) {
- ++src;
- }
- parsed = true;
- }
- }
-
- // If not parsed, copy entire part until the next SEP or EOS.
- if (!parsed) {
- while (*src && *src != '/') {
- *dst++ = *src++;
- }
- if (*src) {
- *dst++ = *src++;
- }
- }
-
- // Skip consecutive SEP occurrences
- while (*src == '/') {
- ++src;
- }
- }
-
- // Calculate and check the length of the cleaned path.
- int path_length = dst - path.begin();
- if (path_length != 0) {
- // Remove trailing '/' except if it is root path ("/" ==> path_length := 1)
- if (path_length > 1 && path[path_length - 1] == '/') {
- --path_length;
- }
- path.resize(path_length);
- } else {
- // The cleaned path is empty; assign "." as per the spec.
- path.assign(1, '.');
- }
- return path;
-}
-
-PosixErrorOr<std::string> GetRelativePath(absl::string_view source,
- absl::string_view dest) {
- if (!absl::StartsWith(source, "/") || !absl::StartsWith(dest, "/")) {
- // At least one of the inputs is not an absolute path.
- return PosixError(
- EINVAL,
- "GetRelativePath: At least one of the inputs is not an absolute path.");
- }
- const std::string clean_source = CleanPath(source);
- const std::string clean_dest = CleanPath(dest);
- auto source_parts = absl::StrSplit(clean_source, '/', absl::SkipEmpty());
- auto dest_parts = absl::StrSplit(clean_dest, '/', absl::SkipEmpty());
- auto source_iter = source_parts.begin();
- auto dest_iter = dest_parts.begin();
-
- // Advance past common prefix.
- while (source_iter != source_parts.end() && dest_iter != dest_parts.end() &&
- *source_iter == *dest_iter) {
- ++source_iter;
- ++dest_iter;
- }
-
- // Build result backtracking.
- std::string result = "";
- while (source_iter != source_parts.end()) {
- absl::StrAppend(&result, "../");
- ++source_iter;
- }
-
- // Add remaining path to dest.
- while (dest_iter != dest_parts.end()) {
- absl::StrAppend(&result, *dest_iter, "/");
- ++dest_iter;
- }
-
- if (result.empty()) {
- return std::string(".");
- }
-
- // Remove trailing slash.
- result.erase(result.size() - 1);
- return result;
-}
-
-absl::string_view Dirname(absl::string_view path) {
- return SplitPath(path).first;
-}
-
-absl::string_view Basename(absl::string_view path) {
- return SplitPath(path).second;
-}
-
-std::pair<absl::string_view, absl::string_view> SplitPath(
- absl::string_view path) {
- std::string::size_type pos = path.find_last_of('/');
-
- // Handle the case with no '/' in 'path'.
- if (pos == absl::string_view::npos) {
- return std::make_pair(path.substr(0, 0), path);
- }
-
- // Handle the case with a single leading '/' in 'path'.
- if (pos == 0) {
- return std::make_pair(path.substr(0, 1), absl::ClippedSubstr(path, 1));
- }
-
- return std::make_pair(path.substr(0, pos),
- absl::ClippedSubstr(path, pos + 1));
-}
-
-std::string JoinPath(absl::string_view path1, absl::string_view path2) {
- if (path1.empty()) {
- return std::string(path2);
- }
- if (path2.empty()) {
- return std::string(path1);
- }
-
- if (path1.back() == '/') {
- if (path2.front() == '/') {
- return absl::StrCat(path1, absl::ClippedSubstr(path2, 1));
- }
- } else {
- if (path2.front() != '/') {
- return absl::StrCat(path1, "/", path2);
- }
- }
- return absl::StrCat(path1, path2);
-}
-
-PosixErrorOr<std::string> ProcessExePath(int pid) {
- if (pid <= 0) {
- return PosixError(EINVAL, "Invalid pid specified");
- }
-
- return ReadLink(absl::StrCat("/proc/", pid, "/exe"));
-}
-
-#ifdef __linux__
-PosixErrorOr<bool> IsTmpfs(const std::string& path) {
- struct statfs stat;
- if (statfs(path.c_str(), &stat)) {
- if (errno == ENOENT) {
- // Nothing at path, don't raise this as an error. Instead, just report no
- // tmpfs at path.
- return false;
- }
- return PosixError(errno,
- absl::StrFormat("statfs(\"%s\", %#p)", path, &stat));
- }
- return stat.f_type == TMPFS_MAGIC;
-}
-#endif // __linux__
-
-PosixErrorOr<bool> IsOverlayfs(const std::string& path) {
- struct statfs stat;
- if (statfs(path.c_str(), &stat)) {
- if (errno == ENOENT) {
- // Nothing at path, don't raise this as an error. Instead, just report no
- // overlayfs at path.
- return false;
- }
- return PosixError(errno,
- absl::StrFormat("statfs(\"%s\", %#p)", path, &stat));
- }
- return stat.f_type == OVERLAYFS_SUPER_MAGIC;
-}
-
-PosixError CheckSameFile(const FileDescriptor& fd1, const FileDescriptor& fd2) {
- struct stat stat_result1, stat_result2;
- int res = fstat(fd1.get(), &stat_result1);
- if (res < 0) {
- return PosixError(errno, absl::StrCat("fstat ", fd1.get()));
- }
-
- res = fstat(fd2.get(), &stat_result2);
- if (res < 0) {
- return PosixError(errno, absl::StrCat("fstat ", fd2.get()));
- }
- EXPECT_EQ(stat_result1.st_dev, stat_result2.st_dev);
- EXPECT_EQ(stat_result1.st_ino, stat_result2.st_ino);
-
- return NoError();
-}
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/fs_util.h b/test/util/fs_util.h
deleted file mode 100644
index bb2d1d3c8..000000000
--- a/test/util/fs_util.h
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_FS_UTIL_H_
-#define GVISOR_TEST_UTIL_FS_UTIL_H_
-
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "absl/strings/string_view.h"
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-// O_LARGEFILE as defined by Linux. glibc tries to be clever by setting it to 0
-// because "it isn't needed", even though Linux can return it via F_GETFL.
-#if defined(__x86_64__)
-constexpr int kOLargeFile = 00100000;
-#elif defined(__aarch64__)
-constexpr int kOLargeFile = 00400000;
-#else
-#error "Unknown architecture"
-#endif
-
-// From linux/magic.h. For some reason, not defined in the headers for some
-// build environments.
-#define OVERLAYFS_SUPER_MAGIC 0x794c7630
-
-// Returns a status or the current working directory.
-PosixErrorOr<std::string> GetCWD();
-
-// Returns true/false depending on whether or not path exists, or an error if it
-// can't be determined.
-PosixErrorOr<bool> Exists(absl::string_view path);
-
-// Returns a stat structure for the given path or an error. If the path
-// represents a symlink, it will be traversed.
-PosixErrorOr<struct stat> Stat(absl::string_view path);
-
-// Returns a stat structure for the given path or an error. If the path
-// represents a symlink, it will not be traversed.
-PosixErrorOr<struct stat> Lstat(absl::string_view path);
-
-// Returns a stat struct for the given fd.
-PosixErrorOr<struct stat> Fstat(int fd);
-
-// Deletes the file or directory at path or returns an error.
-PosixError Delete(absl::string_view path);
-
-// Changes the mode of a file or returns an error.
-PosixError Chmod(absl::string_view path, int mode);
-
-// Create a special or ordinary file.
-PosixError MknodAt(const FileDescriptor& dfd, absl::string_view path, int mode,
- dev_t dev);
-
-// Unlink the file.
-PosixError UnlinkAt(const FileDescriptor& dfd, absl::string_view path,
- int flags);
-
-// Truncates a file to the given length or returns an error.
-PosixError Truncate(absl::string_view path, int length);
-
-// Returns true/false depending on whether or not the path is a directory or
-// returns an error.
-PosixErrorOr<bool> IsDirectory(absl::string_view path);
-
-// Makes a directory or returns an error.
-PosixError Mkdir(absl::string_view path, int mode = 0755);
-
-// Removes a directory or returns an error.
-PosixError Rmdir(absl::string_view path);
-
-// Attempts to set the contents of a file or returns an error.
-PosixError SetContents(absl::string_view path, absl::string_view contents);
-
-// Creates a file with the given contents and mode or returns an error.
-PosixError CreateWithContents(absl::string_view path,
- absl::string_view contents, int mode = 0666);
-
-// Attempts to read the entire contents of the file into the provided string
-// buffer or returns an error.
-PosixError GetContents(absl::string_view path, std::string* output);
-
-// Attempts to read the entire contents of the file or returns an error.
-PosixErrorOr<std::string> GetContents(absl::string_view path);
-
-// Attempts to read the entire contents of the provided fd into the provided
-// string or returns an error.
-PosixError GetContentsFD(int fd, std::string* output);
-
-// Attempts to read the entire contents of the provided fd or returns an error.
-PosixErrorOr<std::string> GetContentsFD(int fd);
-
-// Executes the readlink(2) system call or returns an error.
-PosixErrorOr<std::string> ReadLink(absl::string_view path);
-
-// WalkTree will walk a directory tree in a depth first search manner (if
-// recursive). It will invoke a provided callback for each file and directory,
-// the parent will always be invoked last making this appropriate for things
-// such as deleting an entire directory tree.
-//
-// This method will return an error when it's unable to access the provided
-// path, or when the path is not a directory.
-PosixError WalkTree(
- absl::string_view path, bool recursive,
- const std::function<void(absl::string_view, const struct stat&)>& cb);
-
-// Returns the base filenames for all files under a given absolute path. If
-// skipdots is true the returned vector will not contain "." or "..". This
-// method does not walk the tree recursively it only returns the elements
-// in that directory.
-PosixErrorOr<std::vector<std::string>> ListDir(absl::string_view abspath,
- bool skipdots);
-
-// Check that a directory contains children nodes named in expect, and does not
-// contain any children nodes named in exclude.
-PosixError DirContains(absl::string_view path,
- const std::vector<std::string>& expect,
- const std::vector<std::string>& exclude);
-
-// Same as DirContains, but adds a retry. Suitable for checking a directory
-// being modified asynchronously.
-PosixError EventuallyDirContains(absl::string_view path,
- const std::vector<std::string>& expect,
- const std::vector<std::string>& exclude);
-
-// Attempt to recursively delete a directory or file. Returns an error and
-// the number of undeleted directories and files. If either
-// undeleted_dirs or undeleted_files is nullptr then it will not be used.
-PosixError RecursivelyDelete(absl::string_view path, int* undeleted_dirs,
- int* undeleted_files);
-
-// Recursively create the directory provided or return an error.
-PosixError RecursivelyCreateDir(absl::string_view path);
-
-// Makes a path absolute with respect to an optional base. If no base is
-// provided it will use the current working directory.
-PosixErrorOr<std::string> MakeAbsolute(absl::string_view filename,
- absl::string_view base);
-
-// Generates a relative path from the source directory to the destination
-// (dest) file or directory. This uses ../ when necessary for destinations
-// which are not nested within the source. Both source and dest are required
-// to be absolute paths, and an empty string will be returned if they are not.
-PosixErrorOr<std::string> GetRelativePath(absl::string_view source,
- absl::string_view dest);
-
-// Returns the part of the path before the final "/", EXCEPT:
-// * If there is a single leading "/" in the path, the result will be the
-// leading "/".
-// * If there is no "/" in the path, the result is the empty prefix of the
-// input string.
-absl::string_view Dirname(absl::string_view path);
-
-// Return the parts of the path, split on the final "/". If there is no
-// "/" in the path, the first part of the output is empty and the second
-// is the input. If the only "/" in the path is the first character, it is
-// the first part of the output.
-std::pair<absl::string_view, absl::string_view> SplitPath(
- absl::string_view path);
-
-// Returns the part of the path after the final "/". If there is no
-// "/" in the path, the result is the same as the input.
-// Note that this function's behavior differs from the Unix basename
-// command if path ends with "/". For such paths, this function returns the
-// empty string.
-absl::string_view Basename(absl::string_view path);
-
-// Collapse duplicate "/"s, resolve ".." and "." path elements, remove
-// trailing "/".
-//
-// NOTE: This respects relative vs. absolute paths, but does not
-// invoke any system calls (getcwd(2)) in order to resolve relative
-// paths wrt actual working directory. That is, this is purely a
-// string manipulation, completely independent of process state.
-std::string CleanPath(absl::string_view path);
-
-// Returns the full path to the executable of the given pid or a PosixError.
-PosixErrorOr<std::string> ProcessExePath(int pid);
-
-#ifdef __linux__
-// IsTmpfs returns true if the file at path is backed by tmpfs.
-PosixErrorOr<bool> IsTmpfs(const std::string& path);
-#endif // __linux__
-
-// IsOverlayfs returns true if the file at path is backed by overlayfs.
-PosixErrorOr<bool> IsOverlayfs(const std::string& path);
-
-PosixError CheckSameFile(const FileDescriptor& fd1, const FileDescriptor& fd2);
-
-namespace internal {
-// Not part of the public API.
-std::string JoinPathImpl(std::initializer_list<absl::string_view> paths);
-} // namespace internal
-
-// Join multiple paths together.
-// All paths will be treated as relative paths, regardless of whether or not
-// they start with a leading '/'. That is, all paths will be concatenated
-// together, with the appropriate path separator inserted in between.
-// Arguments must be convertible to absl::string_view.
-//
-// Usage:
-// std::string path = JoinPath("/foo", dirname, filename);
-// std::string path = JoinPath(FLAGS_test_srcdir, filename);
-//
-// 0, 1, 2-path specializations exist to optimize common cases.
-inline std::string JoinPath() { return std::string(); }
-inline std::string JoinPath(absl::string_view path) {
- return std::string(path.data(), path.size());
-}
-
-std::string JoinPath(absl::string_view path1, absl::string_view path2);
-template <typename... T>
-inline std::string JoinPath(absl::string_view path1, absl::string_view path2,
- absl::string_view path3, const T&... args) {
- return internal::JoinPathImpl({path1, path2, path3, args...});
-}
-} // namespace testing
-} // namespace gvisor
-#endif // GVISOR_TEST_UTIL_FS_UTIL_H_
diff --git a/test/util/fs_util_test.cc b/test/util/fs_util_test.cc
deleted file mode 100644
index 657b6a46e..000000000
--- a/test/util/fs_util_test.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/fs_util.h"
-
-#include <errno.h>
-
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "test/util/posix_error.h"
-#include "test/util/temp_path.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-namespace {
-
-TEST(FsUtilTest, RecursivelyCreateDirManualDelete) {
- const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
- const std::string base_path =
- JoinPath(root.path(), "/a/b/c/d/e/f/g/h/i/j/k/l/m");
-
- ASSERT_THAT(Exists(base_path), IsPosixErrorOkAndHolds(false));
- ASSERT_NO_ERRNO(RecursivelyCreateDir(base_path));
-
- // Delete everything until we hit root and then stop, we want to try this
- // without using RecursivelyDelete.
- std::string cur_path = base_path;
- while (cur_path != root.path()) {
- ASSERT_THAT(Exists(cur_path), IsPosixErrorOkAndHolds(true));
- ASSERT_NO_ERRNO(Rmdir(cur_path));
- ASSERT_THAT(Exists(cur_path), IsPosixErrorOkAndHolds(false));
- auto dir = Dirname(cur_path);
- cur_path = std::string(dir);
- }
-}
-
-TEST(FsUtilTest, RecursivelyCreateAndDeleteDir) {
- const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
- const std::string base_path =
- JoinPath(root.path(), "/a/b/c/d/e/f/g/h/i/j/k/l/m");
-
- ASSERT_THAT(Exists(base_path), IsPosixErrorOkAndHolds(false));
- ASSERT_NO_ERRNO(RecursivelyCreateDir(base_path));
-
- const std::string sub_path = JoinPath(root.path(), "a");
- ASSERT_NO_ERRNO(RecursivelyDelete(sub_path, nullptr, nullptr));
- ASSERT_THAT(Exists(sub_path), IsPosixErrorOkAndHolds(false));
-}
-
-TEST(FsUtilTest, RecursivelyCreateAndDeletePartial) {
- const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
- const std::string base_path =
- JoinPath(root.path(), "/a/b/c/d/e/f/g/h/i/j/k/l/m");
-
- ASSERT_THAT(Exists(base_path), IsPosixErrorOkAndHolds(false));
- ASSERT_NO_ERRNO(RecursivelyCreateDir(base_path));
-
- const std::string a = JoinPath(root.path(), "a");
- auto listing = ASSERT_NO_ERRNO_AND_VALUE(ListDir(a, true));
- ASSERT_THAT(listing, ::testing::Contains("b"));
- ASSERT_EQ(listing.size(), 1);
-
- listing = ASSERT_NO_ERRNO_AND_VALUE(ListDir(a, false));
- ASSERT_THAT(listing, ::testing::Contains("."));
- ASSERT_THAT(listing, ::testing::Contains(".."));
- ASSERT_THAT(listing, ::testing::Contains("b"));
- ASSERT_EQ(listing.size(), 3);
-
- const std::string sub_path = JoinPath(root.path(), "/a/b/c/d/e/f");
-
- ASSERT_NO_ERRNO(
- CreateWithContents(JoinPath(Dirname(sub_path), "file"), "Hello World"));
- std::string contents = "";
- ASSERT_NO_ERRNO(GetContents(JoinPath(Dirname(sub_path), "file"), &contents));
- ASSERT_EQ(contents, "Hello World");
-
- ASSERT_NO_ERRNO(RecursivelyDelete(sub_path, nullptr, nullptr));
- ASSERT_THAT(Exists(sub_path), IsPosixErrorOkAndHolds(false));
-
- // The parent of the subpath (directory e) should still exist.
- ASSERT_THAT(Exists(Dirname(sub_path)), IsPosixErrorOkAndHolds(true));
-
- // The file we created along side f should also still exist.
- ASSERT_THAT(Exists(JoinPath(Dirname(sub_path), "file")),
- IsPosixErrorOkAndHolds(true));
-}
-} // namespace
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/fuchsia_capability_util.cc b/test/util/fuchsia_capability_util.cc
deleted file mode 100644
index bbe8643e7..000000000
--- a/test/util/fuchsia_capability_util.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2021 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifdef __Fuchsia__
-
-#include <netinet/if_ether.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-#include "test/util/socket_util.h"
-
-namespace gvisor {
-namespace testing {
-
-// On Linux, access to raw IP and packet socket is controlled by a single
-// capability (CAP_NET_RAW). However on Fuchsia, access to raw IP and packet
-// sockets are controlled by separate capabilities/protocols.
-
-namespace {
-
-PosixErrorOr<bool> HaveSocketCapability(int domain, int type, int protocol) {
- // Fuchsia does not have a platform supported way to check the protocols made
- // available to a sandbox. As a workaround, simply try to create the specified
- // socket and assume no access if we get a no permissions error.
- auto s = Socket(domain, type, protocol);
- if (s.ok()) {
- return true;
- }
- if (s.error().errno_value() == EPERM) {
- return false;
- }
- return s.error();
-}
-
-} // namespace
-
-PosixErrorOr<bool> HaveRawIPSocketCapability() {
- static PosixErrorOr<bool> result(false);
- static std::once_flag once;
-
- std::call_once(once, [&]() {
- result = HaveSocketCapability(AF_INET, SOCK_RAW, IPPROTO_UDP);
- });
-
- return result;
-}
-
-PosixErrorOr<bool> HavePacketSocketCapability() {
- static PosixErrorOr<bool> result(false);
- static std::once_flag once;
-
- std::call_once(once, [&]() {
- result = HaveSocketCapability(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- });
-
- return result;
-}
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // __Fuchsia__
diff --git a/test/util/fuse_util.cc b/test/util/fuse_util.cc
deleted file mode 100644
index 027f8386c..000000000
--- a/test/util/fuse_util.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// Licensed 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 "test/util/fuse_util.h"
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <string>
-
-namespace gvisor {
-namespace testing {
-
-// Create a default FuseAttr struct with specified mode, inode, and size.
-fuse_attr DefaultFuseAttr(mode_t mode, uint64_t inode, uint64_t size) {
- const int time_sec = 1595436289;
- const int time_nsec = 134150844;
- return (struct fuse_attr){
- .ino = inode,
- .size = size,
- .blocks = 4,
- .atime = time_sec,
- .mtime = time_sec,
- .ctime = time_sec,
- .atimensec = time_nsec,
- .mtimensec = time_nsec,
- .ctimensec = time_nsec,
- .mode = mode,
- .nlink = 2,
- .uid = 1234,
- .gid = 4321,
- .rdev = 12,
- .blksize = 4096,
- };
-}
-
-// Create response body with specified mode, nodeID, and size.
-fuse_entry_out DefaultEntryOut(mode_t mode, uint64_t node_id, uint64_t size) {
- struct fuse_entry_out default_entry_out = {
- .nodeid = node_id,
- .generation = 0,
- .entry_valid = 0,
- .attr_valid = 0,
- .entry_valid_nsec = 0,
- .attr_valid_nsec = 0,
- .attr = DefaultFuseAttr(mode, node_id, size),
- };
- return default_entry_out;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/fuse_util.h b/test/util/fuse_util.h
deleted file mode 100644
index 544fe1b38..000000000
--- a/test/util/fuse_util.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_FUSE_UTIL_H_
-#define GVISOR_TEST_UTIL_FUSE_UTIL_H_
-
-#include <linux/fuse.h>
-#include <sys/uio.h>
-
-#include <string>
-#include <vector>
-
-namespace gvisor {
-namespace testing {
-
-// The fundamental generation function with a single argument. If passed by
-// std::string or std::vector<char>, it will call specialized versions as
-// implemented below.
-template <typename T>
-std::vector<struct iovec> FuseGenerateIovecs(T &first) {
- return {(struct iovec){.iov_base = &first, .iov_len = sizeof(first)}};
-}
-
-// If an argument is of type std::string, it must be used in read-only scenario.
-// Because we are setting up iovec, which contains the original address of a
-// data structure, we have to drop const qualification. Usually used with
-// variable-length payload data.
-template <typename T = std::string>
-std::vector<struct iovec> FuseGenerateIovecs(std::string &first) {
- // Pad one byte for null-terminate c-string.
- return {(struct iovec){.iov_base = const_cast<char *>(first.c_str()),
- .iov_len = first.size() + 1}};
-}
-
-// If an argument is of type std::vector<char>, it must be used in write-only
-// scenario and the size of the variable must be greater than or equal to the
-// size of the expected data. Usually used with variable-length payload data.
-template <typename T = std::vector<char>>
-std::vector<struct iovec> FuseGenerateIovecs(std::vector<char> &first) {
- return {(struct iovec){.iov_base = first.data(), .iov_len = first.size()}};
-}
-
-// A helper function to set up an array of iovec struct for testing purpose.
-// Use variadic class template to generalize different numbers and different
-// types of FUSE structs.
-template <typename T, typename... Types>
-std::vector<struct iovec> FuseGenerateIovecs(T &first, Types &...args) {
- auto first_iovec = FuseGenerateIovecs(first);
- auto iovecs = FuseGenerateIovecs(args...);
- first_iovec.insert(std::end(first_iovec), std::begin(iovecs),
- std::end(iovecs));
- return first_iovec;
-}
-
-// Create a fuse_attr filled with the specified mode and inode.
-fuse_attr DefaultFuseAttr(mode_t mode, uint64_t inode, uint64_t size = 512);
-
-// Return a fuse_entry_out FUSE server response body.
-fuse_entry_out DefaultEntryOut(mode_t mode, uint64_t node_id,
- uint64_t size = 512);
-
-} // namespace testing
-} // namespace gvisor
-#endif // GVISOR_TEST_UTIL_FUSE_UTIL_H_
diff --git a/test/util/linux_capability_util.cc b/test/util/linux_capability_util.cc
deleted file mode 100644
index 7218aa4ac..000000000
--- a/test/util/linux_capability_util.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifdef __linux__
-
-#include "test/util/linux_capability_util.h"
-
-#include <linux/capability.h>
-#include <sched.h>
-#include <sys/mman.h>
-#include <sys/wait.h>
-
-#include <iostream>
-
-#include "absl/strings/str_cat.h"
-#include "test/util/memory_util.h"
-#include "test/util/posix_error.h"
-#include "test/util/save_util.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-PosixErrorOr<bool> HaveRawIPSocketCapability() {
- return HaveCapability(CAP_NET_RAW);
-}
-
-PosixErrorOr<bool> HavePacketSocketCapability() {
- return HaveCapability(CAP_NET_RAW);
-}
-
-PosixErrorOr<bool> CanCreateUserNamespace() {
- // The most reliable way to determine if userns creation is possible is by
- // trying to create one; see below.
- ASSIGN_OR_RETURN_ERRNO(
- auto child_stack,
- MmapAnon(kPageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE));
- int const child_pid = clone(
- +[](void*) { return 0; },
- reinterpret_cast<void*>(child_stack.addr() + kPageSize),
- CLONE_NEWUSER | SIGCHLD, /* arg = */ nullptr);
- if (child_pid > 0) {
- int status;
- int const ret = waitpid(child_pid, &status, /* options = */ 0);
- MaybeSave();
- if (ret < 0) {
- return PosixError(errno, "waitpid");
- }
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- return PosixError(
- ESRCH, absl::StrCat("child process exited with status ", status));
- }
- return true;
- } else if (errno == EPERM) {
- // Per clone(2), EPERM can be returned if:
- //
- // - "CLONE_NEWUSER was specified in flags, but either the effective user ID
- // or the effective group ID of the caller does not have a mapping in the
- // parent namespace (see user_namespaces(7))."
- //
- // - "(since Linux 3.9) CLONE_NEWUSER was specified in flags and the caller
- // is in a chroot environment (i.e., the caller's root directory does
- // not match the root directory of the mount namespace in which it
- // resides)."
- std::cerr << "clone(CLONE_NEWUSER) failed with EPERM" << std::endl;
- return false;
- } else if (errno == EUSERS) {
- // "(since Linux 3.11) CLONE_NEWUSER was specified in flags, and the call
- // would cause the limit on the number of nested user namespaces to be
- // exceeded. See user_namespaces(7)."
- std::cerr << "clone(CLONE_NEWUSER) failed with EUSERS" << std::endl;
- return false;
- } else {
- // Unexpected error code; indicate an actual error.
- return PosixError(errno, "clone(CLONE_NEWUSER)");
- }
-}
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // __linux__
diff --git a/test/util/linux_capability_util.h b/test/util/linux_capability_util.h
deleted file mode 100644
index be94ebd19..000000000
--- a/test/util/linux_capability_util.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-// Utilities for testing capabilities on Linux.
-
-#ifndef GVISOR_TEST_UTIL_LINUX_CAPABILITY_UTIL_H_
-#define GVISOR_TEST_UTIL_LINUX_CAPABILITY_UTIL_H_
-
-#ifdef __linux__
-
-#include <errno.h>
-#include <linux/capability.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include "test/util/cleanup.h"
-#include "test/util/posix_error.h"
-#include "test/util/save_util.h"
-#include "test/util/test_util.h"
-
-#ifndef _LINUX_CAPABILITY_VERSION_3
-#error Expecting _LINUX_CAPABILITY_VERSION_3 support
-#endif
-
-namespace gvisor {
-namespace testing {
-
-// HaveCapability returns true if the process has the specified EFFECTIVE
-// capability.
-inline PosixErrorOr<bool> HaveCapability(int cap) {
- if (!cap_valid(cap)) {
- return PosixError(EINVAL, "Invalid capability");
- }
-
- struct __user_cap_header_struct header = {_LINUX_CAPABILITY_VERSION_3, 0};
- struct __user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3] = {};
- RETURN_ERROR_IF_SYSCALL_FAIL(syscall(__NR_capget, &header, &caps));
- MaybeSave();
-
- return (caps[CAP_TO_INDEX(cap)].effective & CAP_TO_MASK(cap)) != 0;
-}
-
-// SetCapability sets the specified EFFECTIVE capability.
-inline PosixError SetCapability(int cap, bool set) {
- if (!cap_valid(cap)) {
- return PosixError(EINVAL, "Invalid capability");
- }
-
- struct __user_cap_header_struct header = {_LINUX_CAPABILITY_VERSION_3, 0};
- struct __user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3] = {};
- RETURN_ERROR_IF_SYSCALL_FAIL(syscall(__NR_capget, &header, &caps));
- MaybeSave();
-
- if (set) {
- caps[CAP_TO_INDEX(cap)].effective |= CAP_TO_MASK(cap);
- } else {
- caps[CAP_TO_INDEX(cap)].effective &= ~CAP_TO_MASK(cap);
- }
- header = {_LINUX_CAPABILITY_VERSION_3, 0};
- RETURN_ERROR_IF_SYSCALL_FAIL(syscall(__NR_capset, &header, &caps));
- MaybeSave();
-
- return NoError();
-}
-
-// DropPermittedCapability drops the specified PERMITTED. The EFFECTIVE
-// capabilities must be a subset of PERMITTED, so those are dropped as well.
-inline PosixError DropPermittedCapability(int cap) {
- if (!cap_valid(cap)) {
- return PosixError(EINVAL, "Invalid capability");
- }
-
- struct __user_cap_header_struct header = {_LINUX_CAPABILITY_VERSION_3, 0};
- struct __user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3] = {};
- RETURN_ERROR_IF_SYSCALL_FAIL(syscall(__NR_capget, &header, &caps));
- MaybeSave();
-
- caps[CAP_TO_INDEX(cap)].effective &= ~CAP_TO_MASK(cap);
- caps[CAP_TO_INDEX(cap)].permitted &= ~CAP_TO_MASK(cap);
-
- header = {_LINUX_CAPABILITY_VERSION_3, 0};
- RETURN_ERROR_IF_SYSCALL_FAIL(syscall(__NR_capset, &header, &caps));
- MaybeSave();
-
- return NoError();
-}
-
-PosixErrorOr<bool> CanCreateUserNamespace();
-
-class AutoCapability {
- public:
- AutoCapability(int cap, bool set) : cap_(cap), set_(set) {
- const bool has = EXPECT_NO_ERRNO_AND_VALUE(HaveCapability(cap));
- if (set != has) {
- EXPECT_NO_ERRNO(SetCapability(cap_, set_));
- applied_ = true;
- }
- }
-
- ~AutoCapability() {
- if (applied_) {
- EXPECT_NO_ERRNO(SetCapability(cap_, !set_));
- }
- }
-
- private:
- int cap_;
- bool set_;
- bool applied_ = false;
-};
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // __linux__
-
-#endif // GVISOR_TEST_UTIL_LINUX_CAPABILITY_UTIL_H_
diff --git a/test/util/logging.cc b/test/util/logging.cc
deleted file mode 100644
index 5fadb076b..000000000
--- a/test/util/logging.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/logging.h"
-
-#include <errno.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-namespace gvisor {
-namespace testing {
-
-namespace {
-
-// We implement this here instead of using test_util to avoid cyclic
-// dependencies.
-int Write(int fd, const char* buf, size_t size) {
- size_t written = 0;
- while (written < size) {
- int res = write(fd, buf + written, size - written);
- if (res < 0 && errno == EINTR) {
- continue;
- } else if (res <= 0) {
- break;
- }
-
- written += res;
- }
- return static_cast<int>(written);
-}
-
-// Write 32-bit decimal number to fd.
-int WriteNumber(int fd, uint32_t val) {
- constexpr char kDigits[] = "0123456789";
- constexpr int kBase = 10;
-
- // 10 chars for 32-bit number in decimal, 1 char for the NUL-terminator.
- constexpr int kBufferSize = 11;
- char buf[kBufferSize];
-
- // Convert the number to string.
- char* s = buf + sizeof(buf) - 1;
- size_t size = 0;
-
- *s = '\0';
- do {
- s--;
- size++;
-
- *s = kDigits[val % kBase];
- val /= kBase;
- } while (val);
-
- return Write(fd, s, size);
-}
-
-} // namespace
-
-void CheckFailure(const char* cond, size_t cond_size, const char* msg,
- size_t msg_size, int errno_value) {
- constexpr char kCheckFailure[] = "Check failed: ";
- Write(2, kCheckFailure, sizeof(kCheckFailure) - 1);
- Write(2, cond, cond_size);
-
- if (msg != nullptr) {
- Write(2, ": ", 2);
- Write(2, msg, msg_size);
- }
-
- if (errno_value != 0) {
- constexpr char kErrnoMessage[] = " (errno ";
- Write(2, kErrnoMessage, sizeof(kErrnoMessage) - 1);
- WriteNumber(2, errno_value);
- Write(2, ")", 1);
- }
-
- Write(2, "\n", 1);
-
- abort();
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/logging.h b/test/util/logging.h
deleted file mode 100644
index 5c17f1233..000000000
--- a/test/util/logging.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_LOGGING_H_
-#define GVISOR_TEST_UTIL_LOGGING_H_
-
-#include <stddef.h>
-
-namespace gvisor {
-namespace testing {
-
-void CheckFailure(const char* cond, size_t cond_size, const char* msg,
- size_t msg_size, int errno_value);
-
-// If cond is false, aborts the current process.
-//
-// This macro is async-signal-safe.
-#define TEST_CHECK(cond) \
- do { \
- if (!(cond)) { \
- ::gvisor::testing::CheckFailure(#cond, sizeof(#cond) - 1, nullptr, \
- 0, 0); \
- } \
- } while (0)
-
-// If cond is false, logs msg then aborts the current process.
-//
-// This macro is async-signal-safe.
-#define TEST_CHECK_MSG(cond, msg) \
- do { \
- if (!(cond)) { \
- ::gvisor::testing::CheckFailure(#cond, sizeof(#cond) - 1, msg, \
- sizeof(msg) - 1, 0); \
- } \
- } while (0)
-
-// If cond is false, logs errno, then aborts the current process.
-//
-// This macro is async-signal-safe.
-#define TEST_PCHECK(cond) \
- do { \
- if (!(cond)) { \
- ::gvisor::testing::CheckFailure(#cond, sizeof(#cond) - 1, nullptr, \
- 0, errno); \
- } \
- } while (0)
-
-// If cond is false, logs msg and errno, then aborts the current process.
-//
-// This macro is async-signal-safe.
-#define TEST_PCHECK_MSG(cond, msg) \
- do { \
- if (!(cond)) { \
- ::gvisor::testing::CheckFailure(#cond, sizeof(#cond) - 1, msg, \
- sizeof(msg) - 1, errno); \
- } \
- } while (0)
-
-// expr must return PosixErrorOr<T>. The current process is aborted if
-// !PosixError<T>.ok().
-//
-// This macro is async-signal-safe.
-#define TEST_CHECK_NO_ERRNO(expr) \
- ({ \
- auto _expr_result = (expr); \
- if (!_expr_result.ok()) { \
- ::gvisor::testing::CheckFailure( \
- #expr, sizeof(#expr) - 1, nullptr, 0, \
- _expr_result.error().errno_value()); \
- } \
- })
-
-// expr must return PosixErrorOr<T>. The current process is aborted if
-// !PosixError<T>.ok(). Otherwise, PosixErrorOr<T> value is returned.
-//
-// This macro is async-signal-safe.
-#define TEST_CHECK_NO_ERRNO_AND_VALUE(expr) \
- ({ \
- auto _expr_result = (expr); \
- if (!_expr_result.ok()) { \
- ::gvisor::testing::CheckFailure( \
- #expr, sizeof(#expr) - 1, nullptr, 0, \
- _expr_result.error().errno_value()); \
- } \
- std::move(_expr_result).ValueOrDie(); \
- })
-
-// cond must be greater or equal than 0. Used to test result of syscalls.
-//
-// This macro is async-signal-safe.
-#define TEST_CHECK_SUCCESS(cond) TEST_PCHECK((cond) >= 0)
-
-// cond must be -1 and errno must match errno_value. Used to test errors from
-// syscalls.
-//
-// This macro is async-signal-safe.
-#define TEST_CHECK_ERRNO(cond, errno_value) \
- do { \
- TEST_PCHECK((cond) == -1); \
- TEST_PCHECK_MSG(errno == (errno_value), #cond " expected " #errno_value); \
- } while (0)
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_LOGGING_H_
diff --git a/test/util/memory_util.h b/test/util/memory_util.h
deleted file mode 100644
index e189b73e8..000000000
--- a/test/util/memory_util.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_MEMORY_UTIL_H_
-#define GVISOR_TEST_UTIL_MEMORY_UTIL_H_
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/mman.h>
-
-#include "absl/strings/str_format.h"
-#include "absl/strings/string_view.h"
-#include "test/util/logging.h"
-#include "test/util/posix_error.h"
-#include "test/util/save_util.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-// RAII type for mmap'ed memory. Only usable in tests due to use of a test-only
-// macro that can't be named without invoking the presubmit's wrath.
-class Mapping {
- public:
- // Constructs a mapping that owns nothing.
- Mapping() = default;
-
- // Constructs a mapping that owns the mmapped memory [ptr, ptr+len). Most
- // users should use Mmap or MmapAnon instead.
- Mapping(void* ptr, size_t len) : ptr_(ptr), len_(len) {}
-
- Mapping(Mapping&& orig) : ptr_(orig.ptr_), len_(orig.len_) { orig.release(); }
-
- Mapping& operator=(Mapping&& orig) {
- ptr_ = orig.ptr_;
- len_ = orig.len_;
- orig.release();
- return *this;
- }
-
- Mapping(Mapping const&) = delete;
- Mapping& operator=(Mapping const&) = delete;
-
- ~Mapping() { reset(); }
-
- void* ptr() const { return ptr_; }
- size_t len() const { return len_; }
-
- // Returns a pointer to the end of the mapping. Useful for when the mapping
- // is used as a thread stack.
- void* endptr() const { return reinterpret_cast<void*>(addr() + len_); }
-
- // Returns the start of this mapping cast to uintptr_t for ease of pointer
- // arithmetic.
- uintptr_t addr() const { return reinterpret_cast<uintptr_t>(ptr_); }
-
- // Returns the end of this mapping cast to uintptr_t for ease of pointer
- // arithmetic.
- uintptr_t endaddr() const { return reinterpret_cast<uintptr_t>(endptr()); }
-
- // Returns this mapping as a StringPiece for ease of comparison.
- //
- // This function is named view in anticipation of the eventual replacement of
- // StringPiece with std::string_view.
- absl::string_view view() const {
- return absl::string_view(static_cast<char const*>(ptr_), len_);
- }
-
- // These are both named reset for consistency with standard smart pointers.
-
- void reset(void* ptr, size_t len) {
- if (len_) {
- TEST_PCHECK(munmap(ptr_, len_) == 0);
- }
- ptr_ = ptr;
- len_ = len;
- }
-
- void reset() { reset(nullptr, 0); }
-
- void release() {
- ptr_ = nullptr;
- len_ = 0;
- }
-
- private:
- void* ptr_ = nullptr;
- size_t len_ = 0;
-};
-
-// Wrapper around mmap(2) that returns a Mapping.
-inline PosixErrorOr<Mapping> Mmap(void* addr, size_t length, int prot,
- int flags, int fd, off_t offset) {
- void* ptr = mmap(addr, length, prot, flags, fd, offset);
- if (ptr == MAP_FAILED) {
- return PosixError(
- errno, absl::StrFormat("mmap(%p, %d, %x, %x, %d, %d)", addr, length,
- prot, flags, fd, offset));
- }
- MaybeSave();
- return Mapping(ptr, length);
-}
-
-// Convenience wrapper around Mmap for anonymous mappings.
-inline PosixErrorOr<Mapping> MmapAnon(size_t length, int prot, int flags) {
- return Mmap(nullptr, length, prot, flags | MAP_ANONYMOUS, -1, 0);
-}
-
-// Wrapper for mremap that returns a PosixErrorOr<>, since the return type of
-// void* isn't directly compatible with SyscallSucceeds.
-inline PosixErrorOr<void*> Mremap(void* old_address, size_t old_size,
- size_t new_size, int flags,
- void* new_address) {
- void* rv = mremap(old_address, old_size, new_size, flags, new_address);
- if (rv == MAP_FAILED) {
- return PosixError(errno, "mremap failed");
- }
- return rv;
-}
-
-// Returns true if the page containing addr is mapped.
-inline bool IsMapped(uintptr_t addr) {
- int const rv = msync(reinterpret_cast<void*>(addr & ~(kPageSize - 1)),
- kPageSize, MS_ASYNC);
- if (rv == 0) {
- return true;
- }
- TEST_PCHECK_MSG(errno == ENOMEM, "msync failed with unexpected errno");
- return false;
-}
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_MEMORY_UTIL_H_
diff --git a/test/util/mount_util.cc b/test/util/mount_util.cc
deleted file mode 100644
index 48640d6a1..000000000
--- a/test/util/mount_util.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2021 The gVisor Authors.
-//
-// Licensed 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 "test/util/mount_util.h"
-
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include "absl/strings/numbers.h"
-#include "absl/strings/str_split.h"
-
-namespace gvisor {
-namespace testing {
-
-PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries() {
- std::string content;
- RETURN_IF_ERRNO(GetContents("/proc/self/mounts", &content));
- return ProcSelfMountsEntriesFrom(content);
-}
-
-PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntriesFrom(
- const std::string& content) {
- std::vector<ProcMountsEntry> entries;
- std::vector<std::string> lines =
- absl::StrSplit(content, absl::ByChar('\n'), absl::AllowEmpty());
- std::cerr << "<contents of /proc/self/mounts>" << std::endl;
- for (const std::string& line : lines) {
- std::cerr << line << std::endl;
- if (line.empty()) {
- continue;
- }
-
- // Parse a single entry from /proc/self/mounts.
- //
- // Example entries:
- //
- // sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
- // proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
- // ^ ^ ^ ^ ^ ^
- // 0 1 2 3 4 5
-
- ProcMountsEntry entry;
- std::vector<std::string> fields =
- absl::StrSplit(line, absl::ByChar(' '), absl::AllowEmpty());
- if (fields.size() != 6) {
- return PosixError(
- EINVAL, absl::StrFormat("Not enough tokens, got %d, content: <<%s>>",
- fields.size(), content));
- }
-
- entry.spec = fields[0];
- entry.mount_point = fields[1];
- entry.fstype = fields[2];
- entry.mount_opts = fields[3];
- ASSIGN_OR_RETURN_ERRNO(entry.dump, Atoi<uint32_t>(fields[4]));
- ASSIGN_OR_RETURN_ERRNO(entry.fsck, Atoi<uint32_t>(fields[5]));
-
- entries.push_back(entry);
- }
- std::cerr << "<end of /proc/self/mounts>" << std::endl;
-
- return entries;
-}
-
-PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntries() {
- std::string content;
- RETURN_IF_ERRNO(GetContents("/proc/self/mountinfo", &content));
- return ProcSelfMountInfoEntriesFrom(content);
-}
-
-PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntriesFrom(
- const std::string& content) {
- std::vector<ProcMountInfoEntry> entries;
- std::vector<std::string> lines =
- absl::StrSplit(content, absl::ByChar('\n'), absl::AllowEmpty());
- std::cerr << "<contents of /proc/self/mountinfo>" << std::endl;
- for (const std::string& line : lines) {
- std::cerr << line << std::endl;
- if (line.empty()) {
- continue;
- }
-
- // Parse a single entry from /proc/self/mountinfo.
- //
- // Example entries:
- //
- // 22 28 0:20 / /sys rw,relatime shared:7 - sysfs sysfs rw
- // 23 28 0:21 / /proc rw,relatime shared:14 - proc proc rw
- // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
- // 0 1 2 3 4 5 6 7 8 9 10
-
- ProcMountInfoEntry entry;
- std::vector<std::string> fields =
- absl::StrSplit(line, absl::ByChar(' '), absl::AllowEmpty());
- if (fields.size() < 10 || fields.size() > 11) {
- return PosixError(
- EINVAL, absl::StrFormat(
- "Unexpected number of tokens, got %d, content: <<%s>>",
- fields.size(), content));
- }
-
- ASSIGN_OR_RETURN_ERRNO(entry.id, Atoi<uint64_t>(fields[0]));
- ASSIGN_OR_RETURN_ERRNO(entry.parent_id, Atoi<uint64_t>(fields[1]));
-
- std::vector<std::string> devs =
- absl::StrSplit(fields[2], absl::ByChar(':'));
- if (devs.size() != 2) {
- return PosixError(
- EINVAL,
- absl::StrFormat(
- "Failed to parse dev number field %s: too many tokens, got %d",
- fields[2], devs.size()));
- }
- ASSIGN_OR_RETURN_ERRNO(entry.major, Atoi<dev_t>(devs[0]));
- ASSIGN_OR_RETURN_ERRNO(entry.minor, Atoi<dev_t>(devs[1]));
-
- entry.root = fields[3];
- entry.mount_point = fields[4];
- entry.mount_opts = fields[5];
-
- // The optional field (fields[6]) may or may not be present. We know based
- // on the total number of tokens.
- int off = -1;
- if (fields.size() == 11) {
- entry.optional = fields[6];
- off = 0;
- }
- // Field 7 is the optional field terminator char '-'.
- entry.fstype = fields[8 + off];
- entry.mount_source = fields[9 + off];
- entry.super_opts = fields[10 + off];
-
- entries.push_back(entry);
- }
- std::cerr << "<end of /proc/self/mountinfo>" << std::endl;
-
- return entries;
-}
-
-absl::flat_hash_map<std::string, std::string> ParseMountOptions(
- std::string mopts) {
- absl::flat_hash_map<std::string, std::string> entries;
- const std::vector<std::string> tokens =
- absl::StrSplit(mopts, absl::ByChar(','), absl::AllowEmpty());
- for (const auto& token : tokens) {
- std::vector<std::string> kv =
- absl::StrSplit(token, absl::MaxSplits('=', 1));
- if (kv.size() == 2) {
- entries[kv[0]] = kv[1];
- } else if (kv.size() == 1) {
- entries[kv[0]] = "";
- } else {
- TEST_CHECK_MSG(
- false,
- absl::StrFormat(
- "Invalid mount option token '%s', was split into %d subtokens",
- token, kv.size())
- .c_str());
- }
- }
- return entries;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/mount_util.h b/test/util/mount_util.h
deleted file mode 100644
index 3f8a1c0f1..000000000
--- a/test/util/mount_util.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_MOUNT_UTIL_H_
-#define GVISOR_TEST_UTIL_MOUNT_UTIL_H_
-
-#include <errno.h>
-#include <sys/mount.h>
-
-#include <functional>
-#include <string>
-
-#include "gmock/gmock.h"
-#include "absl/container/flat_hash_map.h"
-#include "test/util/cleanup.h"
-#include "test/util/posix_error.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-// Mount mounts the filesystem, and unmounts when the returned reference is
-// destroyed.
-inline PosixErrorOr<Cleanup> Mount(const std::string& source,
- const std::string& target,
- const std::string& fstype,
- uint64_t mountflags, const std::string& data,
- uint64_t umountflags) {
- if (mount(source.c_str(), target.c_str(), fstype.c_str(), mountflags,
- data.c_str()) == -1) {
- return PosixError(errno, "mount failed");
- }
- return Cleanup([target, umountflags]() {
- EXPECT_THAT(umount2(target.c_str(), umountflags), SyscallSucceeds());
- });
-}
-
-struct ProcMountsEntry {
- std::string spec;
- std::string mount_point;
- std::string fstype;
- std::string mount_opts;
- uint32_t dump;
- uint32_t fsck;
-};
-
-// ProcSelfMountsEntries returns a parsed representation of /proc/self/mounts.
-PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries();
-
-// ProcSelfMountsEntries returns a parsed representation of mounts from the
-// provided content.
-PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntriesFrom(
- const std::string& content);
-
-struct ProcMountInfoEntry {
- uint64_t id;
- uint64_t parent_id;
- dev_t major;
- dev_t minor;
- std::string root;
- std::string mount_point;
- std::string mount_opts;
- std::string optional;
- std::string fstype;
- std::string mount_source;
- std::string super_opts;
-};
-
-// ProcSelfMountInfoEntries returns a parsed representation of
-// /proc/self/mountinfo.
-PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntries();
-
-// ProcSelfMountInfoEntriesFrom returns a parsed representation of
-// mountinfo from the provided content.
-PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntriesFrom(
- const std::string&);
-
-// Interprets the input string mopts as a comma separated list of mount
-// options. A mount option can either be just a value, or a key=value pair. For
-// example, the string "rw,relatime,fd=7" will be parsed into a map like { "rw":
-// "", "relatime": "", "fd": "7" }.
-absl::flat_hash_map<std::string, std::string> ParseMountOptions(
- std::string mopts);
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_MOUNT_UTIL_H_
diff --git a/test/util/mount_util_test.cc b/test/util/mount_util_test.cc
deleted file mode 100644
index 2bcb6cc43..000000000
--- a/test/util/mount_util_test.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/mount_util.h"
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-namespace {
-
-TEST(ParseMounts, Mounts) {
- auto entries = ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountsEntriesFrom(
- R"proc(sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
-proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
- /mnt tmpfs rw,noexec 0 0
-)proc"));
- EXPECT_EQ(entries.size(), 3);
-}
-
-TEST(ParseMounts, MountInfo) {
- auto entries = ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntriesFrom(
- R"proc(22 28 0:20 / /sys rw,relatime shared:7 - sysfs sysfs rw
-23 28 0:21 / /proc rw,relatime shared:14 - proc proc rw
-2007 8844 0:278 / /mnt rw,noexec - tmpfs rw,mode=123,uid=268601820,gid=5000
-)proc"));
- EXPECT_EQ(entries.size(), 3);
-}
-
-} // namespace
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/multiprocess_util.cc b/test/util/multiprocess_util.cc
deleted file mode 100644
index a6b0de24b..000000000
--- a/test/util/multiprocess_util.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/multiprocess_util.h"
-
-#include <asm/unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/prctl.h>
-#include <unistd.h>
-
-#include "absl/strings/str_cat.h"
-#include "test/util/cleanup.h"
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-#include "test/util/save_util.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-namespace {
-
-// exec_fn wraps a variant of the exec family, e.g. execve or execveat.
-PosixErrorOr<Cleanup> ForkAndExecHelper(const std::function<void()>& exec_fn,
- const std::function<void()>& fn,
- pid_t* child, int* execve_errno) {
- int pfds[2];
- int ret = pipe2(pfds, O_CLOEXEC);
- if (ret < 0) {
- return PosixError(errno, "pipe failed");
- }
- FileDescriptor rfd(pfds[0]);
- FileDescriptor wfd(pfds[1]);
-
- int parent_stdout = dup(STDOUT_FILENO);
- if (parent_stdout < 0) {
- return PosixError(errno, "dup stdout");
- }
- int parent_stderr = dup(STDERR_FILENO);
- if (parent_stdout < 0) {
- return PosixError(errno, "dup stderr");
- }
-
- pid_t pid = fork();
- if (pid < 0) {
- return PosixError(errno, "fork failed");
- } else if (pid == 0) {
- // Child.
- rfd.reset();
- if (dup2(parent_stdout, STDOUT_FILENO) < 0) {
- _exit(3);
- }
- if (dup2(parent_stderr, STDERR_FILENO) < 0) {
- _exit(4);
- }
- close(parent_stdout);
- close(parent_stderr);
-
- // Clean ourself up in case the parent doesn't.
- if (prctl(PR_SET_PDEATHSIG, SIGKILL)) {
- _exit(3);
- }
-
- if (fn) {
- fn();
- }
-
- // Call variant of exec function.
- exec_fn();
-
- int error = errno;
- if (WriteFd(pfds[1], &error, sizeof(error)) != sizeof(error)) {
- // We can't do much if the write fails, but we can at least exit with a
- // different code.
- _exit(2);
- }
- _exit(1);
- }
-
- // Parent.
- if (child) {
- *child = pid;
- }
-
- auto cleanup = Cleanup([pid] {
- kill(pid, SIGKILL);
- RetryEINTR(waitpid)(pid, nullptr, 0);
- });
-
- wfd.reset();
-
- int read_errno;
- ret = ReadFd(rfd.get(), &read_errno, sizeof(read_errno));
- if (ret == 0) {
- // Other end of the pipe closed, execve must have succeeded.
- read_errno = 0;
- } else if (ret < 0) {
- return PosixError(errno, "read pipe failed");
- } else if (ret != sizeof(read_errno)) {
- return PosixError(EPIPE, absl::StrCat("pipe read wrong size ", ret));
- }
-
- if (execve_errno) {
- *execve_errno = read_errno;
- }
-
- return std::move(cleanup);
-}
-
-} // namespace
-
-PosixErrorOr<Cleanup> ForkAndExec(const std::string& filename,
- const ExecveArray& argv,
- const ExecveArray& envv,
- const std::function<void()>& fn, pid_t* child,
- int* execve_errno) {
- char* const* argv_data = argv.get();
- char* const* envv_data = envv.get();
- const std::function<void()> exec_fn = [=] {
- execve(filename.c_str(), argv_data, envv_data);
- };
- return ForkAndExecHelper(exec_fn, fn, child, execve_errno);
-}
-
-PosixErrorOr<Cleanup> ForkAndExecveat(const int32_t dirfd,
- const std::string& pathname,
- const ExecveArray& argv,
- const ExecveArray& envv, const int flags,
- const std::function<void()>& fn,
- pid_t* child, int* execve_errno) {
- char* const* argv_data = argv.get();
- char* const* envv_data = envv.get();
- const std::function<void()> exec_fn = [=] {
- syscall(__NR_execveat, dirfd, pathname.c_str(), argv_data, envv_data,
- flags);
- };
- return ForkAndExecHelper(exec_fn, fn, child, execve_errno);
-}
-
-PosixErrorOr<int> InForkedProcess(const std::function<void()>& fn) {
- pid_t pid = fork();
- if (pid == 0) {
- fn();
- TEST_CHECK_MSG(!::testing::Test::HasFailure(),
- "EXPECT*/ASSERT* failed. These are not async-signal-safe "
- "and must not be called from fn.");
- _exit(0);
- }
- MaybeSave();
- if (pid < 0) {
- return PosixError(errno, "fork failed");
- }
-
- int status;
- if (waitpid(pid, &status, 0) < 0) {
- return PosixError(errno, "waitpid failed");
- }
-
- return status;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/multiprocess_util.h b/test/util/multiprocess_util.h
deleted file mode 100644
index 840fde4ee..000000000
--- a/test/util/multiprocess_util.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_MULTIPROCESS_UTIL_H_
-#define GVISOR_TEST_UTIL_MULTIPROCESS_UTIL_H_
-
-#include <unistd.h>
-
-#include <algorithm>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "absl/strings/string_view.h"
-#include "test/util/cleanup.h"
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-// Immutable holder for a dynamically-sized array of pointers to mutable char,
-// terminated by a null pointer, as required for the argv and envp arguments to
-// execve(2).
-class ExecveArray {
- public:
- // Constructs an empty ExecveArray.
- ExecveArray() = default;
-
- // Constructs an ExecveArray by copying strings from the given range. T must
- // be a range over ranges of char.
- template <typename T>
- explicit ExecveArray(T const& strs) : ExecveArray(strs.begin(), strs.end()) {}
-
- // Constructs an ExecveArray by copying strings from [first, last). InputIt
- // must be an input iterator over a range over char.
- template <typename InputIt>
- ExecveArray(InputIt first, InputIt last) {
- std::vector<size_t> offsets;
- auto output_it = std::back_inserter(str_);
- for (InputIt it = first; it != last; ++it) {
- offsets.push_back(str_.size());
- auto const& s = *it;
- std::copy(s.begin(), s.end(), output_it);
- str_.push_back('\0');
- }
- ptrs_.reserve(offsets.size() + 1);
- for (auto offset : offsets) {
- ptrs_.push_back(str_.data() + offset);
- }
- ptrs_.push_back(nullptr);
- }
-
- // Constructs an ExecveArray by copying strings from list. This overload must
- // exist independently of the single-argument template constructor because
- // std::initializer_list does not participate in template argument deduction
- // (i.e. cannot be type-inferred in an invocation of the templated
- // constructor).
- /* implicit */ ExecveArray(std::initializer_list<absl::string_view> list)
- : ExecveArray(list.begin(), list.end()) {}
-
- // Disable move construction and assignment since ptrs_ points into str_.
- ExecveArray(ExecveArray&&) = delete;
- ExecveArray& operator=(ExecveArray&&) = delete;
-
- char* const* get() const { return ptrs_.data(); }
- size_t get_size() { return str_.size(); }
-
- private:
- std::vector<char> str_;
- std::vector<char*> ptrs_;
-};
-
-// Simplified version of SubProcess. Returns OK and a cleanup function to kill
-// the child if it made it to execve.
-//
-// fn is run between fork and exec. If it needs to fail, it should exit the
-// process.
-//
-// The child pid is returned via child, if provided.
-// execve's error code is returned via execve_errno, if provided.
-PosixErrorOr<Cleanup> ForkAndExec(const std::string& filename,
- const ExecveArray& argv,
- const ExecveArray& envv,
- const std::function<void()>& fn, pid_t* child,
- int* execve_errno);
-
-inline PosixErrorOr<Cleanup> ForkAndExec(const std::string& filename,
- const ExecveArray& argv,
- const ExecveArray& envv, pid_t* child,
- int* execve_errno) {
- return ForkAndExec(
- filename, argv, envv, [] {}, child, execve_errno);
-}
-
-// Equivalent to ForkAndExec, except using dirfd and flags with execveat.
-PosixErrorOr<Cleanup> ForkAndExecveat(int32_t dirfd,
- const std::string& pathname,
- const ExecveArray& argv,
- const ExecveArray& envv, int flags,
- const std::function<void()>& fn,
- pid_t* child, int* execve_errno);
-
-inline PosixErrorOr<Cleanup> ForkAndExecveat(int32_t dirfd,
- const std::string& pathname,
- const ExecveArray& argv,
- const ExecveArray& envv, int flags,
- pid_t* child, int* execve_errno) {
- return ForkAndExecveat(
- dirfd, pathname, argv, envv, flags, [] {}, child, execve_errno);
-}
-
-// Calls fn in a forked subprocess and returns the exit status of the
-// subprocess.
-//
-// fn must be async-signal-safe. Use of ASSERT/EXPECT functions is prohibited.
-// Use TEST_CHECK variants instead.
-PosixErrorOr<int> InForkedProcess(const std::function<void()>& fn);
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_MULTIPROCESS_UTIL_H_
diff --git a/test/util/platform_util.cc b/test/util/platform_util.cc
deleted file mode 100644
index c9200d381..000000000
--- a/test/util/platform_util.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// Licensed 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 "test/util/platform_util.h"
-
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-PlatformSupport PlatformSupport32Bit() {
- if (GvisorPlatform() == Platform::kPtrace ||
- GvisorPlatform() == Platform::kKVM) {
- return PlatformSupport::NotSupported;
- } else {
- return PlatformSupport::Allowed;
- }
-}
-
-PlatformSupport PlatformSupportAlignmentCheck() {
- return PlatformSupport::Allowed;
-}
-
-PlatformSupport PlatformSupportMultiProcess() {
- return PlatformSupport::Allowed;
-}
-
-PlatformSupport PlatformSupportInt3() {
- if (GvisorPlatform() == Platform::kKVM) {
- return PlatformSupport::NotSupported;
- } else {
- return PlatformSupport::Allowed;
- }
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/platform_util.h b/test/util/platform_util.h
deleted file mode 100644
index 28cc92371..000000000
--- a/test/util/platform_util.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_PLATFORM_UTIL_H_
-#define GVISOR_TEST_UTIL_PLATFORM_UTIL_H_
-
-namespace gvisor {
-namespace testing {
-
-// PlatformSupport is a generic enumeration of classes of support.
-//
-// It is up to the individual functions and callers to agree on the precise
-// definition for each case. The document here generally refers to 32-bit
-// as an example. Many cases will use only NotSupported and Allowed.
-enum class PlatformSupport {
- // The feature is not supported on the current platform.
- //
- // In the case of 32-bit, this means that calls will generally be interpreted
- // as 64-bit calls, and there is no support for 32-bit binaries, long calls,
- // etc. This usually means that the underlying implementation just pretends
- // that 32-bit doesn't exist.
- NotSupported,
-
- // Calls will be ignored by the kernel with a fixed error.
- Ignored,
-
- // Calls will result in a SIGSEGV or similar fault.
- Segfault,
-
- // The feature is supported as expected.
- //
- // In the case of 32-bit, this means that the system call or far call will be
- // handled properly.
- Allowed,
-};
-
-PlatformSupport PlatformSupport32Bit();
-PlatformSupport PlatformSupportAlignmentCheck();
-PlatformSupport PlatformSupportMultiProcess();
-PlatformSupport PlatformSupportInt3();
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_PLATFORM_UTL_H_
diff --git a/test/util/posix_error.cc b/test/util/posix_error.cc
deleted file mode 100644
index 8522e4c81..000000000
--- a/test/util/posix_error.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/posix_error.h"
-
-#include <cassert>
-#include <cerrno>
-#include <cstring>
-#include <string>
-
-#include "absl/strings/str_cat.h"
-
-namespace gvisor {
-namespace testing {
-
-std::string PosixError::ToString() const {
- if (ok()) {
- return "No Error";
- }
-
- std::string ret;
-
- char strerrno_buf[1024] = {};
-
- auto res = strerror_r(errno_, strerrno_buf, sizeof(strerrno_buf));
-
-// The GNU version of strerror_r always returns a non-null char* pointing to a
-// buffer containing the stringified errno; the XSI version returns a positive
-// errno which indicates the result of writing the stringified errno into the
-// supplied buffer. The gymnastics below are needed to support both.
-#ifndef _GNU_SOURCE
- if (res != 0) {
- ret = absl::StrCat("PosixError(errno=", errno_, " strerror_r FAILED(", ret,
- "))");
- } else {
- ret = absl::StrCat("PosixError(errno=", errno_, " ", strerrno_buf, ")");
- }
-#else
- ret = absl::StrCat("PosixError(errno=", errno_, " ", res, ")");
-#endif
-
- if (strnlen(msg_, sizeof(msg_)) > 0) {
- ret.append(" ");
- ret.append(msg_);
- }
-
- return ret;
-}
-
-::std::ostream& operator<<(::std::ostream& os, const PosixError& e) {
- os << e.ToString();
- return os;
-}
-
-void PosixErrorIsMatcherCommonImpl::DescribeTo(std::ostream* os) const {
- *os << "has an errno value that ";
- code_matcher_.DescribeTo(os);
- *os << ", and has an error message that ";
- message_matcher_.DescribeTo(os);
-}
-
-void PosixErrorIsMatcherCommonImpl::DescribeNegationTo(std::ostream* os) const {
- *os << "has an errno value that ";
- code_matcher_.DescribeNegationTo(os);
- *os << ", or has an error message that ";
- message_matcher_.DescribeNegationTo(os);
-}
-
-bool PosixErrorIsMatcherCommonImpl::MatchAndExplain(
- const PosixError& error,
- ::testing::MatchResultListener* result_listener) const {
- ::testing::StringMatchResultListener inner_listener;
-
- inner_listener.Clear();
- if (!code_matcher_.MatchAndExplain(error.errno_value(), &inner_listener)) {
- return false;
- }
-
- if (!message_matcher_.Matches(error.message())) {
- return false;
- }
-
- return true;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/posix_error.h b/test/util/posix_error.h
deleted file mode 100644
index 40853cb21..000000000
--- a/test/util/posix_error.h
+++ /dev/null
@@ -1,459 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_POSIX_ERROR_H_
-#define GVISOR_TEST_UTIL_POSIX_ERROR_H_
-
-#include <string>
-
-#include "gmock/gmock.h"
-#include "absl/base/attributes.h"
-#include "absl/strings/string_view.h"
-#include "absl/types/variant.h"
-#include "test/util/logging.h"
-
-namespace gvisor {
-namespace testing {
-
-// PosixError must be async-signal-safe.
-class ABSL_MUST_USE_RESULT PosixError {
- public:
- PosixError() {}
-
- explicit PosixError(int errno_value) : errno_(errno_value) {}
-
- PosixError(int errno_value, std::string_view msg) : errno_(errno_value) {
- // Check that `msg` will fit, leaving room for '\0' at the end.
- TEST_CHECK(msg.size() < sizeof(msg_));
- msg.copy(msg_, msg.size());
- }
-
- PosixError(PosixError&& other) = default;
- PosixError& operator=(PosixError&& other) = default;
- PosixError(const PosixError&) = default;
- PosixError& operator=(const PosixError&) = default;
-
- bool ok() const { return errno_ == 0; }
-
- // Returns a reference to *this to make matchers compatible with
- // PosixErrorOr.
- const PosixError& error() const { return *this; }
-
- int errno_value() const { return errno_; }
- const char* message() const { return msg_; }
-
- // ToString produces a full string representation of this posix error
- // including the printable representation of the errno and the error message.
- std::string ToString() const;
-
- // Ignores any errors. This method does nothing except potentially suppress
- // complaints from any tools that are checking that errors are not dropped on
- // the floor.
- void IgnoreError() const {}
-
- private:
- int errno_ = 0;
- char msg_[1024] = {};
-};
-
-template <typename T>
-class ABSL_MUST_USE_RESULT PosixErrorOr {
- public:
- // A PosixErrorOr will check fail if it is constructed with NoError().
- PosixErrorOr(const PosixError& error);
- PosixErrorOr(const T& value);
- PosixErrorOr(T&& value);
-
- PosixErrorOr(PosixErrorOr&& other) = default;
- PosixErrorOr& operator=(PosixErrorOr&& other) = default;
- PosixErrorOr(const PosixErrorOr&) = default;
- PosixErrorOr& operator=(const PosixErrorOr&) = default;
-
- // Conversion copy/move constructor, T must be convertible from U.
- template <typename U>
- friend class PosixErrorOr;
-
- template <typename U>
- PosixErrorOr(PosixErrorOr<U> other);
-
- template <typename U>
- PosixErrorOr& operator=(PosixErrorOr<U> other);
-
- // Returns true if this PosixErrorOr contains some T.
- bool ok() const;
-
- // Return a copy of the contained PosixError or NoError().
- PosixError error() const;
-
- // Returns a reference to our current value, or CHECK-fails if !this->ok().
- const T& ValueOrDie() const&;
- T& ValueOrDie() &;
- const T&& ValueOrDie() const&&;
- T&& ValueOrDie() &&;
-
- // Ignores any errors. This method does nothing except potentially suppress
- // complaints from any tools that are checking that errors are not dropped on
- // the floor.
- void IgnoreError() const {}
-
- private:
- absl::variant<T, PosixError> value_;
-
- friend class PosixErrorIsMatcherCommonImpl;
-};
-
-template <typename T>
-PosixErrorOr<T>::PosixErrorOr(const PosixError& error) : value_(error) {
- TEST_CHECK_MSG(
- !error.ok(),
- "Constructing PosixErrorOr with NoError, eg. errno 0 is not allowed.");
-}
-
-template <typename T>
-PosixErrorOr<T>::PosixErrorOr(const T& value) : value_(value) {}
-
-template <typename T>
-PosixErrorOr<T>::PosixErrorOr(T&& value) : value_(std::move(value)) {}
-
-// Conversion copy/move constructor, T must be convertible from U.
-template <typename T>
-template <typename U>
-inline PosixErrorOr<T>::PosixErrorOr(PosixErrorOr<U> other) {
- if (absl::holds_alternative<U>(other.value_)) {
- // T is convertible from U.
- value_ = absl::get<U>(std::move(other.value_));
- } else if (absl::holds_alternative<PosixError>(other.value_)) {
- value_ = absl::get<PosixError>(std::move(other.value_));
- } else {
- TEST_CHECK_MSG(false, "PosixErrorOr does not contain PosixError or value");
- }
-}
-
-template <typename T>
-template <typename U>
-inline PosixErrorOr<T>& PosixErrorOr<T>::operator=(PosixErrorOr<U> other) {
- if (absl::holds_alternative<U>(other.value_)) {
- // T is convertible from U.
- value_ = absl::get<U>(std::move(other.value_));
- } else if (absl::holds_alternative<PosixError>(other.value_)) {
- value_ = absl::get<PosixError>(std::move(other.value_));
- } else {
- TEST_CHECK_MSG(false, "PosixErrorOr does not contain PosixError or value");
- }
- return *this;
-}
-
-template <typename T>
-PosixError PosixErrorOr<T>::error() const {
- if (!absl::holds_alternative<PosixError>(value_)) {
- return PosixError();
- }
- return absl::get<PosixError>(value_);
-}
-
-template <typename T>
-bool PosixErrorOr<T>::ok() const {
- return absl::holds_alternative<T>(value_);
-}
-
-template <typename T>
-const T& PosixErrorOr<T>::ValueOrDie() const& {
- TEST_CHECK(absl::holds_alternative<T>(value_));
- return absl::get<T>(value_);
-}
-
-template <typename T>
-T& PosixErrorOr<T>::ValueOrDie() & {
- TEST_CHECK(absl::holds_alternative<T>(value_));
- return absl::get<T>(value_);
-}
-
-template <typename T>
-const T&& PosixErrorOr<T>::ValueOrDie() const&& {
- TEST_CHECK(absl::holds_alternative<T>(value_));
- return std::move(absl::get<T>(value_));
-}
-
-template <typename T>
-T&& PosixErrorOr<T>::ValueOrDie() && {
- TEST_CHECK(absl::holds_alternative<T>(value_));
- return std::move(absl::get<T>(value_));
-}
-
-extern ::std::ostream& operator<<(::std::ostream& os, const PosixError& e);
-
-template <typename T>
-::std::ostream& operator<<(::std::ostream& os, const PosixErrorOr<T>& e) {
- os << e.error();
- return os;
-}
-
-// NoError is a PosixError that represents a successful state, i.e. No Error.
-inline PosixError NoError() { return PosixError(); }
-
-// Monomorphic implementation of matcher IsPosixErrorOk() for a given type T.
-// T can be PosixError, PosixErrorOr<>, or a reference to either of them.
-template <typename T>
-class MonoPosixErrorIsOkMatcherImpl : public ::testing::MatcherInterface<T> {
- public:
- void DescribeTo(std::ostream* os) const override { *os << "is OK"; }
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "is not OK";
- }
- bool MatchAndExplain(T actual_value,
- ::testing::MatchResultListener*) const override {
- return actual_value.ok();
- }
-};
-
-// Implements IsPosixErrorOkMatcher() as a polymorphic matcher.
-class IsPosixErrorOkMatcher {
- public:
- template <typename T>
- operator ::testing::Matcher<T>() const { // NOLINT
- return MakeMatcher(new MonoPosixErrorIsOkMatcherImpl<T>());
- }
-};
-
-// Monomorphic implementation of a matcher for a PosixErrorOr.
-template <typename PosixErrorOrType>
-class IsPosixErrorOkAndHoldsMatcherImpl
- : public ::testing::MatcherInterface<PosixErrorOrType> {
- public:
- using ValueType = typename std::remove_reference<decltype(
- std::declval<PosixErrorOrType>().ValueOrDie())>::type;
-
- template <typename InnerMatcher>
- explicit IsPosixErrorOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
- : inner_matcher_(::testing::SafeMatcherCast<const ValueType&>(
- std::forward<InnerMatcher>(inner_matcher))) {}
-
- void DescribeTo(std::ostream* os) const override {
- *os << "is OK and has a value that ";
- inner_matcher_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "isn't OK or has a value that ";
- inner_matcher_.DescribeNegationTo(os);
- }
-
- bool MatchAndExplain(
- PosixErrorOrType actual_value,
- ::testing::MatchResultListener* listener) const override {
- // We can't extract the value if it doesn't contain one.
- if (!actual_value.ok()) {
- return false;
- }
-
- ::testing::StringMatchResultListener inner_listener;
- const bool matches = inner_matcher_.MatchAndExplain(
- actual_value.ValueOrDie(), &inner_listener);
- const std::string inner_explanation = inner_listener.str();
- *listener << "has a value "
- << ::testing::PrintToString(actual_value.ValueOrDie());
-
- if (!inner_explanation.empty()) {
- *listener << " " << inner_explanation;
- }
- return matches;
- }
-
- private:
- const ::testing::Matcher<const ValueType&> inner_matcher_;
-};
-
-// Implements IsOkAndHolds() as a polymorphic matcher.
-template <typename InnerMatcher>
-class IsPosixErrorOkAndHoldsMatcher {
- public:
- explicit IsPosixErrorOkAndHoldsMatcher(InnerMatcher inner_matcher)
- : inner_matcher_(std::move(inner_matcher)) {}
-
- // Converts this polymorphic matcher to a monomorphic one of the given type.
- // PosixErrorOrType can be either PosixErrorOr<T> or a reference to
- // PosixErrorOr<T>.
- template <typename PosixErrorOrType>
- operator ::testing::Matcher<PosixErrorOrType>() const { // NOLINT
- return ::testing::MakeMatcher(
- new IsPosixErrorOkAndHoldsMatcherImpl<PosixErrorOrType>(
- inner_matcher_));
- }
-
- private:
- const InnerMatcher inner_matcher_;
-};
-
-// PosixErrorIs() is a polymorphic matcher. This class is the common
-// implementation of it shared by all types T where PosixErrorIs() can be
-// used as a Matcher<T>.
-class PosixErrorIsMatcherCommonImpl {
- public:
- PosixErrorIsMatcherCommonImpl(
- ::testing::Matcher<int> code_matcher,
- ::testing::Matcher<const std::string&> message_matcher)
- : code_matcher_(std::move(code_matcher)),
- message_matcher_(std::move(message_matcher)) {}
-
- void DescribeTo(std::ostream* os) const;
-
- void DescribeNegationTo(std::ostream* os) const;
-
- bool MatchAndExplain(const PosixError& error,
- ::testing::MatchResultListener* result_listener) const;
-
- template <typename T>
- bool MatchAndExplain(const PosixErrorOr<T>& error_or,
- ::testing::MatchResultListener* result_listener) const {
- if (error_or.ok()) {
- *result_listener << "has a value "
- << ::testing::PrintToString(error_or.ValueOrDie());
- return false;
- }
-
- return MatchAndExplain(error_or.error(), result_listener);
- }
-
- private:
- const ::testing::Matcher<int> code_matcher_;
- const ::testing::Matcher<const std::string&> message_matcher_;
-};
-
-// Monomorphic implementation of matcher PosixErrorIs() for a given type
-// T. T can be PosixError, PosixErrorOr<>, or a reference to either of them.
-template <typename T>
-class MonoPosixErrorIsMatcherImpl : public ::testing::MatcherInterface<T> {
- public:
- explicit MonoPosixErrorIsMatcherImpl(
- PosixErrorIsMatcherCommonImpl common_impl)
- : common_impl_(std::move(common_impl)) {}
-
- void DescribeTo(std::ostream* os) const override {
- common_impl_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- common_impl_.DescribeNegationTo(os);
- }
-
- bool MatchAndExplain(
- T actual_value,
- ::testing::MatchResultListener* result_listener) const override {
- return common_impl_.MatchAndExplain(actual_value, result_listener);
- }
-
- private:
- PosixErrorIsMatcherCommonImpl common_impl_;
-};
-
-inline ::testing::Matcher<int> ToErrorCodeMatcher(
- const ::testing::Matcher<int>& m) {
- return m;
-}
-
-// Implements PosixErrorIs() as a polymorphic matcher.
-class PosixErrorIsMatcher {
- public:
- template <typename ErrorCodeMatcher>
- PosixErrorIsMatcher(ErrorCodeMatcher&& code_matcher,
- ::testing::Matcher<const std::string&> message_matcher)
- : common_impl_(
- ToErrorCodeMatcher(std::forward<ErrorCodeMatcher>(code_matcher)),
- std::move(message_matcher)) {}
-
- // Converts this polymorphic matcher to a monomorphic matcher of the
- // given type. T can be StatusOr<>, Status, or a reference to
- // either of them.
- template <typename T>
- operator ::testing::Matcher<T>() const { // NOLINT
- return MakeMatcher(new MonoPosixErrorIsMatcherImpl<T>(common_impl_));
- }
-
- private:
- const PosixErrorIsMatcherCommonImpl common_impl_;
-};
-
-// Returns a gMock matcher that matches a PosixError or PosixErrorOr<> whose
-// error code matches code_matcher, and whose error message matches
-// message_matcher.
-template <typename ErrorCodeMatcher>
-PosixErrorIsMatcher PosixErrorIs(
- ErrorCodeMatcher&& code_matcher,
- ::testing::Matcher<const std::string&> message_matcher) {
- return PosixErrorIsMatcher(std::forward<ErrorCodeMatcher>(code_matcher),
- std::move(message_matcher));
-}
-
-// Returns a gMock matcher that matches a PosixError or PosixErrorOr<> whose
-// error code matches code_matcher.
-template <typename ErrorCodeMatcher>
-PosixErrorIsMatcher PosixErrorIs(ErrorCodeMatcher&& code_matcher) {
- return PosixErrorIsMatcher(std::forward<ErrorCodeMatcher>(code_matcher),
- ::testing::_);
-}
-
-// Returns a gMock matcher that matches a PosixErrorOr<> which is ok() and
-// value matches the inner matcher.
-template <typename InnerMatcher>
-IsPosixErrorOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>
-IsPosixErrorOkAndHolds(InnerMatcher&& inner_matcher) {
- return IsPosixErrorOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>(
- std::forward<InnerMatcher>(inner_matcher));
-}
-
-// Internal helper for concatenating macro values.
-#define POSIX_ERROR_IMPL_CONCAT_INNER_(x, y) x##y
-#define POSIX_ERROR_IMPL_CONCAT_(x, y) POSIX_ERROR_IMPL_CONCAT_INNER_(x, y)
-
-#define POSIX_ERROR_IMPL_ASSIGN_OR_RETURN_(posixerroror, lhs, rexpr) \
- auto posixerroror = (rexpr); \
- if (!posixerroror.ok()) { \
- return (posixerroror.error()); \
- } \
- lhs = std::move(posixerroror).ValueOrDie()
-
-#define EXPECT_NO_ERRNO(expression) \
- EXPECT_THAT(expression, IsPosixErrorOkMatcher())
-#define ASSERT_NO_ERRNO(expression) \
- ASSERT_THAT(expression, IsPosixErrorOkMatcher())
-
-#define ASSIGN_OR_RETURN_ERRNO(lhs, rexpr) \
- POSIX_ERROR_IMPL_ASSIGN_OR_RETURN_( \
- POSIX_ERROR_IMPL_CONCAT_(_status_or_value, __LINE__), lhs, rexpr)
-
-#define RETURN_IF_ERRNO(s) \
- do { \
- if (!s.ok()) { \
- return s; \
- } \
- } while (false);
-
-#define ASSERT_NO_ERRNO_AND_VALUE(expr) \
- ({ \
- auto _expr_result = (expr); \
- ASSERT_NO_ERRNO(_expr_result); \
- std::move(_expr_result).ValueOrDie(); \
- })
-
-#define EXPECT_NO_ERRNO_AND_VALUE(expr) \
- ({ \
- auto _expr_result = (expr); \
- EXPECT_NO_ERRNO(_expr_result); \
- std::move(_expr_result).ValueOrDie(); \
- })
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_POSIX_ERROR_H_
diff --git a/test/util/posix_error_test.cc b/test/util/posix_error_test.cc
deleted file mode 100644
index bf9465abb..000000000
--- a/test/util/posix_error_test.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/posix_error.h"
-
-#include <errno.h>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace gvisor {
-namespace testing {
-
-namespace {
-
-TEST(PosixErrorTest, PosixError) {
- auto err = PosixError(EAGAIN);
- EXPECT_THAT(err, PosixErrorIs(EAGAIN, ""));
-}
-
-TEST(PosixErrorTest, PosixErrorOrPosixError) {
- auto err = PosixErrorOr<std::nullptr_t>(PosixError(EAGAIN));
- EXPECT_THAT(err, PosixErrorIs(EAGAIN, ""));
-}
-
-TEST(PosixErrorTest, PosixErrorOrNullptr) {
- auto err = PosixErrorOr<std::nullptr_t>(nullptr);
- EXPECT_TRUE(err.ok());
- EXPECT_NO_ERRNO(err);
-}
-
-} // namespace
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/proc_util.cc b/test/util/proc_util.cc
deleted file mode 100644
index 34d636ba9..000000000
--- a/test/util/proc_util.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/proc_util.h"
-
-#include <algorithm>
-#include <iostream>
-#include <vector>
-
-#include "absl/strings/ascii.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/str_split.h"
-#include "absl/strings/string_view.h"
-#include "test/util/fs_util.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-// Parses a single line from /proc/<xxx>/maps.
-PosixErrorOr<ProcMapsEntry> ParseProcMapsLine(absl::string_view line) {
- ProcMapsEntry map_entry = {};
-
- // Limit splitting to 6 parts so that if there is a file path and it contains
- // spaces, the file path is not split.
- std::vector<std::string> parts =
- absl::StrSplit(line, absl::MaxSplits(' ', 5), absl::SkipEmpty());
-
- // parts.size() should be 6 if there is a file name specified, and 5
- // otherwise.
- if (parts.size() < 5) {
- return PosixError(EINVAL, absl::StrCat("Invalid line: ", line));
- }
-
- // Address range in the form X-X where X are hex values without leading 0x.
- std::vector<std::string> addresses = absl::StrSplit(parts[0], '-');
- if (addresses.size() != 2) {
- return PosixError(EINVAL,
- absl::StrCat("Invalid address range: ", parts[0]));
- }
- ASSIGN_OR_RETURN_ERRNO(map_entry.start, AtoiBase(addresses[0], 16));
- ASSIGN_OR_RETURN_ERRNO(map_entry.end, AtoiBase(addresses[1], 16));
-
- // Permissions are four bytes of the form rwxp or - if permission not set.
- if (parts[1].size() != 4) {
- return PosixError(EINVAL,
- absl::StrCat("Invalid permission field: ", parts[1]));
- }
-
- map_entry.readable = parts[1][0] == 'r';
- map_entry.writable = parts[1][1] == 'w';
- map_entry.executable = parts[1][2] == 'x';
- map_entry.priv = parts[1][3] == 'p';
-
- ASSIGN_OR_RETURN_ERRNO(map_entry.offset, AtoiBase(parts[2], 16));
-
- std::vector<std::string> device = absl::StrSplit(parts[3], ':');
- if (device.size() != 2) {
- return PosixError(EINVAL, absl::StrCat("Invalid device: ", parts[3]));
- }
- ASSIGN_OR_RETURN_ERRNO(map_entry.major, AtoiBase(device[0], 16));
- ASSIGN_OR_RETURN_ERRNO(map_entry.minor, AtoiBase(device[1], 16));
-
- ASSIGN_OR_RETURN_ERRNO(map_entry.inode, Atoi<int64_t>(parts[4]));
- if (parts.size() == 6) {
- // A filename is present. However, absl::StrSplit retained the whitespace
- // between the inode number and the filename.
- map_entry.filename =
- std::string(absl::StripLeadingAsciiWhitespace(parts[5]));
- }
-
- return map_entry;
-}
-
-PosixErrorOr<std::vector<ProcMapsEntry>> ParseProcMaps(
- absl::string_view contents) {
- std::vector<ProcMapsEntry> entries;
- auto lines = absl::StrSplit(contents, '\n', absl::SkipEmpty());
- for (const auto& l : lines) {
- std::cout << "line: " << l << std::endl;
- ASSIGN_OR_RETURN_ERRNO(auto entry, ParseProcMapsLine(l));
- entries.push_back(entry);
- }
- return entries;
-}
-
-PosixErrorOr<bool> IsVsyscallEnabled() {
- ASSIGN_OR_RETURN_ERRNO(auto contents, GetContents("/proc/self/maps"));
- ASSIGN_OR_RETURN_ERRNO(auto maps, ParseProcMaps(contents));
- return std::any_of(maps.begin(), maps.end(), [](const ProcMapsEntry& e) {
- return e.filename == "[vsyscall]";
- });
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/proc_util.h b/test/util/proc_util.h
deleted file mode 100644
index af209a51e..000000000
--- a/test/util/proc_util.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_PROC_UTIL_H_
-#define GVISOR_TEST_UTIL_PROC_UTIL_H_
-
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-#include "test/util/fs_util.h"
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-// ProcMapsEntry contains the data from a single line in /proc/<xxx>/maps.
-struct ProcMapsEntry {
- uint64_t start;
- uint64_t end;
- bool readable;
- bool writable;
- bool executable;
- bool priv;
- uint64_t offset;
- int major;
- int minor;
- int64_t inode;
- std::string filename;
-};
-
-// Parses a ProcMaps line or returns an error.
-PosixErrorOr<ProcMapsEntry> ParseProcMapsLine(absl::string_view line);
-PosixErrorOr<std::vector<ProcMapsEntry>> ParseProcMaps(
- absl::string_view contents);
-
-// Returns true if vsyscall (emmulation or not) is enabled.
-PosixErrorOr<bool> IsVsyscallEnabled();
-
-// Printer for ProcMapsEntry.
-inline std::ostream& operator<<(std::ostream& os, const ProcMapsEntry& entry) {
- std::string str =
- absl::StrCat(absl::Hex(entry.start, absl::PadSpec::kZeroPad8), "-",
- absl::Hex(entry.end, absl::PadSpec::kZeroPad8), " ");
-
- absl::StrAppend(&str, entry.readable ? "r" : "-");
- absl::StrAppend(&str, entry.writable ? "w" : "-");
- absl::StrAppend(&str, entry.executable ? "x" : "-");
- absl::StrAppend(&str, entry.priv ? "p" : "s");
-
- absl::StrAppend(&str, " ", absl::Hex(entry.offset, absl::PadSpec::kZeroPad8),
- " ", absl::Hex(entry.major, absl::PadSpec::kZeroPad2), ":",
- absl::Hex(entry.minor, absl::PadSpec::kZeroPad2), " ",
- entry.inode);
- if (absl::string_view(entry.filename) != "") {
- // Pad to column 74
- int pad = 73 - str.length();
- if (pad > 0) {
- absl::StrAppend(&str, std::string(pad, ' '));
- }
- absl::StrAppend(&str, entry.filename);
- }
- os << str;
- return os;
-}
-
-// Printer for std::vector<ProcMapsEntry>.
-inline std::ostream& operator<<(std::ostream& os,
- const std::vector<ProcMapsEntry>& vec) {
- for (unsigned int i = 0; i < vec.size(); i++) {
- os << vec[i];
- if (i != vec.size() - 1) {
- os << "\n";
- }
- }
- return os;
-}
-
-// GMock printer for std::vector<ProcMapsEntry>.
-inline void PrintTo(const std::vector<ProcMapsEntry>& vec, std::ostream* os) {
- *os << vec;
-}
-
-// Checks that /proc/pid/maps contains all of the passed mappings.
-//
-// The major, minor, and inode fields are ignored.
-MATCHER_P(ContainsMappings, mappings,
- "contains mappings:\n" + ::testing::PrintToString(mappings)) {
- auto contents_or = GetContents(absl::StrCat("/proc/", arg, "/maps"));
- if (!contents_or.ok()) {
- *result_listener << "Unable to read mappings: "
- << contents_or.error().ToString();
- return false;
- }
-
- auto maps_or = ParseProcMaps(contents_or.ValueOrDie());
- if (!maps_or.ok()) {
- *result_listener << "Unable to parse mappings: "
- << maps_or.error().ToString();
- return false;
- }
-
- auto maps = std::move(maps_or).ValueOrDie();
-
- // Does maps contain all elements in mappings? The comparator ignores
- // the major, minor, and inode fields.
- bool all_present = true;
- std::for_each(mappings.begin(), mappings.end(), [&](const ProcMapsEntry& e1) {
- auto it =
- std::find_if(maps.begin(), maps.end(), [&e1](const ProcMapsEntry& e2) {
- return e1.start == e2.start && e1.end == e2.end &&
- e1.readable == e2.readable && e1.writable == e2.writable &&
- e1.executable == e2.executable && e1.priv == e2.priv &&
- e1.offset == e2.offset && e1.filename == e2.filename;
- });
- if (it == maps.end()) {
- // It wasn't found.
- if (all_present) {
- // We will output the message once and then a line for each mapping
- // that wasn't found.
- all_present = false;
- *result_listener << "Got mappings:\n"
- << maps << "\nThat were missing:\n";
- }
- *result_listener << e1 << "\n";
- }
- });
-
- return all_present;
-}
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_PROC_UTIL_H_
diff --git a/test/util/proc_util_test.cc b/test/util/proc_util_test.cc
deleted file mode 100644
index 71dd2355e..000000000
--- a/test/util/proc_util_test.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/proc_util.h"
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "test/util/test_util.h"
-
-using ::testing::IsEmpty;
-
-namespace gvisor {
-namespace testing {
-
-namespace {
-
-TEST(ParseProcMapsLineTest, WithoutFilename) {
- auto entry = ASSERT_NO_ERRNO_AND_VALUE(
- ParseProcMapsLine("2ab4f00b7000-2ab4f00b9000 r-xp 00000000 00:00 0 "));
- EXPECT_EQ(entry.start, 0x2ab4f00b7000);
- EXPECT_EQ(entry.end, 0x2ab4f00b9000);
- EXPECT_TRUE(entry.readable);
- EXPECT_FALSE(entry.writable);
- EXPECT_TRUE(entry.executable);
- EXPECT_TRUE(entry.priv);
- EXPECT_EQ(entry.offset, 0);
- EXPECT_EQ(entry.major, 0);
- EXPECT_EQ(entry.minor, 0);
- EXPECT_EQ(entry.inode, 0);
- EXPECT_THAT(entry.filename, IsEmpty());
-}
-
-TEST(ParseProcMapsLineTest, WithFilename) {
- auto entry = ASSERT_NO_ERRNO_AND_VALUE(
- ParseProcMapsLine("00407000-00408000 rw-p 00006000 00:0e 10 "
- " /bin/cat"));
- EXPECT_EQ(entry.start, 0x407000);
- EXPECT_EQ(entry.end, 0x408000);
- EXPECT_TRUE(entry.readable);
- EXPECT_TRUE(entry.writable);
- EXPECT_FALSE(entry.executable);
- EXPECT_TRUE(entry.priv);
- EXPECT_EQ(entry.offset, 0x6000);
- EXPECT_EQ(entry.major, 0);
- EXPECT_EQ(entry.minor, 0x0e);
- EXPECT_EQ(entry.inode, 10);
- EXPECT_EQ(entry.filename, "/bin/cat");
-}
-
-TEST(ParseProcMapsLineTest, WithFilenameContainingSpaces) {
- auto entry = ASSERT_NO_ERRNO_AND_VALUE(
- ParseProcMapsLine("7f26b3b12000-7f26b3b13000 rw-s 00000000 00:05 1432484 "
- " /dev/zero (deleted)"));
- EXPECT_EQ(entry.start, 0x7f26b3b12000);
- EXPECT_EQ(entry.end, 0x7f26b3b13000);
- EXPECT_TRUE(entry.readable);
- EXPECT_TRUE(entry.writable);
- EXPECT_FALSE(entry.executable);
- EXPECT_FALSE(entry.priv);
- EXPECT_EQ(entry.offset, 0);
- EXPECT_EQ(entry.major, 0);
- EXPECT_EQ(entry.minor, 0x05);
- EXPECT_EQ(entry.inode, 1432484);
- EXPECT_EQ(entry.filename, "/dev/zero (deleted)");
-}
-
-} // namespace
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/pty_util.cc b/test/util/pty_util.cc
deleted file mode 100644
index 351f4730c..000000000
--- a/test/util/pty_util.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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 "test/util/pty_util.h"
-
-#include <sys/ioctl.h>
-#include <termios.h>
-
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-PosixErrorOr<FileDescriptor> OpenReplica(const FileDescriptor& master) {
- return OpenReplica(master, O_NONBLOCK | O_RDWR | O_NOCTTY);
-}
-
-PosixErrorOr<FileDescriptor> OpenReplica(const FileDescriptor& master,
- int flags) {
- PosixErrorOr<int> n = ReplicaID(master);
- if (!n.ok()) {
- return PosixErrorOr<FileDescriptor>(n.error());
- }
- return Open(absl::StrCat("/dev/pts/", n.ValueOrDie()), flags);
-}
-
-PosixErrorOr<int> ReplicaID(const FileDescriptor& master) {
- // Get pty index.
- int n;
- int ret = ioctl(master.get(), TIOCGPTN, &n);
- if (ret < 0) {
- return PosixError(errno, "ioctl(TIOCGPTN) failed");
- }
-
- // Unlock pts.
- int unlock = 0;
- ret = ioctl(master.get(), TIOCSPTLCK, &unlock);
- if (ret < 0) {
- return PosixError(errno, "ioctl(TIOSPTLCK) failed");
- }
-
- return n;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/pty_util.h b/test/util/pty_util.h
deleted file mode 100644
index 0cca2182c..000000000
--- a/test/util/pty_util.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_PTY_UTIL_H_
-#define GVISOR_TEST_UTIL_PTY_UTIL_H_
-
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-// Opens the replica end of the passed master as R/W and nonblocking. It does
-// not set the replica as the controlling TTY.
-PosixErrorOr<FileDescriptor> OpenReplica(const FileDescriptor& master);
-
-// Identical to the above OpenReplica, but flags are all specified by the
-// caller.
-PosixErrorOr<FileDescriptor> OpenReplica(const FileDescriptor& master,
- int flags);
-
-// Get the number of the replica end of the master.
-PosixErrorOr<int> ReplicaID(const FileDescriptor& master);
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_PTY_UTIL_H_
diff --git a/test/util/rlimit_util.cc b/test/util/rlimit_util.cc
deleted file mode 100644
index d7bfc1606..000000000
--- a/test/util/rlimit_util.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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 "test/util/rlimit_util.h"
-
-#include <sys/resource.h>
-
-#include <cerrno>
-
-#include "test/util/cleanup.h"
-#include "test/util/logging.h"
-#include "test/util/posix_error.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-PosixErrorOr<Cleanup> ScopedSetSoftRlimit(int resource, rlim_t newval) {
- struct rlimit old_rlim;
- if (getrlimit(resource, &old_rlim) != 0) {
- return PosixError(errno, "getrlimit failed");
- }
- struct rlimit new_rlim = old_rlim;
- new_rlim.rlim_cur = newval;
- if (setrlimit(resource, &new_rlim) != 0) {
- return PosixError(errno, "setrlimit failed");
- }
- return Cleanup([resource, old_rlim] {
- TEST_PCHECK(setrlimit(resource, &old_rlim) == 0);
- });
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/rlimit_util.h b/test/util/rlimit_util.h
deleted file mode 100644
index 873252a32..000000000
--- a/test/util/rlimit_util.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_RLIMIT_UTIL_H_
-#define GVISOR_TEST_UTIL_RLIMIT_UTIL_H_
-
-#include <sys/resource.h>
-#include <sys/time.h>
-
-#include "test/util/cleanup.h"
-#include "test/util/posix_error.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-PosixErrorOr<Cleanup> ScopedSetSoftRlimit(int resource, rlim_t newval);
-
-} // namespace testing
-} // namespace gvisor
-#endif // GVISOR_TEST_UTIL_RLIMIT_UTIL_H_
diff --git a/test/util/save_util.cc b/test/util/save_util.cc
deleted file mode 100644
index 3e724d99b..000000000
--- a/test/util/save_util.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/save_util.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <cerrno>
-
-#include "absl/types/optional.h"
-
-namespace gvisor {
-namespace testing {
-namespace {
-
-std::atomic<absl::optional<bool>> save_present;
-
-bool SavePresent() {
- auto present = save_present.load();
- if (!present.has_value()) {
- present = getenv("GVISOR_SAVE_TEST") != nullptr;
- save_present.store(present);
- }
- return present.value();
-}
-
-std::atomic<int> save_disable;
-
-} // namespace
-
-bool IsRunningWithSaveRestore() { return SavePresent(); }
-
-void MaybeSave() {
- if (SavePresent() && save_disable.load() == 0) {
- internal::DoCooperativeSave();
- }
-}
-
-DisableSave::DisableSave() { save_disable++; }
-
-DisableSave::~DisableSave() { reset(); }
-
-void DisableSave::reset() {
- if (!reset_) {
- reset_ = true;
- save_disable--;
- }
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/save_util.h b/test/util/save_util.h
deleted file mode 100644
index e7218ae88..000000000
--- a/test/util/save_util.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_SAVE_UTIL_H_
-#define GVISOR_TEST_UTIL_SAVE_UTIL_H_
-
-namespace gvisor {
-namespace testing {
-
-// Returns true if the environment in which the calling process is executing
-// allows the test to be checkpointed and restored during execution.
-bool IsRunningWithSaveRestore();
-
-// May perform a co-operative save cycle.
-//
-// errno is guaranteed to be preserved.
-void MaybeSave();
-
-// Causes MaybeSave to become a no-op until destroyed or reset.
-class DisableSave {
- public:
- DisableSave();
- ~DisableSave();
- DisableSave(DisableSave const&) = delete;
- DisableSave(DisableSave&&) = delete;
- DisableSave& operator=(DisableSave const&) = delete;
- DisableSave& operator=(DisableSave&&) = delete;
-
- // reset allows saves to continue, and is called implicitly by the destructor.
- // It may be called multiple times safely, but is not thread-safe.
- void reset();
-
- private:
- bool reset_ = false;
-};
-
-namespace internal {
-
-// Causes a co-operative save cycle to occur.
-//
-// errno is guaranteed to be preserved.
-void DoCooperativeSave();
-
-} // namespace internal
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_SAVE_UTIL_H_
diff --git a/test/util/save_util_linux.cc b/test/util/save_util_linux.cc
deleted file mode 100644
index 57431b3ea..000000000
--- a/test/util/save_util_linux.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifdef __linux__
-
-#include <errno.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include "test/util/save_util.h"
-
-#if defined(__x86_64__) || defined(__i386__)
-#define SYS_TRIGGER_SAVE SYS_create_module
-#elif defined(__aarch64__)
-#define SYS_TRIGGER_SAVE SYS_finit_module
-#else
-#error "Unknown architecture"
-#endif
-
-namespace gvisor {
-namespace testing {
-namespace internal {
-
-void DoCooperativeSave() {
- int orig_errno = errno;
- // We use it to trigger saving the sentry state
- // when this syscall is called.
- // Notice: this needs to be a valid syscall
- // that is not used in any of the syscall tests.
- syscall(SYS_TRIGGER_SAVE, nullptr, 0);
- errno = orig_errno;
-}
-
-} // namespace internal
-} // namespace testing
-} // namespace gvisor
-
-#endif // __linux__
diff --git a/test/util/save_util_other.cc b/test/util/save_util_other.cc
deleted file mode 100644
index 7749ded76..000000000
--- a/test/util/save_util_other.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef __linux__
-
-#include "test/util/logging.h"
-
-namespace gvisor {
-namespace testing {
-namespace internal {
-
-void DoCooperativeSave() {
- TEST_CHECK_MSG(false, "DoCooperativeSave not implemented");
-}
-
-} // namespace internal
-} // namespace testing
-} // namespace gvisor
-
-#endif
diff --git a/test/util/signal_util.cc b/test/util/signal_util.cc
deleted file mode 100644
index 5ee95ee80..000000000
--- a/test/util/signal_util.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/signal_util.h"
-
-#include <signal.h>
-
-#include <ostream>
-
-#include "gtest/gtest.h"
-#include "test/util/cleanup.h"
-#include "test/util/posix_error.h"
-#include "test/util/test_util.h"
-
-namespace {
-
-struct Range {
- int start;
- int end;
-};
-
-// Format a Range as "start-end" or "start" for single value Ranges.
-static ::std::ostream& operator<<(::std::ostream& os, const Range& range) {
- if (range.end > range.start) {
- return os << range.start << '-' << range.end;
- }
-
- return os << range.start;
-}
-
-} // namespace
-
-// Format a sigset_t as a comma separated list of numeric ranges.
-// Empty sigset: []
-// Full sigset: [1-31,34-64]
-::std::ostream& operator<<(::std::ostream& os, const sigset_t& sigset) {
- const char* delim = "";
- Range range = {0, 0};
-
- os << '[';
-
- for (int sig = 1; sig <= gvisor::testing::kMaxSignal; ++sig) {
- if (sigismember(&sigset, sig)) {
- if (range.start) {
- range.end = sig;
- } else {
- range.start = sig;
- range.end = sig;
- }
- } else if (range.start) {
- os << delim << range;
- delim = ",";
- range.start = 0;
- range.end = 0;
- }
- }
-
- if (range.start) {
- os << delim << range;
- }
-
- return os << ']';
-}
-
-namespace gvisor {
-namespace testing {
-
-PosixErrorOr<Cleanup> ScopedSigaction(int sig, struct sigaction const& sa) {
- struct sigaction old_sa;
- int rc = sigaction(sig, &sa, &old_sa);
- MaybeSave();
- if (rc < 0) {
- return PosixError(errno, "sigaction failed");
- }
- return Cleanup([sig, old_sa] {
- EXPECT_THAT(sigaction(sig, &old_sa, nullptr), SyscallSucceeds());
- });
-}
-
-PosixErrorOr<Cleanup> ScopedSignalMask(int how, sigset_t const& set) {
- sigset_t old;
- int rc = sigprocmask(how, &set, &old);
- MaybeSave();
- if (rc < 0) {
- return PosixError(errno, "sigprocmask failed");
- }
- return Cleanup([old] {
- EXPECT_THAT(sigprocmask(SIG_SETMASK, &old, nullptr), SyscallSucceeds());
- });
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/signal_util.h b/test/util/signal_util.h
deleted file mode 100644
index 20eebd7e4..000000000
--- a/test/util/signal_util.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_SIGNAL_UTIL_H_
-#define GVISOR_TEST_UTIL_SIGNAL_UTIL_H_
-
-#include <signal.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include <ostream>
-
-#include "gmock/gmock.h"
-#include "test/util/cleanup.h"
-#include "test/util/posix_error.h"
-
-// Format a sigset_t as a comma separated list of numeric ranges.
-::std::ostream& operator<<(::std::ostream& os, const sigset_t& sigset);
-
-namespace gvisor {
-namespace testing {
-
-// The maximum signal number.
-static constexpr int kMaxSignal = 64;
-
-// Wrapper for the tgkill(2) syscall, which glibc does not provide.
-inline int tgkill(pid_t tgid, pid_t tid, int sig) {
- return syscall(__NR_tgkill, tgid, tid, sig);
-}
-
-// Installs the passed sigaction and returns a cleanup function to restore the
-// previous handler when it goes out of scope.
-PosixErrorOr<Cleanup> ScopedSigaction(int sig, struct sigaction const& sa);
-
-// Updates the signal mask as per sigprocmask(2) and returns a cleanup function
-// to restore the previous signal mask when it goes out of scope.
-PosixErrorOr<Cleanup> ScopedSignalMask(int how, sigset_t const& set);
-
-// ScopedSignalMask variant that creates a mask of the single signal 'sig'.
-inline PosixErrorOr<Cleanup> ScopedSignalMask(int how, int sig) {
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set, sig);
- return ScopedSignalMask(how, set);
-}
-
-// Asserts equality of two sigset_t values.
-MATCHER_P(EqualsSigset, value, "equals " + ::testing::PrintToString(value)) {
- for (int sig = 1; sig <= kMaxSignal; ++sig) {
- if (sigismember(&arg, sig) != sigismember(&value, sig)) {
- return false;
- }
- }
- return true;
-}
-
-#ifdef __x86_64__
-// Fault can be used to generate a synchronous SIGSEGV.
-//
-// This fault can be fixed up in a handler via fixup, below.
-inline void Fault() {
- // Zero and dereference %ax.
- asm("movabs $0, %%rax\r\n"
- "mov 0(%%rax), %%rax\r\n"
- :
- :
- : "ax");
-}
-
-// FixupFault fixes up a fault generated by fault, above.
-inline void FixupFault(ucontext_t* ctx) {
- // Skip the bad instruction above.
- //
- // The encoding is 0x48 0xab 0x00.
- ctx->uc_mcontext.gregs[REG_RIP] += 3;
-}
-#elif __aarch64__
-inline void Fault() {
- // Zero and dereference x0.
- asm("mov x0, xzr\r\n"
- "str xzr, [x0]\r\n"
- :
- :
- : "x0");
-}
-
-inline void FixupFault(ucontext_t* ctx) {
- // Skip the bad instruction above.
- ctx->uc_mcontext.pc += 4;
-}
-#endif
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_SIGNAL_UTIL_H_
diff --git a/test/util/socket_util.cc b/test/util/socket_util.cc
deleted file mode 100644
index 650b422ae..000000000
--- a/test/util/socket_util.cc
+++ /dev/null
@@ -1,1129 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/socket_util.h"
-
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <poll.h>
-#include <sys/socket.h>
-
-#include <memory>
-
-#include "gtest/gtest.h"
-#include "absl/memory/memory.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/str_split.h"
-#include "absl/time/clock.h"
-#include "absl/types/optional.h"
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-#include "test/util/temp_path.h"
-#include "test/util/thread_util.h"
-
-namespace gvisor {
-namespace testing {
-
-Creator<SocketPair> SyscallSocketPairCreator(int domain, int type,
- int protocol) {
- return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
- int pair[2];
- RETURN_ERROR_IF_SYSCALL_FAIL(socketpair(domain, type, protocol, pair));
- MaybeSave(); // Save on successful creation.
- return absl::make_unique<FDSocketPair>(pair[0], pair[1]);
- };
-}
-
-Creator<FileDescriptor> SyscallSocketCreator(int domain, int type,
- int protocol) {
- return [=]() -> PosixErrorOr<std::unique_ptr<FileDescriptor>> {
- int fd = 0;
- RETURN_ERROR_IF_SYSCALL_FAIL(fd = socket(domain, type, protocol));
- MaybeSave(); // Save on successful creation.
- return absl::make_unique<FileDescriptor>(fd);
- };
-}
-
-PosixErrorOr<struct sockaddr_un> UniqueUnixAddr(bool abstract, int domain) {
- struct sockaddr_un addr = {};
-
-#ifdef ANDROID
- // Using NewTempAbsPath() can cause the tmp directory path to exceed the max
- // length (i.e., sizeof(addr.sun_path)).
- //
- // However, existing systems that are built with the ANDROID configuration
- // have their temp directory in a different location, and must respect the
- // TEST_TMPDIR.
- std::string path = NewTempAbsPath();
-#else
- std::string path = NewTempAbsPathInDir("/tmp");
-#endif // ANDROID
-
- if (path.size() >= sizeof(addr.sun_path)) {
- return PosixError(EINVAL,
- "Unable to generate a temp path of appropriate length");
- }
-
- if (abstract) {
- // Indicate that the path is in the abstract namespace.
- path[0] = 0;
- }
- memcpy(addr.sun_path, path.c_str(), path.length());
- addr.sun_family = domain;
- return addr;
-}
-
-Creator<SocketPair> AcceptBindSocketPairCreator(bool abstract, int domain,
- int type, int protocol) {
- return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
- ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un bind_addr,
- UniqueUnixAddr(abstract, domain));
- ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un extra_addr,
- UniqueUnixAddr(abstract, domain));
-
- int bound;
- RETURN_ERROR_IF_SYSCALL_FAIL(bound = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
- RETURN_ERROR_IF_SYSCALL_FAIL(
- bind(bound, AsSockAddr(&bind_addr), sizeof(bind_addr)));
- MaybeSave(); // Successful bind.
- RETURN_ERROR_IF_SYSCALL_FAIL(
- listen(bound, /* backlog = */ 5)); // NOLINT(bugprone-argument-comment)
- MaybeSave(); // Successful listen.
-
- int connected;
- RETURN_ERROR_IF_SYSCALL_FAIL(connected = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
- RETURN_ERROR_IF_SYSCALL_FAIL(
- connect(connected, AsSockAddr(&bind_addr), sizeof(bind_addr)));
- MaybeSave(); // Successful connect.
-
- int accepted;
- RETURN_ERROR_IF_SYSCALL_FAIL(
- accepted = accept4(bound, nullptr, nullptr,
- type & (SOCK_NONBLOCK | SOCK_CLOEXEC)));
- MaybeSave(); // Successful connect.
-
- // Cleanup no longer needed resources.
- RETURN_ERROR_IF_SYSCALL_FAIL(close(bound));
- MaybeSave(); // Dropped original socket.
-
- // Only unlink if path is not in abstract namespace.
- if (bind_addr.sun_path[0] != 0) {
- RETURN_ERROR_IF_SYSCALL_FAIL(unlink(bind_addr.sun_path));
- MaybeSave(); // Unlinked path.
- }
-
- // accepted is before connected to destruct connected before accepted.
- // Destructors for nonstatic member objects are called in the reverse order
- // in which they appear in the class declaration.
- return absl::make_unique<AddrFDSocketPair>(accepted, connected, bind_addr,
- extra_addr);
- };
-}
-
-Creator<SocketPair> FilesystemAcceptBindSocketPairCreator(int domain, int type,
- int protocol) {
- return AcceptBindSocketPairCreator(/* abstract= */ false, domain, type,
- protocol);
-}
-
-Creator<SocketPair> AbstractAcceptBindSocketPairCreator(int domain, int type,
- int protocol) {
- return AcceptBindSocketPairCreator(/* abstract= */ true, domain, type,
- protocol);
-}
-
-Creator<SocketPair> BidirectionalBindSocketPairCreator(bool abstract,
- int domain, int type,
- int protocol) {
- return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
- ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un addr1,
- UniqueUnixAddr(abstract, domain));
- ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un addr2,
- UniqueUnixAddr(abstract, domain));
-
- int sock1;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock1 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
- RETURN_ERROR_IF_SYSCALL_FAIL(
- bind(sock1, AsSockAddr(&addr1), sizeof(addr1)));
- MaybeSave(); // Successful bind.
-
- int sock2;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock2 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
- RETURN_ERROR_IF_SYSCALL_FAIL(
- bind(sock2, AsSockAddr(&addr2), sizeof(addr2)));
- MaybeSave(); // Successful bind.
-
- RETURN_ERROR_IF_SYSCALL_FAIL(
- connect(sock1, AsSockAddr(&addr2), sizeof(addr2)));
- MaybeSave(); // Successful connect.
-
- RETURN_ERROR_IF_SYSCALL_FAIL(
- connect(sock2, AsSockAddr(&addr1), sizeof(addr1)));
- MaybeSave(); // Successful connect.
-
- // Cleanup no longer needed resources.
-
- // Only unlink if path is not in abstract namespace.
- if (addr1.sun_path[0] != 0) {
- RETURN_ERROR_IF_SYSCALL_FAIL(unlink(addr1.sun_path));
- MaybeSave(); // Successful unlink.
- }
-
- // Only unlink if path is not in abstract namespace.
- if (addr2.sun_path[0] != 0) {
- RETURN_ERROR_IF_SYSCALL_FAIL(unlink(addr2.sun_path));
- MaybeSave(); // Successful unlink.
- }
-
- return absl::make_unique<FDSocketPair>(sock1, sock2);
- };
-}
-
-Creator<SocketPair> FilesystemBidirectionalBindSocketPairCreator(int domain,
- int type,
- int protocol) {
- return BidirectionalBindSocketPairCreator(/* abstract= */ false, domain, type,
- protocol);
-}
-
-Creator<SocketPair> AbstractBidirectionalBindSocketPairCreator(int domain,
- int type,
- int protocol) {
- return BidirectionalBindSocketPairCreator(/* abstract= */ true, domain, type,
- protocol);
-}
-
-Creator<SocketPair> SocketpairGoferSocketPairCreator(int domain, int type,
- int protocol) {
- return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
- struct sockaddr_un addr = {};
- constexpr char kSocketGoferPath[] = "/socket";
- memcpy(addr.sun_path, kSocketGoferPath, sizeof(kSocketGoferPath));
- addr.sun_family = domain;
-
- int sock1;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock1 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
- RETURN_ERROR_IF_SYSCALL_FAIL(
- connect(sock1, AsSockAddr(&addr), sizeof(addr)));
- MaybeSave(); // Successful connect.
-
- int sock2;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock2 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
- RETURN_ERROR_IF_SYSCALL_FAIL(
- connect(sock2, AsSockAddr(&addr), sizeof(addr)));
- MaybeSave(); // Successful connect.
-
- // Make and close another socketpair to ensure that the duped ends of the
- // first socketpair get closed.
- //
- // The problem is that there is no way to atomically send and close an FD.
- // The closest that we can do is send and then immediately close the FD,
- // which is what we do in the gofer. The gofer won't respond to another
- // request until the reply is sent and the FD is closed, so forcing the
- // gofer to handle another request will ensure that this has happened.
- for (int i = 0; i < 2; i++) {
- int sock;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock = socket(domain, type, protocol));
- RETURN_ERROR_IF_SYSCALL_FAIL(
- connect(sock, AsSockAddr(&addr), sizeof(addr)));
- RETURN_ERROR_IF_SYSCALL_FAIL(close(sock));
- }
-
- return absl::make_unique<FDSocketPair>(sock1, sock2);
- };
-}
-
-Creator<SocketPair> SocketpairGoferFileSocketPairCreator(int flags) {
- return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
- constexpr char kSocketGoferPath[] = "/socket";
-
- int sock1;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock1 =
- open(kSocketGoferPath, O_RDWR | flags));
- MaybeSave(); // Successful socket creation.
-
- int sock2;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock2 =
- open(kSocketGoferPath, O_RDWR | flags));
- MaybeSave(); // Successful socket creation.
-
- return absl::make_unique<FDSocketPair>(sock1, sock2);
- };
-}
-
-Creator<SocketPair> UnboundSocketPairCreator(bool abstract, int domain,
- int type, int protocol) {
- return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
- ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un addr1,
- UniqueUnixAddr(abstract, domain));
- ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un addr2,
- UniqueUnixAddr(abstract, domain));
-
- int sock1;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock1 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
- int sock2;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock2 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
- return absl::make_unique<AddrFDSocketPair>(sock1, sock2, addr1, addr2);
- };
-}
-
-Creator<SocketPair> FilesystemUnboundSocketPairCreator(int domain, int type,
- int protocol) {
- return UnboundSocketPairCreator(/* abstract= */ false, domain, type,
- protocol);
-}
-
-Creator<SocketPair> AbstractUnboundSocketPairCreator(int domain, int type,
- int protocol) {
- return UnboundSocketPairCreator(/* abstract= */ true, domain, type, protocol);
-}
-
-void LocalhostAddr(struct sockaddr_in* addr, bool dual_stack) {
- addr->sin_family = AF_INET;
- addr->sin_port = htons(0);
- inet_pton(AF_INET, "127.0.0.1",
- reinterpret_cast<void*>(&addr->sin_addr.s_addr));
-}
-
-void LocalhostAddr(struct sockaddr_in6* addr, bool dual_stack) {
- addr->sin6_family = AF_INET6;
- addr->sin6_port = htons(0);
- if (dual_stack) {
- inet_pton(AF_INET6, "::ffff:127.0.0.1",
- reinterpret_cast<void*>(&addr->sin6_addr.s6_addr));
- } else {
- inet_pton(AF_INET6, "::1",
- reinterpret_cast<void*>(&addr->sin6_addr.s6_addr));
- }
- addr->sin6_scope_id = 0;
-}
-
-template <typename T>
-PosixErrorOr<T> BindIP(int fd, bool dual_stack) {
- T addr = {};
- LocalhostAddr(&addr, dual_stack);
- RETURN_ERROR_IF_SYSCALL_FAIL(bind(fd, AsSockAddr(&addr), sizeof(addr)));
- socklen_t addrlen = sizeof(addr);
- RETURN_ERROR_IF_SYSCALL_FAIL(getsockname(fd, AsSockAddr(&addr), &addrlen));
- return addr;
-}
-
-template <typename T>
-PosixErrorOr<T> TCPBindAndListen(int fd, bool dual_stack) {
- ASSIGN_OR_RETURN_ERRNO(T addr, BindIP<T>(fd, dual_stack));
- RETURN_ERROR_IF_SYSCALL_FAIL(
- listen(fd, /* backlog = */ 5)); // NOLINT(bugprone-argument-comment)
- return addr;
-}
-
-template <typename T>
-PosixErrorOr<std::unique_ptr<AddrFDSocketPair>>
-CreateTCPConnectAcceptSocketPair(int bound, int connected, int type,
- bool dual_stack, T bind_addr) {
- int connect_result = 0;
- RETURN_ERROR_IF_SYSCALL_FAIL(
- (connect_result = RetryEINTR(connect)(connected, AsSockAddr(&bind_addr),
- sizeof(bind_addr))) == -1 &&
- errno == EINPROGRESS
- ? 0
- : connect_result);
- MaybeSave(); // Successful connect.
-
- if (connect_result == -1) {
- struct pollfd connect_poll = {connected, POLLOUT | POLLERR | POLLHUP, 0};
- RETURN_ERROR_IF_SYSCALL_FAIL(RetryEINTR(poll)(&connect_poll, 1, 0));
- int error = 0;
- socklen_t errorlen = sizeof(error);
- RETURN_ERROR_IF_SYSCALL_FAIL(
- getsockopt(connected, SOL_SOCKET, SO_ERROR, &error, &errorlen));
- errno = error;
- RETURN_ERROR_IF_SYSCALL_FAIL(
- /* connect */ error == 0 ? 0 : -1);
- }
-
- int accepted = -1;
- struct pollfd accept_poll = {bound, POLLIN, 0};
- while (accepted == -1) {
- RETURN_ERROR_IF_SYSCALL_FAIL(RetryEINTR(poll)(&accept_poll, 1, 0));
-
- RETURN_ERROR_IF_SYSCALL_FAIL(
- (accepted = RetryEINTR(accept4)(
- bound, nullptr, nullptr, type & (SOCK_NONBLOCK | SOCK_CLOEXEC))) ==
- -1 &&
- errno == EAGAIN
- ? 0
- : accepted);
- }
- MaybeSave(); // Successful accept.
-
- T extra_addr = {};
- LocalhostAddr(&extra_addr, dual_stack);
- return absl::make_unique<AddrFDSocketPair>(connected, accepted, bind_addr,
- extra_addr);
-}
-
-template <typename T>
-PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> CreateTCPAcceptBindSocketPair(
- int bound, int connected, int type, bool dual_stack) {
- ASSIGN_OR_RETURN_ERRNO(T bind_addr, TCPBindAndListen<T>(bound, dual_stack));
-
- auto result = CreateTCPConnectAcceptSocketPair(bound, connected, type,
- dual_stack, bind_addr);
-
- // Cleanup no longer needed resources.
- RETURN_ERROR_IF_SYSCALL_FAIL(close(bound));
- MaybeSave(); // Successful close.
-
- return result;
-}
-
-Creator<SocketPair> TCPAcceptBindSocketPairCreator(int domain, int type,
- int protocol,
- bool dual_stack) {
- return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
- int bound;
- RETURN_ERROR_IF_SYSCALL_FAIL(bound = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
-
- int connected;
- RETURN_ERROR_IF_SYSCALL_FAIL(connected = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
-
- if (domain == AF_INET) {
- return CreateTCPAcceptBindSocketPair<sockaddr_in>(bound, connected, type,
- dual_stack);
- }
- return CreateTCPAcceptBindSocketPair<sockaddr_in6>(bound, connected, type,
- dual_stack);
- };
-}
-
-Creator<SocketPair> TCPAcceptBindPersistentListenerSocketPairCreator(
- int domain, int type, int protocol, bool dual_stack) {
- // These are lazily initialized below, on the first call to the returned
- // lambda. These values are private to each returned lambda, but shared across
- // invocations of a specific lambda.
- //
- // The sharing allows pairs created with the same parameters to share a
- // listener. This prevents future connects from failing if the connecting
- // socket selects a port which had previously been used by a listening socket
- // that still has some connections in TIME-WAIT.
- //
- // The lazy initialization is to avoid creating sockets during parameter
- // enumeration. This is important because parameters are enumerated during the
- // build process where networking may not be available.
- auto listener = std::make_shared<absl::optional<int>>(absl::optional<int>());
- auto addr4 = std::make_shared<absl::optional<sockaddr_in>>(
- absl::optional<sockaddr_in>());
- auto addr6 = std::make_shared<absl::optional<sockaddr_in6>>(
- absl::optional<sockaddr_in6>());
-
- return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
- int connected;
- RETURN_ERROR_IF_SYSCALL_FAIL(connected = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
-
- // Share the listener across invocations.
- if (!listener->has_value()) {
- int fd = socket(domain, type, protocol);
- if (fd < 0) {
- return PosixError(errno, absl::StrCat("socket(", domain, ", ", type,
- ", ", protocol, ")"));
- }
- listener->emplace(fd);
- MaybeSave(); // Successful socket creation.
- }
-
- // Bind the listener once, but create a new connect/accept pair each
- // time.
- if (domain == AF_INET) {
- if (!addr4->has_value()) {
- addr4->emplace(
- TCPBindAndListen<sockaddr_in>(listener->value(), dual_stack)
- .ValueOrDie());
- }
- return CreateTCPConnectAcceptSocketPair(listener->value(), connected,
- type, dual_stack, addr4->value());
- }
- if (!addr6->has_value()) {
- addr6->emplace(
- TCPBindAndListen<sockaddr_in6>(listener->value(), dual_stack)
- .ValueOrDie());
- }
- return CreateTCPConnectAcceptSocketPair(listener->value(), connected, type,
- dual_stack, addr6->value());
- };
-}
-
-template <typename T>
-PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> CreateUDPBoundSocketPair(
- int sock1, int sock2, int type, bool dual_stack) {
- ASSIGN_OR_RETURN_ERRNO(T addr1, BindIP<T>(sock1, dual_stack));
- ASSIGN_OR_RETURN_ERRNO(T addr2, BindIP<T>(sock2, dual_stack));
-
- return absl::make_unique<AddrFDSocketPair>(sock1, sock2, addr1, addr2);
-}
-
-template <typename T>
-PosixErrorOr<std::unique_ptr<AddrFDSocketPair>>
-CreateUDPBidirectionalBindSocketPair(int sock1, int sock2, int type,
- bool dual_stack) {
- ASSIGN_OR_RETURN_ERRNO(
- auto socks, CreateUDPBoundSocketPair<T>(sock1, sock2, type, dual_stack));
-
- // Connect sock1 to sock2.
- RETURN_ERROR_IF_SYSCALL_FAIL(connect(socks->first_fd(), socks->second_addr(),
- socks->second_addr_size()));
- MaybeSave(); // Successful connection.
-
- // Connect sock2 to sock1.
- RETURN_ERROR_IF_SYSCALL_FAIL(connect(socks->second_fd(), socks->first_addr(),
- socks->first_addr_size()));
- MaybeSave(); // Successful connection.
-
- return socks;
-}
-
-Creator<SocketPair> UDPBidirectionalBindSocketPairCreator(int domain, int type,
- int protocol,
- bool dual_stack) {
- return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
- int sock1;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock1 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
-
- int sock2;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock2 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
-
- if (domain == AF_INET) {
- return CreateUDPBidirectionalBindSocketPair<sockaddr_in>(
- sock1, sock2, type, dual_stack);
- }
- return CreateUDPBidirectionalBindSocketPair<sockaddr_in6>(sock1, sock2,
- type, dual_stack);
- };
-}
-
-Creator<SocketPair> UDPUnboundSocketPairCreator(int domain, int type,
- int protocol, bool dual_stack) {
- return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
- int sock1;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock1 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
-
- int sock2;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock2 = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
-
- return absl::make_unique<FDSocketPair>(sock1, sock2);
- };
-}
-
-SocketPairKind Reversed(SocketPairKind const& base) {
- auto const& creator = base.creator;
- return SocketPairKind{
- absl::StrCat("reversed ", base.description), base.domain, base.type,
- base.protocol,
- [creator]() -> PosixErrorOr<std::unique_ptr<ReversedSocketPair>> {
- ASSIGN_OR_RETURN_ERRNO(auto creator_value, creator());
- return absl::make_unique<ReversedSocketPair>(std::move(creator_value));
- }};
-}
-
-Creator<FileDescriptor> UnboundSocketCreator(int domain, int type,
- int protocol) {
- return [=]() -> PosixErrorOr<std::unique_ptr<FileDescriptor>> {
- int sock;
- RETURN_ERROR_IF_SYSCALL_FAIL(sock = socket(domain, type, protocol));
- MaybeSave(); // Successful socket creation.
-
- return absl::make_unique<FileDescriptor>(sock);
- };
-}
-
-std::vector<SocketPairKind> IncludeReversals(std::vector<SocketPairKind> vec) {
- return ApplyVecToVec<SocketPairKind>(std::vector<Middleware>{NoOp, Reversed},
- vec);
-}
-
-SocketPairKind NoOp(SocketPairKind const& base) { return base; }
-
-void TransferTest(int fd1, int fd2) {
- char buf1[20];
- RandomizeBuffer(buf1, sizeof(buf1));
- ASSERT_THAT(WriteFd(fd1, buf1, sizeof(buf1)),
- SyscallSucceedsWithValue(sizeof(buf1)));
-
- char buf2[20];
- ASSERT_THAT(ReadFd(fd2, buf2, sizeof(buf2)),
- SyscallSucceedsWithValue(sizeof(buf2)));
-
- EXPECT_EQ(0, memcmp(buf1, buf2, sizeof(buf1)));
-
- RandomizeBuffer(buf1, sizeof(buf1));
- ASSERT_THAT(WriteFd(fd2, buf1, sizeof(buf1)),
- SyscallSucceedsWithValue(sizeof(buf1)));
-
- ASSERT_THAT(ReadFd(fd1, buf2, sizeof(buf2)),
- SyscallSucceedsWithValue(sizeof(buf2)));
-
- EXPECT_EQ(0, memcmp(buf1, buf2, sizeof(buf1)));
-}
-
-// Initializes the given buffer with random data.
-void RandomizeBuffer(char* ptr, size_t len) {
- uint32_t seed = time(nullptr);
- for (size_t i = 0; i < len; ++i) {
- ptr[i] = static_cast<char>(rand_r(&seed));
- }
-}
-
-size_t CalculateUnixSockAddrLen(const char* sun_path) {
- // Abstract addresses always return the full length.
- if (sun_path[0] == 0) {
- return sizeof(sockaddr_un);
- }
- // Filesystem addresses use the address length plus the 2 byte sun_family
- // and null terminator.
- return strlen(sun_path) + 3;
-}
-
-struct sockaddr_storage AddrFDSocketPair::to_storage(const sockaddr_un& addr) {
- struct sockaddr_storage addr_storage = {};
- memcpy(&addr_storage, &addr, sizeof(addr));
- return addr_storage;
-}
-
-struct sockaddr_storage AddrFDSocketPair::to_storage(const sockaddr_in& addr) {
- struct sockaddr_storage addr_storage = {};
- memcpy(&addr_storage, &addr, sizeof(addr));
- return addr_storage;
-}
-
-struct sockaddr_storage AddrFDSocketPair::to_storage(const sockaddr_in6& addr) {
- struct sockaddr_storage addr_storage = {};
- memcpy(&addr_storage, &addr, sizeof(addr));
- return addr_storage;
-}
-
-SocketKind SimpleSocket(int fam, int type, int proto) {
- return SocketKind{
- absl::StrCat("Family ", fam, ", type ", type, ", proto ", proto), fam,
- type, proto, SyscallSocketCreator(fam, type, proto)};
-}
-
-ssize_t SendLargeSendMsg(const std::unique_ptr<SocketPair>& sockets,
- size_t size, bool reader) {
- const int rfd = sockets->second_fd();
- ScopedThread t([rfd, size, reader] {
- if (!reader) {
- return;
- }
-
- // Potentially too many syscalls in the loop.
- const DisableSave ds;
-
- std::vector<char> buf(size);
- size_t total = 0;
-
- while (total < size) {
- int ret = read(rfd, buf.data(), buf.size());
- if (ret == -1 && errno == EAGAIN) {
- continue;
- }
- if (ret > 0) {
- total += ret;
- }
-
- // Assert to return on first failure.
- ASSERT_THAT(ret, SyscallSucceeds());
- }
- });
-
- std::vector<char> buf(size);
-
- struct iovec iov = {};
- iov.iov_base = buf.data();
- iov.iov_len = buf.size();
-
- struct msghdr msg = {};
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- return RetryEINTR(sendmsg)(sockets->first_fd(), &msg, 0);
-}
-
-namespace internal {
-PosixErrorOr<int> TryPortAvailable(int port, AddressFamily family,
- SocketType type, bool reuse_addr) {
- if (port < 0) {
- return PosixError(EINVAL, "Invalid port");
- }
-
- // Both Ipv6 and Dualstack are AF_INET6.
- int sock_fam = (family == AddressFamily::kIpv4 ? AF_INET : AF_INET6);
- int sock_type = (type == SocketType::kTcp ? SOCK_STREAM : SOCK_DGRAM);
- ASSIGN_OR_RETURN_ERRNO(auto fd, Socket(sock_fam, sock_type, 0));
-
- if (reuse_addr) {
- int one = 1;
- RETURN_ERROR_IF_SYSCALL_FAIL(
- setsockopt(fd.get(), SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)));
- }
-
- // Try to bind.
- sockaddr_storage storage = {};
- int storage_size = 0;
- if (family == AddressFamily::kIpv4) {
- sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(&storage);
- storage_size = sizeof(*addr);
- addr->sin_family = AF_INET;
- addr->sin_port = htons(port);
- addr->sin_addr.s_addr = htonl(INADDR_ANY);
- } else {
- sockaddr_in6* addr = reinterpret_cast<sockaddr_in6*>(&storage);
- storage_size = sizeof(*addr);
- addr->sin6_family = AF_INET6;
- addr->sin6_port = htons(port);
- if (family == AddressFamily::kDualStack) {
- inet_pton(AF_INET6, "::ffff:0.0.0.0",
- reinterpret_cast<void*>(&addr->sin6_addr.s6_addr));
- } else {
- addr->sin6_addr = in6addr_any;
- }
- }
-
- RETURN_ERROR_IF_SYSCALL_FAIL(
- bind(fd.get(), AsSockAddr(&storage), storage_size));
-
- // If the user specified 0 as the port, we will return the port that the
- // kernel gave us, otherwise we will validate that this socket bound to the
- // requested port.
- sockaddr_storage bound_storage = {};
- socklen_t bound_storage_size = sizeof(bound_storage);
- RETURN_ERROR_IF_SYSCALL_FAIL(
- getsockname(fd.get(), AsSockAddr(&bound_storage), &bound_storage_size));
-
- int available_port = -1;
- if (bound_storage.ss_family == AF_INET) {
- sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(&bound_storage);
- available_port = ntohs(addr->sin_port);
- } else if (bound_storage.ss_family == AF_INET6) {
- sockaddr_in6* addr = reinterpret_cast<sockaddr_in6*>(&bound_storage);
- available_port = ntohs(addr->sin6_port);
- } else {
- return PosixError(EPROTOTYPE, "Getsockname returned invalid family");
- }
-
- // If we requested a specific port make sure our bound port is that port.
- if (port != 0 && available_port != port) {
- return PosixError(EINVAL,
- absl::StrCat("Bound port ", available_port,
- " was not equal to requested port ", port));
- }
-
- // If we're trying to do a TCP socket, let's also try to listen.
- if (type == SocketType::kTcp) {
- RETURN_ERROR_IF_SYSCALL_FAIL(listen(fd.get(), 1));
- }
-
- return available_port;
-}
-} // namespace internal
-
-PosixErrorOr<int> SendMsg(int sock, msghdr* msg, char buf[], int buf_size) {
- struct iovec iov;
- iov.iov_base = buf;
- iov.iov_len = buf_size;
- msg->msg_iov = &iov;
- msg->msg_iovlen = 1;
-
- int ret;
- RETURN_ERROR_IF_SYSCALL_FAIL(ret = RetryEINTR(sendmsg)(sock, msg, 0));
- return ret;
-}
-
-PosixErrorOr<int> RecvTimeout(int sock, char buf[], int buf_size, int timeout) {
- fd_set rfd;
- struct timeval to = {.tv_sec = timeout, .tv_usec = 0};
- FD_ZERO(&rfd);
- FD_SET(sock, &rfd);
-
- int ret;
- RETURN_ERROR_IF_SYSCALL_FAIL(ret = select(1, &rfd, NULL, NULL, &to));
- RETURN_ERROR_IF_SYSCALL_FAIL(
- ret = RetryEINTR(recv)(sock, buf, buf_size, MSG_DONTWAIT));
- return ret;
-}
-
-PosixErrorOr<int> RecvMsgTimeout(int sock, struct msghdr* msg, int timeout) {
- fd_set rfd;
- struct timeval to = {.tv_sec = timeout, .tv_usec = 0};
- FD_ZERO(&rfd);
- FD_SET(sock, &rfd);
-
- int ret;
- RETURN_ERROR_IF_SYSCALL_FAIL(ret = select(1, &rfd, NULL, NULL, &to));
- RETURN_ERROR_IF_SYSCALL_FAIL(
- ret = RetryEINTR(recvmsg)(sock, msg, MSG_DONTWAIT));
- return ret;
-}
-
-void RecvNoData(int sock) {
- char data = 0;
- struct iovec iov;
- iov.iov_base = &data;
- iov.iov_len = 1;
- struct msghdr msg = {};
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- ASSERT_THAT(RetryEINTR(recvmsg)(sock, &msg, MSG_DONTWAIT),
- SyscallFailsWithErrno(EAGAIN));
-}
-
-TestAddress TestAddress::WithPort(uint16_t port) const {
- TestAddress addr = *this;
- switch (addr.family()) {
- case AF_INET:
- reinterpret_cast<sockaddr_in*>(&addr.addr)->sin_port = htons(port);
- break;
- case AF_INET6:
- reinterpret_cast<sockaddr_in6*>(&addr.addr)->sin6_port = htons(port);
- break;
- }
- return addr;
-}
-
-namespace {
-
-TestAddress V4Addr(std::string description, in_addr_t addr) {
- TestAddress t(std::move(description));
- t.addr.ss_family = AF_INET;
- t.addr_len = sizeof(sockaddr_in);
- reinterpret_cast<sockaddr_in*>(&t.addr)->sin_addr.s_addr = addr;
- return t;
-}
-
-TestAddress V6Addr(std::string description, const in6_addr& addr) {
- TestAddress t(std::move(description));
- t.addr.ss_family = AF_INET6;
- t.addr_len = sizeof(sockaddr_in6);
- reinterpret_cast<sockaddr_in6*>(&t.addr)->sin6_addr = addr;
- return t;
-}
-
-} // namespace
-
-TestAddress V4AddrStr(std::string description, const char* addr) {
- in_addr_t s_addr;
- inet_pton(AF_INET, addr, &s_addr);
- return V4Addr(description, s_addr);
-}
-
-TestAddress V6AddrStr(std::string description, const char* addr) {
- struct in6_addr s_addr;
- inet_pton(AF_INET6, addr, &s_addr);
- return V6Addr(description, s_addr);
-}
-
-TestAddress V4Any() { return V4Addr("V4Any", htonl(INADDR_ANY)); }
-
-TestAddress V4Broadcast() {
- return V4Addr("V4Broadcast", htonl(INADDR_BROADCAST));
-}
-
-TestAddress V4Loopback() {
- return V4Addr("V4Loopback", htonl(INADDR_LOOPBACK));
-}
-
-TestAddress V4LoopbackSubnetBroadcast() {
- return V4AddrStr("V4LoopbackSubnetBroadcast", "127.255.255.255");
-}
-
-TestAddress V4MappedAny() { return V6AddrStr("V4MappedAny", "::ffff:0.0.0.0"); }
-
-TestAddress V4MappedLoopback() {
- return V6AddrStr("V4MappedLoopback", "::ffff:127.0.0.1");
-}
-
-TestAddress V4Multicast() {
- return V4Addr("V4Multicast", inet_addr(kMulticastAddress));
-}
-
-TestAddress V4MulticastAllHosts() {
- return V4Addr("V4MulticastAllHosts", htonl(INADDR_ALLHOSTS_GROUP));
-}
-
-TestAddress V6Any() { return V6Addr("V6Any", in6addr_any); }
-
-TestAddress V6Loopback() { return V6Addr("V6Loopback", in6addr_loopback); }
-
-TestAddress V6Multicast() { return V6AddrStr("V6Multicast", "ff05::1234"); }
-
-TestAddress V6MulticastInterfaceLocalAllNodes() {
- return V6AddrStr("V6MulticastInterfaceLocalAllNodes", "ff01::1");
-}
-
-TestAddress V6MulticastLinkLocalAllNodes() {
- return V6AddrStr("V6MulticastLinkLocalAllNodes", "ff02::1");
-}
-
-TestAddress V6MulticastLinkLocalAllRouters() {
- return V6AddrStr("V6MulticastLinkLocalAllRouters", "ff02::2");
-}
-
-// Checksum computes the internet checksum of a buffer.
-uint16_t Checksum(uint16_t* buf, ssize_t buf_size) {
- // Add up the 16-bit values in the buffer.
- uint32_t total = 0;
- for (unsigned int i = 0; i < buf_size; i += sizeof(*buf)) {
- total += *buf;
- buf++;
- }
-
- // If buf has an odd size, add the remaining byte.
- if (buf_size % 2) {
- total += *(reinterpret_cast<unsigned char*>(buf) - 1);
- }
-
- // This carries any bits past the lower 16 until everything fits in 16 bits.
- while (total >> 16) {
- uint16_t lower = total & 0xffff;
- uint16_t upper = total >> 16;
- total = lower + upper;
- }
-
- return ~total;
-}
-
-uint16_t IPChecksum(struct iphdr ip) {
- return Checksum(reinterpret_cast<uint16_t*>(&ip), sizeof(ip));
-}
-
-// The pseudo-header defined in RFC 768 for calculating the UDP checksum.
-struct udp_pseudo_hdr {
- uint32_t srcip;
- uint32_t destip;
- char zero;
- char protocol;
- uint16_t udplen;
-};
-
-uint16_t UDPChecksum(struct iphdr iphdr, struct udphdr udphdr,
- const char* payload, ssize_t payload_len) {
- struct udp_pseudo_hdr phdr = {};
- phdr.srcip = iphdr.saddr;
- phdr.destip = iphdr.daddr;
- phdr.zero = 0;
- phdr.protocol = IPPROTO_UDP;
- phdr.udplen = udphdr.len;
-
- ssize_t buf_size = sizeof(phdr) + sizeof(udphdr) + payload_len;
- char* buf = static_cast<char*>(malloc(buf_size));
- memcpy(buf, &phdr, sizeof(phdr));
- memcpy(buf + sizeof(phdr), &udphdr, sizeof(udphdr));
- memcpy(buf + sizeof(phdr) + sizeof(udphdr), payload, payload_len);
-
- uint16_t csum = Checksum(reinterpret_cast<uint16_t*>(buf), buf_size);
- free(buf);
- return csum;
-}
-
-uint16_t ICMPChecksum(struct icmphdr icmphdr, const char* payload,
- ssize_t payload_len) {
- ssize_t buf_size = sizeof(icmphdr) + payload_len;
- char* buf = static_cast<char*>(malloc(buf_size));
- memcpy(buf, &icmphdr, sizeof(icmphdr));
- memcpy(buf + sizeof(icmphdr), payload, payload_len);
-
- uint16_t csum = Checksum(reinterpret_cast<uint16_t*>(buf), buf_size);
- free(buf);
- return csum;
-}
-
-PosixErrorOr<uint16_t> AddrPort(int family, sockaddr_storage const& addr) {
- switch (family) {
- case AF_INET:
- return static_cast<uint16_t>(
- reinterpret_cast<sockaddr_in const*>(&addr)->sin_port);
- case AF_INET6:
- return static_cast<uint16_t>(
- reinterpret_cast<sockaddr_in6 const*>(&addr)->sin6_port);
- default:
- return PosixError(EINVAL,
- absl::StrCat("unknown socket family: ", family));
- }
-}
-
-PosixError SetAddrPort(int family, sockaddr_storage* addr, uint16_t port) {
- switch (family) {
- case AF_INET:
- reinterpret_cast<sockaddr_in*>(addr)->sin_port = port;
- return NoError();
- case AF_INET6:
- reinterpret_cast<sockaddr_in6*>(addr)->sin6_port = port;
- return NoError();
- default:
- return PosixError(EINVAL,
- absl::StrCat("unknown socket family: ", family));
- }
-}
-
-void SetupTimeWaitClose(const TestAddress* listener,
- const TestAddress* connector, bool reuse,
- bool accept_close, sockaddr_storage* listen_addr,
- sockaddr_storage* conn_bound_addr) {
- // Create the listening socket.
- FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE(
- Socket(listener->family(), SOCK_STREAM, IPPROTO_TCP));
- if (reuse) {
- ASSERT_THAT(setsockopt(listen_fd.get(), SOL_SOCKET, SO_REUSEADDR,
- &kSockOptOn, sizeof(kSockOptOn)),
- SyscallSucceeds());
- }
- ASSERT_THAT(
- bind(listen_fd.get(), AsSockAddr(listen_addr), listener->addr_len),
- SyscallSucceeds());
- ASSERT_THAT(listen(listen_fd.get(), SOMAXCONN), SyscallSucceeds());
-
- // Get the port bound by the listening socket.
- socklen_t addrlen = listener->addr_len;
- ASSERT_THAT(getsockname(listen_fd.get(), AsSockAddr(listen_addr), &addrlen),
- SyscallSucceeds());
-
- uint16_t const port =
- ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener->family(), *listen_addr));
-
- // Connect to the listening socket.
- FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE(
- Socket(connector->family(), SOCK_STREAM, IPPROTO_TCP));
-
- // We disable saves after this point as a S/R causes the netstack seed
- // to be regenerated which changes what ports/ISN is picked for a given
- // tuple (src ip,src port, dst ip, dst port). This can cause the final
- // SYN to use a sequence number that looks like one from the current
- // connection in TIME_WAIT and will not be accepted causing the test
- // to timeout.
- //
- // TODO(gvisor.dev/issue/940): S/R portSeed/portHint
- DisableSave ds;
-
- sockaddr_storage conn_addr = connector->addr;
- ASSERT_NO_ERRNO(SetAddrPort(connector->family(), &conn_addr, port));
- ASSERT_THAT(RetryEINTR(connect)(conn_fd.get(), AsSockAddr(&conn_addr),
- connector->addr_len),
- SyscallSucceeds());
-
- // Accept the connection.
- auto accepted =
- ASSERT_NO_ERRNO_AND_VALUE(Accept(listen_fd.get(), nullptr, nullptr));
-
- // Get the address/port bound by the connecting socket.
- socklen_t conn_addrlen = connector->addr_len;
- ASSERT_THAT(
- getsockname(conn_fd.get(), AsSockAddr(conn_bound_addr), &conn_addrlen),
- SyscallSucceeds());
-
- FileDescriptor active_closefd, passive_closefd;
- if (accept_close) {
- active_closefd = std::move(accepted);
- passive_closefd = std::move(conn_fd);
- } else {
- active_closefd = std::move(conn_fd);
- passive_closefd = std::move(accepted);
- }
-
- // shutdown to trigger TIME_WAIT.
- ASSERT_THAT(shutdown(active_closefd.get(), SHUT_WR), SyscallSucceeds());
- {
- constexpr int kTimeout = 10000;
- pollfd pfd = {
- .fd = passive_closefd.get(),
- .events = POLLIN,
- };
- ASSERT_THAT(poll(&pfd, 1, kTimeout), SyscallSucceedsWithValue(1));
- ASSERT_EQ(pfd.revents, POLLIN);
- }
- ASSERT_THAT(shutdown(passive_closefd.get(), SHUT_WR), SyscallSucceeds());
- {
- constexpr int kTimeout = 10000;
- constexpr int16_t want_events = POLLHUP;
- pollfd pfd = {
- .fd = active_closefd.get(),
- .events = want_events,
- };
- ASSERT_THAT(poll(&pfd, 1, kTimeout), SyscallSucceedsWithValue(1));
- }
-
- // This sleep is needed to reduce flake to ensure that the passive-close
- // ensures the state transitions to CLOSE from LAST_ACK.
- absl::SleepFor(absl::Seconds(1));
-}
-
-constexpr char kRangeFile[] = "/proc/sys/net/ipv4/ip_local_port_range";
-
-PosixErrorOr<int> MaybeLimitEphemeralPorts() {
- int min = 0;
- int max = 1 << 16;
-
- // Read the ephemeral range from /proc.
- ASSIGN_OR_RETURN_ERRNO(std::string rangefile, GetContents(kRangeFile));
- const std::string err_msg =
- absl::StrFormat("%s has invalid content: %s", kRangeFile, rangefile);
- if (rangefile.back() != '\n') {
- return PosixError(EINVAL, err_msg);
- }
- rangefile.pop_back();
- std::vector<std::string> range =
- absl::StrSplit(rangefile, absl::ByAnyChar("\t "));
- if (range.size() < 2 || !absl::SimpleAtoi(range.front(), &min) ||
- !absl::SimpleAtoi(range.back(), &max)) {
- return PosixError(EINVAL, err_msg);
- }
-
- // If we can open as writable, limit the range.
- if (!access(kRangeFile, W_OK)) {
- ASSIGN_OR_RETURN_ERRNO(FileDescriptor fd,
- Open(kRangeFile, O_WRONLY | O_TRUNC, 0));
- int newMax = min + 50;
- const std::string small_range = absl::StrFormat("%d %d", min, newMax);
- int n = write(fd.get(), small_range.c_str(), small_range.size());
- if (n < 0) {
- // Hostinet doesn't allow modifying the host port range. And if we're root
- // (as we are in some tests), access and open will succeed even if the
- // file mode is readonly.
- if (errno != EACCES) {
- return PosixError(
- errno,
- absl::StrFormat("write(%d [%s], \"%s\", %d)", fd.get(), kRangeFile,
- small_range.c_str(), small_range.size()));
- }
- } else {
- max = newMax;
- }
- }
- return max - min;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/socket_util.h b/test/util/socket_util.h
deleted file mode 100644
index 0e2be63cc..000000000
--- a/test/util/socket_util.h
+++ /dev/null
@@ -1,591 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_SYSCALLS_SOCKET_TEST_UTIL_H_
-#define GVISOR_TEST_SYSCALLS_SOCKET_TEST_UTIL_H_
-
-#include <errno.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/udp.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "gtest/gtest.h"
-#include "absl/strings/str_format.h"
-#include "test/util/file_descriptor.h"
-#include "test/util/posix_error.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-// Wrapper for socket(2) that returns a FileDescriptor.
-inline PosixErrorOr<FileDescriptor> Socket(int family, int type, int protocol) {
- int fd = socket(family, type, protocol);
- MaybeSave();
- if (fd < 0) {
- return PosixError(
- errno, absl::StrFormat("socket(%d, %d, %d)", family, type, protocol));
- }
- return FileDescriptor(fd);
-}
-
-// Wrapper for accept(2) that returns a FileDescriptor.
-inline PosixErrorOr<FileDescriptor> Accept(int sockfd, sockaddr* addr,
- socklen_t* addrlen) {
- int fd = RetryEINTR(accept)(sockfd, addr, addrlen);
- MaybeSave();
- if (fd < 0) {
- return PosixError(
- errno, absl::StrFormat("accept(%d, %p, %p)", sockfd, addr, addrlen));
- }
- return FileDescriptor(fd);
-}
-
-// Wrapper for accept4(2) that returns a FileDescriptor.
-inline PosixErrorOr<FileDescriptor> Accept4(int sockfd, sockaddr* addr,
- socklen_t* addrlen, int flags) {
- int fd = RetryEINTR(accept4)(sockfd, addr, addrlen, flags);
- MaybeSave();
- if (fd < 0) {
- return PosixError(errno, absl::StrFormat("accept4(%d, %p, %p, %#x)", sockfd,
- addr, addrlen, flags));
- }
- return FileDescriptor(fd);
-}
-
-inline ssize_t SendFd(int fd, void* buf, size_t count, int flags) {
- return internal::ApplyFileIoSyscall(
- [&](size_t completed) {
- return sendto(fd, static_cast<char*>(buf) + completed,
- count - completed, flags, nullptr, 0);
- },
- count);
-}
-
-PosixErrorOr<struct sockaddr_un> UniqueUnixAddr(bool abstract, int domain);
-
-// A Creator<T> is a function that attempts to create and return a new T. (This
-// is copy/pasted from cloud/gvisor/api/sandbox_util.h and is just duplicated
-// here for clarity.)
-template <typename T>
-using Creator = std::function<PosixErrorOr<std::unique_ptr<T>>()>;
-
-// A SocketPair represents a pair of socket file descriptors owned by the
-// SocketPair.
-class SocketPair {
- public:
- virtual ~SocketPair() = default;
-
- virtual int first_fd() const = 0;
- virtual int second_fd() const = 0;
- virtual int release_first_fd() = 0;
- virtual int release_second_fd() = 0;
- virtual const struct sockaddr* first_addr() const = 0;
- virtual const struct sockaddr* second_addr() const = 0;
- virtual size_t first_addr_size() const = 0;
- virtual size_t second_addr_size() const = 0;
- virtual size_t first_addr_len() const = 0;
- virtual size_t second_addr_len() const = 0;
-};
-
-// A FDSocketPair is a SocketPair that consists of only a pair of file
-// descriptors.
-class FDSocketPair : public SocketPair {
- public:
- FDSocketPair(int first_fd, int second_fd)
- : first_(first_fd), second_(second_fd) {}
- FDSocketPair(std::unique_ptr<FileDescriptor> first_fd,
- std::unique_ptr<FileDescriptor> second_fd)
- : first_(first_fd->release()), second_(second_fd->release()) {}
-
- int first_fd() const override { return first_.get(); }
- int second_fd() const override { return second_.get(); }
- int release_first_fd() override { return first_.release(); }
- int release_second_fd() override { return second_.release(); }
- const struct sockaddr* first_addr() const override { return nullptr; }
- const struct sockaddr* second_addr() const override { return nullptr; }
- size_t first_addr_size() const override { return 0; }
- size_t second_addr_size() const override { return 0; }
- size_t first_addr_len() const override { return 0; }
- size_t second_addr_len() const override { return 0; }
-
- private:
- FileDescriptor first_;
- FileDescriptor second_;
-};
-
-// CalculateUnixSockAddrLen calculates the length returned by recvfrom(2) and
-// recvmsg(2) for Unix sockets.
-size_t CalculateUnixSockAddrLen(const char* sun_path);
-
-// A AddrFDSocketPair is a SocketPair that consists of a pair of file
-// descriptors in addition to a pair of socket addresses.
-class AddrFDSocketPair : public SocketPair {
- public:
- AddrFDSocketPair(int first_fd, int second_fd,
- const struct sockaddr_un& first_address,
- const struct sockaddr_un& second_address)
- : first_(first_fd),
- second_(second_fd),
- first_addr_(to_storage(first_address)),
- second_addr_(to_storage(second_address)),
- first_len_(CalculateUnixSockAddrLen(first_address.sun_path)),
- second_len_(CalculateUnixSockAddrLen(second_address.sun_path)),
- first_size_(sizeof(first_address)),
- second_size_(sizeof(second_address)) {}
-
- AddrFDSocketPair(int first_fd, int second_fd,
- const struct sockaddr_in& first_address,
- const struct sockaddr_in& second_address)
- : first_(first_fd),
- second_(second_fd),
- first_addr_(to_storage(first_address)),
- second_addr_(to_storage(second_address)),
- first_len_(sizeof(first_address)),
- second_len_(sizeof(second_address)),
- first_size_(sizeof(first_address)),
- second_size_(sizeof(second_address)) {}
-
- AddrFDSocketPair(int first_fd, int second_fd,
- const struct sockaddr_in6& first_address,
- const struct sockaddr_in6& second_address)
- : first_(first_fd),
- second_(second_fd),
- first_addr_(to_storage(first_address)),
- second_addr_(to_storage(second_address)),
- first_len_(sizeof(first_address)),
- second_len_(sizeof(second_address)),
- first_size_(sizeof(first_address)),
- second_size_(sizeof(second_address)) {}
-
- int first_fd() const override { return first_.get(); }
- int second_fd() const override { return second_.get(); }
- int release_first_fd() override { return first_.release(); }
- int release_second_fd() override { return second_.release(); }
- const struct sockaddr* first_addr() const override {
- return reinterpret_cast<const struct sockaddr*>(&first_addr_);
- }
- const struct sockaddr* second_addr() const override {
- return reinterpret_cast<const struct sockaddr*>(&second_addr_);
- }
- size_t first_addr_size() const override { return first_size_; }
- size_t second_addr_size() const override { return second_size_; }
- size_t first_addr_len() const override { return first_len_; }
- size_t second_addr_len() const override { return second_len_; }
-
- private:
- // to_storage coverts a sockaddr_* to a sockaddr_storage.
- static struct sockaddr_storage to_storage(const sockaddr_un& addr);
- static struct sockaddr_storage to_storage(const sockaddr_in& addr);
- static struct sockaddr_storage to_storage(const sockaddr_in6& addr);
-
- FileDescriptor first_;
- FileDescriptor second_;
- const struct sockaddr_storage first_addr_;
- const struct sockaddr_storage second_addr_;
- const size_t first_len_;
- const size_t second_len_;
- const size_t first_size_;
- const size_t second_size_;
-};
-
-// SyscallSocketPairCreator returns a Creator<SocketPair> that obtains file
-// descriptors by invoking the socketpair() syscall.
-Creator<SocketPair> SyscallSocketPairCreator(int domain, int type,
- int protocol);
-
-// SyscallSocketCreator returns a Creator<FileDescriptor> that obtains a file
-// descriptor by invoking the socket() syscall.
-Creator<FileDescriptor> SyscallSocketCreator(int domain, int type,
- int protocol);
-
-// FilesystemBidirectionalBindSocketPairCreator returns a Creator<SocketPair>
-// that obtains file descriptors by invoking the bind() and connect() syscalls
-// on filesystem paths. Only works for DGRAM sockets.
-Creator<SocketPair> FilesystemBidirectionalBindSocketPairCreator(int domain,
- int type,
- int protocol);
-
-// AbstractBidirectionalBindSocketPairCreator returns a Creator<SocketPair> that
-// obtains file descriptors by invoking the bind() and connect() syscalls on
-// abstract namespace paths. Only works for DGRAM sockets.
-Creator<SocketPair> AbstractBidirectionalBindSocketPairCreator(int domain,
- int type,
- int protocol);
-
-// SocketpairGoferSocketPairCreator returns a Creator<SocketPair> that
-// obtains file descriptors by connect() syscalls on two sockets with socketpair
-// gofer paths.
-Creator<SocketPair> SocketpairGoferSocketPairCreator(int domain, int type,
- int protocol);
-
-// SocketpairGoferFileSocketPairCreator returns a Creator<SocketPair> that
-// obtains file descriptors by open() syscalls on socketpair gofer paths.
-Creator<SocketPair> SocketpairGoferFileSocketPairCreator(int flags);
-
-// FilesystemAcceptBindSocketPairCreator returns a Creator<SocketPair> that
-// obtains file descriptors by invoking the accept() and bind() syscalls on
-// a filesystem path. Only works for STREAM and SEQPACKET sockets.
-Creator<SocketPair> FilesystemAcceptBindSocketPairCreator(int domain, int type,
- int protocol);
-
-// AbstractAcceptBindSocketPairCreator returns a Creator<SocketPair> that
-// obtains file descriptors by invoking the accept() and bind() syscalls on a
-// abstract namespace path. Only works for STREAM and SEQPACKET sockets.
-Creator<SocketPair> AbstractAcceptBindSocketPairCreator(int domain, int type,
- int protocol);
-
-// FilesystemUnboundSocketPairCreator returns a Creator<SocketPair> that obtains
-// file descriptors by invoking the socket() syscall and generates a filesystem
-// path for binding.
-Creator<SocketPair> FilesystemUnboundSocketPairCreator(int domain, int type,
- int protocol);
-
-// AbstractUnboundSocketPairCreator returns a Creator<SocketPair> that obtains
-// file descriptors by invoking the socket() syscall and generates an abstract
-// path for binding.
-Creator<SocketPair> AbstractUnboundSocketPairCreator(int domain, int type,
- int protocol);
-
-// TCPAcceptBindSocketPairCreator returns a Creator<SocketPair> that obtains
-// file descriptors by invoking the accept() and bind() syscalls on TCP sockets.
-Creator<SocketPair> TCPAcceptBindSocketPairCreator(int domain, int type,
- int protocol,
- bool dual_stack);
-
-// TCPAcceptBindPersistentListenerSocketPairCreator is like
-// TCPAcceptBindSocketPairCreator, except it uses the same listening socket to
-// create all SocketPairs.
-Creator<SocketPair> TCPAcceptBindPersistentListenerSocketPairCreator(
- int domain, int type, int protocol, bool dual_stack);
-
-// UDPBidirectionalBindSocketPairCreator returns a Creator<SocketPair> that
-// obtains file descriptors by invoking the bind() and connect() syscalls on UDP
-// sockets.
-Creator<SocketPair> UDPBidirectionalBindSocketPairCreator(int domain, int type,
- int protocol,
- bool dual_stack);
-
-// UDPUnboundSocketPairCreator returns a Creator<SocketPair> that obtains file
-// descriptors by creating UDP sockets.
-Creator<SocketPair> UDPUnboundSocketPairCreator(int domain, int type,
- int protocol, bool dual_stack);
-
-// UnboundSocketCreator returns a Creator<FileDescriptor> that obtains a file
-// descriptor by creating a socket.
-Creator<FileDescriptor> UnboundSocketCreator(int domain, int type,
- int protocol);
-
-// A SocketPairKind couples a human-readable description of a socket pair with
-// a function that creates such a socket pair.
-struct SocketPairKind {
- std::string description;
- int domain;
- int type;
- int protocol;
- Creator<SocketPair> creator;
-
- // Create creates a socket pair of this kind.
- PosixErrorOr<std::unique_ptr<SocketPair>> Create() const { return creator(); }
-};
-
-// A SocketKind couples a human-readable description of a socket with
-// a function that creates such a socket.
-struct SocketKind {
- std::string description;
- int domain;
- int type;
- int protocol;
- Creator<FileDescriptor> creator;
-
- // Create creates a socket pair of this kind.
- PosixErrorOr<std::unique_ptr<FileDescriptor>> Create() const {
- return creator();
- }
-};
-
-// A ReversedSocketPair wraps another SocketPair but flips the first and second
-// file descriptors. ReversedSocketPair is used to test socket pairs that
-// should be symmetric.
-class ReversedSocketPair : public SocketPair {
- public:
- explicit ReversedSocketPair(std::unique_ptr<SocketPair> base)
- : base_(std::move(base)) {}
-
- int first_fd() const override { return base_->second_fd(); }
- int second_fd() const override { return base_->first_fd(); }
- int release_first_fd() override { return base_->release_second_fd(); }
- int release_second_fd() override { return base_->release_first_fd(); }
- const struct sockaddr* first_addr() const override {
- return base_->second_addr();
- }
- const struct sockaddr* second_addr() const override {
- return base_->first_addr();
- }
- size_t first_addr_size() const override { return base_->second_addr_size(); }
- size_t second_addr_size() const override { return base_->first_addr_size(); }
- size_t first_addr_len() const override { return base_->second_addr_len(); }
- size_t second_addr_len() const override { return base_->first_addr_len(); }
-
- private:
- std::unique_ptr<SocketPair> base_;
-};
-
-// Reversed returns a SocketPairKind that represents SocketPairs created by
-// flipping the file descriptors provided by another SocketPair.
-SocketPairKind Reversed(SocketPairKind const& base);
-
-// IncludeReversals returns a vector<SocketPairKind> that returns all
-// SocketPairKinds in `vec` as well as all SocketPairKinds obtained by flipping
-// the file descriptors provided by the kinds in `vec`.
-std::vector<SocketPairKind> IncludeReversals(std::vector<SocketPairKind> vec);
-
-// A Middleware is a function wraps a SocketPairKind.
-using Middleware = std::function<SocketPairKind(SocketPairKind)>;
-
-// Reversed returns a SocketPairKind that represents SocketPairs created by
-// flipping the file descriptors provided by another SocketPair.
-template <typename T>
-Middleware SetSockOpt(int level, int optname, T* value) {
- return [=](SocketPairKind const& base) {
- auto const& creator = base.creator;
- return SocketPairKind{
- absl::StrCat("setsockopt(", level, ", ", optname, ", ", *value, ") ",
- base.description),
- base.domain, base.type, base.protocol,
- [creator, level, optname,
- value]() -> PosixErrorOr<std::unique_ptr<SocketPair>> {
- ASSIGN_OR_RETURN_ERRNO(auto creator_value, creator());
- if (creator_value->first_fd() >= 0) {
- RETURN_ERROR_IF_SYSCALL_FAIL(setsockopt(
- creator_value->first_fd(), level, optname, value, sizeof(T)));
- }
- if (creator_value->second_fd() >= 0) {
- RETURN_ERROR_IF_SYSCALL_FAIL(setsockopt(
- creator_value->second_fd(), level, optname, value, sizeof(T)));
- }
- return creator_value;
- }};
- };
-}
-
-constexpr int kSockOptOn = 1;
-constexpr int kSockOptOff = 0;
-
-// NoOp returns the same SocketPairKind that it is passed.
-SocketPairKind NoOp(SocketPairKind const& base);
-
-// TransferTest tests that data can be send back and fourth between two
-// specified FDs. Note that calls to this function should be wrapped in
-// ASSERT_NO_FATAL_FAILURE().
-void TransferTest(int fd1, int fd2);
-
-// Fills [buf, buf+len) with random bytes.
-void RandomizeBuffer(char* buf, size_t len);
-
-// Base test fixture for tests that operate on pairs of connected sockets.
-class SocketPairTest : public ::testing::TestWithParam<SocketPairKind> {
- protected:
- SocketPairTest() {
- // gUnit uses printf, so so will we.
- printf("Testing with %s\n", GetParam().description.c_str());
- fflush(stdout);
- }
-
- PosixErrorOr<std::unique_ptr<SocketPair>> NewSocketPair() const {
- return GetParam().Create();
- }
-};
-
-// Base test fixture for tests that operate on simple Sockets.
-class SimpleSocketTest : public ::testing::TestWithParam<SocketKind> {
- protected:
- SimpleSocketTest() {
- // gUnit uses printf, so so will we.
- printf("Testing with %s\n", GetParam().description.c_str());
- }
-
- PosixErrorOr<std::unique_ptr<FileDescriptor>> NewSocket() const {
- return GetParam().Create();
- }
-};
-
-SocketKind SimpleSocket(int fam, int type, int proto);
-
-// Send a buffer of size 'size' to sockets->first_fd(), returning the result of
-// sendmsg.
-//
-// If reader, read from second_fd() until size bytes have been read.
-ssize_t SendLargeSendMsg(const std::unique_ptr<SocketPair>& sockets,
- size_t size, bool reader);
-
-// Initializes the given buffer with random data.
-void RandomizeBuffer(char* ptr, size_t len);
-
-enum class AddressFamily { kIpv4 = 1, kIpv6 = 2, kDualStack = 3 };
-enum class SocketType { kUdp = 1, kTcp = 2 };
-
-// Returns a PosixError or a port that is available. If 0 is specified as the
-// port it will bind port 0 (and allow the kernel to select any free port).
-// Otherwise, it will try to bind the specified port and validate that it can be
-// used for the requested family and socket type. The final option is
-// reuse_addr. This specifies whether SO_REUSEADDR should be applied before a
-// bind(2) attempt. SO_REUSEADDR means that sockets in TIME_WAIT states or other
-// bound UDP sockets would not cause an error on bind(2). This option should be
-// set if subsequent calls to bind on the returned port will also use
-// SO_REUSEADDR.
-//
-// Note: That this test will attempt to bind the ANY address for the respective
-// protocol.
-PosixErrorOr<int> PortAvailable(int port, AddressFamily family, SocketType type,
- bool reuse_addr);
-
-// FreeAvailablePort is used to return a port that was obtained by using
-// the PortAvailable helper with port 0.
-PosixError FreeAvailablePort(int port);
-
-// SendMsg converts a buffer to an iovec and adds it to msg before sending it.
-PosixErrorOr<int> SendMsg(int sock, msghdr* msg, char buf[], int buf_size);
-
-// RecvTimeout calls select on sock with timeout and then calls recv on sock.
-PosixErrorOr<int> RecvTimeout(int sock, char buf[], int buf_size, int timeout);
-
-// RecvMsgTimeout calls select on sock with timeout and then calls recvmsg on
-// sock.
-PosixErrorOr<int> RecvMsgTimeout(int sock, msghdr* msg, int timeout);
-
-// RecvNoData checks that no data is receivable on sock.
-void RecvNoData(int sock);
-
-// Base test fixture for tests that apply to all kinds of pairs of connected
-// sockets.
-using AllSocketPairTest = SocketPairTest;
-
-struct TestAddress {
- std::string description;
- sockaddr_storage addr;
- socklen_t addr_len;
-
- explicit TestAddress(std::string description = "")
- : description(std::move(description)), addr(), addr_len() {}
-
- int family() const { return addr.ss_family; }
-
- // Returns a new TestAddress with specified port. If port is not supported,
- // the same TestAddress is returned.
- TestAddress WithPort(uint16_t port) const;
-};
-
-constexpr char kMulticastAddress[] = "224.0.2.1";
-constexpr char kBroadcastAddress[] = "255.255.255.255";
-
-// Returns a TestAddress with `addr` parsed as an IPv4 address described by
-// `description`.
-TestAddress V4AddrStr(std::string description, const char* addr);
-// Returns a TestAddress with `addr` parsed as an IPv6 address described by
-// `description`.
-TestAddress V6AddrStr(std::string description, const char* addr);
-
-// Returns a TestAddress for the IPv4 any address.
-TestAddress V4Any();
-// Returns a TestAddress for the IPv4 limited broadcast address.
-TestAddress V4Broadcast();
-// Returns a TestAddress for the IPv4 loopback address.
-TestAddress V4Loopback();
-// Returns a TestAddress for the subnet broadcast of the IPv4 loopback address.
-TestAddress V4LoopbackSubnetBroadcast();
-// Returns a TestAddress for the IPv4-mapped IPv6 any address.
-TestAddress V4MappedAny();
-// Returns a TestAddress for the IPv4-mapped IPv6 loopback address.
-TestAddress V4MappedLoopback();
-// Returns a TestAddress for a IPv4 multicast address.
-TestAddress V4Multicast();
-// Returns a TestAddress for the IPv4 all-hosts multicast group address.
-TestAddress V4MulticastAllHosts();
-
-// Returns a TestAddress for the IPv6 any address.
-TestAddress V6Any();
-// Returns a TestAddress for the IPv6 loopback address.
-TestAddress V6Loopback();
-// Returns a TestAddress for a IPv6 multicast address.
-TestAddress V6Multicast();
-// Returns a TestAddress for the IPv6 interface-local all-nodes multicast group
-// address.
-TestAddress V6MulticastInterfaceLocalAllNodes();
-// Returns a TestAddress for the IPv6 link-local all-nodes multicast group
-// address.
-TestAddress V6MulticastLinkLocalAllNodes();
-// Returns a TestAddress for the IPv6 link-local all-routers multicast group
-// address.
-TestAddress V6MulticastLinkLocalAllRouters();
-
-// Compute the internet checksum of an IP header.
-uint16_t IPChecksum(struct iphdr ip);
-
-// Compute the internet checksum of a UDP header.
-uint16_t UDPChecksum(struct iphdr iphdr, struct udphdr udphdr,
- const char* payload, ssize_t payload_len);
-
-// Compute the internet checksum of an ICMP header.
-uint16_t ICMPChecksum(struct icmphdr icmphdr, const char* payload,
- ssize_t payload_len);
-
-// Convenient functions for reinterpreting common types to sockaddr pointer.
-inline sockaddr* AsSockAddr(sockaddr_storage* s) {
- return reinterpret_cast<sockaddr*>(s);
-}
-inline sockaddr* AsSockAddr(sockaddr_in* s) {
- return reinterpret_cast<sockaddr*>(s);
-}
-inline sockaddr* AsSockAddr(sockaddr_in6* s) {
- return reinterpret_cast<sockaddr*>(s);
-}
-inline sockaddr* AsSockAddr(sockaddr_un* s) {
- return reinterpret_cast<sockaddr*>(s);
-}
-
-PosixErrorOr<uint16_t> AddrPort(int family, sockaddr_storage const& addr);
-
-PosixError SetAddrPort(int family, sockaddr_storage* addr, uint16_t port);
-
-// setupTimeWaitClose sets up a socket endpoint in TIME_WAIT state.
-// Callers can choose to perform active close on either ends of the connection
-// and also specify if they want to enabled SO_REUSEADDR.
-void SetupTimeWaitClose(const TestAddress* listener,
- const TestAddress* connector, bool reuse,
- bool accept_close, sockaddr_storage* listen_addr,
- sockaddr_storage* conn_bound_addr);
-
-// MaybeLimitEphemeralPorts attempts to reduce the number of ephemeral ports and
-// returns the number of ephemeral ports.
-PosixErrorOr<int> MaybeLimitEphemeralPorts();
-
-namespace internal {
-PosixErrorOr<int> TryPortAvailable(int port, AddressFamily family,
- SocketType type, bool reuse_addr);
-} // namespace internal
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_SYSCALLS_SOCKET_TEST_UTIL_H_
diff --git a/test/util/socket_util_impl.cc b/test/util/socket_util_impl.cc
deleted file mode 100644
index 04550ad7c..000000000
--- a/test/util/socket_util_impl.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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 "test/util/socket_util.h"
-
-namespace gvisor {
-namespace testing {
-
-PosixErrorOr<int> PortAvailable(int port, AddressFamily family, SocketType type,
- bool reuse_addr) {
- return internal::TryPortAvailable(port, family, type, reuse_addr);
-}
-
-PosixError FreeAvailablePort(int port) { return NoError(); }
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/temp_path.cc b/test/util/temp_path.cc
deleted file mode 100644
index e1bdee7fd..000000000
--- a/test/util/temp_path.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/temp_path.h"
-
-#include <unistd.h>
-
-#include <atomic>
-#include <cstdlib>
-#include <iostream>
-
-#include "gtest/gtest.h"
-#include "absl/time/clock.h"
-#include "absl/time/time.h"
-#include "test/util/fs_util.h"
-#include "test/util/posix_error.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-namespace {
-
-std::atomic<uint64_t> global_temp_file_number = ATOMIC_VAR_INIT(1);
-
-// Return a new temp filename, intended to be unique system-wide.
-//
-// The global file number helps maintain file naming consistency across
-// different runs of a test.
-//
-// The timestamp is necessary because the test infrastructure invokes each
-// test case in a separate process (resetting global_temp_file_number) and
-// potentially in parallel, which allows for races between selecting and using a
-// name.
-std::string NextTempBasename() {
- return absl::StrCat("gvisor_test_temp_", global_temp_file_number++, "_",
- absl::ToUnixNanos(absl::Now()));
-}
-
-void TryDeleteRecursively(std::string const& path) {
- if (!path.empty()) {
- int undeleted_dirs = 0;
- int undeleted_files = 0;
- auto status = RecursivelyDelete(path, &undeleted_dirs, &undeleted_files);
- if (undeleted_dirs || undeleted_files || !status.ok()) {
- std::cerr << path << ": failed to delete " << undeleted_dirs
- << " directories and " << undeleted_files
- << " files: " << status << std::endl;
- }
- }
-}
-
-} // namespace
-
-constexpr mode_t TempPath::kDefaultFileMode;
-constexpr mode_t TempPath::kDefaultDirMode;
-
-std::string NewTempAbsPathInDir(absl::string_view const dir) {
- return JoinPath(dir, NextTempBasename());
-}
-
-std::string NewTempAbsPath() {
- return NewTempAbsPathInDir(GetAbsoluteTestTmpdir());
-}
-
-std::string NewTempRelPath() { return NextTempBasename(); }
-
-std::string GetAbsoluteTestTmpdir() {
- // Note that TEST_TMPDIR is guaranteed to be set.
- char* env_tmpdir = getenv("TEST_TMPDIR");
- std::string tmp_dir =
- env_tmpdir != nullptr ? std::string(env_tmpdir) : "/tmp";
-
- return MakeAbsolute(tmp_dir, "").ValueOrDie();
-}
-
-PosixErrorOr<TempPath> TempPath::CreateFileWith(absl::string_view const parent,
- absl::string_view const content,
- mode_t const mode) {
- return CreateIn(parent, [=](absl::string_view path) -> PosixError {
- // CreateWithContents will call open(O_WRONLY) with the given mode. If the
- // mode is not user-writable, save/restore cannot preserve the fd. Hence
- // the little permission dance that's done here.
- auto res = CreateWithContents(path, content, mode | 0200);
- RETURN_IF_ERRNO(res);
-
- return Chmod(path, mode);
- });
-}
-
-PosixErrorOr<TempPath> TempPath::CreateDirWith(absl::string_view const parent,
- mode_t const mode) {
- return CreateIn(parent,
- [=](absl::string_view path) { return Mkdir(path, mode); });
-}
-
-PosixErrorOr<TempPath> TempPath::CreateSymlinkTo(absl::string_view const parent,
- std::string const& dest) {
- return CreateIn(parent, [=](absl::string_view path) {
- int ret = symlink(dest.c_str(), std::string(path).c_str());
- if (ret != 0) {
- return PosixError(errno, "symlink failed");
- }
- return NoError();
- });
-}
-
-PosixErrorOr<TempPath> TempPath::CreateFileIn(absl::string_view const parent) {
- return TempPath::CreateFileWith(parent, absl::string_view(),
- kDefaultFileMode);
-}
-
-PosixErrorOr<TempPath> TempPath::CreateDirIn(absl::string_view const parent) {
- return TempPath::CreateDirWith(parent, kDefaultDirMode);
-}
-
-PosixErrorOr<TempPath> TempPath::CreateFileMode(mode_t mode) {
- return TempPath::CreateFileWith(GetAbsoluteTestTmpdir(), absl::string_view(),
- mode);
-}
-
-PosixErrorOr<TempPath> TempPath::CreateFile() {
- return TempPath::CreateFileIn(GetAbsoluteTestTmpdir());
-}
-
-PosixErrorOr<TempPath> TempPath::CreateDir() {
- return TempPath::CreateDirIn(GetAbsoluteTestTmpdir());
-}
-
-TempPath::~TempPath() { TryDeleteRecursively(path_); }
-
-TempPath::TempPath(TempPath&& orig) { reset(orig.release()); }
-
-TempPath& TempPath::operator=(TempPath&& orig) {
- reset(orig.release());
- return *this;
-}
-
-std::string TempPath::reset(std::string newpath) {
- std::string path = path_;
- TryDeleteRecursively(path_);
- path_ = std::move(newpath);
- return path;
-}
-
-std::string TempPath::release() {
- std::string path = path_;
- path_ = std::string();
- return path;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/temp_path.h b/test/util/temp_path.h
deleted file mode 100644
index 9e5ac11f4..000000000
--- a/test/util/temp_path.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_TEMP_PATH_H_
-#define GVISOR_TEST_UTIL_TEMP_PATH_H_
-
-#include <sys/stat.h>
-
-#include <string>
-#include <utility>
-
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-// Returns an absolute path for a file in `dir` that does not yet exist.
-// Distinct calls to NewTempAbsPathInDir from the same process, even from
-// multiple threads, are guaranteed to return different paths. Distinct calls to
-// NewTempAbsPathInDir from different processes are not synchronized.
-std::string NewTempAbsPathInDir(absl::string_view const dir);
-
-// Like NewTempAbsPathInDir, but the returned path is in the test's temporary
-// directory, as provided by the testing framework.
-std::string NewTempAbsPath();
-
-// Like NewTempAbsPathInDir, but the returned path is relative (to the current
-// working directory).
-std::string NewTempRelPath();
-
-// Returns the absolute path for the test temp dir.
-std::string GetAbsoluteTestTmpdir();
-
-// Represents a temporary file or directory.
-class TempPath {
- public:
- // Default creation mode for files.
- static constexpr mode_t kDefaultFileMode = 0644;
-
- // Default creation mode for directories.
- static constexpr mode_t kDefaultDirMode = 0755;
-
- // Creates a temporary file in directory `parent` with mode `mode` and
- // contents `content`.
- static PosixErrorOr<TempPath> CreateFileWith(absl::string_view parent,
- absl::string_view content,
- mode_t mode);
-
- // Creates an empty temporary subdirectory in directory `parent` with mode
- // `mode`.
- static PosixErrorOr<TempPath> CreateDirWith(absl::string_view parent,
- mode_t mode);
-
- // Creates a temporary symlink in directory `parent` to destination `dest`.
- static PosixErrorOr<TempPath> CreateSymlinkTo(absl::string_view parent,
- std::string const& dest);
-
- // Creates an empty temporary file in directory `parent` with mode
- // kDefaultFileMode.
- static PosixErrorOr<TempPath> CreateFileIn(absl::string_view parent);
-
- // Creates an empty temporary subdirectory in directory `parent` with mode
- // kDefaultDirMode.
- static PosixErrorOr<TempPath> CreateDirIn(absl::string_view parent);
-
- // Creates an empty temporary file in the test's temporary directory with mode
- // `mode`.
- static PosixErrorOr<TempPath> CreateFileMode(mode_t mode);
-
- // Creates an empty temporary file in the test's temporary directory with
- // mode kDefaultFileMode.
- static PosixErrorOr<TempPath> CreateFile();
-
- // Creates an empty temporary subdirectory in the test's temporary directory
- // with mode kDefaultDirMode.
- static PosixErrorOr<TempPath> CreateDir();
-
- // Constructs a TempPath that represents nothing.
- TempPath() = default;
-
- // Constructs a TempPath that represents the given path, which will be deleted
- // when the TempPath is destroyed.
- explicit TempPath(std::string path) : path_(std::move(path)) {}
-
- // Attempts to delete the represented temporary file or directory (in the
- // latter case, also attempts to delete its contents).
- ~TempPath();
-
- // Attempts to delete the represented temporary file or directory, then
- // transfers ownership of the path represented by orig to this TempPath.
- TempPath(TempPath&& orig);
- TempPath& operator=(TempPath&& orig);
-
- // Changes the path this TempPath represents. If the TempPath already
- // represented a path, deletes and returns that path. Otherwise returns the
- // empty string.
- std::string reset(std::string newpath);
- std::string reset() { return reset(""); }
-
- // Forgets and returns the path this TempPath represents. The path is not
- // deleted.
- std::string release();
-
- // Returns the path this TempPath represents.
- std::string path() const { return path_; }
-
- private:
- template <typename F>
- static PosixErrorOr<TempPath> CreateIn(absl::string_view const parent,
- F const& f) {
- std::string path = NewTempAbsPathInDir(parent);
- RETURN_IF_ERRNO(f(path));
- return TempPath(std::move(path));
- }
-
- std::string path_;
-};
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_TEMP_PATH_H_
diff --git a/test/util/temp_umask.h b/test/util/temp_umask.h
deleted file mode 100644
index e7de84a54..000000000
--- a/test/util/temp_umask.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_TEMP_UMASK_H_
-#define GVISOR_TEST_UTIL_TEMP_UMASK_H_
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-namespace gvisor {
-namespace testing {
-
-class TempUmask {
- public:
- // Sets the process umask to `mask`.
- explicit TempUmask(mode_t mask) : old_mask_(umask(mask)) {}
-
- // Sets the process umask to its previous value.
- ~TempUmask() { umask(old_mask_); }
-
- private:
- mode_t old_mask_;
-};
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_TEMP_UMASK_H_
diff --git a/test/util/test_main.cc b/test/util/test_main.cc
deleted file mode 100644
index 1f389e58f..000000000
--- a/test/util/test_main.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/test_util.h"
-
-int main(int argc, char** argv) {
- gvisor::testing::TestInit(&argc, &argv);
- return gvisor::testing::RunAllTests();
-}
diff --git a/test/util/test_util.cc b/test/util/test_util.cc
deleted file mode 100644
index d0c1d6426..000000000
--- a/test/util/test_util.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/test_util.h"
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-
-#include <ctime>
-#include <iostream>
-#include <vector>
-
-#include "absl/base/attributes.h"
-#include "absl/flags/flag.h" // IWYU pragma: keep
-#include "absl/flags/parse.h" // IWYU pragma: keep
-#include "absl/strings/numbers.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/str_split.h"
-#include "absl/time/time.h"
-#include "test/util/fs_util.h"
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-constexpr char kGvisorNetwork[] = "GVISOR_NETWORK";
-constexpr char kGvisorVfs[] = "GVISOR_VFS";
-constexpr char kFuseEnabled[] = "FUSE_ENABLED";
-
-bool IsRunningOnGvisor() { return GvisorPlatform() != Platform::kNative; }
-
-const std::string GvisorPlatform() {
- // Set by runner.go.
- const char* env = getenv(kTestOnGvisor);
- if (!env) {
- return Platform::kNative;
- }
- return std::string(env);
-}
-
-bool IsRunningWithHostinet() {
- const char* env = getenv(kGvisorNetwork);
- return env && strcmp(env, "host") == 0;
-}
-
-bool IsRunningWithVFS1() {
- const char* env = getenv(kGvisorVfs);
- if (env == nullptr) {
- // If not set, it's running on Linux.
- return false;
- }
- return strcmp(env, "VFS1") == 0;
-}
-
-bool IsFUSEEnabled() {
- const char* env = getenv(kFuseEnabled);
- return env && strcmp(env, "TRUE") == 0;
-}
-
-// Inline cpuid instruction. Preserve %ebx/%rbx register. In PIC compilations
-// %ebx contains the address of the global offset table. %rbx is occasionally
-// used to address stack variables in presence of dynamic allocas.
-#if defined(__x86_64__)
-#define GETCPUID(a, b, c, d, a_inp, c_inp) \
- asm("mov %%rbx, %%rdi\n" \
- "cpuid\n" \
- "xchg %%rdi, %%rbx\n" \
- : "=a"(a), "=D"(b), "=c"(c), "=d"(d) \
- : "a"(a_inp), "2"(c_inp))
-
-CPUVendor GetCPUVendor() {
- uint32_t eax, ebx, ecx, edx;
- std::string vendor_str;
- // Get vendor string (issue CPUID with eax = 0)
- GETCPUID(eax, ebx, ecx, edx, 0, 0);
- vendor_str.append(reinterpret_cast<char*>(&ebx), 4);
- vendor_str.append(reinterpret_cast<char*>(&edx), 4);
- vendor_str.append(reinterpret_cast<char*>(&ecx), 4);
- if (vendor_str == "GenuineIntel") {
- return CPUVendor::kIntel;
- } else if (vendor_str == "AuthenticAMD") {
- return CPUVendor::kAMD;
- }
- return CPUVendor::kUnknownVendor;
-}
-#endif // defined(__x86_64__)
-
-bool operator==(const KernelVersion& first, const KernelVersion& second) {
- return first.major == second.major && first.minor == second.minor &&
- first.micro == second.micro;
-}
-
-PosixErrorOr<KernelVersion> ParseKernelVersion(absl::string_view vers_str) {
- KernelVersion version = {};
- std::vector<std::string> values =
- absl::StrSplit(vers_str, absl::ByAnyChar(".-"));
- if (values.size() == 2) {
- ASSIGN_OR_RETURN_ERRNO(version.major, Atoi<int>(values[0]));
- ASSIGN_OR_RETURN_ERRNO(version.minor, Atoi<int>(values[1]));
- return version;
- } else if (values.size() >= 3) {
- ASSIGN_OR_RETURN_ERRNO(version.major, Atoi<int>(values[0]));
- ASSIGN_OR_RETURN_ERRNO(version.minor, Atoi<int>(values[1]));
- ASSIGN_OR_RETURN_ERRNO(version.micro, Atoi<int>(values[2]));
- return version;
- }
- return PosixError(EINVAL, absl::StrCat("Unknown kernel release: ", vers_str));
-}
-
-PosixErrorOr<KernelVersion> GetKernelVersion() {
- utsname buf;
- RETURN_ERROR_IF_SYSCALL_FAIL(uname(&buf));
- return ParseKernelVersion(buf.release);
-}
-
-std::string CPUSetToString(const cpu_set_t& set, size_t cpus) {
- std::string str = "cpuset[";
- for (unsigned int n = 0; n < cpus; n++) {
- if (CPU_ISSET(n, &set)) {
- if (n != 0) {
- absl::StrAppend(&str, " ");
- }
- absl::StrAppend(&str, n);
- }
- }
- absl::StrAppend(&str, "]");
- return str;
-}
-
-// An overloaded operator<< makes it easy to dump the value of an OpenFd.
-std::ostream& operator<<(std::ostream& out, OpenFd const& ofd) {
- out << ofd.fd << " -> " << ofd.link;
- return out;
-}
-
-// An overloaded operator<< makes it easy to dump a vector of OpenFDs.
-std::ostream& operator<<(std::ostream& out, std::vector<OpenFd> const& v) {
- for (const auto& ofd : v) {
- out << ofd << std::endl;
- }
- return out;
-}
-
-PosixErrorOr<std::vector<OpenFd>> GetOpenFDs() {
- // Get the results from /proc/self/fd.
- ASSIGN_OR_RETURN_ERRNO(auto dir_list,
- ListDir("/proc/self/fd", /*skipdots=*/true));
-
- std::vector<OpenFd> ret_fds;
- for (const auto& str_fd : dir_list) {
- OpenFd open_fd = {};
- ASSIGN_OR_RETURN_ERRNO(open_fd.fd, Atoi<int>(str_fd));
- std::string path = absl::StrCat("/proc/self/fd/", open_fd.fd);
-
- // Resolve the link.
- char buf[PATH_MAX] = {};
- int ret = readlink(path.c_str(), buf, sizeof(buf));
- if (ret < 0) {
- if (errno == ENOENT) {
- // The FD may have been closed, let's be resilient.
- continue;
- }
-
- return PosixError(
- errno, absl::StrCat("readlink of ", path, " returned errno ", errno));
- }
- open_fd.link = std::string(buf, ret);
- ret_fds.emplace_back(std::move(open_fd));
- }
- return ret_fds;
-}
-
-PosixErrorOr<uint64_t> Links(const std::string& path) {
- struct stat st;
- if (stat(path.c_str(), &st)) {
- return PosixError(errno, absl::StrCat("Failed to stat ", path));
- }
- return static_cast<uint64_t>(st.st_nlink);
-}
-
-void RandomizeBuffer(void* buffer, size_t len) {
- struct timespec ts = {};
- clock_gettime(CLOCK_MONOTONIC, &ts);
- uint32_t seed = static_cast<uint32_t>(ts.tv_nsec);
- char* const buf = static_cast<char*>(buffer);
- for (size_t i = 0; i < len; i++) {
- buf[i] = rand_r(&seed) % 255;
- }
-}
-
-std::vector<std::vector<struct iovec>> GenerateIovecs(uint64_t total_size,
- void* buf,
- size_t buflen) {
- std::vector<std::vector<struct iovec>> result;
- for (uint64_t offset = 0; offset < total_size;) {
- auto& iovec_array = *result.emplace(result.end());
-
- for (; offset < total_size && iovec_array.size() < IOV_MAX;
- offset += buflen) {
- struct iovec iov = {};
- iov.iov_base = buf;
- iov.iov_len = std::min<uint64_t>(total_size - offset, buflen);
- iovec_array.push_back(iov);
- }
- }
-
- return result;
-}
-
-uint64_t Megabytes(uint64_t n) {
- // Overflow check, upper 20 bits in n shouldn't be set.
- TEST_CHECK(!(0xfffff00000000000 & n));
- return n << 20;
-}
-
-bool Equivalent(uint64_t current, uint64_t target, double tolerance) {
- auto abs_diff = target > current ? target - current : current - target;
- return abs_diff <= static_cast<uint64_t>(tolerance * target);
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/test_util.h b/test/util/test_util.h
deleted file mode 100644
index bcbb388ed..000000000
--- a/test/util/test_util.h
+++ /dev/null
@@ -1,816 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-// Utilities for syscall testing.
-//
-// Initialization
-// ==============
-//
-// Prior to calling RUN_ALL_TESTS, all tests must use TestInit(&argc, &argv).
-// See the TestInit function for exact side-effects and semantics.
-//
-// Configuration
-// =============
-//
-// IsRunningOnGvisor returns true if the test is known to be running on gVisor.
-// GvisorPlatform can be used to get more detail:
-//
-// if (GvisorPlatform() == Platform::kPtrace) {
-// ...
-// }
-//
-// SetupGvisorDeathTest ensures that signal handling does not interfere with
-/// tests that rely on fatal signals.
-//
-// Matchers
-// ========
-//
-// ElementOf(xs) matches if the matched value is equal to an element of the
-// container xs. Example:
-//
-// // PASS
-// EXPECT_THAT(1, ElementOf({0, 1, 2}));
-//
-// // FAIL
-// // Value of: 3
-// // Expected: one of {0, 1, 2}
-// // Actual: 3
-// EXPECT_THAT(3, ElementOf({0, 1, 2}));
-//
-// SyscallSucceeds() matches if the syscall is successful. A successful syscall
-// is defined by either a return value not equal to -1, or a return value of -1
-// with an errno of 0 (which is a possible successful return for e.g.
-// PTRACE_PEEK). Example:
-//
-// // PASS
-// EXPECT_THAT(open("/dev/null", O_RDONLY), SyscallSucceeds());
-//
-// // FAIL
-// // Value of: open("/", O_RDWR)
-// // Expected: not -1 (success)
-// // Actual: -1 (of type int), with errno 21 (Is a directory)
-// EXPECT_THAT(open("/", O_RDWR), SyscallSucceeds());
-//
-// SyscallSucceedsWithValue(m) matches if the syscall is successful, and the
-// value also matches m. Example:
-//
-// // PASS
-// EXPECT_THAT(read(4, buf, 8192), SyscallSucceedsWithValue(8192));
-//
-// // FAIL
-// // Value of: read(-1, buf, 8192)
-// // Expected: is equal to 8192
-// // Actual: -1 (of type long), with errno 9 (Bad file number)
-// EXPECT_THAT(read(-1, buf, 8192), SyscallSucceedsWithValue(8192));
-//
-// // FAIL
-// // Value of: read(4, buf, 1)
-// // Expected: is > 4096
-// // Actual: 1 (of type long)
-// EXPECT_THAT(read(4, buf, 1), SyscallSucceedsWithValue(Gt(4096)));
-//
-// SyscallFails() matches if the syscall is unsuccessful. An unsuccessful
-// syscall is defined by a return value of -1 with a non-zero errno. Example:
-//
-// // PASS
-// EXPECT_THAT(open("/", O_RDWR), SyscallFails());
-//
-// // FAIL
-// // Value of: open("/dev/null", O_RDONLY)
-// // Expected: -1 (failure)
-// // Actual: 0 (of type int)
-// EXPECT_THAT(open("/dev/null", O_RDONLY), SyscallFails());
-//
-// SyscallFailsWithErrno(m) matches if the syscall is unsuccessful, and errno
-// matches m. Example:
-//
-// // PASS
-// EXPECT_THAT(open("/", O_RDWR), SyscallFailsWithErrno(EISDIR));
-//
-// // PASS
-// EXPECT_THAT(open("/etc/passwd", O_RDWR | O_DIRECTORY),
-// SyscallFailsWithErrno(AnyOf(EACCES, ENOTDIR)));
-//
-// // FAIL
-// // Value of: open("/dev/null", O_RDONLY)
-// // Expected: -1 (failure) with errno 21 (Is a directory)
-// // Actual: 0 (of type int)
-// EXPECT_THAT(open("/dev/null", O_RDONLY), SyscallFailsWithErrno(EISDIR));
-//
-// // FAIL
-// // Value of: open("/", O_RDWR)
-// // Expected: -1 (failure) with errno 22 (Invalid argument)
-// // Actual: -1 (of type int), failure, but with errno 21 (Is a directory)
-// EXPECT_THAT(open("/", O_RDWR), SyscallFailsWithErrno(EINVAL));
-//
-// Because the syscall matchers encode save/restore functionality, their meaning
-// should not be inverted via Not. That is, AnyOf(SyscallSucceedsWithValue(1),
-// SyscallSucceedsWithValue(2)) is permitted, but not
-// Not(SyscallFailsWithErrno(EPERM)).
-//
-// Syscalls
-// ========
-//
-// RetryEINTR wraps a function that returns -1 and sets errno on failure
-// to be automatically retried when EINTR occurs. Example:
-//
-// auto rv = RetryEINTR(waitpid)(pid, &status, 0);
-//
-// ReadFd/WriteFd/PreadFd/PwriteFd are interface-compatible wrappers around the
-// read/write/pread/pwrite syscalls to handle both EINTR and partial
-// reads/writes. Example:
-//
-// EXPECT_THAT(ReadFd(fd, &buf, size), SyscallSucceedsWithValue(size));
-//
-// General Utilities
-// =================
-//
-// ApplyVec(f, xs) returns a vector containing the result of applying function
-// `f` to each value in `xs`.
-//
-// AllBitwiseCombinations takes a variadic number of ranges containing integers
-// and returns a vector containing every integer that can be formed by ORing
-// together exactly one integer from each list. List<T> is an alias for
-// std::initializer_list<T> that makes AllBitwiseCombinations more ergonomic to
-// use with list literals (initializer lists do not otherwise participate in
-// template argument deduction). Example:
-//
-// EXPECT_THAT(
-// AllBitwiseCombinations<int>(
-// List<int>{SOCK_DGRAM, SOCK_STREAM},
-// List<int>{0, SOCK_NONBLOCK}),
-// Contains({SOCK_DGRAM, SOCK_STREAM, SOCK_DGRAM | SOCK_NONBLOCK,
-// SOCK_STREAM | SOCK_NONBLOCK}));
-//
-// VecCat takes a variadic number of containers and returns a vector containing
-// the concatenated contents.
-//
-// VecAppend takes an initial container and a variadic number of containers and
-// appends each to the initial container.
-//
-// RandomizeBuffer will use MTRandom to fill the given buffer with random bytes.
-//
-// GenerateIovecs will return the smallest number of iovec arrays for writing a
-// given total number of bytes to a file, each iovec array size up to IOV_MAX,
-// each iovec in each array pointing to the same buffer.
-
-#ifndef GVISOR_TEST_UTIL_TEST_UTIL_H_
-#define GVISOR_TEST_UTIL_TEST_UTIL_H_
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <sys/uio.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <cerrno>
-#include <initializer_list>
-#include <iterator>
-#include <string>
-#include <thread> // NOLINT: using std::thread::hardware_concurrency().
-#include <utility>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/str_format.h"
-#include "absl/strings/string_view.h"
-#include "absl/time/time.h"
-#include "test/util/fs_util.h"
-#include "test/util/logging.h"
-#include "test/util/posix_error.h"
-#include "test/util/save_util.h"
-
-namespace gvisor {
-namespace testing {
-
-constexpr char kTestOnGvisor[] = "TEST_ON_GVISOR";
-
-// TestInit must be called prior to RUN_ALL_TESTS.
-//
-// This parses all arguments and adjusts argc and argv appropriately.
-//
-// TestInit may create background threads.
-void TestInit(int* argc, char*** argv);
-
-// SKIP_IF may be used to skip a test case.
-//
-// These cases are still emitted, but a SKIPPED line will appear.
-#define SKIP_IF(expr) \
- do { \
- if (expr) GTEST_SKIP() << #expr; \
- } while (0)
-
-// Platform contains platform names.
-namespace Platform {
-constexpr char kNative[] = "native";
-constexpr char kPtrace[] = "ptrace";
-constexpr char kKVM[] = "kvm";
-constexpr char kFuchsia[] = "fuchsia";
-} // namespace Platform
-
-bool IsRunningOnGvisor();
-const std::string GvisorPlatform();
-bool IsRunningWithHostinet();
-// TODO(gvisor.dev/issue/1624): Delete once VFS1 is gone.
-bool IsRunningWithVFS1();
-bool IsFUSEEnabled();
-
-#ifdef __linux__
-void SetupGvisorDeathTest();
-#endif
-
-struct KernelVersion {
- int major;
- int minor;
- int micro;
-};
-
-bool operator==(const KernelVersion& first, const KernelVersion& second);
-
-PosixErrorOr<KernelVersion> ParseKernelVersion(absl::string_view vers_string);
-PosixErrorOr<KernelVersion> GetKernelVersion();
-
-static const size_t kPageSize = sysconf(_SC_PAGESIZE);
-
-enum class CPUVendor { kIntel, kAMD, kUnknownVendor };
-
-CPUVendor GetCPUVendor();
-
-inline int NumCPUs() { return std::thread::hardware_concurrency(); }
-
-// Converts cpu_set_t to a std::string for easy examination.
-std::string CPUSetToString(const cpu_set_t& set, size_t cpus = CPU_SETSIZE);
-
-struct OpenFd {
- // fd is the open file descriptor number.
- int fd = -1;
-
- // link is the resolution of the symbolic link.
- std::string link;
-};
-
-// Make it easier to log OpenFds to error streams.
-std::ostream& operator<<(std::ostream& out, std::vector<OpenFd> const& v);
-std::ostream& operator<<(std::ostream& out, OpenFd const& ofd);
-
-// Gets a detailed list of open fds for this process.
-PosixErrorOr<std::vector<OpenFd>> GetOpenFDs();
-
-// Returns the number of hard links to a path.
-PosixErrorOr<uint64_t> Links(const std::string& path);
-
-inline uint64_t ns_elapsed(const struct timespec& begin,
- const struct timespec& end) {
- return (end.tv_sec - begin.tv_sec) * 1000000000 +
- (end.tv_nsec - begin.tv_nsec);
-}
-
-inline uint64_t ms_elapsed(const struct timespec& begin,
- const struct timespec& end) {
- return ns_elapsed(begin, end) / 1000000;
-}
-
-namespace internal {
-
-template <typename Container>
-class ElementOfMatcher {
- public:
- explicit ElementOfMatcher(Container container)
- : container_(::std::move(container)) {}
-
- template <typename T>
- bool MatchAndExplain(T const& rv,
- ::testing::MatchResultListener* const listener) const {
- using std::count;
- return count(container_.begin(), container_.end(), rv) != 0;
- }
-
- void DescribeTo(::std::ostream* const os) const {
- *os << "one of {";
- char const* sep = "";
- for (auto const& elem : container_) {
- *os << sep << elem;
- sep = ", ";
- }
- *os << "}";
- }
-
- void DescribeNegationTo(::std::ostream* const os) const {
- *os << "none of {";
- char const* sep = "";
- for (auto const& elem : container_) {
- *os << sep << elem;
- sep = ", ";
- }
- *os << "}";
- }
-
- private:
- Container const container_;
-};
-
-template <typename E>
-class SyscallSuccessMatcher {
- public:
- explicit SyscallSuccessMatcher(E expected)
- : expected_(::std::move(expected)) {}
-
- template <typename T>
- operator ::testing::Matcher<T>() const {
- // E is one of three things:
- // - T, or a type losslessly and implicitly convertible to T.
- // - A monomorphic Matcher<T>.
- // - A polymorphic matcher.
- // SafeMatcherCast handles any of the above correctly.
- //
- // Similarly, gMock will invoke this conversion operator to obtain a
- // monomorphic matcher (this is how polymorphic matchers are implemented).
- return ::testing::MakeMatcher(
- new Impl<T>(::testing::SafeMatcherCast<T>(expected_)));
- }
-
- private:
- template <typename T>
- class Impl : public ::testing::MatcherInterface<T> {
- public:
- explicit Impl(::testing::Matcher<T> matcher)
- : matcher_(::std::move(matcher)) {}
-
- bool MatchAndExplain(
- T const& rv,
- ::testing::MatchResultListener* const listener) const override {
- if (rv == static_cast<decltype(rv)>(-1) && errno != 0) {
- *listener << "with errno " << PosixError(errno);
- return false;
- }
- bool match = matcher_.MatchAndExplain(rv, listener);
- if (match) {
- MaybeSave();
- }
- return match;
- }
-
- void DescribeTo(::std::ostream* const os) const override {
- matcher_.DescribeTo(os);
- }
-
- void DescribeNegationTo(::std::ostream* const os) const override {
- matcher_.DescribeNegationTo(os);
- }
-
- private:
- ::testing::Matcher<T> matcher_;
- };
-
- private:
- E expected_;
-};
-
-// A polymorphic matcher equivalent to ::testing::internal::AnyMatcher, except
-// not in namespace ::testing::internal, and describing SyscallSucceeds()'s
-// match constraints (which are enforced by SyscallSuccessMatcher::Impl).
-class AnySuccessValueMatcher {
- public:
- template <typename T>
- operator ::testing::Matcher<T>() const {
- return ::testing::MakeMatcher(new Impl<T>());
- }
-
- private:
- template <typename T>
- class Impl : public ::testing::MatcherInterface<T> {
- public:
- bool MatchAndExplain(
- T const& rv,
- ::testing::MatchResultListener* const listener) const override {
- return true;
- }
-
- void DescribeTo(::std::ostream* const os) const override {
- *os << "not -1 (success)";
- }
-
- void DescribeNegationTo(::std::ostream* const os) const override {
- *os << "-1 (failure)";
- }
- };
-};
-
-class SyscallFailureMatcher {
- public:
- explicit SyscallFailureMatcher(::testing::Matcher<int> errno_matcher)
- : errno_matcher_(std::move(errno_matcher)) {}
-
- template <typename T>
- bool MatchAndExplain(T const& rv,
- ::testing::MatchResultListener* const listener) const {
- if (rv != static_cast<decltype(rv)>(-1)) {
- return false;
- }
- int actual_errno = errno;
- *listener << "with errno " << PosixError(actual_errno);
- bool match = errno_matcher_.MatchAndExplain(actual_errno, listener);
- if (match) {
- MaybeSave();
- }
- return match;
- }
-
- void DescribeTo(::std::ostream* const os) const {
- *os << "-1 (failure), with errno ";
- errno_matcher_.DescribeTo(os);
- }
-
- void DescribeNegationTo(::std::ostream* const os) const {
- *os << "not -1 (success), with errno ";
- errno_matcher_.DescribeNegationTo(os);
- }
-
- private:
- ::testing::Matcher<int> errno_matcher_;
-};
-
-class SpecificErrnoMatcher : public ::testing::MatcherInterface<int> {
- public:
- explicit SpecificErrnoMatcher(int const expected) : expected_(expected) {}
-
- bool MatchAndExplain(
- int const actual_errno,
- ::testing::MatchResultListener* const listener) const override {
- return actual_errno == expected_;
- }
-
- void DescribeTo(::std::ostream* const os) const override {
- *os << PosixError(expected_);
- }
-
- void DescribeNegationTo(::std::ostream* const os) const override {
- *os << "not " << PosixError(expected_);
- }
-
- private:
- int const expected_;
-};
-
-inline ::testing::Matcher<int> SpecificErrno(int const expected) {
- return ::testing::MakeMatcher(new SpecificErrnoMatcher(expected));
-}
-
-} // namespace internal
-
-template <typename Container>
-inline ::testing::PolymorphicMatcher<internal::ElementOfMatcher<Container>>
-ElementOf(Container container) {
- return ::testing::MakePolymorphicMatcher(
- internal::ElementOfMatcher<Container>(::std::move(container)));
-}
-
-template <typename T>
-inline ::testing::PolymorphicMatcher<
- internal::ElementOfMatcher<::std::vector<T>>>
-ElementOf(::std::initializer_list<T> elems) {
- return ::testing::MakePolymorphicMatcher(
- internal::ElementOfMatcher<::std::vector<T>>(::std::vector<T>(elems)));
-}
-
-template <typename E>
-inline internal::SyscallSuccessMatcher<E> SyscallSucceedsWithValue(E expected) {
- return internal::SyscallSuccessMatcher<E>(::std::move(expected));
-}
-
-inline internal::SyscallSuccessMatcher<internal::AnySuccessValueMatcher>
-SyscallSucceeds() {
- return SyscallSucceedsWithValue(
- ::gvisor::testing::internal::AnySuccessValueMatcher());
-}
-
-inline ::testing::PolymorphicMatcher<internal::SyscallFailureMatcher>
-SyscallFailsWithErrno(::testing::Matcher<int> expected) {
- return ::testing::MakePolymorphicMatcher(
- internal::SyscallFailureMatcher(::std::move(expected)));
-}
-
-// Overload taking an int so that SyscallFailsWithErrno(<specific errno>) uses
-// internal::SpecificErrno (which stringifies the errno) rather than
-// ::testing::Eq (which doesn't).
-inline ::testing::PolymorphicMatcher<internal::SyscallFailureMatcher>
-SyscallFailsWithErrno(int const expected) {
- return SyscallFailsWithErrno(internal::SpecificErrno(expected));
-}
-
-inline ::testing::PolymorphicMatcher<internal::SyscallFailureMatcher>
-SyscallFails() {
- return SyscallFailsWithErrno(::testing::Gt(0));
-}
-
-// As of GCC 7.2, -Wall => -Wc++17-compat => -Wnoexcept-type generates an
-// irrelevant, non-actionable warning about ABI compatibility when
-// RetryEINTRImpl is constructed with a noexcept function, such as glibc's
-// syscall(). See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80985.
-#if defined(__GNUC__) && !defined(__clang__) && \
- (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2))
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wnoexcept-type"
-#endif
-
-namespace internal {
-
-template <typename F>
-struct RetryEINTRImpl {
- F const f;
-
- explicit constexpr RetryEINTRImpl(F f) : f(std::move(f)) {}
-
- template <typename... Args>
- auto operator()(Args&&... args) const
- -> decltype(f(std::forward<Args>(args)...)) {
- while (true) {
- errno = 0;
- auto const ret = f(std::forward<Args>(args)...);
- if (ret != -1 || errno != EINTR) {
- return ret;
- }
- }
- }
-};
-
-} // namespace internal
-
-template <typename F>
-constexpr internal::RetryEINTRImpl<F> RetryEINTR(F&& f) {
- return internal::RetryEINTRImpl<F>(std::forward<F>(f));
-}
-
-#if defined(__GNUC__) && !defined(__clang__) && \
- (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2))
-#pragma GCC diagnostic pop
-#endif
-
-namespace internal {
-
-template <typename F>
-ssize_t ApplyFileIoSyscall(F const& f, size_t const count) {
- size_t completed = 0;
- // `do ... while` because some callers actually want to make a syscall with a
- // count of 0.
- do {
- auto const cur = RetryEINTR(f)(completed);
- if (cur < 0) {
- return cur;
- } else if (cur == 0) {
- break;
- }
- completed += cur;
- } while (completed < count);
- return completed;
-}
-
-} // namespace internal
-
-inline PosixErrorOr<std::string> ReadAllFd(int fd) {
- std::string all;
- all.reserve(128 * 1024); // arbitrary.
-
- std::vector<char> buffer(16 * 1024);
- for (;;) {
- auto const bytes = RetryEINTR(read)(fd, buffer.data(), buffer.size());
- if (bytes < 0) {
- return PosixError(errno, "file read");
- }
- if (bytes == 0) {
- return std::move(all);
- }
- if (bytes > 0) {
- all.append(buffer.data(), bytes);
- }
- }
-}
-
-inline ssize_t ReadFd(int fd, void* buf, size_t count) {
- return internal::ApplyFileIoSyscall(
- [&](size_t completed) {
- return read(fd, static_cast<char*>(buf) + completed, count - completed);
- },
- count);
-}
-
-inline ssize_t WriteFd(int fd, void const* buf, size_t count) {
- return internal::ApplyFileIoSyscall(
- [&](size_t completed) {
- return write(fd, static_cast<char const*>(buf) + completed,
- count - completed);
- },
- count);
-}
-
-inline ssize_t PreadFd(int fd, void* buf, size_t count, off_t offset) {
- return internal::ApplyFileIoSyscall(
- [&](size_t completed) {
- return pread(fd, static_cast<char*>(buf) + completed, count - completed,
- offset + completed);
- },
- count);
-}
-
-inline ssize_t PwriteFd(int fd, void const* buf, size_t count, off_t offset) {
- return internal::ApplyFileIoSyscall(
- [&](size_t completed) {
- return pwrite(fd, static_cast<char const*>(buf) + completed,
- count - completed, offset + completed);
- },
- count);
-}
-
-template <typename T>
-using List = std::initializer_list<T>;
-
-namespace internal {
-
-template <typename T>
-void AppendAllBitwiseCombinations(std::vector<T>* combinations, T current) {
- combinations->push_back(current);
-}
-
-template <typename T, typename Arg, typename... Args>
-void AppendAllBitwiseCombinations(std::vector<T>* combinations, T current,
- Arg&& next, Args&&... rest) {
- for (auto const option : next) {
- AppendAllBitwiseCombinations(combinations, current | option, rest...);
- }
-}
-
-inline size_t CombinedSize(size_t accum) { return accum; }
-
-template <typename T, typename... Args>
-size_t CombinedSize(size_t accum, T const& x, Args&&... xs) {
- return CombinedSize(accum + x.size(), std::forward<Args>(xs)...);
-}
-
-// Base case: no more containers, so do nothing.
-template <typename T>
-void DoMoveExtendContainer(T* c) {}
-
-// Append each container next to c.
-template <typename T, typename U, typename... Args>
-void DoMoveExtendContainer(T* c, U&& next, Args&&... rest) {
- std::move(std::begin(next), std::end(next), std::back_inserter(*c));
- DoMoveExtendContainer(c, std::forward<Args>(rest)...);
-}
-
-} // namespace internal
-
-template <typename T = int>
-std::vector<T> AllBitwiseCombinations() {
- return std::vector<T>();
-}
-
-template <typename T = int, typename... Args>
-std::vector<T> AllBitwiseCombinations(Args&&... args) {
- std::vector<T> combinations;
- internal::AppendAllBitwiseCombinations(&combinations, 0, args...);
- return combinations;
-}
-
-template <typename T, typename U, typename F>
-std::vector<T> ApplyVec(F const& f, std::vector<U> const& us) {
- std::vector<T> vec;
- vec.reserve(us.size());
- for (auto const& u : us) {
- vec.push_back(f(u));
- }
- return vec;
-}
-
-template <typename T, typename U>
-std::vector<T> ApplyVecToVec(std::vector<std::function<T(U)>> const& fs,
- std::vector<U> const& us) {
- std::vector<T> vec;
- vec.reserve(us.size() * fs.size());
- for (auto const& f : fs) {
- for (auto const& u : us) {
- vec.push_back(f(u));
- }
- }
- return vec;
-}
-
-// Moves all elements from the containers `args` to the end of `c`.
-template <typename T, typename... Args>
-void VecAppend(T* c, Args&&... args) {
- c->reserve(internal::CombinedSize(c->size(), args...));
- internal::DoMoveExtendContainer(c, std::forward<Args>(args)...);
-}
-
-// Returns a vector containing the concatenated contents of the containers
-// `args`.
-template <typename T, typename... Args>
-std::vector<T> VecCat(Args&&... args) {
- std::vector<T> combined;
- VecAppend(&combined, std::forward<Args>(args)...);
- return combined;
-}
-
-#define RETURN_ERROR_IF_SYSCALL_FAIL(syscall) \
- do { \
- if ((syscall) < 0 && errno != 0) { \
- return PosixError(errno, #syscall); \
- } \
- } while (false)
-
-// Fill the given buffer with random bytes.
-void RandomizeBuffer(void* buffer, size_t len);
-
-template <typename T>
-inline PosixErrorOr<T> Atoi(absl::string_view str) {
- T ret;
- if (!absl::SimpleAtoi<T>(str, &ret)) {
- return PosixError(EINVAL, "String not a number.");
- }
- return ret;
-}
-
-inline PosixErrorOr<uint64_t> AtoiBase(absl::string_view str, int base) {
- if (base > 255 || base < 2) {
- return PosixError(EINVAL, "Invalid Base");
- }
-
- uint64_t ret = 0;
- if (!absl::numbers_internal::safe_strtou64_base(str, &ret, base)) {
- return PosixError(EINVAL, "String not a number.");
- }
-
- return ret;
-}
-
-inline PosixErrorOr<double> Atod(absl::string_view str) {
- double ret;
- if (!absl::SimpleAtod(str, &ret)) {
- return PosixError(EINVAL, "String not a double type.");
- }
- return ret;
-}
-
-inline PosixErrorOr<float> Atof(absl::string_view str) {
- float ret;
- if (!absl::SimpleAtof(str, &ret)) {
- return PosixError(EINVAL, "String not a float type.");
- }
- return ret;
-}
-
-// Return the smallest number of iovec arrays that can be used to write
-// "total_bytes" number of bytes, each iovec writing one "buf".
-std::vector<std::vector<struct iovec>> GenerateIovecs(uint64_t total_size,
- void* buf, size_t buflen);
-
-// Returns bytes in 'n' megabytes. Used for readability.
-uint64_t Megabytes(uint64_t n);
-
-// Predicate for checking that a value is within some tolerance of another
-// value. Returns true iff current is in the range [target * (1 - tolerance),
-// target * (1 + tolerance)].
-bool Equivalent(uint64_t current, uint64_t target, double tolerance);
-
-// Matcher wrapping the Equivalent predicate.
-MATCHER_P2(EquivalentWithin, target, tolerance,
- std::string(negation ? "Isn't" : "Is") +
- ::absl::StrFormat(" within %.2f%% of the target of %zd bytes",
- tolerance * 100, target)) {
- if (target == 0) {
- *result_listener << ::absl::StreamFormat("difference of infinity%%");
- } else {
- int64_t delta = static_cast<int64_t>(arg) - static_cast<int64_t>(target);
- double delta_percent =
- static_cast<double>(delta) / static_cast<double>(target) * 100;
- *result_listener << ::absl::StreamFormat("difference of %.2f%%",
- delta_percent);
- }
- return Equivalent(arg, target, tolerance);
-}
-
-// Returns the absolute path to the a data dependency. 'path' is the runfile
-// location relative to workspace root.
-#ifdef __linux__
-std::string RunfilePath(std::string path);
-#endif
-
-void TestInit(int* argc, char*** argv);
-int RunAllTests(void);
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_TEST_UTIL_H_
diff --git a/test/util/test_util_impl.cc b/test/util/test_util_impl.cc
deleted file mode 100644
index 6b6826898..000000000
--- a/test/util/test_util_impl.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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 <signal.h>
-
-#include "gtest/gtest.h"
-#include "absl/flags/flag.h"
-#include "absl/flags/parse.h"
-#include "benchmark/benchmark.h"
-#include "test/util/logging.h"
-
-extern bool FLAGS_gtest_list_tests;
-extern bool FLAGS_benchmark_list_tests;
-extern std::string FLAGS_benchmark_filter;
-
-namespace gvisor {
-namespace testing {
-
-void SetupGvisorDeathTest() {}
-
-void TestInit(int* argc, char*** argv) {
- ::testing::InitGoogleTest(argc, *argv);
- benchmark::Initialize(argc, *argv);
- ::absl::ParseCommandLine(*argc, *argv);
-
- // Always mask SIGPIPE as it's common and tests aren't expected to handle it.
- struct sigaction sa = {};
- sa.sa_handler = SIG_IGN;
- TEST_CHECK(sigaction(SIGPIPE, &sa, nullptr) == 0);
-}
-
-int RunAllTests() {
- if (::testing::FLAGS_gtest_list_tests) {
- return RUN_ALL_TESTS();
- }
- if (FLAGS_benchmark_list_tests) {
- benchmark::RunSpecifiedBenchmarks();
- return 0;
- }
-
- // Run selected tests & benchmarks.
- int rc = RUN_ALL_TESTS();
- benchmark::RunSpecifiedBenchmarks();
- return rc;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/test_util_runfiles.cc b/test/util/test_util_runfiles.cc
deleted file mode 100644
index 7210094eb..000000000
--- a/test/util/test_util_runfiles.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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 <iostream>
-#include <string>
-
-#include "test/util/fs_util.h"
-#include "test/util/test_util.h"
-#include "tools/cpp/runfiles/runfiles.h"
-
-namespace gvisor {
-namespace testing {
-
-std::string RunfilePath(std::string path) {
- static const bazel::tools::cpp::runfiles::Runfiles* const runfiles = [] {
- std::string error;
- auto* runfiles =
- bazel::tools::cpp::runfiles::Runfiles::CreateForTest(&error);
- if (runfiles == nullptr) {
- std::cerr << "Unable to find runfiles: " << error << std::endl;
- }
- return runfiles;
- }();
-
- if (!runfiles) {
- // Can't find runfiles? This probably won't work, but __main__/path is our
- // best guess.
- return JoinPath("__main__", path);
- }
-
- return runfiles->Rlocation(JoinPath("__main__", path));
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/test_util_test.cc b/test/util/test_util_test.cc
deleted file mode 100644
index f42100374..000000000
--- a/test/util/test_util_test.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/test_util.h"
-
-#include <errno.h>
-
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-using ::testing::AnyOf;
-using ::testing::Gt;
-using ::testing::IsEmpty;
-using ::testing::Lt;
-using ::testing::Not;
-using ::testing::TypedEq;
-using ::testing::UnorderedElementsAre;
-using ::testing::UnorderedElementsAreArray;
-
-namespace gvisor {
-namespace testing {
-
-namespace {
-
-TEST(KernelVersionParsing, ValidateParsing) {
- KernelVersion v = ASSERT_NO_ERRNO_AND_VALUE(
- ParseKernelVersion("4.18.10-1foo2-amd64 baz blah"));
- ASSERT_TRUE(v == KernelVersion({4, 18, 10}));
-
- v = ASSERT_NO_ERRNO_AND_VALUE(ParseKernelVersion("4.18.10-1foo2-amd64"));
- ASSERT_TRUE(v == KernelVersion({4, 18, 10}));
-
- v = ASSERT_NO_ERRNO_AND_VALUE(ParseKernelVersion("4.18.10-14-amd64"));
- ASSERT_TRUE(v == KernelVersion({4, 18, 10}));
-
- v = ASSERT_NO_ERRNO_AND_VALUE(ParseKernelVersion("4.18.10-amd64"));
- ASSERT_TRUE(v == KernelVersion({4, 18, 10}));
-
- v = ASSERT_NO_ERRNO_AND_VALUE(ParseKernelVersion("4.18.10"));
- ASSERT_TRUE(v == KernelVersion({4, 18, 10}));
-
- v = ASSERT_NO_ERRNO_AND_VALUE(ParseKernelVersion("4.0.10"));
- ASSERT_TRUE(v == KernelVersion({4, 0, 10}));
-
- v = ASSERT_NO_ERRNO_AND_VALUE(ParseKernelVersion("4.0"));
- ASSERT_TRUE(v == KernelVersion({4, 0, 0}));
-
- ASSERT_THAT(ParseKernelVersion("4.a"), PosixErrorIs(EINVAL, ::testing::_));
- ASSERT_THAT(ParseKernelVersion("3"), PosixErrorIs(EINVAL, ::testing::_));
- ASSERT_THAT(ParseKernelVersion(""), PosixErrorIs(EINVAL, ::testing::_));
- ASSERT_THAT(ParseKernelVersion("version 3.3.10"),
- PosixErrorIs(EINVAL, ::testing::_));
-}
-
-TEST(MatchersTest, SyscallSucceeds) {
- EXPECT_THAT(0, SyscallSucceeds());
- EXPECT_THAT(0L, SyscallSucceeds());
-
- errno = 0;
- EXPECT_THAT(-1, SyscallSucceeds());
- EXPECT_THAT(-1L, SyscallSucceeds());
-
- errno = ENOMEM;
- EXPECT_THAT(-1, Not(SyscallSucceeds()));
- EXPECT_THAT(-1L, Not(SyscallSucceeds()));
-}
-
-TEST(MatchersTest, SyscallSucceedsWithValue) {
- EXPECT_THAT(0, SyscallSucceedsWithValue(0));
- EXPECT_THAT(1, SyscallSucceedsWithValue(Lt(3)));
- EXPECT_THAT(-1, Not(SyscallSucceedsWithValue(Lt(3))));
- EXPECT_THAT(4, Not(SyscallSucceedsWithValue(Lt(3))));
-
- // Non-int -1
- EXPECT_THAT(-1L, Not(SyscallSucceedsWithValue(0)));
-
- // Non-int, truncates to -1 if converted to int, with expected value
- EXPECT_THAT(0xffffffffL, SyscallSucceedsWithValue(0xffffffffL));
-
- // Non-int, truncates to -1 if converted to int, with monomorphic matcher
- EXPECT_THAT(0xffffffffL,
- SyscallSucceedsWithValue(TypedEq<long>(0xffffffffL)));
-
- // Non-int, truncates to -1 if converted to int, with polymorphic matcher
- EXPECT_THAT(0xffffffffL, SyscallSucceedsWithValue(Gt(1)));
-}
-
-TEST(MatchersTest, SyscallFails) {
- EXPECT_THAT(0, Not(SyscallFails()));
- EXPECT_THAT(0L, Not(SyscallFails()));
-
- errno = 0;
- EXPECT_THAT(-1, Not(SyscallFails()));
- EXPECT_THAT(-1L, Not(SyscallFails()));
-
- errno = ENOMEM;
- EXPECT_THAT(-1, SyscallFails());
- EXPECT_THAT(-1L, SyscallFails());
-}
-
-TEST(MatchersTest, SyscallFailsWithErrno) {
- EXPECT_THAT(0, Not(SyscallFailsWithErrno(EINVAL)));
- EXPECT_THAT(0L, Not(SyscallFailsWithErrno(EINVAL)));
-
- errno = ENOMEM;
- EXPECT_THAT(-1, Not(SyscallFailsWithErrno(EINVAL)));
- EXPECT_THAT(-1L, Not(SyscallFailsWithErrno(EINVAL)));
-
- errno = EINVAL;
- EXPECT_THAT(-1, SyscallFailsWithErrno(EINVAL));
- EXPECT_THAT(-1L, SyscallFailsWithErrno(EINVAL));
-
- EXPECT_THAT(-1, SyscallFailsWithErrno(AnyOf(EINVAL, ENOMEM)));
- EXPECT_THAT(-1L, SyscallFailsWithErrno(AnyOf(EINVAL, ENOMEM)));
-
- std::vector<int> expected_errnos({EINVAL, ENOMEM});
- errno = ENOMEM;
- EXPECT_THAT(-1, SyscallFailsWithErrno(ElementOf(expected_errnos)));
- EXPECT_THAT(-1L, SyscallFailsWithErrno(ElementOf(expected_errnos)));
-}
-
-TEST(AllBitwiseCombinationsTest, NoArguments) {
- EXPECT_THAT(AllBitwiseCombinations(), IsEmpty());
-}
-
-TEST(AllBitwiseCombinationsTest, EmptyList) {
- EXPECT_THAT(AllBitwiseCombinations(List<int>{}), IsEmpty());
-}
-
-TEST(AllBitwiseCombinationsTest, SingleElementList) {
- EXPECT_THAT(AllBitwiseCombinations(List<int>{5}), UnorderedElementsAre(5));
-}
-
-TEST(AllBitwiseCombinationsTest, SingleList) {
- EXPECT_THAT(AllBitwiseCombinations(List<int>{0, 1, 2, 4}),
- UnorderedElementsAre(0, 1, 2, 4));
-}
-
-TEST(AllBitwiseCombinationsTest, MultipleLists) {
- EXPECT_THAT(
- AllBitwiseCombinations(List<int>{0, 1, 2, 3}, List<int>{0, 4, 8, 12}),
- UnorderedElementsAreArray(
- {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}));
-}
-
-TEST(RandomizeBuffer, Works) {
- const std::vector<char> original(4096);
- std::vector<char> buffer = original;
- RandomizeBuffer(buffer.data(), buffer.size());
- EXPECT_NE(buffer, original);
-}
-
-// Enable comparison of vectors of iovec arrays for the following test.
-MATCHER_P(IovecsListEq, expected, "") {
- if (arg.size() != expected.size()) {
- *result_listener << "sizes are different (actual: " << arg.size()
- << ", expected: " << expected.size() << ")";
- return false;
- }
-
- for (uint64_t i = 0; i < expected.size(); ++i) {
- const std::vector<struct iovec>& actual_iovecs = arg[i];
- const std::vector<struct iovec>& expected_iovecs = expected[i];
- if (actual_iovecs.size() != expected_iovecs.size()) {
- *result_listener << "iovec array size at position " << i
- << " is different (actual: " << actual_iovecs.size()
- << ", expected: " << expected_iovecs.size() << ")";
- return false;
- }
-
- for (uint64_t j = 0; j < expected_iovecs.size(); ++j) {
- const struct iovec& actual_iov = actual_iovecs[j];
- const struct iovec& expected_iov = expected_iovecs[j];
- if (actual_iov.iov_base != expected_iov.iov_base) {
- *result_listener << "iovecs in array " << i << " at position " << j
- << " are different (expected iov_base: "
- << expected_iov.iov_base
- << ", got: " << actual_iov.iov_base << ")";
- return false;
- }
- if (actual_iov.iov_len != expected_iov.iov_len) {
- *result_listener << "iovecs in array " << i << " at position " << j
- << " are different (expected iov_len: "
- << expected_iov.iov_len
- << ", got: " << actual_iov.iov_len << ")";
- return false;
- }
- }
- }
-
- return true;
-}
-
-// Verify empty iovec list generation.
-TEST(GenerateIovecs, EmptyList) {
- std::vector<char> buffer = {'a', 'b', 'c'};
-
- EXPECT_THAT(GenerateIovecs(0, buffer.data(), buffer.size()),
- IovecsListEq(std::vector<std::vector<struct iovec>>()));
-}
-
-// Verify generating a single array of only one, partial, iovec.
-TEST(GenerateIovecs, OneArray) {
- std::vector<char> buffer = {'a', 'b', 'c'};
-
- std::vector<std::vector<struct iovec>> expected;
- struct iovec iov = {};
- iov.iov_base = buffer.data();
- iov.iov_len = 2;
- expected.push_back(std::vector<struct iovec>({iov}));
- EXPECT_THAT(GenerateIovecs(2, buffer.data(), buffer.size()),
- IovecsListEq(expected));
-}
-
-// Verify that it wraps around after IOV_MAX iovecs.
-TEST(GenerateIovecs, WrapsAtIovMax) {
- std::vector<char> buffer = {'a', 'b', 'c'};
-
- std::vector<std::vector<struct iovec>> expected;
- struct iovec iov = {};
- iov.iov_base = buffer.data();
- iov.iov_len = buffer.size();
- expected.emplace_back();
- for (int i = 0; i < IOV_MAX; ++i) {
- expected[0].push_back(iov);
- }
- iov.iov_len = 1;
- expected.push_back(std::vector<struct iovec>({iov}));
-
- EXPECT_THAT(
- GenerateIovecs(IOV_MAX * buffer.size() + 1, buffer.data(), buffer.size()),
- IovecsListEq(expected));
-}
-
-} // namespace
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/thread_util.h b/test/util/thread_util.h
deleted file mode 100644
index 923c4fe10..000000000
--- a/test/util/thread_util.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_THREAD_UTIL_H_
-#define GVISOR_TEST_UTIL_THREAD_UTIL_H_
-
-#include <pthread.h>
-#ifdef __linux__
-#include <sys/syscall.h>
-#endif
-#include <unistd.h>
-
-#include <functional>
-#include <utility>
-
-#include "test/util/logging.h"
-
-namespace gvisor {
-namespace testing {
-
-// ScopedThread is a minimal wrapper around pthreads.
-//
-// This is used in lieu of more complex mechanisms because it provides very
-// predictable behavior (no messing with timers, etc.) The thread will
-// automatically joined when it is destructed (goes out of scope), but can be
-// joined manually as well.
-class ScopedThread {
- public:
- // Constructs a thread that executes f exactly once.
- explicit ScopedThread(std::function<void*()> f) : f_(std::move(f)) {
- CreateThread();
- }
-
- explicit ScopedThread(const std::function<void()>& f) {
- f_ = [=] {
- f();
- return nullptr;
- };
- CreateThread();
- }
-
- ScopedThread(const ScopedThread& other) = delete;
- ScopedThread& operator=(const ScopedThread& other) = delete;
-
- // Joins the thread.
- ~ScopedThread() { Join(); }
-
- // Waits until this thread has finished executing. Join is idempotent and may
- // be called multiple times, however Join itself is not thread-safe.
- void* Join() {
- if (!joined_) {
- TEST_PCHECK(pthread_join(pt_, &retval_) == 0);
- joined_ = true;
- }
- return retval_;
- }
-
- private:
- void CreateThread() {
- TEST_PCHECK_MSG(pthread_create(
- &pt_, /* attr = */ nullptr,
- +[](void* arg) -> void* {
- return static_cast<ScopedThread*>(arg)->f_();
- },
- this) == 0,
- "thread creation failed");
- }
-
- std::function<void*()> f_;
- pthread_t pt_;
- bool joined_ = false;
- void* retval_ = nullptr;
-};
-
-#ifdef __linux__
-inline pid_t gettid() { return syscall(SYS_gettid); }
-#endif
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_THREAD_UTIL_H_
diff --git a/test/util/time_util.cc b/test/util/time_util.cc
deleted file mode 100644
index 1ddfbfc9c..000000000
--- a/test/util/time_util.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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 "test/util/time_util.h"
-
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include "absl/time/time.h"
-
-namespace gvisor {
-namespace testing {
-
-void SleepSafe(absl::Duration duration) {
- if (duration == absl::ZeroDuration()) {
- return;
- }
-
- struct timespec ts = absl::ToTimespec(duration);
- int ret;
- while (1) {
- ret = syscall(__NR_nanosleep, &ts, &ts);
- if (ret == 0 || (ret <= 0 && errno != EINTR)) {
- break;
- }
- }
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/time_util.h b/test/util/time_util.h
deleted file mode 100644
index f3ddc9fde..000000000
--- a/test/util/time_util.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_TIME_UTIL_H_
-#define GVISOR_TEST_UTIL_TIME_UTIL_H_
-
-#include "absl/time/time.h"
-
-namespace gvisor {
-namespace testing {
-
-// Sleep for at least the specified duration. Avoids glibc.
-void SleepSafe(absl::Duration duration);
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_TIME_UTIL_H_
diff --git a/test/util/timer_util.cc b/test/util/timer_util.cc
deleted file mode 100644
index 75cfc4f40..000000000
--- a/test/util/timer_util.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/timer_util.h"
-
-namespace gvisor {
-namespace testing {
-
-absl::Time Now(clockid_t id) {
- struct timespec now;
- TEST_PCHECK(clock_gettime(id, &now) == 0);
- return absl::TimeFromTimespec(now);
-}
-
-#ifdef __linux__
-
-PosixErrorOr<IntervalTimer> TimerCreate(clockid_t clockid,
- const struct sigevent& sev) {
- int timerid;
- int ret = syscall(SYS_timer_create, clockid, &sev, &timerid);
- if (ret < 0) {
- return PosixError(errno, "timer_create");
- }
- if (ret > 0) {
- return PosixError(EINVAL, "timer_create should never return positive");
- }
- MaybeSave();
- return IntervalTimer(timerid);
-}
-
-#endif // __linux__
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/timer_util.h b/test/util/timer_util.h
deleted file mode 100644
index e389108ef..000000000
--- a/test/util/timer_util.h
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_TIMER_UTIL_H_
-#define GVISOR_TEST_UTIL_TIMER_UTIL_H_
-
-#include <errno.h>
-#ifdef __linux__
-#include <sys/syscall.h>
-#endif
-#include <sys/time.h>
-
-#include <functional>
-
-#include "gmock/gmock.h"
-#include "absl/time/time.h"
-#include "test/util/cleanup.h"
-#include "test/util/logging.h"
-#include "test/util/posix_error.h"
-#include "test/util/test_util.h"
-
-namespace gvisor {
-namespace testing {
-
-// From Linux's include/uapi/asm-generic/siginfo.h.
-#ifndef sigev_notify_thread_id
-#define sigev_notify_thread_id _sigev_un._tid
-#endif
-
-// Returns the current time.
-absl::Time Now(clockid_t id);
-
-// MonotonicTimer is a simple timer that uses a monotonic clock.
-class MonotonicTimer {
- public:
- MonotonicTimer() {}
- absl::Duration Duration() {
- struct timespec ts;
- TEST_CHECK(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
- return absl::TimeFromTimespec(ts) - start_;
- }
-
- void Start() {
- struct timespec ts;
- TEST_CHECK(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
- start_ = absl::TimeFromTimespec(ts);
- }
-
- protected:
- absl::Time start_;
-};
-
-// Sets the given itimer and returns a cleanup function that restores the
-// previous itimer when it goes out of scope.
-inline PosixErrorOr<Cleanup> ScopedItimer(int which,
- struct itimerval const& new_value) {
- struct itimerval old_value;
- int rc = setitimer(which, &new_value, &old_value);
- MaybeSave();
- if (rc < 0) {
- return PosixError(errno, "setitimer failed");
- }
- return Cleanup(std::function<void(void)>([which, old_value] {
- EXPECT_THAT(setitimer(which, &old_value, nullptr), SyscallSucceeds());
- }));
-}
-
-#ifdef __linux__
-
-// RAII type for a kernel "POSIX" interval timer. (The kernel provides system
-// calls such as timer_create that behave very similarly, but not identically,
-// to those described by timer_create(2); in particular, the kernel does not
-// implement SIGEV_THREAD. glibc builds POSIX-compliant interval timers based on
-// these kernel interval timers.)
-//
-// Compare implementation to FileDescriptor.
-class IntervalTimer {
- public:
- IntervalTimer() = default;
-
- explicit IntervalTimer(int id) { set_id(id); }
-
- IntervalTimer(IntervalTimer&& orig) : id_(orig.release()) {}
-
- IntervalTimer& operator=(IntervalTimer&& orig) {
- if (this == &orig) return *this;
- reset(orig.release());
- return *this;
- }
-
- IntervalTimer(const IntervalTimer& other) = delete;
- IntervalTimer& operator=(const IntervalTimer& other) = delete;
-
- ~IntervalTimer() { reset(); }
-
- int get() const { return id_; }
-
- int release() {
- int const id = id_;
- id_ = -1;
- return id;
- }
-
- void reset() { reset(-1); }
-
- void reset(int id) {
- if (id_ >= 0) {
- TEST_PCHECK(syscall(SYS_timer_delete, id_) == 0);
- MaybeSave();
- }
- set_id(id);
- }
-
- PosixErrorOr<struct itimerspec> Set(
- int flags, const struct itimerspec& new_value) const {
- struct itimerspec old_value = {};
- if (syscall(SYS_timer_settime, id_, flags, &new_value, &old_value) < 0) {
- return PosixError(errno, "timer_settime");
- }
- MaybeSave();
- return old_value;
- }
-
- PosixErrorOr<struct itimerspec> Get() const {
- struct itimerspec curr_value = {};
- if (syscall(SYS_timer_gettime, id_, &curr_value) < 0) {
- return PosixError(errno, "timer_gettime");
- }
- MaybeSave();
- return curr_value;
- }
-
- PosixErrorOr<int> Overruns() const {
- int rv = syscall(SYS_timer_getoverrun, id_);
- if (rv < 0) {
- return PosixError(errno, "timer_getoverrun");
- }
- MaybeSave();
- return rv;
- }
-
- private:
- void set_id(int id) { id_ = std::max(id, -1); }
-
- // Kernel timer_t is int; glibc timer_t is void*.
- int id_ = -1;
-};
-
-// A wrapper around timer_create(2).
-PosixErrorOr<IntervalTimer> TimerCreate(clockid_t clockid,
- const struct sigevent& sev);
-
-#endif // __linux__
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_TIMER_UTIL_H_
diff --git a/test/util/uid_util.cc b/test/util/uid_util.cc
deleted file mode 100644
index b131b4b99..000000000
--- a/test/util/uid_util.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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 "test/util/posix_error.h"
-#include "test/util/save_util.h"
-
-namespace gvisor {
-namespace testing {
-
-PosixErrorOr<bool> IsRoot() {
- uid_t ruid, euid, suid;
- int rc = getresuid(&ruid, &euid, &suid);
- MaybeSave();
- if (rc < 0) {
- return PosixError(errno, "getresuid");
- }
- if (ruid != 0 || euid != 0 || suid != 0) {
- return false;
- }
- gid_t rgid, egid, sgid;
- rc = getresgid(&rgid, &egid, &sgid);
- MaybeSave();
- if (rc < 0) {
- return PosixError(errno, "getresgid");
- }
- if (rgid != 0 || egid != 0 || sgid != 0) {
- return false;
- }
- return true;
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/uid_util.h b/test/util/uid_util.h
deleted file mode 100644
index 2cd387fb0..000000000
--- a/test/util/uid_util.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_SYSCALLS_UID_UTIL_H_
-#define GVISOR_TEST_SYSCALLS_UID_UTIL_H_
-
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-// Returns true if the caller's real/effective/saved user/group IDs are all 0.
-PosixErrorOr<bool> IsRoot();
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_SYSCALLS_UID_UTIL_H_
diff --git a/test/util/verity_util.cc b/test/util/verity_util.cc
deleted file mode 100644
index b7d1cb212..000000000
--- a/test/util/verity_util.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2021 The gVisor Authors.
-//
-// Licensed 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 "test/util/verity_util.h"
-
-#include "test/util/fs_util.h"
-#include "test/util/mount_util.h"
-#include "test/util/temp_path.h"
-
-namespace gvisor {
-namespace testing {
-
-std::string BytesToHexString(uint8_t bytes[], int size) {
- std::stringstream ss;
- ss << std::hex;
- for (int i = 0; i < size; ++i) {
- ss << std::setw(2) << std::setfill('0') << static_cast<int>(bytes[i]);
- }
- return ss.str();
-}
-
-std::string MerklePath(absl::string_view path) {
- return JoinPath(Dirname(path),
- std::string(kMerklePrefix) + std::string(Basename(path)));
-}
-
-std::string MerkleRootPath(absl::string_view path) {
- return JoinPath(Dirname(path),
- std::string(kMerkleRootPrefix) + std::string(Basename(path)));
-}
-
-PosixError FlipRandomBit(int fd, int size) {
- // Generate a random offset in the file.
- srand(time(nullptr));
- unsigned int seed = 0;
- int random_offset = rand_r(&seed) % size;
-
- // Read a random byte and flip a bit in it.
- char buf[1];
- RETURN_ERROR_IF_SYSCALL_FAIL(PreadFd(fd, buf, 1, random_offset));
- buf[0] ^= 1;
- RETURN_ERROR_IF_SYSCALL_FAIL(PwriteFd(fd, buf, 1, random_offset));
- return NoError();
-}
-
-PosixErrorOr<std::string> MountVerity(std::string lower_dir,
- std::vector<EnableTarget> targets) {
- // Mount a verity fs on the existing mount.
- std::string mount_opts = "lower_path=" + lower_dir;
- ASSIGN_OR_RETURN_ERRNO(TempPath verity_dir, TempPath::CreateDir());
- RETURN_ERROR_IF_SYSCALL_FAIL(
- mount("", verity_dir.path().c_str(), "verity", 0, mount_opts.c_str()));
-
- for (const EnableTarget& target : targets) {
- ASSIGN_OR_RETURN_ERRNO(
- auto target_fd,
- Open(JoinPath(verity_dir.path(), target.path), target.flags, 0777));
- RETURN_ERROR_IF_SYSCALL_FAIL(ioctl(target_fd.get(), FS_IOC_ENABLE_VERITY));
- }
-
- ASSIGN_OR_RETURN_ERRNO(auto dir_fd, Open(verity_dir.path(), O_RDONLY, 0777));
- RETURN_ERROR_IF_SYSCALL_FAIL(ioctl(dir_fd.get(), FS_IOC_ENABLE_VERITY));
-
- // Measure the root hash.
- uint8_t digest_array[sizeof(struct fsverity_digest) + kMaxDigestSize] = {0};
- struct fsverity_digest* digest =
- reinterpret_cast<struct fsverity_digest*>(digest_array);
- digest->digest_size = kMaxDigestSize;
- RETURN_ERROR_IF_SYSCALL_FAIL(
- ioctl(dir_fd.get(), FS_IOC_MEASURE_VERITY, digest));
-
- // Mount a verity fs with specified root hash.
- mount_opts +=
- ",root_hash=" + BytesToHexString(digest->digest, digest->digest_size);
- ASSIGN_OR_RETURN_ERRNO(TempPath verity_with_hash_dir, TempPath::CreateDir());
- RETURN_ERROR_IF_SYSCALL_FAIL(mount("", verity_with_hash_dir.path().c_str(),
- "verity", 0, mount_opts.c_str()));
-
- // Verity directories should not be deleted. Release the TempPath objects to
- // prevent those directories from being deleted by the destructor.
- verity_dir.release();
- return verity_with_hash_dir.release();
-}
-
-} // namespace testing
-} // namespace gvisor
diff --git a/test/util/verity_util.h b/test/util/verity_util.h
deleted file mode 100644
index ebb78b4bb..000000000
--- a/test/util/verity_util.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2021 The gVisor Authors.
-//
-// Licensed 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.
-
-#ifndef GVISOR_TEST_UTIL_VERITY_UTIL_H_
-#define GVISOR_TEST_UTIL_VERITY_UTIL_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "test/util/posix_error.h"
-
-namespace gvisor {
-namespace testing {
-
-#ifndef FS_IOC_ENABLE_VERITY
-#define FS_IOC_ENABLE_VERITY 1082156677
-#endif
-
-#ifndef FS_IOC_MEASURE_VERITY
-#define FS_IOC_MEASURE_VERITY 3221513862
-#endif
-
-#ifndef FS_VERITY_FL
-#define FS_VERITY_FL 1048576
-#endif
-
-#ifndef FS_IOC_GETFLAGS
-#define FS_IOC_GETFLAGS 2148034049
-#endif
-
-struct fsverity_digest {
- unsigned short digest_algorithm;
- unsigned short digest_size; /* input/output */
- unsigned char digest[];
-};
-
-struct EnableTarget {
- std::string path;
- int flags;
-
- EnableTarget(std::string path, int flags) : path(path), flags(flags) {}
-};
-
-constexpr int kMaxDigestSize = 64;
-constexpr int kDefaultDigestSize = 32;
-constexpr char kContents[] = "foobarbaz";
-constexpr char kMerklePrefix[] = ".merkle.verity.";
-constexpr char kMerkleRootPrefix[] = ".merkleroot.verity.";
-
-// Get the Merkle tree file path for |path|.
-std::string MerklePath(absl::string_view path);
-
-// Get the root Merkle tree file path for |path|.
-std::string MerkleRootPath(absl::string_view path);
-
-// Provide a function to convert bytes to hex string, since
-// absl::BytesToHexString does not seem to be compatible with golang
-// hex.DecodeString used in verity due to zero-padding.
-std::string BytesToHexString(uint8_t bytes[], int size);
-
-// Flip a random bit in the file represented by fd.
-PosixError FlipRandomBit(int fd, int size);
-
-// Mount a verity on the tmpfs and enable both the file and the direcotry. Then
-// mount a new verity with measured root hash.
-PosixErrorOr<std::string> MountVerity(std::string tmpfs_dir,
- std::vector<EnableTarget> targets);
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_UTIL_VERITY_UTIL_H_