#include #include #include #include #include using android::pdx::BorrowedChannelHandle; using android::pdx::BorrowedHandle; using android::pdx::Channel; using android::pdx::ChannelReference; using android::pdx::ErrorStatus; using android::pdx::FileReference; using android::pdx::LocalChannelHandle; using android::pdx::LocalHandle; using android::pdx::Message; using android::pdx::MessageInfo; using android::pdx::MockEndpoint; using android::pdx::RemoteChannelHandle; using android::pdx::RemoteHandle; using android::pdx::Service; using android::pdx::Status; using testing::A; using testing::ByMove; using testing::DoAll; using testing::Invoke; using testing::Matcher; using testing::Ref; using testing::Return; using testing::SetArgPointee; using testing::WithArg; using testing::WithoutArgs; using testing::_; namespace { // Helper functions to construct fake void pointers for tests. inline void* IntToPtr(intptr_t addr) { return reinterpret_cast(addr); } // Helper matchers for working with iovec structures in tests. // Simple matcher for one element iovec array: // EXPECT_CALL(mock, method(IoVecMatcher(ptr, size))); MATCHER_P2(IoVecMatcher, ptr, size, "") { return arg->iov_base == ptr && arg->iov_len == size; } // Matcher for an array of iovecs: // EXPECT_CALL(mock, // method(IoVecMatcher(IoVecArray{{ptr1, size1}, {ptr2, size2}}))); using IoVecArray = std::vector; MATCHER_P(IoVecMatcher, iovec_array, "") { auto local_arg = arg; for (const iovec& item : iovec_array) { if (local_arg->iov_base != item.iov_base || local_arg->iov_len != item.iov_len) return false; local_arg++; } return true; } using IoVecData = std::vector; MATCHER_P(IoVecDataMatcher, iovec_data, "") { auto local_arg = arg; for (const std::string& item : iovec_data) { std::string data{reinterpret_cast(local_arg->iov_base), local_arg->iov_len}; if (data != item) return false; local_arg++; } return true; } MATCHER_P(FileHandleMatcher, value, "") { return arg.Get() == value; } MATCHER_P(ChannelHandleMatcher, value, "") { return arg.value() == value; } enum : int { kTestPid = 1, kTestTid, kTestCid, kTestMid, kTestEuid, kTestEgid, kTestOp, }; class MockService : public Service { public: using Service::Service; MOCK_METHOD1(OnChannelOpen, std::shared_ptr(Message& message)); MOCK_METHOD2(OnChannelClose, void(Message& message, const std::shared_ptr& channel)); MOCK_METHOD1(HandleMessage, Status(Message& message)); MOCK_METHOD1(HandleImpulse, void(Message& impulse)); MOCK_METHOD0(OnSysPropChange, void()); MOCK_METHOD1(DumpState, std::string(size_t max_length)); }; class ServiceTest : public testing::Test { public: ServiceTest() { auto endpoint = std::make_unique>(); EXPECT_CALL(*endpoint, SetService(_)) .Times(2) .WillRepeatedly(Return(Status{})); service_ = std::make_shared("MockSvc", std::move(endpoint)); } MockEndpoint* endpoint() { return static_cast(service_->endpoint()); } void SetupMessageInfo(MessageInfo* info, int32_t op, bool impulse = false) { info->pid = kTestPid; info->tid = kTestTid; info->cid = kTestCid; info->mid = impulse ? Message::IMPULSE_MESSAGE_ID : kTestMid; info->euid = kTestEuid; info->egid = kTestEgid; info->op = op; info->flags = 0; info->service = service_.get(); info->channel = nullptr; info->send_len = 0; info->recv_len = 0; info->fd_count = 0; memset(info->impulse, 0, sizeof(info->impulse)); } void SetupMessageInfoAndDefaultExpectations(MessageInfo* info, int32_t op, bool impulse = false) { SetupMessageInfo(info, op, impulse); EXPECT_CALL(*endpoint(), AllocateMessageState()).WillOnce(Return(kState)); EXPECT_CALL(*endpoint(), FreeMessageState(kState)); } void ExpectDefaultHandleMessage() { EXPECT_CALL(*endpoint(), MessageReply(_, -EOPNOTSUPP)) .WillOnce(Return(Status{})); } std::shared_ptr service_; void* kState = IntToPtr(123456); }; class ServiceMessageTest : public ServiceTest { public: ServiceMessageTest() { MessageInfo info; SetupMessageInfoAndDefaultExpectations(&info, kTestOp); message_ = std::make_unique(info); } std::unique_ptr message_; }; } // anonymous namespace /////////////////////////////////////////////////////////////////////////////// // Service class tests /////////////////////////////////////////////////////////////////////////////// TEST_F(ServiceTest, IsInitialized) { EXPECT_TRUE(service_->IsInitialized()); service_ = std::make_shared("MockSvc2", nullptr); EXPECT_FALSE(service_->IsInitialized()); } TEST_F(ServiceTest, ConstructMessage) { MessageInfo info; SetupMessageInfo(&info, kTestOp); auto test_channel = std::make_shared(); info.channel = test_channel.get(); EXPECT_CALL(*endpoint(), AllocateMessageState()).WillOnce(Return(kState)); Message message{info}; EXPECT_FALSE(message.IsImpulse()); EXPECT_EQ(kTestPid, message.GetProcessId()); EXPECT_EQ(kTestTid, message.GetThreadId()); EXPECT_EQ(kTestCid, message.GetChannelId()); EXPECT_EQ(kTestMid, message.GetMessageId()); EXPECT_EQ((unsigned) kTestEuid, message.GetEffectiveUserId()); EXPECT_EQ((unsigned) kTestEgid, message.GetEffectiveGroupId()); EXPECT_EQ(kTestOp, message.GetOp()); EXPECT_EQ(service_, message.GetService()); EXPECT_EQ(test_channel, message.GetChannel()); EXPECT_FALSE(message.replied()); EXPECT_FALSE(message.IsChannelExpired()); EXPECT_FALSE(message.IsServiceExpired()); EXPECT_EQ(kState, message.GetState()); ExpectDefaultHandleMessage(); EXPECT_CALL(*endpoint(), FreeMessageState(kState)); } TEST_F(ServiceTest, ConstructImpulseMessage) { MessageInfo info; SetupMessageInfo(&info, kTestOp, true); auto test_channel = std::make_shared(); info.channel = test_channel.get(); EXPECT_CALL(*endpoint(), AllocateMessageState()).WillOnce(Return(nullptr)); Message message{info}; EXPECT_TRUE(message.IsImpulse()); EXPECT_EQ(kTestOp, message.GetOp()); EXPECT_EQ(service_, message.GetService()); EXPECT_EQ(test_channel, message.GetChannel()); EXPECT_TRUE(message.replied()); EXPECT_FALSE(message.IsChannelExpired()); EXPECT_FALSE(message.IsServiceExpired()); // DefaultHandleMessage should not be called here. EXPECT_CALL(*endpoint(), FreeMessageState(nullptr)); } TEST_F(ServiceTest, HandleMessageChannelOpen) { MessageInfo info; SetupMessageInfoAndDefaultExpectations(&info, android::pdx::opcodes::CHANNEL_OPEN); Message message{info}; auto channel = std::make_shared(); EXPECT_CALL(*service_, OnChannelOpen(Ref(message))).WillOnce(Return(channel)); EXPECT_CALL(*endpoint(), SetChannel(kTestCid, channel.get())) .WillOnce(Return(Status{})); EXPECT_CALL(*endpoint(), MessageReply(&message, 0)) .WillOnce(Return(Status{})); EXPECT_TRUE(service_->Service::HandleMessage(message)); } TEST_F(ServiceTest, HandleMessageChannelClose) { MessageInfo info; SetupMessageInfoAndDefaultExpectations(&info, android::pdx::opcodes::CHANNEL_CLOSE); auto channel = std::make_shared(); info.channel = channel.get(); Message message{info}; EXPECT_CALL(*service_, OnChannelClose(Ref(message), channel)); EXPECT_CALL(*endpoint(), SetChannel(kTestCid, nullptr)) .WillOnce(Return(Status{})); EXPECT_CALL(*endpoint(), MessageReply(&message, 0)) .WillOnce(Return(Status{})); EXPECT_TRUE(service_->Service::HandleMessage(message)); } TEST_F(ServiceTest, HandleMessageOnSysPropChange) { MessageInfo info; SetupMessageInfoAndDefaultExpectations( &info, android::pdx::opcodes::REPORT_SYSPROP_CHANGE); Message message{info}; EXPECT_CALL(*service_, OnSysPropChange()); EXPECT_CALL(*endpoint(), MessageReply(&message, 0)) .WillOnce(Return(Status{})); EXPECT_TRUE(service_->Service::HandleMessage(message)); } TEST_F(ServiceTest, HandleMessageOnDumpState) { const size_t kRecvBufSize = 1000; MessageInfo info; SetupMessageInfoAndDefaultExpectations(&info, android::pdx::opcodes::DUMP_STATE); info.recv_len = kRecvBufSize; Message message{info}; const std::string kReply = "foo"; EXPECT_CALL(*service_, DumpState(kRecvBufSize)).WillOnce(Return(kReply)); EXPECT_CALL( *endpoint(), WriteMessageData(&message, IoVecDataMatcher(IoVecData{kReply}), 1)) .WillOnce(Return(kReply.size())); EXPECT_CALL(*endpoint(), MessageReply(&message, kReply.size())) .WillOnce(Return(Status{})); EXPECT_TRUE(service_->Service::HandleMessage(message)); } TEST_F(ServiceTest, HandleMessageOnDumpStateTooLarge) { const size_t kRecvBufSize = 3; MessageInfo info; SetupMessageInfoAndDefaultExpectations(&info, android::pdx::opcodes::DUMP_STATE); info.recv_len = kRecvBufSize; Message message{info}; const std::string kReply = "0123456789"; const std::string kActualReply = kReply.substr(0, kRecvBufSize); EXPECT_CALL(*service_, DumpState(kRecvBufSize)).WillOnce(Return(kReply)); EXPECT_CALL( *endpoint(), WriteMessageData(&message, IoVecDataMatcher(IoVecData{kActualReply}), 1)) .WillOnce(Return(kActualReply.size())); EXPECT_CALL(*endpoint(), MessageReply(&message, kActualReply.size())) .WillOnce(Return(Status{})); EXPECT_TRUE(service_->Service::HandleMessage(message)); } TEST_F(ServiceTest, HandleMessageOnDumpStateFail) { const size_t kRecvBufSize = 1000; MessageInfo info; SetupMessageInfoAndDefaultExpectations(&info, android::pdx::opcodes::DUMP_STATE); info.recv_len = kRecvBufSize; Message message{info}; const std::string kReply = "foo"; EXPECT_CALL(*service_, DumpState(kRecvBufSize)).WillOnce(Return(kReply)); EXPECT_CALL( *endpoint(), WriteMessageData(&message, IoVecDataMatcher(IoVecData{kReply}), 1)) .WillOnce(Return(1)); EXPECT_CALL(*endpoint(), MessageReply(&message, -EIO)) .WillOnce(Return(Status{})); EXPECT_TRUE(service_->Service::HandleMessage(message)); } TEST_F(ServiceTest, HandleMessageCustom) { MessageInfo info; SetupMessageInfoAndDefaultExpectations(&info, kTestOp); Message message{info}; EXPECT_CALL(*endpoint(), MessageReply(&message, -EOPNOTSUPP)) .WillOnce(Return(Status{})); EXPECT_TRUE(service_->Service::HandleMessage(message)); } TEST_F(ServiceTest, ReplyMessageWithoutService) { MessageInfo info; SetupMessageInfo(&info, kTestOp); EXPECT_CALL(*endpoint(), AllocateMessageState()).WillOnce(Return(nullptr)); Message message{info}; EXPECT_FALSE(message.IsServiceExpired()); service_.reset(); EXPECT_TRUE(message.IsServiceExpired()); EXPECT_EQ(EINVAL, message.Reply(12).error()); } TEST_F(ServiceTest, ReceiveAndDispatchMessage) { MessageInfo info; SetupMessageInfoAndDefaultExpectations(&info, kTestOp); ExpectDefaultHandleMessage(); auto on_receive = [&info](Message* message) -> Status { *message = Message{info}; return {}; }; EXPECT_CALL(*endpoint(), MessageReceive(_)).WillOnce(Invoke(on_receive)); EXPECT_CALL(*service_, HandleMessage(_)).WillOnce(Return(Status{})); EXPECT_TRUE(service_->ReceiveAndDispatch()); } TEST_F(ServiceTest, ReceiveAndDispatchImpulse) { MessageInfo info; SetupMessageInfoAndDefaultExpectations(&info, kTestOp, true); auto on_receive = [&info](Message* message) -> Status { *message = Message{info}; return {}; }; EXPECT_CALL(*endpoint(), MessageReceive(_)).WillOnce(Invoke(on_receive)); EXPECT_CALL(*service_, HandleImpulse(_)); EXPECT_TRUE(service_->ReceiveAndDispatch()); } TEST_F(ServiceTest, Cancel) { EXPECT_CALL(*endpoint(), Cancel()).WillOnce(Return(Status{})); EXPECT_TRUE(service_->Cancel()); } /////////////////////////////////////////////////////////////////////////////// // Message class tests /////////////////////////////////////////////////////////////////////////////// TEST_F(ServiceMessageTest, Reply) { EXPECT_CALL(*endpoint(), MessageReply(message_.get(), 12)) .WillOnce(Return(Status{})); EXPECT_FALSE(message_->replied()); EXPECT_TRUE(message_->Reply(12)); EXPECT_TRUE(message_->replied()); EXPECT_EQ(EINVAL, message_->Reply(12).error()); // Already replied. } TEST_F(ServiceMessageTest, ReplyFail) { EXPECT_CALL(*endpoint(), MessageReply(message_.get(), 12)) .WillOnce(Return(ErrorStatus{EIO})); EXPECT_EQ(EIO, message_->Reply(12).error()); ExpectDefaultHandleMessage(); } TEST_F(ServiceMessageTest, ReplyError) { EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -12)) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->ReplyError(12)); } TEST_F(ServiceMessageTest, ReplyFileDescriptor) { EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), 5)) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->ReplyFileDescriptor(5)); } TEST_F(ServiceMessageTest, ReplyLocalFileHandle) { const int kFakeFd = 12345; LocalHandle handle{kFakeFd}; EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), kFakeFd)) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(handle)); handle.Release(); // Make sure we do not close the fake file descriptor. } TEST_F(ServiceMessageTest, ReplyLocalFileHandleError) { LocalHandle handle{-EINVAL}; EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EINVAL)) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(handle)); } TEST_F(ServiceMessageTest, ReplyBorrowedFileHandle) { const int kFakeFd = 12345; BorrowedHandle handle{kFakeFd}; EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), kFakeFd)) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(handle)); } TEST_F(ServiceMessageTest, ReplyBorrowedFileHandleError) { BorrowedHandle handle{-EACCES}; EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EACCES)) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(handle)); } TEST_F(ServiceMessageTest, ReplyRemoteFileHandle) { RemoteHandle handle{123}; EXPECT_CALL(*endpoint(), MessageReply(message_.get(), handle.Get())) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(handle)); } TEST_F(ServiceMessageTest, ReplyRemoteFileHandleError) { RemoteHandle handle{-EIO}; EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EIO)) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(handle)); } TEST_F(ServiceMessageTest, ReplyLocalChannelHandle) { LocalChannelHandle handle{nullptr, 12345}; EXPECT_CALL(*endpoint(), MessageReplyChannelHandle( message_.get(), A())) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(handle)); } TEST_F(ServiceMessageTest, ReplyBorrowedChannelHandle) { BorrowedChannelHandle handle{12345}; EXPECT_CALL(*endpoint(), MessageReplyChannelHandle(message_.get(), A())) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(handle)); } TEST_F(ServiceMessageTest, ReplyRemoteChannelHandle) { RemoteChannelHandle handle{12345}; EXPECT_CALL(*endpoint(), MessageReplyChannelHandle( message_.get(), A())) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(handle)); } TEST_F(ServiceMessageTest, ReplyStatusInt) { Status status{123}; EXPECT_CALL(*endpoint(), MessageReply(message_.get(), status.get())) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(status)); } TEST_F(ServiceMessageTest, ReplyStatusError) { Status status{ErrorStatus{EIO}}; EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -status.error())) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->Reply(status)); } TEST_F(ServiceMessageTest, Read) { ExpectDefaultHandleMessage(); void* const kDataBuffer = IntToPtr(12345); const size_t kDataSize = 100; EXPECT_CALL( *endpoint(), ReadMessageData(message_.get(), IoVecMatcher(kDataBuffer, kDataSize), 1)) .WillOnce(Return(50)) .WillOnce(Return(ErrorStatus{EACCES})); EXPECT_EQ(50u, message_->Read(kDataBuffer, kDataSize).get()); EXPECT_EQ(EACCES, message_->Read(kDataBuffer, kDataSize).error()); } TEST_F(ServiceMessageTest, ReadVector) { ExpectDefaultHandleMessage(); char buffer1[10]; char buffer2[20]; iovec vec[] = {{buffer1, sizeof(buffer1)}, {buffer2, sizeof(buffer2)}}; EXPECT_CALL(*endpoint(), ReadMessageData( message_.get(), IoVecMatcher(IoVecArray{std::begin(vec), std::end(vec)}), 2)) .WillOnce(Return(30)) .WillOnce(Return(15)) .WillOnce(Return(ErrorStatus{EBADF})); EXPECT_EQ(30u, message_->ReadVector(vec, 2).get()); EXPECT_EQ(15u, message_->ReadVector(vec).get()); EXPECT_EQ(EBADF, message_->ReadVector(vec).error()); } TEST_F(ServiceMessageTest, Write) { ExpectDefaultHandleMessage(); void* const kDataBuffer = IntToPtr(12345); const size_t kDataSize = 100; EXPECT_CALL( *endpoint(), WriteMessageData(message_.get(), IoVecMatcher(kDataBuffer, kDataSize), 1)) .WillOnce(Return(50)) .WillOnce(Return(ErrorStatus{EBADMSG})); EXPECT_EQ(50u, message_->Write(kDataBuffer, kDataSize).get()); EXPECT_EQ(EBADMSG, message_->Write(kDataBuffer, kDataSize).error()); } TEST_F(ServiceMessageTest, WriteVector) { ExpectDefaultHandleMessage(); char buffer1[10]; char buffer2[20]; iovec vec[] = {{buffer1, sizeof(buffer1)}, {buffer2, sizeof(buffer2)}}; EXPECT_CALL(*endpoint(), WriteMessageData( message_.get(), IoVecMatcher(IoVecArray{std::begin(vec), std::end(vec)}), 2)) .WillOnce(Return(30)) .WillOnce(Return(15)) .WillOnce(Return(ErrorStatus{EIO})); EXPECT_EQ(30u, message_->WriteVector(vec, 2).get()); EXPECT_EQ(15u, message_->WriteVector(vec).get()); EXPECT_EQ(EIO, message_->WriteVector(vec, 2).error()); } TEST_F(ServiceMessageTest, PushLocalFileHandle) { ExpectDefaultHandleMessage(); const int kFakeFd = 12345; LocalHandle handle{kFakeFd}; EXPECT_CALL(*endpoint(), PushFileHandle(message_.get(), Matcher( FileHandleMatcher(kFakeFd)))) .WillOnce(Return(12)) .WillOnce(Return(ErrorStatus{EIO})); EXPECT_EQ(12, message_->PushFileHandle(handle).get()); EXPECT_EQ(EIO, message_->PushFileHandle(handle).error()); handle.Release(); // Make sure we do not close the fake file descriptor. } TEST_F(ServiceMessageTest, PushBorrowedFileHandle) { ExpectDefaultHandleMessage(); const int kFakeFd = 12345; BorrowedHandle handle{kFakeFd}; EXPECT_CALL(*endpoint(), PushFileHandle(message_.get(), Matcher( FileHandleMatcher(kFakeFd)))) .WillOnce(Return(13)) .WillOnce(Return(ErrorStatus{EACCES})); EXPECT_EQ(13, message_->PushFileHandle(handle).get()); EXPECT_EQ(EACCES, message_->PushFileHandle(handle).error()); } TEST_F(ServiceMessageTest, PushRemoteFileHandle) { ExpectDefaultHandleMessage(); const int kFakeFd = 12345; RemoteHandle handle{kFakeFd}; EXPECT_CALL(*endpoint(), PushFileHandle(message_.get(), Matcher( FileHandleMatcher(kFakeFd)))) .WillOnce(Return(kFakeFd)) .WillOnce(Return(ErrorStatus{EIO})); EXPECT_EQ(kFakeFd, message_->PushFileHandle(handle).get()); EXPECT_EQ(EIO, message_->PushFileHandle(handle).error()); } TEST_F(ServiceMessageTest, PushLocalChannelHandle) { ExpectDefaultHandleMessage(); int32_t kValue = 12345; LocalChannelHandle handle{nullptr, kValue}; EXPECT_CALL(*endpoint(), PushChannelHandle(message_.get(), Matcher( ChannelHandleMatcher(kValue)))) .WillOnce(Return(7)) .WillOnce(Return(ErrorStatus{EIO})); EXPECT_EQ(7, message_->PushChannelHandle(handle).get()); EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error()); } TEST_F(ServiceMessageTest, PushBorrowedChannelHandle) { ExpectDefaultHandleMessage(); int32_t kValue = 12345; BorrowedChannelHandle handle{kValue}; EXPECT_CALL( *endpoint(), PushChannelHandle(message_.get(), Matcher( ChannelHandleMatcher(kValue)))) .WillOnce(Return(8)) .WillOnce(Return(ErrorStatus{EIO})); EXPECT_EQ(8, message_->PushChannelHandle(handle).get()); EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error()); } TEST_F(ServiceMessageTest, PushRemoteChannelHandle) { ExpectDefaultHandleMessage(); int32_t kValue = 12345; RemoteChannelHandle handle{kValue}; EXPECT_CALL( *endpoint(), PushChannelHandle(message_.get(), Matcher( ChannelHandleMatcher(kValue)))) .WillOnce(Return(kValue)) .WillOnce(Return(ErrorStatus{EIO})); EXPECT_EQ(kValue, message_->PushChannelHandle(handle).get()); EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error()); } TEST_F(ServiceMessageTest, GetFileHandle) { ExpectDefaultHandleMessage(); auto make_file_handle = [](FileReference ref) { return LocalHandle{ref}; }; EXPECT_CALL(*endpoint(), GetFileHandle(message_.get(), _)) .WillOnce(WithArg<1>(Invoke(make_file_handle))); LocalHandle handle; FileReference kRef = 12345; EXPECT_TRUE(message_->GetFileHandle(kRef, &handle)); EXPECT_EQ(kRef, handle.Get()); handle.Release(); // Make sure we do not close the fake file descriptor. } TEST_F(ServiceMessageTest, GetFileHandleInvalid) { ExpectDefaultHandleMessage(); LocalHandle handle; FileReference kRef = -12; EXPECT_TRUE(message_->GetFileHandle(kRef, &handle)); EXPECT_EQ(kRef, handle.Get()); } TEST_F(ServiceMessageTest, GetFileHandleError) { ExpectDefaultHandleMessage(); EXPECT_CALL(*endpoint(), GetFileHandle(message_.get(), _)) .WillOnce(WithoutArgs(Invoke([] { return LocalHandle{-EIO}; }))); LocalHandle handle; FileReference kRef = 12345; EXPECT_FALSE(message_->GetFileHandle(kRef, &handle)); EXPECT_EQ(-EIO, handle.Get()); } TEST_F(ServiceMessageTest, GetChannelHandle) { ExpectDefaultHandleMessage(); auto make_channel_handle = [](ChannelReference ref) { return LocalChannelHandle{nullptr, ref}; }; EXPECT_CALL(*endpoint(), GetChannelHandle(message_.get(), _)) .WillOnce(WithArg<1>(Invoke(make_channel_handle))); LocalChannelHandle handle; ChannelReference kRef = 12345; EXPECT_TRUE(message_->GetChannelHandle(kRef, &handle)); EXPECT_EQ(kRef, handle.value()); } TEST_F(ServiceMessageTest, GetChannelHandleInvalid) { ExpectDefaultHandleMessage(); LocalChannelHandle handle; ChannelReference kRef = -12; EXPECT_TRUE(message_->GetChannelHandle(kRef, &handle)); EXPECT_EQ(-12, handle.value()); } TEST_F(ServiceMessageTest, GetChannelHandleError) { ExpectDefaultHandleMessage(); EXPECT_CALL(*endpoint(), GetChannelHandle(message_.get(), _)) .WillOnce(WithoutArgs(Invoke([] { return LocalChannelHandle{nullptr, -EIO}; }))); LocalChannelHandle handle; ChannelReference kRef = 12345; EXPECT_FALSE(message_->GetChannelHandle(kRef, &handle)); EXPECT_EQ(-EIO, handle.value()); } TEST_F(ServiceMessageTest, ModifyChannelEvents) { ExpectDefaultHandleMessage(); int kClearMask = 1; int kSetMask = 2; EXPECT_CALL(*endpoint(), ModifyChannelEvents(kTestCid, kClearMask, kSetMask)) .WillOnce(Return(Status{})); EXPECT_TRUE(message_->ModifyChannelEvents(kClearMask, kSetMask)); } TEST_F(ServiceMessageTest, PushChannelSameService) { ExpectDefaultHandleMessage(); int kFlags = 123; int32_t kValue = 12; EXPECT_CALL(*endpoint(), PushChannel(message_.get(), kFlags, nullptr, _)) .WillOnce(DoAll(SetArgPointee<3>(kTestCid), Return(ByMove(RemoteChannelHandle{kValue})))); int channel_id = -1; auto status = message_->PushChannel(kFlags, nullptr, &channel_id); ASSERT_TRUE(status); EXPECT_EQ(kValue, status.get().value()); EXPECT_EQ(kTestCid, channel_id); } TEST_F(ServiceMessageTest, PushChannelFailure) { ExpectDefaultHandleMessage(); int kFlags = 123; EXPECT_CALL(*endpoint(), PushChannel(message_.get(), kFlags, nullptr, _)) .WillOnce(Return(ByMove(ErrorStatus{EIO}))); int channel_id = -1; auto status = message_->PushChannel(kFlags, nullptr, &channel_id); ASSERT_FALSE(status); EXPECT_EQ(EIO, status.error()); } TEST_F(ServiceMessageTest, PushChannelDifferentService) { ExpectDefaultHandleMessage(); auto endpoint2 = std::make_unique>(); EXPECT_CALL(*endpoint2, SetService(_)) .Times(2) .WillRepeatedly(Return(Status{})); auto service2 = std::make_shared("MockSvc2", std::move(endpoint2)); int kFlags = 123; int32_t kValue = 12; EXPECT_CALL(*static_cast(service2->endpoint()), PushChannel(message_.get(), kFlags, nullptr, _)) .WillOnce(DoAll(SetArgPointee<3>(kTestCid), Return(ByMove(RemoteChannelHandle{kValue})))); int channel_id = -1; auto status = message_->PushChannel(service2.get(), kFlags, nullptr, &channel_id); ASSERT_TRUE(status); EXPECT_EQ(kValue, status.get().value()); EXPECT_EQ(kTestCid, channel_id); } TEST_F(ServiceMessageTest, CheckChannelSameService) { ExpectDefaultHandleMessage(); auto test_channel = std::make_shared(); ChannelReference kRef = 123; EXPECT_CALL(*endpoint(), CheckChannel(message_.get(), kRef, _)) .WillOnce(DoAll(SetArgPointee<2>(test_channel.get()), Return(kTestCid))); std::shared_ptr channel; auto status = message_->CheckChannel(kRef, &channel); ASSERT_TRUE(status); EXPECT_EQ(kTestCid, status.get()); EXPECT_EQ(test_channel, channel); } TEST_F(ServiceMessageTest, CheckChannelFailure) { ExpectDefaultHandleMessage(); ChannelReference kRef = 123; EXPECT_CALL(*endpoint(), CheckChannel(message_.get(), kRef, _)) .WillOnce(Return(ByMove(ErrorStatus{EOPNOTSUPP}))); std::shared_ptr channel; auto status = message_->CheckChannel(kRef, &channel); ASSERT_FALSE(status); EXPECT_EQ(EOPNOTSUPP, status.error()); } TEST_F(ServiceMessageTest, CheckChannelDifferentService) { ExpectDefaultHandleMessage(); auto endpoint2 = std::make_unique>(); EXPECT_CALL(*endpoint2, SetService(_)) .Times(2) .WillRepeatedly(Return(Status{})); auto service2 = std::make_shared("MockSvc2", std::move(endpoint2)); auto test_channel = std::make_shared(); ChannelReference kRef = 123; EXPECT_CALL(*static_cast(service2->endpoint()), CheckChannel(message_.get(), kRef, _)) .WillOnce(DoAll(SetArgPointee<2>(test_channel.get()), Return(kTestCid))); std::shared_ptr channel; auto status = message_->CheckChannel(service2.get(), kRef, &channel); ASSERT_TRUE(status); EXPECT_EQ(kTestCid, status.get()); EXPECT_EQ(test_channel, channel); }