diff options
Diffstat (limited to 'test')
69 files changed, 673 insertions, 94 deletions
diff --git a/test/e2e/integration_test.go b/test/e2e/integration_test.go index 7cc0de129..28064e557 100644 --- a/test/e2e/integration_test.go +++ b/test/e2e/integration_test.go @@ -175,6 +175,9 @@ func TestCheckpointRestore(t *testing.T) { t.Fatal(err) } + // TODO(b/143498576): Remove after github.com/moby/moby/issues/38963 is fixed. + time.Sleep(1 * time.Second) + if err := d.Restore("test"); err != nil { t.Fatal("docker restore failed:", err) } diff --git a/test/root/oom_score_adj_test.go b/test/root/oom_score_adj_test.go index 6cd378a1b..126f0975a 100644 --- a/test/root/oom_score_adj_test.go +++ b/test/root/oom_score_adj_test.go @@ -40,6 +40,15 @@ var ( // TestOOMScoreAdjSingle tests that oom_score_adj is set properly in a // single container sandbox. func TestOOMScoreAdjSingle(t *testing.T) { + rootDir, err := testutil.SetupRootDir() + if err != nil { + t.Fatalf("error creating root dir: %v", err) + } + defer os.RemoveAll(rootDir) + + conf := testutil.TestConfig() + conf.RootDir = rootDir + ppid, err := specutils.GetParentPid(os.Getpid()) if err != nil { t.Fatalf("getting parent pid: %v", err) @@ -84,7 +93,6 @@ func TestOOMScoreAdjSingle(t *testing.T) { s := testutil.NewSpecWithArgs("sleep", "1000") s.Process.OOMScoreAdj = testCase.OOMScoreAdj - conf := testutil.TestConfig() containers, cleanup, err := startContainers(conf, []*specs.Spec{s}, []string{id}) if err != nil { t.Fatalf("error starting containers: %v", err) @@ -123,6 +131,15 @@ func TestOOMScoreAdjSingle(t *testing.T) { // TestOOMScoreAdjMulti tests that oom_score_adj is set properly in a // multi-container sandbox. func TestOOMScoreAdjMulti(t *testing.T) { + rootDir, err := testutil.SetupRootDir() + if err != nil { + t.Fatalf("error creating root dir: %v", err) + } + defer os.RemoveAll(rootDir) + + conf := testutil.TestConfig() + conf.RootDir = rootDir + ppid, err := specutils.GetParentPid(os.Getpid()) if err != nil { t.Fatalf("getting parent pid: %v", err) @@ -240,7 +257,6 @@ func TestOOMScoreAdjMulti(t *testing.T) { } } - conf := testutil.TestConfig() containers, cleanup, err := startContainers(conf, specs, ids) if err != nil { t.Fatalf("error starting containers: %v", err) @@ -327,13 +343,8 @@ func createSpecs(cmds ...[]string) ([]*specs.Spec, []string) { } func startContainers(conf *boot.Config, specs []*specs.Spec, ids []string) ([]*container.Container, func(), error) { - // Setup root dir if one hasn't been provided. if len(conf.RootDir) == 0 { - rootDir, err := testutil.SetupRootDir() - if err != nil { - return nil, nil, fmt.Errorf("error creating root dir: %v", err) - } - conf.RootDir = rootDir + panic("conf.RootDir not set. Call testutil.SetupRootDir() to set.") } var containers []*container.Container @@ -345,7 +356,6 @@ func startContainers(conf *boot.Config, specs []*specs.Spec, ids []string) ([]*c for _, b := range bundles { os.RemoveAll(b) } - os.RemoveAll(conf.RootDir) } for i, spec := range specs { bundleDir, err := testutil.SetupBundleDir(spec) diff --git a/test/runtimes/BUILD b/test/runtimes/BUILD index 2e125525b..367295206 100644 --- a/test/runtimes/BUILD +++ b/test/runtimes/BUILD @@ -16,32 +16,32 @@ go_binary( ) runtime_test( + name = "go1.12", blacklist_file = "blacklist_go1.12.csv", - image = "gcr.io/gvisor-presubmit/go1.12", lang = "go", ) runtime_test( + name = "java11", blacklist_file = "blacklist_java11.csv", - image = "gcr.io/gvisor-presubmit/java11", lang = "java", ) runtime_test( + name = "nodejs12.4.0", blacklist_file = "blacklist_nodejs12.4.0.csv", - image = "gcr.io/gvisor-presubmit/nodejs12.4.0", lang = "nodejs", ) runtime_test( + name = "php7.3.6", blacklist_file = "blacklist_php7.3.6.csv", - image = "gcr.io/gvisor-presubmit/php7.3.6", lang = "php", ) runtime_test( + name = "python3.7.3", blacklist_file = "blacklist_python3.7.3.csv", - image = "gcr.io/gvisor-presubmit/python3.7.3", lang = "python", ) diff --git a/test/runtimes/build_defs.bzl b/test/runtimes/build_defs.bzl index 7c11624b4..d458df1fd 100644 --- a/test/runtimes/build_defs.bzl +++ b/test/runtimes/build_defs.bzl @@ -2,32 +2,48 @@ load("@io_bazel_rules_go//go:def.bzl", "go_test") -# runtime_test is a macro that will create targets to run the given test target -# with different runtime options. def runtime_test( + name, lang, - image, + image_repo = "gcr.io/gvisor-presubmit", + image_name = None, + blacklist_file = None, shard_count = 50, - size = "enormous", - blacklist_file = ""): + size = "enormous"): + """Generates sh_test and blacklist test targets for a given runtime. + + Args: + name: The name of the runtime being tested. Typically, the lang + version. + This is used in the names of the generated test targets. + lang: The language being tested. + image_repo: The docker repository containing the proctor image to run. + i.e., the prefix to the fully qualified docker image id. + image_name: The name of the image in the image_repo. + Defaults to the test name. + blacklist_file: A test blacklist to pass to the runtime test's runner. + shard_count: See Bazel common test attributes. + size: See Bazel common test attributes. + """ + if image_name == None: + image_name = name args = [ "--lang", lang, "--image", - image, + "/".join([image_repo, image_name]), ] data = [ ":runner", ] - if blacklist_file != "": + if blacklist_file: args += ["--blacklist_file", "test/runtimes/" + blacklist_file] data += [blacklist_file] # Add a test that the blacklist parses correctly. - blacklist_test(lang, blacklist_file) + blacklist_test(name, blacklist_file) sh_test( - name = lang + "_test", + name = name + "_test", srcs = ["runner.sh"], args = args, data = data, @@ -35,15 +51,14 @@ def runtime_test( shard_count = shard_count, tags = [ # Requires docker and runsc to be configured before the test runs. - "manual", "local", ], ) -def blacklist_test(lang, blacklist_file): +def blacklist_test(name, blacklist_file): """Test that a blacklist parses correctly.""" go_test( - name = lang + "_blacklist_test", + name = name + "_blacklist_test", embed = [":runner"], srcs = ["blacklist_test.go"], args = ["--blacklist_file", "test/runtimes/" + blacklist_file], diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index b869ca6f9..833fbaa09 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -1568,11 +1568,14 @@ cc_binary( srcs = ["proc_net.cc"], linkstatic = 1, deps = [ + ":socket_test_util", "//test/util:capability_util", "//test/util:file_descriptor", "//test/util:fs_util", "//test/util:test_main", "//test/util:test_util", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/time", "@com_google_googletest//:gtest", ], ) diff --git a/test/syscalls/linux/accept_bind.cc b/test/syscalls/linux/accept_bind.cc index 328192a05..427c42ede 100644 --- a/test/syscalls/linux/accept_bind.cc +++ b/test/syscalls/linux/accept_bind.cc @@ -17,7 +17,6 @@ #include <algorithm> #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/file_descriptor.h" diff --git a/test/syscalls/linux/accept_bind_stream.cc b/test/syscalls/linux/accept_bind_stream.cc index b6cdb3f4f..7bcd91e9e 100644 --- a/test/syscalls/linux/accept_bind_stream.cc +++ b/test/syscalls/linux/accept_bind_stream.cc @@ -17,7 +17,6 @@ #include <algorithm> #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/file_descriptor.h" diff --git a/test/syscalls/linux/bind.cc b/test/syscalls/linux/bind.cc index de8cca53b..9547c4ab2 100644 --- a/test/syscalls/linux/bind.cc +++ b/test/syscalls/linux/bind.cc @@ -17,7 +17,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/chroot.cc b/test/syscalls/linux/chroot.cc index 498c45f16..de1611c21 100644 --- a/test/syscalls/linux/chroot.cc +++ b/test/syscalls/linux/chroot.cc @@ -24,7 +24,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" diff --git a/test/syscalls/linux/connect_external.cc b/test/syscalls/linux/connect_external.cc index 98032ac19..bfe1da82e 100644 --- a/test/syscalls/linux/connect_external.cc +++ b/test/syscalls/linux/connect_external.cc @@ -22,7 +22,6 @@ #include <tuple> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/util/file_descriptor.h" #include "test/util/fs_util.h" diff --git a/test/syscalls/linux/exec.cc b/test/syscalls/linux/exec.cc index 85734c290..581f03533 100644 --- a/test/syscalls/linux/exec.cc +++ b/test/syscalls/linux/exec.cc @@ -533,6 +533,47 @@ TEST(ExecTest, CloexecEventfd) { W_EXITCODE(0, 0), ""); } +constexpr int kLinuxMaxSymlinks = 40; + +TEST(ExecTest, SymlinkLimitExceeded) { + std::string path = WorkloadPath(kBasicWorkload); + + // Hold onto TempPath objects so they are not destructed prematurely. + std::vector<TempPath> symlinks; + for (int i = 0; i < kLinuxMaxSymlinks + 1; i++) { + symlinks.push_back( + ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateSymlinkTo("/tmp", path))); + path = symlinks[i].path(); + } + + int execve_errno; + ASSERT_NO_ERRNO_AND_VALUE( + ForkAndExec(path, {path}, {}, /*child=*/nullptr, &execve_errno)); + EXPECT_EQ(execve_errno, ELOOP); +} + +TEST(ExecTest, SymlinkLimitRefreshedForInterpreter) { + std::string tmp_dir = "/tmp"; + std::string interpreter_path = "/bin/echo"; + TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( + tmp_dir, absl::StrCat("#!", interpreter_path), 0755)); + std::string script_path = script.path(); + + // Hold onto TempPath objects so they are not destructed prematurely. + std::vector<TempPath> interpreter_symlinks; + std::vector<TempPath> script_symlinks; + for (int i = 0; i < kLinuxMaxSymlinks; i++) { + interpreter_symlinks.push_back(ASSERT_NO_ERRNO_AND_VALUE( + TempPath::CreateSymlinkTo(tmp_dir, interpreter_path))); + interpreter_path = interpreter_symlinks[i].path(); + script_symlinks.push_back(ASSERT_NO_ERRNO_AND_VALUE( + TempPath::CreateSymlinkTo(tmp_dir, script_path))); + script_path = script_symlinks[i].path(); + } + + CheckExec(script_path, {script_path}, {}, ArgEnvExitStatus(0, 0), ""); +} + TEST(ExecveatTest, BasicWithFDCWD) { std::string path = WorkloadPath(kBasicWorkload); CheckExecveat(AT_FDCWD, path, {path}, {}, /*flags=*/0, ArgEnvExitStatus(0, 0), @@ -542,14 +583,26 @@ TEST(ExecveatTest, BasicWithFDCWD) { TEST(ExecveatTest, Basic) { std::string absolute_path = WorkloadPath(kBasicWorkload); std::string parent_dir = std::string(Dirname(absolute_path)); - std::string relative_path = std::string(Basename(absolute_path)); + std::string base = std::string(Basename(absolute_path)); const FileDescriptor dirfd = ASSERT_NO_ERRNO_AND_VALUE(Open(parent_dir, O_DIRECTORY)); - CheckExecveat(dirfd.get(), relative_path, {absolute_path}, {}, /*flags=*/0, + CheckExecveat(dirfd.get(), base, {absolute_path}, {}, /*flags=*/0, ArgEnvExitStatus(0, 0), absl::StrCat(absolute_path, "\n")); } +TEST(ExecveatTest, FDNotADirectory) { + std::string absolute_path = WorkloadPath(kBasicWorkload); + std::string base = std::string(Basename(absolute_path)); + const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(absolute_path, 0)); + + int execve_errno; + ASSERT_NO_ERRNO_AND_VALUE(ForkAndExecveat(fd.get(), base, {absolute_path}, {}, + /*flags=*/0, /*child=*/nullptr, + &execve_errno)); + EXPECT_EQ(execve_errno, ENOTDIR); +} + TEST(ExecveatTest, AbsolutePathWithFDCWD) { std::string path = WorkloadPath(kBasicWorkload); CheckExecveat(AT_FDCWD, path, {path}, {}, ArgEnvExitStatus(0, 0), 0, @@ -564,6 +617,152 @@ TEST(ExecveatTest, AbsolutePath) { absl::StrCat(path, "\n")); } +TEST(ExecveatTest, EmptyPathBasic) { + std::string path = WorkloadPath(kBasicWorkload); + const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_PATH)); + + CheckExecveat(fd.get(), "", {path}, {}, AT_EMPTY_PATH, ArgEnvExitStatus(0, 0), + absl::StrCat(path, "\n")); +} + +TEST(ExecveatTest, EmptyPathWithDirFD) { + std::string path = WorkloadPath(kBasicWorkload); + std::string parent_dir = std::string(Dirname(path)); + const FileDescriptor dirfd = + ASSERT_NO_ERRNO_AND_VALUE(Open(parent_dir, O_DIRECTORY)); + + int execve_errno; + ASSERT_NO_ERRNO_AND_VALUE(ForkAndExecveat(dirfd.get(), "", {path}, {}, + AT_EMPTY_PATH, + /*child=*/nullptr, &execve_errno)); + EXPECT_EQ(execve_errno, EACCES); +} + +TEST(ExecveatTest, EmptyPathWithoutEmptyPathFlag) { + std::string path = WorkloadPath(kBasicWorkload); + const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_PATH)); + + int execve_errno; + ASSERT_NO_ERRNO_AND_VALUE(ForkAndExecveat( + fd.get(), "", {path}, {}, /*flags=*/0, /*child=*/nullptr, &execve_errno)); + EXPECT_EQ(execve_errno, ENOENT); +} + +TEST(ExecveatTest, AbsolutePathWithEmptyPathFlag) { + std::string path = WorkloadPath(kBasicWorkload); + const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_PATH)); + + CheckExecveat(fd.get(), path, {path}, {}, AT_EMPTY_PATH, + ArgEnvExitStatus(0, 0), absl::StrCat(path, "\n")); +} + +TEST(ExecveatTest, RelativePathWithEmptyPathFlag) { + std::string absolute_path = WorkloadPath(kBasicWorkload); + std::string parent_dir = std::string(Dirname(absolute_path)); + std::string base = std::string(Basename(absolute_path)); + const FileDescriptor dirfd = + ASSERT_NO_ERRNO_AND_VALUE(Open(parent_dir, O_DIRECTORY)); + + CheckExecveat(dirfd.get(), base, {absolute_path}, {}, AT_EMPTY_PATH, + ArgEnvExitStatus(0, 0), absl::StrCat(absolute_path, "\n")); +} + +TEST(ExecveatTest, SymlinkNoFollowWithRelativePath) { + std::string parent_dir = "/tmp"; + TempPath link = ASSERT_NO_ERRNO_AND_VALUE( + TempPath::CreateSymlinkTo(parent_dir, WorkloadPath(kBasicWorkload))); + const FileDescriptor dirfd = + ASSERT_NO_ERRNO_AND_VALUE(Open(parent_dir, O_DIRECTORY)); + std::string base = std::string(Basename(link.path())); + + int execve_errno; + ASSERT_NO_ERRNO_AND_VALUE(ForkAndExecveat(dirfd.get(), base, {base}, {}, + AT_SYMLINK_NOFOLLOW, + /*child=*/nullptr, &execve_errno)); + EXPECT_EQ(execve_errno, ELOOP); +} + +TEST(ExecveatTest, SymlinkNoFollowWithAbsolutePath) { + std::string parent_dir = "/tmp"; + TempPath link = ASSERT_NO_ERRNO_AND_VALUE( + TempPath::CreateSymlinkTo(parent_dir, WorkloadPath(kBasicWorkload))); + std::string path = link.path(); + + int execve_errno; + ASSERT_NO_ERRNO_AND_VALUE(ForkAndExecveat(AT_FDCWD, path, {path}, {}, + AT_SYMLINK_NOFOLLOW, + /*child=*/nullptr, &execve_errno)); + EXPECT_EQ(execve_errno, ELOOP); +} + +TEST(ExecveatTest, SymlinkNoFollowAndEmptyPath) { + TempPath link = ASSERT_NO_ERRNO_AND_VALUE( + TempPath::CreateSymlinkTo("/tmp", WorkloadPath(kBasicWorkload))); + std::string path = link.path(); + const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, 0)); + + CheckExecveat(fd.get(), "", {path}, {}, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW, + ArgEnvExitStatus(0, 0), absl::StrCat(path, "\n")); +} + +TEST(ExecveatTest, SymlinkNoFollowIgnoreSymlinkAncestor) { + TempPath parent_link = + ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateSymlinkTo("/tmp", "/bin")); + std::string path_with_symlink = JoinPath(parent_link.path(), "echo"); + + CheckExecveat(AT_FDCWD, path_with_symlink, {path_with_symlink}, {}, + AT_SYMLINK_NOFOLLOW, ArgEnvExitStatus(0, 0), ""); +} + +TEST(ExecveatTest, SymlinkNoFollowWithNormalFile) { + const FileDescriptor dirfd = + ASSERT_NO_ERRNO_AND_VALUE(Open("/bin", O_DIRECTORY)); + + CheckExecveat(dirfd.get(), "echo", {"echo"}, {}, AT_SYMLINK_NOFOLLOW, + ArgEnvExitStatus(0, 0), ""); +} + +TEST(ExecveatTest, BasicWithCloexecFD) { + std::string path = WorkloadPath(kBasicWorkload); + const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_CLOEXEC)); + + CheckExecveat(fd.get(), "", {path}, {}, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH, + ArgEnvExitStatus(0, 0), absl::StrCat(path, "\n")); +} + +TEST(ExecveatTest, InterpreterScriptWithCloexecFD) { + std::string path = WorkloadPath(kExitScript); + const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_CLOEXEC)); + + int execve_errno; + ASSERT_NO_ERRNO_AND_VALUE(ForkAndExecveat(fd.get(), "", {path}, {}, + AT_EMPTY_PATH, /*child=*/nullptr, + &execve_errno)); + EXPECT_EQ(execve_errno, ENOENT); +} + +TEST(ExecveatTest, InterpreterScriptWithCloexecDirFD) { + std::string absolute_path = WorkloadPath(kExitScript); + std::string parent_dir = std::string(Dirname(absolute_path)); + std::string base = std::string(Basename(absolute_path)); + const FileDescriptor dirfd = + ASSERT_NO_ERRNO_AND_VALUE(Open(parent_dir, O_CLOEXEC | O_DIRECTORY)); + + int execve_errno; + ASSERT_NO_ERRNO_AND_VALUE(ForkAndExecveat(dirfd.get(), base, {base}, {}, + /*flags=*/0, /*child=*/nullptr, + &execve_errno)); + EXPECT_EQ(execve_errno, ENOENT); +} + +TEST(ExecveatTest, InvalidFlags) { + int execve_errno; + ASSERT_NO_ERRNO_AND_VALUE(ForkAndExecveat( + /*dirfd=*/-1, "", {}, {}, /*flags=*/0xFFFF, /*child=*/nullptr, + &execve_errno)); + EXPECT_EQ(execve_errno, EINVAL); +} + // Priority consistent across calls to execve() TEST(GetpriorityTest, ExecveMaintainsPriority) { int prio = 16; diff --git a/test/syscalls/linux/file_base.h b/test/syscalls/linux/file_base.h index 36efabcae..4d155b618 100644 --- a/test/syscalls/linux/file_base.h +++ b/test/syscalls/linux/file_base.h @@ -32,7 +32,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/string_view.h" #include "test/util/file_descriptor.h" #include "test/util/posix_error.h" diff --git a/test/syscalls/linux/ioctl.cc b/test/syscalls/linux/ioctl.cc index 4948a76f0..c4f8bff08 100644 --- a/test/syscalls/linux/ioctl.cc +++ b/test/syscalls/linux/ioctl.cc @@ -25,7 +25,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/ip_socket_test_util.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" diff --git a/test/syscalls/linux/madvise.cc b/test/syscalls/linux/madvise.cc index 08ff4052c..7fd0ea20c 100644 --- a/test/syscalls/linux/madvise.cc +++ b/test/syscalls/linux/madvise.cc @@ -25,7 +25,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/util/file_descriptor.h" #include "test/util/logging.h" #include "test/util/memory_util.h" diff --git a/test/syscalls/linux/memory_accounting.cc b/test/syscalls/linux/memory_accounting.cc index a6e20f9c3..ff2f49863 100644 --- a/test/syscalls/linux/memory_accounting.cc +++ b/test/syscalls/linux/memory_accounting.cc @@ -16,7 +16,6 @@ #include <map> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/match.h" #include "absl/strings/numbers.h" #include "absl/strings/str_format.h" diff --git a/test/syscalls/linux/packet_socket.cc b/test/syscalls/linux/packet_socket.cc index fcf64ee59..92ae55eec 100644 --- a/test/syscalls/linux/packet_socket.cc +++ b/test/syscalls/linux/packet_socket.cc @@ -130,6 +130,20 @@ void CookedPacketTest::SetUp() { GTEST_SKIP(); } + if (!IsRunningOnGvisor()) { + FileDescriptor acceptLocal = ASSERT_NO_ERRNO_AND_VALUE( + Open("/proc/sys/net/ipv4/conf/lo/accept_local", O_RDONLY)); + FileDescriptor routeLocalnet = ASSERT_NO_ERRNO_AND_VALUE( + Open("/proc/sys/net/ipv4/conf/lo/route_localnet", O_RDONLY)); + char enabled; + ASSERT_THAT(read(acceptLocal.get(), &enabled, 1), + SyscallSucceedsWithValue(1)); + ASSERT_EQ(enabled, '1'); + ASSERT_THAT(read(routeLocalnet.get(), &enabled, 1), + SyscallSucceedsWithValue(1)); + ASSERT_EQ(enabled, '1'); + } + ASSERT_THAT(socket_ = socket(AF_PACKET, SOCK_DGRAM, htons(GetParam())), SyscallSucceeds()); } diff --git a/test/syscalls/linux/pipe.cc b/test/syscalls/linux/pipe.cc index 10e2a6dfc..c0b354e65 100644 --- a/test/syscalls/linux/pipe.cc +++ b/test/syscalls/linux/pipe.cc @@ -20,7 +20,6 @@ #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/str_cat.h" #include "absl/synchronization/notification.h" #include "absl/time/clock.h" diff --git a/test/syscalls/linux/pread64.cc b/test/syscalls/linux/pread64.cc index 5e3eb1735..2cecf2e5f 100644 --- a/test/syscalls/linux/pread64.cc +++ b/test/syscalls/linux/pread64.cc @@ -20,7 +20,6 @@ #include <unistd.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/util/file_descriptor.h" #include "test/util/temp_path.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/preadv.cc b/test/syscalls/linux/preadv.cc index eebd129f2..f7ea44054 100644 --- a/test/syscalls/linux/preadv.cc +++ b/test/syscalls/linux/preadv.cc @@ -22,7 +22,6 @@ #include <string> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "test/util/file_descriptor.h" diff --git a/test/syscalls/linux/preadv2.cc b/test/syscalls/linux/preadv2.cc index aac960130..c9246367d 100644 --- a/test/syscalls/linux/preadv2.cc +++ b/test/syscalls/linux/preadv2.cc @@ -21,7 +21,6 @@ #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/memory/memory.h" #include "test/syscalls/linux/file_base.h" #include "test/util/file_descriptor.h" diff --git a/test/syscalls/linux/proc_net.cc b/test/syscalls/linux/proc_net.cc index efdaf202b..65bad06d4 100644 --- a/test/syscalls/linux/proc_net.cc +++ b/test/syscalls/linux/proc_net.cc @@ -12,8 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include <arpa/inet.h> +#include <errno.h> +#include <netinet/in.h> +#include <poll.h> +#include <sys/socket.h> +#include <sys/syscall.h> +#include <sys/types.h> + #include "gtest/gtest.h" -#include "gtest/gtest.h" +#include "absl/strings/str_split.h" +#include "absl/time/clock.h" +#include "test/syscalls/linux/socket_test_util.h" #include "test/util/capability_util.h" #include "test/util/file_descriptor.h" #include "test/util/fs_util.h" @@ -57,6 +67,265 @@ TEST(ProcSysNetIpv4Sack, CanReadAndWrite) { EXPECT_EQ(buf, to_write); } +PosixErrorOr<uint64_t> GetSNMPMetricFromProc(const std::string snmp, + const std::string &type, + const std::string &item) { + std::vector<std::string> snmp_vec = absl::StrSplit(snmp, '\n'); + + // /proc/net/snmp prints a line of headers followed by a line of metrics. + // Only search the headers. + for (unsigned i = 0; i < snmp_vec.size(); i = i + 2) { + if (!absl::StartsWith(snmp_vec[i], type)) continue; + + std::vector<std::string> fields = + absl::StrSplit(snmp_vec[i], ' ', absl::SkipWhitespace()); + + EXPECT_TRUE((i + 1) < snmp_vec.size()); + std::vector<std::string> values = + absl::StrSplit(snmp_vec[i + 1], ' ', absl::SkipWhitespace()); + + EXPECT_TRUE(!fields.empty() && fields.size() == values.size()); + + // Metrics start at the first index. + for (unsigned j = 1; j < fields.size(); j++) { + if (fields[j] == item) { + uint64_t val; + if (!absl::SimpleAtoi(values[j], &val)) { + return PosixError(EINVAL, + absl::StrCat("field is not a number: ", values[j])); + } + + return val; + } + } + } + // We should never get here. + return PosixError( + EINVAL, absl::StrCat("failed to find ", type, "/", item, " in:", snmp)); +} + +TEST(ProcNetSnmp, TcpReset_NoRandomSave) { + // TODO(gvisor.dev/issue/866): epsocket metrics are not savable. + DisableSave ds; + + uint64_t oldAttemptFails; + uint64_t oldActiveOpens; + uint64_t oldOutRsts; + auto snmp = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/net/snmp")); + oldActiveOpens = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "ActiveOpens")); + oldOutRsts = + ASSERT_NO_ERRNO_AND_VALUE(GetSNMPMetricFromProc(snmp, "Tcp", "OutRsts")); + oldAttemptFails = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "AttemptFails")); + + FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_STREAM, 0)); + + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_port = htons(1234), + }; + + ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &(sin.sin_addr)), 1); + ASSERT_THAT(connect(s.get(), (struct sockaddr *)&sin, sizeof(sin)), + SyscallFailsWithErrno(ECONNREFUSED)); + + uint64_t newAttemptFails; + uint64_t newActiveOpens; + uint64_t newOutRsts; + snmp = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/net/snmp")); + newActiveOpens = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "ActiveOpens")); + newOutRsts = + ASSERT_NO_ERRNO_AND_VALUE(GetSNMPMetricFromProc(snmp, "Tcp", "OutRsts")); + newAttemptFails = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "AttemptFails")); + + EXPECT_EQ(oldActiveOpens, newActiveOpens - 1); + EXPECT_EQ(oldOutRsts, newOutRsts - 1); + EXPECT_EQ(oldAttemptFails, newAttemptFails - 1); +} + +TEST(ProcNetSnmp, TcpEstab_NoRandomSave) { + // TODO(gvisor.dev/issue/866): epsocket metrics are not savable. + DisableSave ds; + + uint64_t oldEstabResets; + uint64_t oldActiveOpens; + uint64_t oldPassiveOpens; + uint64_t oldCurrEstab; + auto snmp = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/net/snmp")); + oldActiveOpens = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "ActiveOpens")); + oldPassiveOpens = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "PassiveOpens")); + oldCurrEstab = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "CurrEstab")); + oldEstabResets = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "EstabResets")); + + FileDescriptor s_listen = + ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_STREAM, 0)); + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_port = 0, + }; + + ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &(sin.sin_addr)), 1); + ASSERT_THAT(bind(s_listen.get(), (struct sockaddr *)&sin, sizeof(sin)), + SyscallSucceeds()); + ASSERT_THAT(listen(s_listen.get(), 1), SyscallSucceeds()); + + // Get the port bound by the listening socket. + socklen_t addrlen = sizeof(sin); + ASSERT_THAT( + getsockname(s_listen.get(), reinterpret_cast<sockaddr *>(&sin), &addrlen), + SyscallSucceeds()); + + FileDescriptor s_connect = + ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_STREAM, 0)); + ASSERT_THAT(connect(s_connect.get(), (struct sockaddr *)&sin, sizeof(sin)), + SyscallSucceeds()); + + auto s_accept = + ASSERT_NO_ERRNO_AND_VALUE(Accept(s_listen.get(), nullptr, nullptr)); + + uint64_t newEstabResets; + uint64_t newActiveOpens; + uint64_t newPassiveOpens; + uint64_t newCurrEstab; + snmp = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/net/snmp")); + newActiveOpens = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "ActiveOpens")); + newPassiveOpens = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "PassiveOpens")); + newCurrEstab = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "CurrEstab")); + + EXPECT_EQ(oldActiveOpens, newActiveOpens - 1); + EXPECT_EQ(oldPassiveOpens, newPassiveOpens - 1); + EXPECT_EQ(oldCurrEstab, newCurrEstab - 2); + + // Send 1 byte from client to server. + ASSERT_THAT(send(s_connect.get(), "a", 1, 0), SyscallSucceedsWithValue(1)); + + constexpr int kPollTimeoutMs = 20000; // Wait up to 20 seconds for the data. + + // Wait until server-side fd sees the data on its side but don't read it. + struct pollfd poll_fd = {s_accept.get(), POLLIN, 0}; + ASSERT_THAT(RetryEINTR(poll)(&poll_fd, 1, kPollTimeoutMs), + SyscallSucceedsWithValue(1)); + + // Now close server-side fd without reading the data which leads to a RST + // packet sent to client side. + s_accept.reset(-1); + + // Wait until client-side fd sees RST packet. + struct pollfd poll_fd1 = {s_connect.get(), POLLIN, 0}; + ASSERT_THAT(RetryEINTR(poll)(&poll_fd1, 1, kPollTimeoutMs), + SyscallSucceedsWithValue(1)); + + // Now close client-side fd. + s_connect.reset(-1); + + // Wait until the process of the netstack. + absl::SleepFor(absl::Seconds(1)); + + snmp = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/net/snmp")); + newCurrEstab = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "CurrEstab")); + newEstabResets = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Tcp", "EstabResets")); + + EXPECT_EQ(oldCurrEstab, newCurrEstab); + EXPECT_EQ(oldEstabResets, newEstabResets - 2); +} + +TEST(ProcNetSnmp, UdpNoPorts_NoRandomSave) { + // TODO(gvisor.dev/issue/866): epsocket metrics are not savable. + DisableSave ds; + + uint64_t oldOutDatagrams; + uint64_t oldNoPorts; + auto snmp = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/net/snmp")); + oldOutDatagrams = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Udp", "OutDatagrams")); + oldNoPorts = + ASSERT_NO_ERRNO_AND_VALUE(GetSNMPMetricFromProc(snmp, "Udp", "NoPorts")); + + FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0)); + + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_port = htons(4444), + }; + ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &(sin.sin_addr)), 1); + ASSERT_THAT(sendto(s.get(), "a", 1, 0, (struct sockaddr *)&sin, sizeof(sin)), + SyscallSucceedsWithValue(1)); + + uint64_t newOutDatagrams; + uint64_t newNoPorts; + snmp = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/net/snmp")); + newOutDatagrams = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Udp", "OutDatagrams")); + newNoPorts = + ASSERT_NO_ERRNO_AND_VALUE(GetSNMPMetricFromProc(snmp, "Udp", "NoPorts")); + + EXPECT_EQ(oldOutDatagrams, newOutDatagrams - 1); + EXPECT_EQ(oldNoPorts, newNoPorts - 1); +} + +TEST(ProcNetSnmp, UdpIn) { + // TODO(gvisor.dev/issue/866): epsocket metrics are not savable. + const DisableSave ds; + + uint64_t oldOutDatagrams; + uint64_t oldInDatagrams; + auto snmp = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/net/snmp")); + oldOutDatagrams = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Udp", "OutDatagrams")); + oldInDatagrams = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Udp", "InDatagrams")); + + std::cerr << "snmp: " << std::endl << snmp << std::endl; + FileDescriptor server = + ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0)); + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_port = htons(0), + }; + ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &(sin.sin_addr)), 1); + ASSERT_THAT(bind(server.get(), (struct sockaddr *)&sin, sizeof(sin)), + SyscallSucceeds()); + // Get the port bound by the server socket. + socklen_t addrlen = sizeof(sin); + ASSERT_THAT( + getsockname(server.get(), reinterpret_cast<sockaddr *>(&sin), &addrlen), + SyscallSucceeds()); + + FileDescriptor client = + ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0)); + ASSERT_THAT( + sendto(client.get(), "a", 1, 0, (struct sockaddr *)&sin, sizeof(sin)), + SyscallSucceedsWithValue(1)); + + char buf[128]; + ASSERT_THAT(recvfrom(server.get(), buf, sizeof(buf), 0, NULL, NULL), + SyscallSucceedsWithValue(1)); + + uint64_t newOutDatagrams; + uint64_t newInDatagrams; + snmp = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/net/snmp")); + std::cerr << "new snmp: " << std::endl << snmp << std::endl; + newOutDatagrams = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Udp", "OutDatagrams")); + newInDatagrams = ASSERT_NO_ERRNO_AND_VALUE( + GetSNMPMetricFromProc(snmp, "Udp", "InDatagrams")); + + EXPECT_EQ(oldOutDatagrams, newOutDatagrams - 1); + EXPECT_EQ(oldInDatagrams, newInDatagrams - 1); +} + } // namespace } // namespace testing } // namespace gvisor diff --git a/test/syscalls/linux/proc_net_tcp.cc b/test/syscalls/linux/proc_net_tcp.cc index f61795592..2659f6a98 100644 --- a/test/syscalls/linux/proc_net_tcp.cc +++ b/test/syscalls/linux/proc_net_tcp.cc @@ -18,7 +18,6 @@ #include <unistd.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/numbers.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" diff --git a/test/syscalls/linux/proc_net_udp.cc b/test/syscalls/linux/proc_net_udp.cc index 369df8e0e..f06f1a24b 100644 --- a/test/syscalls/linux/proc_net_udp.cc +++ b/test/syscalls/linux/proc_net_udp.cc @@ -18,7 +18,6 @@ #include <unistd.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/numbers.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" diff --git a/test/syscalls/linux/proc_net_unix.cc b/test/syscalls/linux/proc_net_unix.cc index 83dbd1364..66db0acaa 100644 --- a/test/syscalls/linux/proc_net_unix.cc +++ b/test/syscalls/linux/proc_net_unix.cc @@ -13,7 +13,6 @@ // limitations under the License. #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/numbers.h" #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" diff --git a/test/syscalls/linux/pwrite64.cc b/test/syscalls/linux/pwrite64.cc index e1603fc2d..b48fe540d 100644 --- a/test/syscalls/linux/pwrite64.cc +++ b/test/syscalls/linux/pwrite64.cc @@ -19,7 +19,6 @@ #include <unistd.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/util/temp_path.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/pwritev2.cc b/test/syscalls/linux/pwritev2.cc index f6a0fc96c..1dbc0d6df 100644 --- a/test/syscalls/linux/pwritev2.cc +++ b/test/syscalls/linux/pwritev2.cc @@ -21,7 +21,6 @@ #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/file_base.h" #include "test/util/file_descriptor.h" #include "test/util/temp_path.h" diff --git a/test/syscalls/linux/readv.cc b/test/syscalls/linux/readv.cc index f327ec3a9..4069cbc7e 100644 --- a/test/syscalls/linux/readv.cc +++ b/test/syscalls/linux/readv.cc @@ -19,7 +19,6 @@ #include <unistd.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/file_base.h" #include "test/syscalls/linux/readv_common.h" #include "test/util/file_descriptor.h" diff --git a/test/syscalls/linux/readv_common.cc b/test/syscalls/linux/readv_common.cc index 35d2dd9e3..9658f7d42 100644 --- a/test/syscalls/linux/readv_common.cc +++ b/test/syscalls/linux/readv_common.cc @@ -19,7 +19,6 @@ #include <unistd.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/file_base.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/readv_socket.cc b/test/syscalls/linux/readv_socket.cc index 3c315cc02..9b6972201 100644 --- a/test/syscalls/linux/readv_socket.cc +++ b/test/syscalls/linux/readv_socket.cc @@ -19,7 +19,6 @@ #include <unistd.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/file_base.h" #include "test/syscalls/linux/readv_common.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/rename.cc b/test/syscalls/linux/rename.cc index c9d76c2e2..5b474ff32 100644 --- a/test/syscalls/linux/rename.cc +++ b/test/syscalls/linux/rename.cc @@ -17,7 +17,6 @@ #include <string> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/string_view.h" #include "test/util/capability_util.h" #include "test/util/cleanup.h" diff --git a/test/syscalls/linux/select.cc b/test/syscalls/linux/select.cc index 88c010aec..e06a2666d 100644 --- a/test/syscalls/linux/select.cc +++ b/test/syscalls/linux/select.cc @@ -21,7 +21,6 @@ #include <cstdio> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/time/time.h" #include "test/syscalls/linux/base_poll_test.h" #include "test/util/file_descriptor.h" diff --git a/test/syscalls/linux/sendfile_socket.cc b/test/syscalls/linux/sendfile_socket.cc index 1c56540bc..3331288b7 100644 --- a/test/syscalls/linux/sendfile_socket.cc +++ b/test/syscalls/linux/sendfile_socket.cc @@ -185,7 +185,7 @@ TEST_P(SendFileTest, Shutdown) { // Create a socket. std::tuple<int, int> fds = ASSERT_NO_ERRNO_AND_VALUE(Sockets()); const FileDescriptor client(std::get<0>(fds)); - FileDescriptor server(std::get<1>(fds)); // non-const, released below. + FileDescriptor server(std::get<1>(fds)); // non-const, reset below. // If this is a TCP socket, then turn off linger. if (GetParam() == AF_INET) { @@ -210,14 +210,14 @@ TEST_P(SendFileTest, Shutdown) { // checking the contents (other tests do that), so we just re-use the same // buffer as above. ScopedThread t([&]() { - int done = 0; + size_t done = 0; while (done < data.size()) { - int n = read(server.get(), data.data(), data.size()); + int n = RetryEINTR(read)(server.get(), data.data(), data.size()); ASSERT_THAT(n, SyscallSucceeds()); done += n; } // Close the server side socket. - ASSERT_THAT(close(server.release()), SyscallSucceeds()); + server.reset(); }); // Continuously stream from the file to the socket. Note we do not assert diff --git a/test/syscalls/linux/sigaltstack.cc b/test/syscalls/linux/sigaltstack.cc index 69b6e4f90..6fd3989a4 100644 --- a/test/syscalls/linux/sigaltstack.cc +++ b/test/syscalls/linux/sigaltstack.cc @@ -22,7 +22,6 @@ #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/util/cleanup.h" #include "test/util/fs_util.h" #include "test/util/multiprocess_util.h" diff --git a/test/syscalls/linux/signalfd.cc b/test/syscalls/linux/signalfd.cc index 9379d5878..09ecad34a 100644 --- a/test/syscalls/linux/signalfd.cc +++ b/test/syscalls/linux/signalfd.cc @@ -24,7 +24,6 @@ #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/synchronization/mutex.h" #include "test/util/file_descriptor.h" #include "test/util/posix_error.h" diff --git a/test/syscalls/linux/socket_bind_to_device.cc b/test/syscalls/linux/socket_bind_to_device.cc index d20821cac..6b27f6eab 100644 --- a/test/syscalls/linux/socket_bind_to_device.cc +++ b/test/syscalls/linux/socket_bind_to_device.cc @@ -32,7 +32,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/ip_socket_test_util.h" #include "test/syscalls/linux/socket_bind_to_device_util.h" #include "test/syscalls/linux/socket_test_util.h" diff --git a/test/syscalls/linux/socket_bind_to_device_distribution.cc b/test/syscalls/linux/socket_bind_to_device_distribution.cc index 4d2400328..5767181a1 100644 --- a/test/syscalls/linux/socket_bind_to_device_distribution.cc +++ b/test/syscalls/linux/socket_bind_to_device_distribution.cc @@ -33,7 +33,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/ip_socket_test_util.h" #include "test/syscalls/linux/socket_bind_to_device_util.h" #include "test/syscalls/linux/socket_test_util.h" diff --git a/test/syscalls/linux/socket_bind_to_device_sequence.cc b/test/syscalls/linux/socket_bind_to_device_sequence.cc index a7365d139..e4641c62e 100644 --- a/test/syscalls/linux/socket_bind_to_device_sequence.cc +++ b/test/syscalls/linux/socket_bind_to_device_sequence.cc @@ -33,7 +33,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/ip_socket_test_util.h" #include "test/syscalls/linux/socket_bind_to_device_util.h" #include "test/syscalls/linux/socket_test_util.h" diff --git a/test/syscalls/linux/socket_blocking.cc b/test/syscalls/linux/socket_blocking.cc index 00c50d1bf..d7ce57566 100644 --- a/test/syscalls/linux/socket_blocking.cc +++ b/test/syscalls/linux/socket_blocking.cc @@ -20,7 +20,6 @@ #include <cstdio> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "test/syscalls/linux/socket_test_util.h" diff --git a/test/syscalls/linux/socket_generic.cc b/test/syscalls/linux/socket_generic.cc index 51d614639..e8f24a59e 100644 --- a/test/syscalls/linux/socket_generic.cc +++ b/test/syscalls/linux/socket_generic.cc @@ -20,7 +20,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "test/syscalls/linux/socket_test_util.h" diff --git a/test/syscalls/linux/socket_inet_loopback.cc b/test/syscalls/linux/socket_inet_loopback.cc index 322ee07ad..ab375aaaf 100644 --- a/test/syscalls/linux/socket_inet_loopback.cc +++ b/test/syscalls/linux/socket_inet_loopback.cc @@ -16,6 +16,7 @@ #include <netinet/in.h> #include <poll.h> #include <string.h> +#include <sys/epoll.h> #include <sys/socket.h> #include <atomic> @@ -516,6 +517,112 @@ TEST_P(SocketInetReusePortTest, UdpPortReuseMultiThread) { EquivalentWithin((kConnectAttempts / kThreadCount), 0.10)); } +TEST_P(SocketInetReusePortTest, UdpPortReuseMultiThreadShort) { + auto const& param = GetParam(); + + TestAddress const& listener = param.listener; + TestAddress const& connector = param.connector; + sockaddr_storage listen_addr = listener.addr; + sockaddr_storage conn_addr = connector.addr; + constexpr int kThreadCount = 3; + + // TODO(b/141211329): endpointsByNic.seed has to be saved/restored. + const DisableSave ds141211329; + + // Create listening sockets. + FileDescriptor listener_fds[kThreadCount]; + for (int i = 0; i < kThreadCount; i++) { + listener_fds[i] = + ASSERT_NO_ERRNO_AND_VALUE(Socket(listener.family(), SOCK_DGRAM, 0)); + int fd = listener_fds[i].get(); + + ASSERT_THAT(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &kSockOptOn, + sizeof(kSockOptOn)), + SyscallSucceeds()); + ASSERT_THAT( + bind(fd, reinterpret_cast<sockaddr*>(&listen_addr), listener.addr_len), + SyscallSucceeds()); + + // On the first bind we need to determine which port was bound. + if (i != 0) { + continue; + } + + // Get the port bound by the listening socket. + socklen_t addrlen = listener.addr_len; + ASSERT_THAT( + getsockname(listener_fds[0].get(), + reinterpret_cast<sockaddr*>(&listen_addr), &addrlen), + SyscallSucceeds()); + uint16_t const port = + ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); + ASSERT_NO_ERRNO(SetAddrPort(listener.family(), &listen_addr, port)); + ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); + } + + constexpr int kConnectAttempts = 10; + FileDescriptor client_fds[kConnectAttempts]; + + // Do the first run without save/restore. + DisableSave ds; + for (int i = 0; i < kConnectAttempts; i++) { + client_fds[i] = + ASSERT_NO_ERRNO_AND_VALUE(Socket(connector.family(), SOCK_DGRAM, 0)); + EXPECT_THAT(RetryEINTR(sendto)(client_fds[i].get(), &i, sizeof(i), 0, + reinterpret_cast<sockaddr*>(&conn_addr), + connector.addr_len), + SyscallSucceedsWithValue(sizeof(i))); + } + ds.reset(); + + // Check that a mapping of client and server sockets has + // not been change after save/restore. + for (int i = 0; i < kConnectAttempts; i++) { + EXPECT_THAT(RetryEINTR(sendto)(client_fds[i].get(), &i, sizeof(i), 0, + reinterpret_cast<sockaddr*>(&conn_addr), + connector.addr_len), + SyscallSucceedsWithValue(sizeof(i))); + } + + int epollfd; + ASSERT_THAT(epollfd = epoll_create1(0), SyscallSucceeds()); + + for (int i = 0; i < kThreadCount; i++) { + int fd = listener_fds[i].get(); + struct epoll_event ev; + ev.data.fd = fd; + ev.events = EPOLLIN; + ASSERT_THAT(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev), SyscallSucceeds()); + } + + std::map<uint16_t, int> portToFD; + + for (int i = 0; i < kConnectAttempts * 2; i++) { + struct sockaddr_storage addr = {}; + socklen_t addrlen = sizeof(addr); + struct epoll_event ev; + int data, fd; + + ASSERT_THAT(epoll_wait(epollfd, &ev, 1, -1), SyscallSucceedsWithValue(1)); + + fd = ev.data.fd; + EXPECT_THAT(RetryEINTR(recvfrom)(fd, &data, sizeof(data), 0, + reinterpret_cast<struct sockaddr*>(&addr), + &addrlen), + SyscallSucceedsWithValue(sizeof(data))); + uint16_t const port = + ASSERT_NO_ERRNO_AND_VALUE(AddrPort(connector.family(), addr)); + auto prev_port = portToFD.find(port); + // Check that all packets from one client have been delivered to the same + // server socket. + if (prev_port == portToFD.end()) { + portToFD[port] = ev.data.fd; + } else { + EXPECT_EQ(portToFD[port], ev.data.fd); + } + } +} + INSTANTIATE_TEST_SUITE_P( All, SocketInetReusePortTest, ::testing::Values( diff --git a/test/syscalls/linux/socket_ip_tcp_generic.cc b/test/syscalls/linux/socket_ip_tcp_generic.cc index bfa7943b1..592448289 100644 --- a/test/syscalls/linux/socket_ip_tcp_generic.cc +++ b/test/syscalls/linux/socket_ip_tcp_generic.cc @@ -24,14 +24,13 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/util/test_util.h" namespace gvisor { namespace testing { -TEST_P(TCPSocketPairTest, TcpInfoSucceedes) { +TEST_P(TCPSocketPairTest, TcpInfoSucceeds) { auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); struct tcp_info opt = {}; @@ -40,7 +39,7 @@ TEST_P(TCPSocketPairTest, TcpInfoSucceedes) { SyscallSucceeds()); } -TEST_P(TCPSocketPairTest, ShortTcpInfoSucceedes) { +TEST_P(TCPSocketPairTest, ShortTcpInfoSucceeds) { auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); struct tcp_info opt = {}; @@ -49,7 +48,7 @@ TEST_P(TCPSocketPairTest, ShortTcpInfoSucceedes) { SyscallSucceeds()); } -TEST_P(TCPSocketPairTest, ZeroTcpInfoSucceedes) { +TEST_P(TCPSocketPairTest, ZeroTcpInfoSucceeds) { auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); struct tcp_info opt = {}; diff --git a/test/syscalls/linux/socket_ip_tcp_udp_generic.cc b/test/syscalls/linux/socket_ip_tcp_udp_generic.cc index de63f79d9..f178f1af9 100644 --- a/test/syscalls/linux/socket_ip_tcp_udp_generic.cc +++ b/test/syscalls/linux/socket_ip_tcp_udp_generic.cc @@ -22,7 +22,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/ip_socket_test_util.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_ip_udp_generic.cc b/test/syscalls/linux/socket_ip_udp_generic.cc index 044394ba7..2a4ed04a5 100644 --- a/test/syscalls/linux/socket_ip_udp_generic.cc +++ b/test/syscalls/linux/socket_ip_udp_generic.cc @@ -24,7 +24,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_ip_unbound.cc b/test/syscalls/linux/socket_ip_unbound.cc index fa9a9df6f..b02872308 100644 --- a/test/syscalls/linux/socket_ip_unbound.cc +++ b/test/syscalls/linux/socket_ip_unbound.cc @@ -23,7 +23,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/ip_socket_test_util.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_ipv4_tcp_unbound_external_networking.cc b/test/syscalls/linux/socket_ipv4_tcp_unbound_external_networking.cc index 3a068aacf..3c3712b50 100644 --- a/test/syscalls/linux/socket_ipv4_tcp_unbound_external_networking.cc +++ b/test/syscalls/linux/socket_ipv4_tcp_unbound_external_networking.cc @@ -23,7 +23,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_ipv4_udp_unbound.cc b/test/syscalls/linux/socket_ipv4_udp_unbound.cc index 67d29af0a..b828b6844 100644 --- a/test/syscalls/linux/socket_ipv4_udp_unbound.cc +++ b/test/syscalls/linux/socket_ipv4_udp_unbound.cc @@ -21,7 +21,6 @@ #include <cstdio> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/ip_socket_test_util.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.cc b/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.cc index 8b8993d3d..98ae414f3 100644 --- a/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.cc +++ b/test/syscalls/linux/socket_ipv4_udp_unbound_external_networking.cc @@ -27,7 +27,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/ip_socket_test_util.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_non_blocking.cc b/test/syscalls/linux/socket_non_blocking.cc index 73e6dc618..c3520cadd 100644 --- a/test/syscalls/linux/socket_non_blocking.cc +++ b/test/syscalls/linux/socket_non_blocking.cc @@ -20,7 +20,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_non_stream.cc b/test/syscalls/linux/socket_non_stream.cc index 3c599b6e8..d91c5ed39 100644 --- a/test/syscalls/linux/socket_non_stream.cc +++ b/test/syscalls/linux/socket_non_stream.cc @@ -19,7 +19,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/ip_socket_test_util.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" diff --git a/test/syscalls/linux/socket_non_stream_blocking.cc b/test/syscalls/linux/socket_non_stream_blocking.cc index 76127d181..62d87c1af 100644 --- a/test/syscalls/linux/socket_non_stream_blocking.cc +++ b/test/syscalls/linux/socket_non_stream_blocking.cc @@ -20,7 +20,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "test/syscalls/linux/socket_test_util.h" diff --git a/test/syscalls/linux/socket_stream.cc b/test/syscalls/linux/socket_stream.cc index 0417dd347..346443f96 100644 --- a/test/syscalls/linux/socket_stream.cc +++ b/test/syscalls/linux/socket_stream.cc @@ -20,7 +20,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/time/clock.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" diff --git a/test/syscalls/linux/socket_stream_blocking.cc b/test/syscalls/linux/socket_stream_blocking.cc index 8367460d2..e9cc082bf 100644 --- a/test/syscalls/linux/socket_stream_blocking.cc +++ b/test/syscalls/linux/socket_stream_blocking.cc @@ -20,7 +20,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "test/syscalls/linux/socket_test_util.h" diff --git a/test/syscalls/linux/socket_stream_nonblock.cc b/test/syscalls/linux/socket_stream_nonblock.cc index b00748b97..74d608741 100644 --- a/test/syscalls/linux/socket_stream_nonblock.cc +++ b/test/syscalls/linux/socket_stream_nonblock.cc @@ -20,7 +20,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_test_util.h b/test/syscalls/linux/socket_test_util.h index 70710195c..be38907c2 100644 --- a/test/syscalls/linux/socket_test_util.h +++ b/test/syscalls/linux/socket_test_util.h @@ -30,7 +30,6 @@ #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/str_format.h" #include "test/util/file_descriptor.h" #include "test/util/posix_error.h" diff --git a/test/syscalls/linux/socket_unix.cc b/test/syscalls/linux/socket_unix.cc index 875f0391f..8a28202a8 100644 --- a/test/syscalls/linux/socket_unix.cc +++ b/test/syscalls/linux/socket_unix.cc @@ -25,7 +25,6 @@ #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/string_view.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" diff --git a/test/syscalls/linux/socket_unix_cmsg.cc b/test/syscalls/linux/socket_unix_cmsg.cc index 1092e29b1..1159c5229 100644 --- a/test/syscalls/linux/socket_unix_cmsg.cc +++ b/test/syscalls/linux/socket_unix_cmsg.cc @@ -25,7 +25,6 @@ #include <vector> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/string_view.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" diff --git a/test/syscalls/linux/socket_unix_dgram.cc b/test/syscalls/linux/socket_unix_dgram.cc index 3e0f611d2..3245cf7c9 100644 --- a/test/syscalls/linux/socket_unix_dgram.cc +++ b/test/syscalls/linux/socket_unix_dgram.cc @@ -17,7 +17,6 @@ #include <stdio.h> #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_unix_dgram_non_blocking.cc b/test/syscalls/linux/socket_unix_dgram_non_blocking.cc index 707052af8..cd4fba25c 100644 --- a/test/syscalls/linux/socket_unix_dgram_non_blocking.cc +++ b/test/syscalls/linux/socket_unix_dgram_non_blocking.cc @@ -15,7 +15,6 @@ #include <stdio.h> #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_unix_non_stream.cc b/test/syscalls/linux/socket_unix_non_stream.cc index b5c82cd67..276a94eb8 100644 --- a/test/syscalls/linux/socket_unix_non_stream.cc +++ b/test/syscalls/linux/socket_unix_non_stream.cc @@ -19,7 +19,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/memory_util.h" diff --git a/test/syscalls/linux/socket_unix_seqpacket.cc b/test/syscalls/linux/socket_unix_seqpacket.cc index 6f6367dd5..60fa9e38a 100644 --- a/test/syscalls/linux/socket_unix_seqpacket.cc +++ b/test/syscalls/linux/socket_unix_seqpacket.cc @@ -17,7 +17,6 @@ #include <stdio.h> #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_unix_stream.cc b/test/syscalls/linux/socket_unix_stream.cc index 8f38ed92f..563467365 100644 --- a/test/syscalls/linux/socket_unix_stream.cc +++ b/test/syscalls/linux/socket_unix_stream.cc @@ -17,7 +17,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_unix_unbound_abstract.cc b/test/syscalls/linux/socket_unix_unbound_abstract.cc index 4b5832de8..7f5816ace 100644 --- a/test/syscalls/linux/socket_unix_unbound_abstract.cc +++ b/test/syscalls/linux/socket_unix_unbound_abstract.cc @@ -15,7 +15,6 @@ #include <stdio.h> #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_unix_unbound_dgram.cc b/test/syscalls/linux/socket_unix_unbound_dgram.cc index 52aef891f..907dca0f1 100644 --- a/test/syscalls/linux/socket_unix_unbound_dgram.cc +++ b/test/syscalls/linux/socket_unix_unbound_dgram.cc @@ -17,7 +17,6 @@ #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_unix_unbound_filesystem.cc b/test/syscalls/linux/socket_unix_unbound_filesystem.cc index 8cb03c450..b14f24086 100644 --- a/test/syscalls/linux/socket_unix_unbound_filesystem.cc +++ b/test/syscalls/linux/socket_unix_unbound_filesystem.cc @@ -15,7 +15,6 @@ #include <stdio.h> #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_unix_unbound_seqpacket.cc b/test/syscalls/linux/socket_unix_unbound_seqpacket.cc index 0575f2e1d..50ffa1d04 100644 --- a/test/syscalls/linux/socket_unix_unbound_seqpacket.cc +++ b/test/syscalls/linux/socket_unix_unbound_seqpacket.cc @@ -15,7 +15,6 @@ #include <stdio.h> #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/socket_unix_unbound_stream.cc b/test/syscalls/linux/socket_unix_unbound_stream.cc index e483d2777..344918c34 100644 --- a/test/syscalls/linux/socket_unix_unbound_stream.cc +++ b/test/syscalls/linux/socket_unix_unbound_stream.cc @@ -15,7 +15,6 @@ #include <stdio.h> #include <sys/un.h> #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" #include "test/util/test_util.h" diff --git a/test/syscalls/linux/stat.cc b/test/syscalls/linux/stat.cc index 88ab90b5b..30de2f8ff 100644 --- a/test/syscalls/linux/stat.cc +++ b/test/syscalls/linux/stat.cc @@ -24,7 +24,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "gtest/gtest.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" diff --git a/test/syscalls/linux/tcp_socket.cc b/test/syscalls/linux/tcp_socket.cc index bfa031bce..277d6835a 100644 --- a/test/syscalls/linux/tcp_socket.cc +++ b/test/syscalls/linux/tcp_socket.cc @@ -394,8 +394,15 @@ TEST_P(TcpSocketTest, PollWithFullBufferBlocks) { sizeof(tcp_nodelay_flag)), SyscallSucceeds()); + // Set a 256KB send/receive buffer. + int buf_sz = 1 << 18; + EXPECT_THAT(setsockopt(t_, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)), + SyscallSucceedsWithValue(0)); + EXPECT_THAT(setsockopt(s_, SOL_SOCKET, SO_SNDBUF, &buf_sz, sizeof(buf_sz)), + SyscallSucceedsWithValue(0)); + // Create a large buffer that will be used for sending. - std::vector<char> buf(10 * sendbuf_size_); + std::vector<char> buf(1 << 16); // Write until we receive an error. while (RetryEINTR(send)(s_, buf.data(), buf.size(), 0) != -1) { diff --git a/test/util/multiprocess_util.h b/test/util/multiprocess_util.h index c413d63ea..61526b4e7 100644 --- a/test/util/multiprocess_util.h +++ b/test/util/multiprocess_util.h @@ -109,6 +109,15 @@ PosixErrorOr<Cleanup> ForkAndExecveat(int32_t dirfd, const std::string& pathname 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. // |