#include "uds/ipc_helper.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using testing::Return;
using testing::SetErrnoAndReturn;
using testing::_;
using android::pdx::BorrowedHandle;
using android::pdx::uds::SendInterface;
using android::pdx::uds::RecvInterface;
using android::pdx::uds::SendAll;
using android::pdx::uds::SendMsgAll;
using android::pdx::uds::RecvAll;
using android::pdx::uds::RecvMsgAll;
namespace {
// Useful constants for tests.
static constexpr intptr_t kPtr = 1234;
static constexpr int kSocketFd = 5678;
static const BorrowedHandle kSocket{kSocketFd};
// Helper functions to construct test data pointer values.
void* IntToPtr(intptr_t value) { return reinterpret_cast<void*>(value); }
const void* IntToConstPtr(intptr_t value) {
return reinterpret_cast<const void*>(value);
}
// Mock classes for SendInterface/RecvInterface.
class MockSender : public SendInterface {
public:
MOCK_METHOD4(Send, ssize_t(int socket_fd, const void* data, size_t size,
int flags));
MOCK_METHOD3(SendMessage,
ssize_t(int socket_fd, const msghdr* msg, int flags));
};
class MockReceiver : public RecvInterface {
public:
MOCK_METHOD4(Receive,
ssize_t(int socket_fd, void* data, size_t size, int flags));
MOCK_METHOD3(ReceiveMessage, ssize_t(int socket_fd, msghdr* msg, int flags));
};
// Test case classes.
class SendTest : public testing::Test {
public:
SendTest() {
ON_CALL(sender_, Send(_, _, _, _))
.WillByDefault(SetErrnoAndReturn(EIO, -1));
ON_CALL(sender_, SendMessage(_, _, _))
.WillByDefault(SetErrnoAndReturn(EIO, -1));
}
protected:
MockSender sender_;
};
class RecvTest : public testing::Test {
public:
RecvTest() {
ON_CALL(receiver_, Receive(_, _, _, _))
.WillByDefault(SetErrnoAndReturn(EIO, -1));
ON_CALL(receiver_, ReceiveMessage(_, _, _))
.WillByDefault(SetErrnoAndReturn(EIO, -1));
}
protected:
MockReceiver receiver_;
};
class MessageTestBase : public testing::Test {
public:
MessageTestBase() {
memset(&msg_, 0, sizeof(msg_));
msg_.msg_iovlen = data_.size();
msg_.msg_iov = data_.data();
}
protected:
static constexpr intptr_t kPtr1 = kPtr;
static constexpr intptr_t kPtr2 = kPtr + 200;
static constexpr intptr_t kPtr3 = kPtr + 1000;
MockSender sender_;
msghdr msg_;
std::vector<iovec> data_{
{IntToPtr(kPtr1), 100}, {IntToPtr(kPtr2), 200}, {IntToPtr(kPtr3), 300}};
};
class SendMessageTest : public MessageTestBase {
public:
SendMessageTest() {
ON_CALL(sender_, Send(_, _, _, _))
.WillByDefault(SetErrnoAndReturn(EIO, -1));
ON_CALL(sender_, SendMessage(_, _, _))
.WillByDefault(SetErrnoAndReturn(EIO, -1));
}
protected:
MockSender sender_;
};
class RecvMessageTest : public MessageTestBase {
public:
RecvMessageTest() {
ON_CALL(receiver_, Receive(_, _, _, _))
.WillByDefault(SetErrnoAndReturn(EIO, -1));
ON_CALL(receiver_, ReceiveMessage(_, _, _))
.WillByDefault(SetErrnoAndReturn(EIO, -1));
}
protected:
MockReceiver receiver_;
};
// Actual tests.
// SendAll
TEST_F(SendTest, Complete) {
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
.WillOnce(Return(100));
auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
EXPECT_TRUE(status);
}
TEST_F(SendTest, Signal) {
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
.WillOnce(Return(20));
EXPECT_CALL(sender_,
Send(kSocketFd, IntToConstPtr(kPtr + 20), 80, MSG_NOSIGNAL))
.WillOnce(Return(40));
EXPECT_CALL(sender_,
Send(kSocketFd, IntToConstPtr(kPtr + 60), 40, MSG_NOSIGNAL))
.WillOnce(Return(40));
auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
EXPECT_TRUE(status);
}
TEST_F(SendTest, Eintr) {
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
.WillOnce(SetErrnoAndReturn(EINTR, -1))
.WillOnce(Return(100));
auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
EXPECT_TRUE(status);
}
TEST_F(SendTest, Error) {
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
.WillOnce(SetErrnoAndReturn(EIO, -1));
auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
ASSERT_FALSE(status);
EXPECT_EQ(EIO, status.error());
}
TEST_F(SendTest, Error2) {
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
.WillOnce(Return(50));
EXPECT_CALL(sender_,
Send(kSocketFd, IntToConstPtr(kPtr + 50), 50, MSG_NOSIGNAL))
.WillOnce(SetErrnoAndReturn(EIO, -1));
auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
ASSERT_FALSE(status);
EXPECT_EQ(EIO, status.error());
}
// RecvAll
TEST_F(RecvTest, Complete) {
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100,
MSG_WAITALL | MSG_CMSG_CLOEXEC))
.WillOnce(Return(100));
auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
EXPECT_TRUE(status);
}
TEST_F(RecvTest, Signal) {
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _))
.WillOnce(Return(20));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr + 20), 80, _))
.WillOnce(Return(40));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr + 60), 40, _))
.WillOnce(Return(40));
auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
EXPECT_TRUE(status);
}
TEST_F(RecvTest, Eintr) {
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _))
.WillOnce(SetErrnoAndReturn(EINTR, -1))
.WillOnce(Return(100));
auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
EXPECT_TRUE(status);
}
TEST_F(RecvTest, Error) {
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _))
.WillOnce(SetErrnoAndReturn(EIO, -1));
auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
ASSERT_FALSE(status);
EXPECT_EQ(EIO, status.error());
}
TEST_F(RecvTest, Error2) {
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _))
.WillOnce(Return(30));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr + 30), 70, _))
.WillOnce(SetErrnoAndReturn(EIO, -1));
auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
ASSERT_FALSE(status);
EXPECT_EQ(EIO, status.error());
}
// SendMsgAll
TEST_F(SendMessageTest, Complete) {
EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, MSG_NOSIGNAL))
.WillOnce(Return(600));
auto status = SendMsgAll(&sender_, kSocket, &msg_);
EXPECT_TRUE(status);
}
TEST_F(SendMessageTest, Partial) {
EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)).WillOnce(Return(70));
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr1 + 70), 30, _))
.WillOnce(Return(30));
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr2), 200, _))
.WillOnce(Return(190));
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr2 + 190), 10, _))
.WillOnce(Return(10));
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr3), 300, _))
.WillOnce(Return(300));
auto status = SendMsgAll(&sender_, kSocket, &msg_);
EXPECT_TRUE(status);
}
TEST_F(SendMessageTest, Partial2) {
EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)).WillOnce(Return(310));
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr3 + 10), 290, _))
.WillOnce(Return(290));
auto status = SendMsgAll(&sender_, kSocket, &msg_);
EXPECT_TRUE(status);
}
TEST_F(SendMessageTest, Eintr) {
EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _))
.WillOnce(SetErrnoAndReturn(EINTR, -1))
.WillOnce(Return(70));
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr1 + 70), 30, _))
.WillOnce(SetErrnoAndReturn(EINTR, -1))
.WillOnce(Return(30));
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr2), 200, _))
.WillOnce(Return(200));
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr3), 300, _))
.WillOnce(Return(300));
auto status = SendMsgAll(&sender_, kSocket, &msg_);
EXPECT_TRUE(status);
}
TEST_F(SendMessageTest, Error) {
EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _))
.WillOnce(SetErrnoAndReturn(EBADF, -1));
auto status = SendMsgAll(&sender_, kSocket, &msg_);
ASSERT_FALSE(status);
EXPECT_EQ(EBADF, status.error());
}
TEST_F(SendMessageTest, Error2) {
EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)).WillOnce(Return(20));
EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr1 + 20), 80, _))
.WillOnce(SetErrnoAndReturn(EBADF, -1));
auto status = SendMsgAll(&sender_, kSocket, &msg_);
ASSERT_FALSE(status);
EXPECT_EQ(EBADF, status.error());
}
// RecvMsgAll
TEST_F(RecvMessageTest, Complete) {
EXPECT_CALL(receiver_,
ReceiveMessage(kSocketFd, &msg_, MSG_WAITALL | MSG_CMSG_CLOEXEC))
.WillOnce(Return(600));
auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
EXPECT_TRUE(status);
}
TEST_F(RecvMessageTest, Partial) {
EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
.WillOnce(Return(70));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr1 + 70), 30, _))
.WillOnce(Return(30));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr2), 200, _))
.WillOnce(Return(190));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr2 + 190), 10, _))
.WillOnce(Return(10));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr3), 300, _))
.WillOnce(Return(300));
auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
EXPECT_TRUE(status);
}
TEST_F(RecvMessageTest, Partial2) {
EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
.WillOnce(Return(310));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr3 + 10), 290, _))
.WillOnce(Return(290));
auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
EXPECT_TRUE(status);
}
TEST_F(RecvMessageTest, Eintr) {
EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
.WillOnce(SetErrnoAndReturn(EINTR, -1))
.WillOnce(Return(70));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr1 + 70), 30, _))
.WillOnce(SetErrnoAndReturn(EINTR, -1))
.WillOnce(Return(30));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr2), 200, _))
.WillOnce(Return(200));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr3), 300, _))
.WillOnce(Return(300));
auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
EXPECT_TRUE(status);
}
TEST_F(RecvMessageTest, Error) {
EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
.WillOnce(SetErrnoAndReturn(EBADF, -1));
auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
ASSERT_FALSE(status);
EXPECT_EQ(EBADF, status.error());
}
TEST_F(RecvMessageTest, Error2) {
EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
.WillOnce(Return(20));
EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr1 + 20), 80, _))
.WillOnce(SetErrnoAndReturn(EBADF, -1));
auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
ASSERT_FALSE(status);
EXPECT_EQ(EBADF, status.error());
}
} // namespace