| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| /// | |
| /// \file | |
| /// Unittests for getsockname and getpeername. | |
| /// | |
| //===----------------------------------------------------------------------===// | |
| #include "hdr/sys_socket_macros.h" | |
| #include "hdr/types/sa_family_t.h" | |
| #include "hdr/types/socklen_t.h" | |
| #include "hdr/types/struct_sockaddr_un.h" | |
| #include "src/__support/CPP/scope.h" | |
| #include "src/stdio/remove.h" | |
| #include "src/sys/socket/accept.h" | |
| #include "src/sys/socket/bind.h" | |
| #include "src/sys/socket/connect.h" | |
| #include "src/sys/socket/getpeername.h" | |
| #include "src/sys/socket/getsockname.h" | |
| #include "src/sys/socket/listen.h" | |
| #include "src/sys/socket/socket.h" | |
| #include "src/unistd/close.h" | |
| #include "test/UnitTest/ErrnoCheckingTest.h" | |
| #include "test/UnitTest/ErrnoSetterMatcher.h" | |
| #include "test/src/sys/socket/linux/socket_test_support.h" | |
| using LIBC_NAMESPACE::testing::make_sockaddr_un; | |
| using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; | |
| using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; | |
| using LlvmLibcSockNameTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; | |
| using LIBC_NAMESPACE::cpp::scope_exit; | |
| TEST_F(LlvmLibcSockNameTest, GetSockNameAndPeerName) { | |
| LIBC_NAMESPACE::testing::TestDirectoryScope dir_scope; | |
| // 1. Invalid Socket | |
| struct sockaddr_un addr; | |
| socklen_t addr_len = sizeof(addr); | |
| ASSERT_THAT(LIBC_NAMESPACE::getsockname( | |
| -1, reinterpret_cast<struct sockaddr *>(&addr), &addr_len), | |
| Fails(EBADF)); | |
| ASSERT_THAT(LIBC_NAMESPACE::getpeername( | |
| -1, reinterpret_cast<struct sockaddr *>(&addr), &addr_len), | |
| Fails(EBADF)); | |
| // 2. Unbound Socket | |
| int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0); | |
| ASSERT_GE(sock, 0); | |
| ASSERT_ERRNO_SUCCESS(); | |
| scope_exit close_sock( | |
| [&] { ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0)); }); | |
| // getsockname on unbound socket should succeed | |
| addr_len = sizeof(addr); | |
| ASSERT_THAT(LIBC_NAMESPACE::getsockname( | |
| sock, reinterpret_cast<struct sockaddr *>(&addr), &addr_len), | |
| Succeeds(0)); | |
| ASSERT_GE(addr_len, static_cast<socklen_t>(sizeof(sa_family_t))); | |
| ASSERT_EQ(addr.sun_family, static_cast<sa_family_t>(AF_UNIX)); | |
| // getpeername on unbound/unconnected socket should fail with ENOTCONN | |
| addr_len = sizeof(addr); | |
| ASSERT_THAT(LIBC_NAMESPACE::getpeername( | |
| sock, reinterpret_cast<struct sockaddr *>(&addr), &addr_len), | |
| Fails(ENOTCONN)); | |
| // 3. Connected Sockets | |
| constexpr char CLIENT_PATH[] = "getsockname_client.test"; | |
| struct sockaddr_un client_addr; | |
| ASSERT_TRUE(make_sockaddr_un(CLIENT_PATH, client_addr)); | |
| constexpr char SERVER_PATH[] = "getsockname_server.test"; | |
| struct sockaddr_un server_addr; | |
| ASSERT_TRUE(make_sockaddr_un(SERVER_PATH, server_addr)); | |
| int server_sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0); | |
| ASSERT_GE(server_sock, 0); | |
| ASSERT_ERRNO_SUCCESS(); | |
| scope_exit close_server_sock( | |
| [&] { ASSERT_THAT(LIBC_NAMESPACE::close(server_sock), Succeeds(0)); }); | |
| ASSERT_THAT(LIBC_NAMESPACE::bind( | |
| server_sock, | |
| reinterpret_cast<const struct sockaddr *>(&server_addr), | |
| sizeof(struct sockaddr_un)), | |
| Succeeds(0)); | |
| scope_exit remove_server_path( | |
| [&] { ASSERT_THAT(LIBC_NAMESPACE::remove(SERVER_PATH), Succeeds(0)); }); | |
| ASSERT_THAT(LIBC_NAMESPACE::listen(server_sock, 1), Succeeds(0)); | |
| int client_sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0); | |
| ASSERT_GE(client_sock, 0); | |
| ASSERT_ERRNO_SUCCESS(); | |
| scope_exit close_client_sock( | |
| [&] { ASSERT_THAT(LIBC_NAMESPACE::close(client_sock), Succeeds(0)); }); | |
| ASSERT_THAT(LIBC_NAMESPACE::bind( | |
| client_sock, | |
| reinterpret_cast<const struct sockaddr *>(&client_addr), | |
| sizeof(struct sockaddr_un)), | |
| Succeeds(0)); | |
| scope_exit remove_client_path( | |
| [&] { ASSERT_THAT(LIBC_NAMESPACE::remove(CLIENT_PATH), Succeeds(0)); }); | |
| ASSERT_THAT(LIBC_NAMESPACE::connect( | |
| client_sock, | |
| reinterpret_cast<const struct sockaddr *>(&server_addr), | |
| sizeof(struct sockaddr_un)), | |
| Succeeds(0)); | |
| int accepted_sock = LIBC_NAMESPACE::accept(server_sock, nullptr, nullptr); | |
| ASSERT_GE(accepted_sock, 0); | |
| ASSERT_ERRNO_SUCCESS(); | |
| scope_exit close_accepted_sock( | |
| [&] { ASSERT_THAT(LIBC_NAMESPACE::close(accepted_sock), Succeeds(0)); }); | |
| // Test getsockname on client_sock (should be client_path) | |
| addr_len = sizeof(addr); | |
| ASSERT_THAT( | |
| LIBC_NAMESPACE::getsockname( | |
| client_sock, reinterpret_cast<struct sockaddr *>(&addr), &addr_len), | |
| Succeeds(0)); | |
| ASSERT_THAT((LIBC_NAMESPACE::testing::SocketAddress{addr, addr_len}), | |
| LIBC_NAMESPACE::testing::MatchesAddress(CLIENT_PATH)); | |
| // Test getpeername on client_sock (should be server_path) | |
| addr_len = sizeof(addr); | |
| ASSERT_THAT( | |
| LIBC_NAMESPACE::getpeername( | |
| client_sock, reinterpret_cast<struct sockaddr *>(&addr), &addr_len), | |
| Succeeds(0)); | |
| ASSERT_THAT((LIBC_NAMESPACE::testing::SocketAddress{addr, addr_len}), | |
| LIBC_NAMESPACE::testing::MatchesAddress(SERVER_PATH)); | |
| // Test getsockname on accepted_sock (should be server_path) | |
| addr_len = sizeof(addr); | |
| ASSERT_THAT( | |
| LIBC_NAMESPACE::getsockname( | |
| accepted_sock, reinterpret_cast<struct sockaddr *>(&addr), &addr_len), | |
| Succeeds(0)); | |
| ASSERT_THAT((LIBC_NAMESPACE::testing::SocketAddress{addr, addr_len}), | |
| LIBC_NAMESPACE::testing::MatchesAddress(SERVER_PATH)); | |
| // Test getpeername on accepted_sock (should be client_path) | |
| addr_len = sizeof(addr); | |
| ASSERT_THAT( | |
| LIBC_NAMESPACE::getpeername( | |
| accepted_sock, reinterpret_cast<struct sockaddr *>(&addr), &addr_len), | |
| Succeeds(0)); | |
| ASSERT_THAT((LIBC_NAMESPACE::testing::SocketAddress{addr, addr_len}), | |
| LIBC_NAMESPACE::testing::MatchesAddress(CLIENT_PATH)); | |
| } |