diff options
Diffstat (limited to 'test/syscalls')
-rw-r--r-- | test/syscalls/linux/mkdir.cc | 33 | ||||
-rw-r--r-- | test/syscalls/linux/splice.cc | 106 |
2 files changed, 139 insertions, 0 deletions
diff --git a/test/syscalls/linux/mkdir.cc b/test/syscalls/linux/mkdir.cc index 27758203d..11fbfa5c5 100644 --- a/test/syscalls/linux/mkdir.cc +++ b/test/syscalls/linux/mkdir.cc @@ -82,6 +82,39 @@ TEST_F(MkdirTest, FailsOnDirWithoutWritePerms) { SyscallFailsWithErrno(EACCES)); } +TEST_F(MkdirTest, DirAlreadyExists) { + // Drop capabilities that allow us to override file and directory permissions. + ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false)); + ASSERT_NO_ERRNO(SetCapability(CAP_DAC_READ_SEARCH, false)); + + ASSERT_THAT(mkdir(dirname_.c_str(), 0777), SyscallSucceeds()); + auto dir = JoinPath(dirname_.c_str(), "foo"); + EXPECT_THAT(mkdir(dir.c_str(), 0777), SyscallSucceeds()); + + struct { + int mode; + int err; + } tests[] = { + {.mode = 0000, .err = EACCES}, // No perm + {.mode = 0100, .err = EEXIST}, // Exec only + {.mode = 0200, .err = EACCES}, // Write only + {.mode = 0300, .err = EEXIST}, // Write+exec + {.mode = 0400, .err = EACCES}, // Read only + {.mode = 0500, .err = EEXIST}, // Read+exec + {.mode = 0600, .err = EACCES}, // Read+write + {.mode = 0700, .err = EEXIST}, // All + }; + for (const auto& t : tests) { + printf("mode: 0%o\n", t.mode); + EXPECT_THAT(chmod(dirname_.c_str(), t.mode), SyscallSucceeds()); + EXPECT_THAT(mkdir(dir.c_str(), 0777), SyscallFailsWithErrno(t.err)); + } + + // Clean up. + EXPECT_THAT(chmod(dirname_.c_str(), 0777), SyscallSucceeds()); + ASSERT_THAT(rmdir(dir.c_str()), SyscallSucceeds()); +} + TEST_F(MkdirTest, MkdirAtEmptyPath) { ASSERT_THAT(mkdir(dirname_.c_str(), 0777), SyscallSucceeds()); auto fd = diff --git a/test/syscalls/linux/splice.cc b/test/syscalls/linux/splice.cc index c2369db54..e5730a606 100644 --- a/test/syscalls/linux/splice.cc +++ b/test/syscalls/linux/splice.cc @@ -483,6 +483,112 @@ TEST(SpliceTest, TwoPipes) { EXPECT_EQ(memcmp(rbuf.data(), buf.data(), kPageSize), 0); } +TEST(SpliceTest, TwoPipesPartialRead) { + // Create two pipes. + int fds[2]; + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + const FileDescriptor first_rfd(fds[0]); + const FileDescriptor first_wfd(fds[1]); + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + const FileDescriptor second_rfd(fds[0]); + const FileDescriptor second_wfd(fds[1]); + + // Write half a page of data to the first pipe. + std::vector<char> buf(kPageSize / 2); + RandomizeBuffer(buf.data(), buf.size()); + ASSERT_THAT(write(first_wfd.get(), buf.data(), buf.size()), + SyscallSucceedsWithValue(kPageSize / 2)); + + // Attempt to splice one page from the first pipe to the second; it should + // immediately return after splicing the half-page previously written to the + // first pipe. + EXPECT_THAT( + splice(first_rfd.get(), nullptr, second_wfd.get(), nullptr, kPageSize, 0), + SyscallSucceedsWithValue(kPageSize / 2)); +} + +TEST(SpliceTest, TwoPipesPartialWrite) { + // Create two pipes. + int fds[2]; + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + const FileDescriptor first_rfd(fds[0]); + const FileDescriptor first_wfd(fds[1]); + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + const FileDescriptor second_rfd(fds[0]); + const FileDescriptor second_wfd(fds[1]); + + // Write two pages of data to the first pipe. + std::vector<char> buf(2 * kPageSize); + RandomizeBuffer(buf.data(), buf.size()); + ASSERT_THAT(write(first_wfd.get(), buf.data(), buf.size()), + SyscallSucceedsWithValue(2 * kPageSize)); + + // Limit the second pipe to two pages, then write one page of data to it. + ASSERT_THAT(fcntl(second_wfd.get(), F_SETPIPE_SZ, 2 * kPageSize), + SyscallSucceeds()); + ASSERT_THAT(write(second_wfd.get(), buf.data(), buf.size() / 2), + SyscallSucceedsWithValue(kPageSize)); + + // Attempt to splice two pages from the first pipe to the second; it should + // immediately return after splicing the first page previously written to the + // first pipe. + EXPECT_THAT(splice(first_rfd.get(), nullptr, second_wfd.get(), nullptr, + 2 * kPageSize, 0), + SyscallSucceedsWithValue(kPageSize)); +} + +TEST(TeeTest, TwoPipesPartialRead) { + // Create two pipes. + int fds[2]; + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + const FileDescriptor first_rfd(fds[0]); + const FileDescriptor first_wfd(fds[1]); + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + const FileDescriptor second_rfd(fds[0]); + const FileDescriptor second_wfd(fds[1]); + + // Write half a page of data to the first pipe. + std::vector<char> buf(kPageSize / 2); + RandomizeBuffer(buf.data(), buf.size()); + ASSERT_THAT(write(first_wfd.get(), buf.data(), buf.size()), + SyscallSucceedsWithValue(kPageSize / 2)); + + // Attempt to tee one page from the first pipe to the second; it should + // immediately return after copying the half-page previously written to the + // first pipe. + EXPECT_THAT(tee(first_rfd.get(), second_wfd.get(), kPageSize, 0), + SyscallSucceedsWithValue(kPageSize / 2)); +} + +TEST(TeeTest, TwoPipesPartialWrite) { + // Create two pipes. + int fds[2]; + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + const FileDescriptor first_rfd(fds[0]); + const FileDescriptor first_wfd(fds[1]); + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + const FileDescriptor second_rfd(fds[0]); + const FileDescriptor second_wfd(fds[1]); + + // Write two pages of data to the first pipe. + std::vector<char> buf(2 * kPageSize); + RandomizeBuffer(buf.data(), buf.size()); + ASSERT_THAT(write(first_wfd.get(), buf.data(), buf.size()), + SyscallSucceedsWithValue(2 * kPageSize)); + + // Limit the second pipe to two pages, then write one page of data to it. + ASSERT_THAT(fcntl(second_wfd.get(), F_SETPIPE_SZ, 2 * kPageSize), + SyscallSucceeds()); + ASSERT_THAT(write(second_wfd.get(), buf.data(), buf.size() / 2), + SyscallSucceedsWithValue(kPageSize)); + + // Attempt to tee two pages from the first pipe to the second; it should + // immediately return after copying the first page previously written to the + // first pipe. + EXPECT_THAT(tee(first_rfd.get(), second_wfd.get(), 2 * kPageSize, 0), + SyscallSucceedsWithValue(kPageSize)); +} + TEST(SpliceTest, TwoPipesCircular) { // This test deadlocks the sentry on VFS1 because VFS1 splice ordering is // based on fs.File.UniqueID, which does not prevent circular ordering between |