| #include <pdx/client.h> | |
| #include <gmock/gmock.h> | |
| #include <sys/eventfd.h> | |
| #include <pdx/mock_client_channel.h> | |
| #include <pdx/mock_client_channel_factory.h> | |
| #include <pdx/rpc/remote_method.h> | |
| using android::pdx::BorrowedChannelHandle; | |
| using android::pdx::BorrowedHandle; | |
| using android::pdx::ClientBase; | |
| using android::pdx::ClientChannel; | |
| using android::pdx::ClientChannelFactory; | |
| using android::pdx::ErrorStatus; | |
| using android::pdx::LocalChannelHandle; | |
| using android::pdx::LocalHandle; | |
| using android::pdx::MockClientChannel; | |
| using android::pdx::MockClientChannelFactory; | |
| using android::pdx::RemoteChannelHandle; | |
| using android::pdx::RemoteHandle; | |
| using android::pdx::Status; | |
| using android::pdx::Transaction; | |
| using android::pdx::rpc::Void; | |
| using testing::A; | |
| using testing::AnyNumber; | |
| using testing::ByMove; | |
| using testing::Invoke; | |
| using testing::Ne; | |
| using testing::Return; | |
| using testing::_; | |
| namespace { | |
| inline void* IntToPtr(intptr_t addr) { return reinterpret_cast<void*>(addr); } | |
| inline const void* IntToConstPtr(intptr_t addr) { | |
| return reinterpret_cast<const void*>(addr); | |
| } | |
| struct TestInterface final { | |
| // Op codes. | |
| enum { | |
| kOpAdd = 0, | |
| kOpSendFile, | |
| kOpGetFile, | |
| kOpPushChannel, | |
| }; | |
| // Methods. | |
| PDX_REMOTE_METHOD(Add, kOpAdd, int(int, int)); | |
| PDX_REMOTE_METHOD(SendFile, kOpSendFile, void(const LocalHandle& fd)); | |
| PDX_REMOTE_METHOD(GetFile, kOpGetFile, LocalHandle(const std::string&, int)); | |
| PDX_REMOTE_METHOD(PushChannel, kOpPushChannel, LocalChannelHandle(Void)); | |
| PDX_REMOTE_API(API, Add, SendFile, GetFile, PushChannel); | |
| }; | |
| class SimpleClient : public ClientBase<SimpleClient> { | |
| public: | |
| explicit SimpleClient(std::unique_ptr<ClientChannel> channel) | |
| : BASE{std::move(channel)} {} | |
| SimpleClient(std::unique_ptr<ClientChannelFactory> channel_factory, | |
| int64_t timeout_ms) | |
| : BASE{std::move(channel_factory), timeout_ms} { | |
| EnableAutoReconnect(timeout_ms); | |
| } | |
| using BASE::SendImpulse; | |
| using BASE::InvokeRemoteMethod; | |
| using BASE::InvokeRemoteMethodInPlace; | |
| using BASE::Close; | |
| using BASE::IsConnected; | |
| using BASE::EnableAutoReconnect; | |
| using BASE::DisableAutoReconnect; | |
| using BASE::event_fd; | |
| using BASE::GetChannel; | |
| MOCK_METHOD0(OnConnect, void()); | |
| }; | |
| class FailingClient : public ClientBase<FailingClient> { | |
| public: | |
| explicit FailingClient(std::unique_ptr<ClientChannel> channel, int error_code) | |
| : BASE{std::move(channel)} { | |
| Close(error_code); | |
| } | |
| }; | |
| class ClientChannelTest : public testing::Test { | |
| public: | |
| ClientChannelTest() | |
| : client_{SimpleClient::Create( | |
| std::make_unique<testing::StrictMock<MockClientChannel>>())} {} | |
| MockClientChannel* mock_channel() { | |
| return static_cast<MockClientChannel*>(client_->GetChannel()); | |
| } | |
| std::unique_ptr<SimpleClient> client_; | |
| }; | |
| class ClientChannelFactoryTest : public testing::Test { | |
| public: | |
| ClientChannelFactoryTest() { | |
| auto factory = | |
| std::make_unique<testing::NiceMock<MockClientChannelFactory>>(); | |
| ON_CALL(*factory, Connect(kTimeout)) | |
| .WillByDefault(Invoke(this, &ClientChannelFactoryTest::OnConnect)); | |
| client_ = SimpleClient::Create(std::move(factory), kTimeout); | |
| } | |
| MockClientChannel* mock_channel() { | |
| return static_cast<MockClientChannel*>(client_->GetChannel()); | |
| } | |
| Status<std::unique_ptr<ClientChannel>> OnConnect(int64_t /*timeout_ms*/) { | |
| if (on_connect_error_) | |
| return ErrorStatus(on_connect_error_); | |
| std::unique_ptr<MockClientChannel> channel = | |
| std::make_unique<testing::StrictMock<MockClientChannel>>(); | |
| if (on_connect_callback_) | |
| on_connect_callback_(channel.get()); | |
| return Status<std::unique_ptr<ClientChannel>>{std::move(channel)}; | |
| } | |
| void OnConnectCallback(std::function<void(MockClientChannel*)> callback) { | |
| on_connect_callback_ = callback; | |
| } | |
| void SetOnConnectError(int error) { on_connect_error_ = error; } | |
| void ResetOnConnectError() { on_connect_error_ = 0; } | |
| constexpr static int64_t kTimeout = 123; | |
| std::unique_ptr<SimpleClient> client_; | |
| std::function<void(MockClientChannel*)> on_connect_callback_; | |
| int on_connect_error_{0}; | |
| }; | |
| constexpr int64_t ClientChannelFactoryTest::kTimeout; | |
| class ClientTransactionTest : public ClientChannelTest { | |
| public: | |
| ClientTransactionTest() : transaction_{*client_} {} | |
| Transaction transaction_; | |
| }; | |
| } // anonymous namespace | |
| TEST_F(ClientChannelTest, IsInitialized) { | |
| ASSERT_NE(client_.get(), nullptr); | |
| EXPECT_TRUE(client_->IsInitialized()); | |
| EXPECT_TRUE(client_->IsConnected()); | |
| } | |
| TEST_F(ClientChannelTest, CloseOnConstruction) { | |
| FailingClient failed_client1{std::make_unique<MockClientChannel>(), EACCES}; | |
| ASSERT_FALSE(failed_client1.IsInitialized()); | |
| EXPECT_EQ(-EACCES, failed_client1.error()); | |
| FailingClient failed_client2{std::make_unique<MockClientChannel>(), -EACCES}; | |
| ASSERT_FALSE(failed_client2.IsInitialized()); | |
| EXPECT_EQ(-EACCES, failed_client2.error()); | |
| auto failed_client3 = | |
| FailingClient::Create(std::make_unique<MockClientChannel>(), EIO); | |
| ASSERT_EQ(failed_client3.get(), nullptr); | |
| } | |
| TEST_F(ClientChannelTest, IsConnected) { | |
| EXPECT_TRUE(client_->IsConnected()); | |
| EXPECT_EQ(0, client_->error()); | |
| client_->Close(-EINVAL); | |
| EXPECT_FALSE(client_->IsConnected()); | |
| EXPECT_EQ(-EINVAL, client_->error()); | |
| } | |
| TEST_F(ClientChannelTest, event_fd) { | |
| EXPECT_CALL(*mock_channel(), event_fd()).WillOnce(Return(12)); | |
| EXPECT_EQ(12, client_->event_fd()); | |
| } | |
| TEST_F(ClientChannelTest, SendImpulse) { | |
| EXPECT_CALL(*mock_channel(), SendImpulse(123, nullptr, 0)) | |
| .WillOnce(Return(Status<void>{})); | |
| EXPECT_TRUE(client_->SendImpulse(123)); | |
| EXPECT_CALL(*mock_channel(), SendImpulse(17, nullptr, 0)) | |
| .WillOnce(Return(ErrorStatus{EIO})); | |
| auto status = client_->SendImpulse(17); | |
| ASSERT_FALSE(status); | |
| EXPECT_EQ(EIO, status.error()); | |
| const void* const kTestPtr = IntToConstPtr(1234); | |
| EXPECT_CALL(*mock_channel(), SendImpulse(1, kTestPtr, 17)) | |
| .WillOnce(Return(Status<void>{})); | |
| EXPECT_TRUE(client_->SendImpulse(1, kTestPtr, 17)); | |
| } | |
| TEST_F(ClientChannelTest, InvokeRemoteMethodNullTransactionState) { | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(nullptr)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithInt(nullptr, TestInterface::kOpAdd, _, _, nullptr, 0)) | |
| .WillOnce(Return(9)); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr)); | |
| EXPECT_TRUE(client_->InvokeRemoteMethod<TestInterface::Add>(4, 5)); | |
| } | |
| TEST_F(ClientChannelTest, InvokeRemoteMethodAddSuccess) { | |
| void* const kTransactionState = IntToPtr(123); | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL( | |
| *mock_channel(), | |
| SendWithInt(kTransactionState, TestInterface::kOpAdd, _, _, nullptr, 0)) | |
| .WillOnce(Return(3)); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| Status<int> status = client_->InvokeRemoteMethod<TestInterface::Add>(1, 2); | |
| ASSERT_TRUE(status); | |
| EXPECT_EQ(3, status.get()); | |
| } | |
| TEST_F(ClientChannelTest, InvokeRemoteMethodAddFailure) { | |
| void* const kTransactionState = IntToPtr(123); | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL( | |
| *mock_channel(), | |
| SendWithInt(kTransactionState, TestInterface::kOpAdd, _, _, nullptr, 0)) | |
| .WillOnce(Return(ErrorStatus{EIO})); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| Status<int> status = client_->InvokeRemoteMethod<TestInterface::Add>(1, 2); | |
| ASSERT_FALSE(status); | |
| EXPECT_EQ(EIO, status.error()); | |
| } | |
| TEST_F(ClientChannelTest, InvokeRemoteMethodGetFileSuccess) { | |
| void* const kTransactionState = IntToPtr(123); | |
| int fd = eventfd(0, 0); | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithFileHandle(kTransactionState, TestInterface::kOpGetFile, | |
| _, _, nullptr, 0)) | |
| .WillOnce(Return(ByMove(LocalHandle{fd}))); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| Status<LocalHandle> status = | |
| client_->InvokeRemoteMethod<TestInterface::GetFile>(); | |
| ASSERT_TRUE(status); | |
| EXPECT_EQ(fd, status.get().Get()); | |
| } | |
| TEST_F(ClientChannelTest, InvokeRemoteMethodGetFileFailure) { | |
| void* const kTransactionState = IntToPtr(123); | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithFileHandle(kTransactionState, TestInterface::kOpGetFile, | |
| _, _, nullptr, 0)) | |
| .WillOnce(Return(ByMove(ErrorStatus{EACCES}))); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| Status<LocalHandle> status = | |
| client_->InvokeRemoteMethod<TestInterface::GetFile>("file", 0); | |
| ASSERT_FALSE(status); | |
| EXPECT_EQ(EACCES, status.error()); | |
| } | |
| TEST_F(ClientChannelTest, InvokeRemoteMethodPushChannelSuccess) { | |
| void* const kTransactionState = IntToPtr(123); | |
| const int32_t kHandleValue = 17; | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL( | |
| *mock_channel(), | |
| SendWithChannelHandle(kTransactionState, TestInterface::kOpPushChannel, _, | |
| _, nullptr, 0)) | |
| .WillOnce(Return(ByMove(LocalChannelHandle{nullptr, kHandleValue}))); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| Status<LocalChannelHandle> status = | |
| client_->InvokeRemoteMethod<TestInterface::PushChannel>(); | |
| ASSERT_TRUE(status); | |
| EXPECT_EQ(kHandleValue, status.get().value()); | |
| } | |
| TEST_F(ClientChannelTest, InvokeRemoteMethodPushChannelFailure) { | |
| void* const kTransactionState = IntToPtr(123); | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL( | |
| *mock_channel(), | |
| SendWithChannelHandle(kTransactionState, TestInterface::kOpPushChannel, _, | |
| _, nullptr, 0)) | |
| .WillOnce(Return(ByMove(ErrorStatus{EACCES}))); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| Status<LocalChannelHandle> status = | |
| client_->InvokeRemoteMethod<TestInterface::PushChannel>(); | |
| ASSERT_FALSE(status); | |
| EXPECT_EQ(EACCES, status.error()); | |
| } | |
| TEST_F(ClientChannelTest, InvokeRemoteMethodSendFileSuccess) { | |
| void* const kTransactionState = IntToPtr(123); | |
| LocalHandle fd{eventfd(0, 0)}; | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), | |
| PushFileHandle(kTransactionState, A<const LocalHandle&>())) | |
| .WillOnce(Return(1)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithInt(kTransactionState, TestInterface::kOpSendFile, _, _, | |
| nullptr, 0)) | |
| .WillOnce(Return(0)); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| EXPECT_TRUE(client_->InvokeRemoteMethod<TestInterface::SendFile>(fd)); | |
| } | |
| TEST_F(ClientChannelTest, InvokeRemoteMethodSendFileFailure) { | |
| void* const kTransactionState = IntToPtr(123); | |
| LocalHandle fd{eventfd(0, 0)}; | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), | |
| PushFileHandle(kTransactionState, A<const LocalHandle&>())) | |
| .WillOnce(Return(1)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithInt(kTransactionState, TestInterface::kOpSendFile, _, _, | |
| nullptr, 0)) | |
| .WillOnce(Return(ErrorStatus{EACCES})); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| EXPECT_FALSE(client_->InvokeRemoteMethod<TestInterface::SendFile>(fd)); | |
| } | |
| TEST_F(ClientChannelFactoryTest, IsInitialized) { | |
| ASSERT_NE(client_.get(), nullptr); | |
| EXPECT_TRUE(client_->IsInitialized()); | |
| EXPECT_TRUE(client_->IsConnected()); | |
| } | |
| TEST_F(ClientChannelFactoryTest, NotConnectedButInitialized) { | |
| auto factory = | |
| std::make_unique<testing::NiceMock<MockClientChannelFactory>>(); | |
| EXPECT_CALL(*factory, Connect(kTimeout)) | |
| .WillOnce(Return(ByMove(ErrorStatus(ESHUTDOWN)))) | |
| .WillOnce(Invoke(this, &ClientChannelFactoryTest::OnConnect)); | |
| client_ = SimpleClient::Create(std::move(factory), kTimeout); | |
| ASSERT_NE(client_.get(), nullptr); | |
| EXPECT_TRUE(client_->IsInitialized()); | |
| EXPECT_FALSE(client_->IsConnected()); | |
| client_->DisableAutoReconnect(); | |
| ASSERT_FALSE(client_->SendImpulse(17)); | |
| EXPECT_FALSE(client_->IsConnected()); | |
| client_->EnableAutoReconnect(kTimeout); | |
| EXPECT_CALL(*client_, OnConnect()); | |
| OnConnectCallback([](auto* mock) { | |
| EXPECT_CALL(*mock, SendImpulse(17, nullptr, 0)) | |
| .WillOnce(Return(Status<void>{})); | |
| }); | |
| ASSERT_TRUE(client_->SendImpulse(17)); | |
| EXPECT_TRUE(client_->IsConnected()); | |
| } | |
| TEST_F(ClientChannelFactoryTest, CheckDisconnect) { | |
| EXPECT_CALL(*mock_channel(), SendImpulse(17, nullptr, 0)) | |
| .WillOnce(Return(ErrorStatus{ESHUTDOWN})); | |
| ASSERT_FALSE(client_->SendImpulse(17)); | |
| EXPECT_FALSE(client_->IsConnected()); | |
| EXPECT_EQ(-ESHUTDOWN, client_->error()); | |
| } | |
| TEST_F(ClientChannelFactoryTest, CheckReconnect) { | |
| client_->Close(ESHUTDOWN); | |
| ASSERT_FALSE(client_->IsConnected()); | |
| EXPECT_CALL(*client_, OnConnect()); | |
| OnConnectCallback([](auto* mock) { | |
| EXPECT_CALL(*mock, SendImpulse(17, nullptr, 0)) | |
| .WillOnce(Return(Status<void>{})); | |
| }); | |
| ASSERT_TRUE(client_->SendImpulse(17)); | |
| EXPECT_TRUE(client_->IsConnected()); | |
| } | |
| TEST_F(ClientChannelFactoryTest, CloseOnConnect) { | |
| client_->Close(ESHUTDOWN); | |
| EXPECT_CALL(*client_, OnConnect()).WillOnce(Invoke([this] { | |
| client_->Close(EIO); | |
| })); | |
| auto status = client_->SendImpulse(17); | |
| ASSERT_FALSE(status); | |
| EXPECT_EQ(EIO, status.error()); | |
| EXPECT_FALSE(client_->IsConnected()); | |
| EXPECT_EQ(-EIO, client_->error()); | |
| } | |
| TEST_F(ClientChannelFactoryTest, DisableAutoReconnect) { | |
| client_->Close(EIO); | |
| ASSERT_FALSE(client_->IsConnected()); | |
| client_->DisableAutoReconnect(); | |
| auto status = client_->SendImpulse(17); | |
| ASSERT_FALSE(status); | |
| EXPECT_EQ(ESHUTDOWN, status.error()); | |
| EXPECT_FALSE(client_->IsConnected()); | |
| client_->EnableAutoReconnect(kTimeout); | |
| EXPECT_CALL(*client_, OnConnect()); | |
| OnConnectCallback([](auto* mock) { | |
| EXPECT_CALL(*mock, SendImpulse(17, nullptr, 0)) | |
| .WillOnce(Return(Status<void>{})); | |
| }); | |
| ASSERT_TRUE(client_->SendImpulse(17)); | |
| EXPECT_TRUE(client_->IsConnected()); | |
| } | |
| TEST_F(ClientTransactionTest, SendNoData) { | |
| void* const kTransactionState = IntToPtr(123); | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithInt(kTransactionState, 1, nullptr, 0, nullptr, 0)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.Send<void>(1)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithFileHandle(kTransactionState, 2, nullptr, 0, nullptr, 0)) | |
| .WillOnce(Return(ByMove(LocalHandle{-1}))); | |
| EXPECT_TRUE(transaction_.Send<LocalHandle>(2)); | |
| EXPECT_CALL(*mock_channel(), SendWithChannelHandle(kTransactionState, 3, | |
| nullptr, 0, nullptr, 0)) | |
| .WillOnce(Return(ByMove(LocalChannelHandle{nullptr, 1}))); | |
| EXPECT_TRUE(transaction_.Send<LocalChannelHandle>(3)); | |
| } | |
| TEST_F(ClientTransactionTest, SendNoState) { | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(nullptr)); | |
| EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 1, nullptr, 0, nullptr, 0)) | |
| .WillOnce(Return(0)); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr)); | |
| EXPECT_TRUE(transaction_.Send<void>(1)); | |
| } | |
| TEST_F(ClientTransactionTest, SendBuffers) { | |
| const void* const kSendBuffer = IntToConstPtr(123); | |
| const size_t kSendSize = 12; | |
| void* const kReceiveBuffer = IntToPtr(456); | |
| const size_t kReceiveSize = 34; | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(nullptr)); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr)); | |
| EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 1, nullptr, 0, nullptr, 0)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.Send<void>(1, nullptr, 0, nullptr, 0)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithInt(nullptr, 2, Ne(nullptr), 1, nullptr, 0)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.Send<void>(2, kSendBuffer, kSendSize, nullptr, 0)); | |
| EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 3, nullptr, 0, nullptr, 0)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.Send<void>(3, kSendBuffer, 0, nullptr, 0)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithInt(nullptr, 4, nullptr, 0, Ne(nullptr), 1)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE( | |
| transaction_.Send<void>(4, nullptr, 0, kReceiveBuffer, kReceiveSize)); | |
| EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 5, nullptr, 0, nullptr, 0)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.Send<void>(5, nullptr, 0, kReceiveBuffer, 0)); | |
| EXPECT_CALL(*mock_channel(), | |
| SendWithInt(nullptr, 5, Ne(nullptr), 1, Ne(nullptr), 1)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.Send<void>(5, kSendBuffer, kSendSize, kReceiveBuffer, | |
| kReceiveSize)); | |
| } | |
| TEST_F(ClientTransactionTest, SendVector) { | |
| iovec send[3] = {}; | |
| iovec recv[4] = {}; | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(nullptr)); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr)); | |
| EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 1, nullptr, 0, nullptr, 0)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.SendVector<void>(1, nullptr, 0, nullptr, 0)); | |
| EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 2, send, 3, recv, 4)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.SendVector<void>(2, send, 3, recv, 4)); | |
| EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 3, send, 3, nullptr, 0)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.SendVector<void>(3, send, nullptr)); | |
| EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 4, nullptr, 0, recv, 4)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.SendVector<void>(4, nullptr, recv)); | |
| EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 5, send, 3, recv, 4)) | |
| .WillOnce(Return(0)); | |
| EXPECT_TRUE(transaction_.SendVector<void>(5, send, recv)); | |
| } | |
| TEST_F(ClientTransactionTest, PushHandle) { | |
| void* const kTransactionState = IntToPtr(123); | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), | |
| PushFileHandle(kTransactionState, A<const LocalHandle&>())) | |
| .WillOnce(Return(1)); | |
| EXPECT_EQ(1, transaction_.PushFileHandle(LocalHandle{-1}).get()); | |
| EXPECT_CALL(*mock_channel(), | |
| PushFileHandle(kTransactionState, A<const BorrowedHandle&>())) | |
| .WillOnce(Return(2)); | |
| EXPECT_EQ(2, transaction_.PushFileHandle(BorrowedHandle{-1}).get()); | |
| EXPECT_EQ(3, transaction_.PushFileHandle(RemoteHandle{3}).get()); | |
| EXPECT_CALL( | |
| *mock_channel(), | |
| PushChannelHandle(kTransactionState, A<const LocalChannelHandle&>())) | |
| .WillOnce(Return(11)); | |
| EXPECT_EQ( | |
| 11, transaction_.PushChannelHandle(LocalChannelHandle{nullptr, 1}).get()); | |
| EXPECT_CALL( | |
| *mock_channel(), | |
| PushChannelHandle(kTransactionState, A<const BorrowedChannelHandle&>())) | |
| .WillOnce(Return(12)); | |
| EXPECT_EQ(12, transaction_.PushChannelHandle(BorrowedChannelHandle{2}).get()); | |
| EXPECT_EQ(13, transaction_.PushChannelHandle(RemoteChannelHandle{13}).get()); | |
| } | |
| TEST_F(ClientTransactionTest, GetHandle) { | |
| void* const kTransactionState = IntToPtr(123); | |
| EXPECT_CALL(*mock_channel(), AllocateTransactionState()) | |
| .WillOnce(Return(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); | |
| EXPECT_CALL(*mock_channel(), GetFileHandle(kTransactionState, 1, _)) | |
| .WillOnce(Return(false)) | |
| .WillOnce(Return(true)); | |
| LocalHandle file_handle; | |
| EXPECT_FALSE(transaction_.GetFileHandle(1, &file_handle)); | |
| EXPECT_TRUE(transaction_.GetFileHandle(1, &file_handle)); | |
| EXPECT_CALL(*mock_channel(), GetChannelHandle(kTransactionState, 2, _)) | |
| .WillOnce(Return(false)) | |
| .WillOnce(Return(true)); | |
| LocalChannelHandle channel_handle; | |
| EXPECT_FALSE(transaction_.GetChannelHandle(2, &channel_handle)); | |
| EXPECT_TRUE(transaction_.GetChannelHandle(2, &channel_handle)); | |
| } |