github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/socket_stream_blocking.cc (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include "test/syscalls/linux/socket_stream_blocking.h"
    16  
    17  #include <stdio.h>
    18  #include <sys/socket.h>
    19  #include <sys/types.h>
    20  #include <sys/un.h>
    21  
    22  #include "gtest/gtest.h"
    23  #include "absl/time/clock.h"
    24  #include "absl/time/time.h"
    25  #include "test/syscalls/linux/socket_test_util.h"
    26  #include "test/syscalls/linux/unix_domain_socket_test_util.h"
    27  #include "test/util/test_util.h"
    28  #include "test/util/thread_util.h"
    29  #include "test/util/timer_util.h"
    30  
    31  namespace gvisor {
    32  namespace testing {
    33  
    34  TEST_P(BlockingStreamSocketPairTest, BlockPartialWriteClosed) {
    35    // FIXME(b/35921550): gVisor doesn't support SO_SNDBUF on UDS, nor does it
    36    // enforce any limit; it will write arbitrary amounts of data without
    37    // blocking.
    38    SKIP_IF(IsRunningOnGvisor());
    39  
    40    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    41  
    42    int buffer_size;
    43    socklen_t length = sizeof(buffer_size);
    44    ASSERT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF,
    45                           &buffer_size, &length),
    46                SyscallSucceeds());
    47  
    48    int wfd = sockets->first_fd();
    49    ScopedThread t([wfd, buffer_size]() {
    50      std::vector<char> buf(2 * buffer_size);
    51      // Write more than fits in the buffer. Blocks then returns partial write
    52      // when the other end is closed. The next call returns EPIPE.
    53      //
    54      // N.B. writes occur in chunks, so we may see less than buffer_size from
    55      // the first call.
    56      ASSERT_THAT(write(wfd, buf.data(), buf.size()),
    57                  SyscallSucceedsWithValue(::testing::Gt(0)));
    58      ASSERT_THAT(write(wfd, buf.data(), buf.size()),
    59                  ::testing::AnyOf(SyscallFailsWithErrno(EPIPE),
    60                                   SyscallFailsWithErrno(ECONNRESET)));
    61    });
    62  
    63    // Leave time for write to become blocked.
    64    absl::SleepFor(absl::Seconds(1));
    65  
    66    ASSERT_THAT(close(sockets->release_second_fd()), SyscallSucceeds());
    67  }
    68  
    69  // Random save may interrupt the call to sendmsg() in SendLargeSendMsg(),
    70  // causing the write to be incomplete and the test to hang.
    71  TEST_P(BlockingStreamSocketPairTest, SendMsgTooLarge) {
    72    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    73  
    74    int sndbuf;
    75    socklen_t length = sizeof(sndbuf);
    76    ASSERT_THAT(
    77        getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF, &sndbuf, &length),
    78        SyscallSucceeds());
    79  
    80    // Make the call too large to fit in the send buffer.
    81    const int buffer_size = 3 * sndbuf;
    82  
    83    EXPECT_THAT(SendLargeSendMsg(sockets, buffer_size, true /* reader */),
    84                SyscallSucceedsWithValue(buffer_size));
    85  }
    86  
    87  TEST_P(BlockingStreamSocketPairTest, RecvLessThanBuffer) {
    88    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    89  
    90    char sent_data[100];
    91    RandomizeBuffer(sent_data, sizeof(sent_data));
    92  
    93    ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
    94                SyscallSucceedsWithValue(sizeof(sent_data)));
    95  
    96    char received_data[200] = {};
    97    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
    98                                 sizeof(received_data), 0),
    99                SyscallSucceedsWithValue(sizeof(sent_data)));
   100  }
   101  
   102  // Test that MSG_WAITALL causes recv to block until all requested data is
   103  // received. Random save can interrupt blocking and cause received data to be
   104  // returned, even if the amount received is less than the full requested amount.
   105  TEST_P(BlockingStreamSocketPairTest, RecvLessThanBufferWaitAll) {
   106    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   107  
   108    char sent_data[100];
   109    RandomizeBuffer(sent_data, sizeof(sent_data));
   110  
   111    ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
   112                SyscallSucceedsWithValue(sizeof(sent_data)));
   113  
   114    constexpr auto kDuration = absl::Milliseconds(200);
   115    auto before = Now(CLOCK_MONOTONIC);
   116  
   117    const ScopedThread t([&]() {
   118      absl::SleepFor(kDuration);
   119  
   120      // Don't let saving after the write interrupt the blocking recv.
   121      const DisableSave ds;
   122  
   123      ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
   124                  SyscallSucceedsWithValue(sizeof(sent_data)));
   125    });
   126  
   127    char received_data[sizeof(sent_data) * 2] = {};
   128    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
   129                                 sizeof(received_data), MSG_WAITALL),
   130                SyscallSucceedsWithValue(sizeof(received_data)));
   131  
   132    auto after = Now(CLOCK_MONOTONIC);
   133    EXPECT_GE(after - before, kDuration);
   134  }
   135  
   136  TEST_P(BlockingStreamSocketPairTest, SendTimeout) {
   137    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   138  
   139    struct timeval tv {
   140      .tv_sec = 0, .tv_usec = 10
   141    };
   142    EXPECT_THAT(
   143        setsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)),
   144        SyscallSucceeds());
   145  
   146    std::vector<char> buf(kPageSize);
   147    // We don't know how much data the socketpair will buffer, so we may do an
   148    // arbitrarily large number of writes; saving after each write causes this
   149    // test's time to explode.
   150    const DisableSave ds;
   151    for (;;) {
   152      int ret;
   153      ASSERT_THAT(
   154          ret = RetryEINTR(send)(sockets->first_fd(), buf.data(), buf.size(), 0),
   155          ::testing::AnyOf(SyscallSucceeds(), SyscallFailsWithErrno(EAGAIN)));
   156      if (ret == -1) {
   157        break;
   158      }
   159    }
   160  }
   161  
   162  }  // namespace testing
   163  }  // namespace gvisor