blob: 75f352802f124ce8af08f983383e8e4f3cbcacd3 [file] [edit]
//===----------------------------------------------------------------------===//
//
// 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
/// Unit tests for sendmmsg and recvmmsg.
///
//===----------------------------------------------------------------------===//
#include "hdr/sys_socket_macros.h"
#include "hdr/types/struct_iovec.h"
#include "hdr/types/struct_mmsghdr.h"
#include "hdr/types/struct_timespec.h"
#include "src/__support/CPP/scope.h"
#include "src/string/strlen.h"
#include "src/sys/socket/recvmmsg.h"
#include "src/sys/socket/sendmmsg.h"
#include "src/sys/socket/socketpair.h"
#include "src/unistd/close.h"
#include "test/UnitTest/ErrnoCheckingTest.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/LibcTest.h"
#include "test/UnitTest/Test.h"
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
using LlvmLibcSendRecvMmsgTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
TEST_F(LlvmLibcSendRecvMmsgTest, SendRecvMmsgSucceedsWithSocketPair) {
const char *const TEST_MESSAGES[] = {"message one", "message two"};
const size_t MESSAGES_COUNT = 2;
int sockpair[2] = {0, 0};
ASSERT_THAT(LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_DGRAM, 0, sockpair),
Succeeds(0));
LIBC_NAMESPACE::cpp::scope_exit close_sockpair([&] {
ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[0]), Succeeds(0));
ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[1]), Succeeds(0));
});
struct iovec send_msg_vec[MESSAGES_COUNT] = {};
struct mmsghdr send_msg_hdr[MESSAGES_COUNT] = {};
for (size_t i = 0; i < MESSAGES_COUNT; ++i) {
send_msg_vec[i].iov_base = const_cast<char *>(TEST_MESSAGES[i]);
send_msg_vec[i].iov_len = LIBC_NAMESPACE::strlen(TEST_MESSAGES[i]) + 1;
send_msg_hdr[i].msg_hdr.msg_iov = &send_msg_vec[i];
send_msg_hdr[i].msg_hdr.msg_iovlen = 1;
}
ASSERT_THAT(
LIBC_NAMESPACE::sendmmsg(sockpair[0], send_msg_hdr, MESSAGES_COUNT, 0),
Succeeds<int>(MESSAGES_COUNT));
for (size_t i = 0; i < MESSAGES_COUNT; ++i) {
ASSERT_EQ(static_cast<size_t>(send_msg_hdr[i].msg_len),
LIBC_NAMESPACE::strlen(TEST_MESSAGES[i]) + 1);
}
char recv_buffers[MESSAGES_COUNT][256] = {};
struct iovec recv_msg_vec[MESSAGES_COUNT] = {};
struct mmsghdr recv_msg_hdr[MESSAGES_COUNT] = {};
for (size_t i = 0; i < MESSAGES_COUNT; ++i) {
recv_msg_vec[i].iov_base = recv_buffers[i];
recv_msg_vec[i].iov_len = sizeof(recv_buffers[i]);
recv_msg_hdr[i].msg_hdr.msg_iov = &recv_msg_vec[i];
recv_msg_hdr[i].msg_hdr.msg_iovlen = 1;
}
struct timespec invalid_timeout = {-1, 0};
ASSERT_THAT(LIBC_NAMESPACE::recvmmsg(sockpair[1], recv_msg_hdr,
MESSAGES_COUNT, 0, &invalid_timeout),
Fails<int>(EINVAL));
ASSERT_THAT(LIBC_NAMESPACE::recvmmsg(sockpair[1], recv_msg_hdr,
MESSAGES_COUNT, 0, nullptr),
Succeeds<int>(MESSAGES_COUNT));
for (size_t i = 0; i < MESSAGES_COUNT; ++i) {
ASSERT_EQ(static_cast<size_t>(recv_msg_hdr[i].msg_len),
LIBC_NAMESPACE::strlen(TEST_MESSAGES[i]) + 1);
ASSERT_STREQ(recv_buffers[i], TEST_MESSAGES[i]);
}
}
TEST_F(LlvmLibcSendRecvMmsgTest, SendMmsgFails) {
struct mmsghdr msg_hdrs = {};
ASSERT_THAT(LIBC_NAMESPACE::sendmmsg(-1, &msg_hdrs, 1, 0), Fails(EBADF, -1));
}
TEST_F(LlvmLibcSendRecvMmsgTest, RecvmmsgFails) {
struct mmsghdr msg_hdrs = {};
ASSERT_THAT(LIBC_NAMESPACE::recvmmsg(-1, &msg_hdrs, 1, 0, nullptr),
Fails(EBADF, -1));
}