diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/syscalls/linux/BUILD | 3 | ||||
-rw-r--r-- | test/syscalls/linux/socket_generic.cc | 2 | ||||
-rw-r--r-- | test/syscalls/linux/socket_unix_dgram.cc | 35 | ||||
-rw-r--r-- | test/syscalls/linux/socket_unix_seqpacket.cc | 35 | ||||
-rw-r--r-- | test/syscalls/linux/socket_unix_stream.cc | 80 |
5 files changed, 154 insertions, 1 deletions
diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index 499027e7c..42fc363a2 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -2346,6 +2346,7 @@ cc_library( deps = [ ":socket_test_util", ":unix_domain_socket_test_util", + "@com_google_absl//absl/time", gtest, "//test/util:test_util", ], @@ -2360,6 +2361,7 @@ cc_library( deps = [ ":socket_test_util", ":unix_domain_socket_test_util", + "@com_google_absl//absl/time", gtest, "//test/util:test_util", ], @@ -2678,6 +2680,7 @@ cc_binary( deps = [ ":socket_test_util", ":unix_domain_socket_test_util", + "@com_google_absl//absl/time", gtest, "//test/util:test_main", "//test/util:test_util", diff --git a/test/syscalls/linux/socket_generic.cc b/test/syscalls/linux/socket_generic.cc index de0b8bb11..f70047a09 100644 --- a/test/syscalls/linux/socket_generic.cc +++ b/test/syscalls/linux/socket_generic.cc @@ -379,7 +379,7 @@ TEST_P(AllSocketPairTest, RcvBufSucceeds) { EXPECT_GT(size, 0); } -TEST_P(AllSocketPairTest, SndBufSucceeds) { +TEST_P(AllSocketPairTest, GetSndBufSucceeds) { auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); int size = 0; socklen_t size_size = sizeof(size); diff --git a/test/syscalls/linux/socket_unix_dgram.cc b/test/syscalls/linux/socket_unix_dgram.cc index af0df4fb4..5b0844493 100644 --- a/test/syscalls/linux/socket_unix_dgram.cc +++ b/test/syscalls/linux/socket_unix_dgram.cc @@ -18,6 +18,8 @@ #include <sys/un.h> #include "gtest/gtest.h" +#include "absl/time/clock.h" +#include "absl/time/time.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" @@ -39,6 +41,39 @@ TEST_P(DgramUnixSocketPairTest, WriteOneSideClosed) { SyscallFailsWithErrno(ECONNREFUSED)); } +TEST_P(DgramUnixSocketPairTest, IncreasedSocketSendBufUnblocksWrites) { + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + int sock = sockets->first_fd(); + int buf_size = 0; + socklen_t buf_size_len = sizeof(buf_size); + ASSERT_THAT(getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buf_size, &buf_size_len), + SyscallSucceeds()); + int opts; + ASSERT_THAT(opts = fcntl(sock, F_GETFL), SyscallSucceeds()); + opts |= O_NONBLOCK; + ASSERT_THAT(fcntl(sock, F_SETFL, opts), SyscallSucceeds()); + + std::vector<char> buf(buf_size / 4); + // Write till the socket buffer is full. + while (RetryEINTR(send)(sock, buf.data(), buf.size(), 0) != -1) { + // Sleep to give linux a chance to move data from the send buffer to the + // receive buffer. + absl::SleepFor(absl::Milliseconds(10)); // 10ms. + } + // The last error should have been EWOULDBLOCK. + ASSERT_EQ(errno, EWOULDBLOCK); + + // Now increase the socket send buffer. + buf_size = buf_size * 2; + ASSERT_THAT( + setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)), + SyscallSucceeds()); + + // The send should succeed again. + ASSERT_THAT(RetryEINTR(send)(sock, buf.data(), buf.size(), 0), + SyscallSucceeds()); +} + } // namespace } // namespace testing diff --git a/test/syscalls/linux/socket_unix_seqpacket.cc b/test/syscalls/linux/socket_unix_seqpacket.cc index 6d03df4d9..eb373373d 100644 --- a/test/syscalls/linux/socket_unix_seqpacket.cc +++ b/test/syscalls/linux/socket_unix_seqpacket.cc @@ -18,6 +18,8 @@ #include <sys/un.h> #include "gtest/gtest.h" +#include "absl/time/clock.h" +#include "absl/time/time.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" @@ -61,6 +63,39 @@ TEST_P(SeqpacketUnixSocketPairTest, Sendto) { SyscallSucceedsWithValue(3)); } +TEST_P(SeqpacketUnixSocketPairTest, IncreasedSocketSendBufUnblocksWrites) { + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + int sock = sockets->first_fd(); + int buf_size = 0; + socklen_t buf_size_len = sizeof(buf_size); + ASSERT_THAT(getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buf_size, &buf_size_len), + SyscallSucceeds()); + int opts; + ASSERT_THAT(opts = fcntl(sock, F_GETFL), SyscallSucceeds()); + opts |= O_NONBLOCK; + ASSERT_THAT(fcntl(sock, F_SETFL, opts), SyscallSucceeds()); + + std::vector<char> buf(buf_size / 4); + // Write till the socket buffer is full. + while (RetryEINTR(send)(sock, buf.data(), buf.size(), 0) != -1) { + // Sleep to give linux a chance to move data from the send buffer to the + // receive buffer. + absl::SleepFor(absl::Milliseconds(10)); // 10ms. + } + // The last error should have been EWOULDBLOCK. + ASSERT_EQ(errno, EWOULDBLOCK); + + // Now increase the socket send buffer. + buf_size = buf_size * 2; + ASSERT_THAT( + setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)), + SyscallSucceeds()); + + // The send should succeed again. + ASSERT_THAT(RetryEINTR(send)(sock, buf.data(), buf.size(), 0), + SyscallSucceeds()); +} + } // namespace } // namespace testing diff --git a/test/syscalls/linux/socket_unix_stream.cc b/test/syscalls/linux/socket_unix_stream.cc index ad9c4bf37..3ff810914 100644 --- a/test/syscalls/linux/socket_unix_stream.cc +++ b/test/syscalls/linux/socket_unix_stream.cc @@ -17,6 +17,8 @@ #include <sys/un.h> #include "gtest/gtest.h" +#include "absl/time/clock.h" +#include "absl/time/time.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" @@ -134,6 +136,84 @@ TEST_P(StreamUnixSocketPairTest, GetSocketAcceptConn) { EXPECT_EQ(got, 0); } +TEST_P(StreamUnixSocketPairTest, SetSocketSendBuf) { + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + auto s = sockets->first_fd(); + int max = 0; + int min = 0; + { + // Discover maxmimum buffer size by setting to a really large value. + constexpr int kRcvBufSz = INT_MAX; + ASSERT_THAT( + setsockopt(s, SOL_SOCKET, SO_SNDBUF, &kRcvBufSz, sizeof(kRcvBufSz)), + SyscallSucceeds()); + + max = 0; + socklen_t max_len = sizeof(max); + ASSERT_THAT(getsockopt(s, SOL_SOCKET, SO_SNDBUF, &max, &max_len), + SyscallSucceeds()); + } + + { + // Discover minimum buffer size by setting it to zero. + constexpr int kRcvBufSz = 0; + ASSERT_THAT( + setsockopt(s, SOL_SOCKET, SO_SNDBUF, &kRcvBufSz, sizeof(kRcvBufSz)), + SyscallSucceeds()); + + socklen_t min_len = sizeof(min); + ASSERT_THAT(getsockopt(s, SOL_SOCKET, SO_SNDBUF, &min, &min_len), + SyscallSucceeds()); + } + + int quarter_sz = min + (max - min) / 4; + ASSERT_THAT( + setsockopt(s, SOL_SOCKET, SO_SNDBUF, &quarter_sz, sizeof(quarter_sz)), + SyscallSucceeds()); + + int val = 0; + socklen_t val_len = sizeof(val); + ASSERT_THAT(getsockopt(s, SOL_SOCKET, SO_SNDBUF, &val, &val_len), + SyscallSucceeds()); + + // Linux doubles the value set by SO_SNDBUF/SO_SNDBUF. + quarter_sz *= 2; + ASSERT_EQ(quarter_sz, val); +} + +TEST_P(StreamUnixSocketPairTest, IncreasedSocketSendBufUnblocksWrites) { + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + int sock = sockets->first_fd(); + int buf_size = 0; + socklen_t buf_size_len = sizeof(buf_size); + ASSERT_THAT(getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buf_size, &buf_size_len), + SyscallSucceeds()); + int opts; + ASSERT_THAT(opts = fcntl(sock, F_GETFL), SyscallSucceeds()); + opts |= O_NONBLOCK; + ASSERT_THAT(fcntl(sock, F_SETFL, opts), SyscallSucceeds()); + + std::vector<char> buf(buf_size / 4); + // Write till the socket buffer is full. + while (RetryEINTR(send)(sock, buf.data(), buf.size(), 0) != -1) { + // Sleep to give linux a chance to move data from the send buffer to the + // receive buffer. + absl::SleepFor(absl::Milliseconds(10)); // 10ms. + } + // The last error should have been EWOULDBLOCK. + ASSERT_EQ(errno, EWOULDBLOCK); + + // Now increase the socket send buffer. + buf_size = buf_size * 2; + ASSERT_THAT( + setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)), + SyscallSucceeds()); + + // The send should succeed again. + ASSERT_THAT(RetryEINTR(send)(sock, buf.data(), buf.size(), 0), + SyscallSucceeds()); +} + INSTANTIATE_TEST_SUITE_P( AllUnixDomainSockets, StreamUnixSocketPairTest, ::testing::ValuesIn(IncludeReversals(VecCat<SocketPairKind>( |