From 5c8be5da4d34c74dcebb978cea44402a3d24e0c9 Mon Sep 17 00:00:00 2001 From: Ayush Ranjan Date: Wed, 3 Jan 2024 22:09:45 -0800 Subject: [PATCH] Add regression test for #9848. Updates #9848 PiperOrigin-RevId: 595593495 --- test/syscalls/linux/bind_external.cc | 61 +++++++++++++++++++++++++++- test/uds/uds.go | 28 ++++++------- 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/test/syscalls/linux/bind_external.cc b/test/syscalls/linux/bind_external.cc index 8e86c8002..1f7a32faf 100644 --- a/test/syscalls/linux/bind_external.cc +++ b/test/syscalls/linux/bind_external.cc @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#ifdef __linux__ +#include +#endif // __linux__ #include #include #include @@ -84,7 +87,63 @@ TEST_P(GoferStreamSeqpacketTest, BindListenAccept) { FileDescriptor accSock = ASSERT_NO_ERRNO_AND_VALUE(Accept(sock.get(), NULL, NULL)); - // Other socket should be echo server. + // Other socket should be echo client. + constexpr int kBufferSize = 64; + char send_buffer[kBufferSize]; + memset(send_buffer, 'a', sizeof(send_buffer)); + + ASSERT_THAT(WriteFd(accSock.get(), send_buffer, sizeof(send_buffer)), + SyscallSucceedsWithValue(sizeof(send_buffer))); + + char recv_buffer[kBufferSize]; + ASSERT_THAT(ReadFd(accSock.get(), recv_buffer, sizeof(recv_buffer)), + SyscallSucceedsWithValue(sizeof(recv_buffer))); + ASSERT_EQ(0, memcmp(send_buffer, recv_buffer, sizeof(send_buffer))); +} + +// Create socket, register with epoll, bind to socket, Listen, wait for socket +// to become ready using epoll and then Accept. +TEST_P(GoferStreamSeqpacketTest, EpollBindListenWaitAccept) { + std::string env; + ProtocolSocket proto; + std::tie(env, proto) = GetParam(); + + char* val = getenv(env.c_str()); + ASSERT_NE(val, nullptr); + std::string root(val); + + FileDescriptor sock = + ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, proto.protocol, 0)); + + // Epoll on sockfd. + int efd; + ASSERT_THAT(efd = epoll_create(1), SyscallSucceeds()); + FileDescriptor epollfd(efd); + struct epoll_event event = {}; + event.events = EPOLLIN; + ASSERT_THAT(epoll_ctl(epollfd.get(), EPOLL_CTL_ADD, sock.get(), &event), + SyscallSucceeds()); + + std::string socket_path = + JoinPath(root, proto.name, "created-in-sandbox-epoll"); + + struct sockaddr_un addr = {}; + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, socket_path.c_str(), socket_path.length()); + + ASSERT_THAT( + bind(sock.get(), reinterpret_cast(&addr), sizeof(addr)), + SyscallSucceeds()); + ASSERT_THAT(listen(sock.get(), 1), SyscallSucceeds()); + + struct epoll_event results = {}; + ASSERT_THAT(RetryEINTR(epoll_wait)(epollfd.get(), &results, 1, -1), + SyscallSucceeds()); + + FileDescriptor accSock = + ASSERT_NO_ERRNO_AND_VALUE(Accept(sock.get(), NULL, NULL)); + + // Other socket should be echo client. constexpr int kBufferSize = 64; char send_buffer[kBufferSize]; memset(send_buffer, 'a', sizeof(send_buffer)); diff --git a/test/uds/uds.go b/test/uds/uds.go index 941fcfcf9..81c71c741 100644 --- a/test/uds/uds.go +++ b/test/uds/uds.go @@ -44,10 +44,8 @@ func doEcho(s *unet.Socket) error { return nil } -// createEchoSocket creates a socket that echoes back anything received. -// -// Only works for stream, seqpacket sockets. -func createEchoSocket(path string, protocol int) (cleanup func(), err error) { +// createEchoServer creates a socket that echoes back anything received. +func createEchoServer(path string, protocol int) (cleanup func(), err error) { fd, err := unix.Socket(unix.AF_UNIX, protocol, 0) if err != nil { return nil, fmt.Errorf("error creating echo(%d) socket: %v", protocol, err) @@ -101,8 +99,8 @@ func createEchoSocket(path string, protocol int) (cleanup func(), err error) { return cleanup, nil } -// connectAndBecomeEcho connects to the given socket and turns into an echo server. -func connectAndBecomeEcho(path string, protocol int) (cleanup func(), err error) { +// createEchoClient connects to the given socket and turns into an echo client. +func createEchoClient(path string, protocol int) (cleanup func(), err error) { usePacket := protocol == unix.SOCK_SEQPACKET go func() { for { @@ -115,7 +113,7 @@ func connectAndBecomeEcho(path string, protocol int) (cleanup func(), err error) } defer sock.Close() for { - log.Infof("Connected to UDS at %q, running echo server", path) + log.Infof("Connected to UDS at %q, running echo client", path) if err := doEcho(sock); err != nil { return } @@ -337,7 +335,7 @@ func CreateBoundUDSTree(baseDir string) (string, func(), error) { protocol: unix.SOCK_STREAM, name: "stream", sockets: map[string]socketCreator{ - "echo": createEchoSocket, + "echo": createEchoServer, "nonlistening": createNonListeningSocket, }, }, @@ -345,7 +343,7 @@ func CreateBoundUDSTree(baseDir string) (string, func(), error) { protocol: unix.SOCK_SEQPACKET, name: "seqpacket", sockets: map[string]socketCreator{ - "echo": createEchoSocket, + "echo": createEchoServer, "nonlistening": createNonListeningSocket, }, }, @@ -360,24 +358,26 @@ func CreateBoundUDSTree(baseDir string) (string, func(), error) { } // CreateSocketConnectors creates goroutines that will attempt to connect to -// sockets at the following locations, and turn into an echo server once +// sockets at the following locations, and turn into an echo client once // connected: -// - /stream/created-in-sandbox -// - /seqpacket/created-in-sandbox +// - /stream/created-in-sandbox{-epoll} +// - /seqpacket/created-in-sandbox{-epoll} func CreateSocketConnectors(baseDir string) (string, func(), error) { return createSocketTree(baseDir, []socketCreatorSpec{ { protocol: unix.SOCK_STREAM, name: "stream", sockets: map[string]socketCreator{ - "created-in-sandbox": connectAndBecomeEcho, + "created-in-sandbox": createEchoClient, + "created-in-sandbox-epoll": createEchoClient, }, }, { protocol: unix.SOCK_SEQPACKET, name: "seqpacket", sockets: map[string]socketCreator{ - "created-in-sandbox": connectAndBecomeEcho, + "created-in-sandbox": createEchoClient, + "created-in-sandbox-epoll": createEchoClient, }, }, })