| #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)); |
| } |