#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