1#include <pdx/client.h>
2
3#include <gmock/gmock.h>
4#include <sys/eventfd.h>
5
6#include <pdx/mock_client_channel.h>
7#include <pdx/mock_client_channel_factory.h>
8#include <pdx/rpc/remote_method.h>
9
10using android::pdx::BorrowedChannelHandle;
11using android::pdx::BorrowedHandle;
12using android::pdx::ClientBase;
13using android::pdx::ClientChannel;
14using android::pdx::ClientChannelFactory;
15using android::pdx::ErrorStatus;
16using android::pdx::LocalChannelHandle;
17using android::pdx::LocalHandle;
18using android::pdx::MockClientChannel;
19using android::pdx::MockClientChannelFactory;
20using android::pdx::RemoteChannelHandle;
21using android::pdx::RemoteHandle;
22using android::pdx::Status;
23using android::pdx::Transaction;
24using android::pdx::rpc::Void;
25
26using testing::A;
27using testing::AnyNumber;
28using testing::ByMove;
29using testing::Invoke;
30using testing::Ne;
31using testing::Return;
32using testing::_;
33
34namespace {
35
36inline void* IntToPtr(intptr_t addr) { return reinterpret_cast<void*>(addr); }
37inline const void* IntToConstPtr(intptr_t addr) {
38  return reinterpret_cast<const void*>(addr);
39}
40
41struct TestInterface final {
42  // Op codes.
43  enum {
44    kOpAdd = 0,
45    kOpSendFile,
46    kOpGetFile,
47    kOpPushChannel,
48  };
49
50  // Methods.
51  PDX_REMOTE_METHOD(Add, kOpAdd, int(int, int));
52  PDX_REMOTE_METHOD(SendFile, kOpSendFile, void(const LocalHandle& fd));
53  PDX_REMOTE_METHOD(GetFile, kOpGetFile, LocalHandle(const std::string&, int));
54  PDX_REMOTE_METHOD(PushChannel, kOpPushChannel, LocalChannelHandle(Void));
55
56  PDX_REMOTE_API(API, Add, SendFile, GetFile, PushChannel);
57};
58
59class SimpleClient : public ClientBase<SimpleClient> {
60 public:
61  explicit SimpleClient(std::unique_ptr<ClientChannel> channel)
62      : BASE{std::move(channel)} {}
63  SimpleClient(std::unique_ptr<ClientChannelFactory> channel_factory,
64               int64_t timeout_ms)
65      : BASE{std::move(channel_factory), timeout_ms} {
66    EnableAutoReconnect(timeout_ms);
67  }
68
69  using BASE::SendImpulse;
70  using BASE::InvokeRemoteMethod;
71  using BASE::InvokeRemoteMethodInPlace;
72  using BASE::Close;
73  using BASE::IsConnected;
74  using BASE::EnableAutoReconnect;
75  using BASE::DisableAutoReconnect;
76  using BASE::event_fd;
77  using BASE::GetChannel;
78
79  MOCK_METHOD0(OnConnect, void());
80};
81
82class FailingClient : public ClientBase<FailingClient> {
83 public:
84  explicit FailingClient(std::unique_ptr<ClientChannel> channel, int error_code)
85      : BASE{std::move(channel)} {
86    Close(error_code);
87  }
88};
89
90class ClientChannelTest : public testing::Test {
91 public:
92  ClientChannelTest()
93      : client_{SimpleClient::Create(
94            std::make_unique<testing::StrictMock<MockClientChannel>>())} {}
95
96  MockClientChannel* mock_channel() {
97    return static_cast<MockClientChannel*>(client_->GetChannel());
98  }
99
100  std::unique_ptr<SimpleClient> client_;
101};
102
103class ClientChannelFactoryTest : public testing::Test {
104 public:
105  ClientChannelFactoryTest() {
106    auto factory =
107        std::make_unique<testing::NiceMock<MockClientChannelFactory>>();
108    ON_CALL(*factory, Connect(kTimeout))
109        .WillByDefault(Invoke(this, &ClientChannelFactoryTest::OnConnect));
110    client_ = SimpleClient::Create(std::move(factory), kTimeout);
111  }
112
113  MockClientChannel* mock_channel() {
114    return static_cast<MockClientChannel*>(client_->GetChannel());
115  }
116
117  Status<std::unique_ptr<ClientChannel>> OnConnect(int64_t /*timeout_ms*/) {
118    if (on_connect_error_)
119      return ErrorStatus(on_connect_error_);
120    std::unique_ptr<MockClientChannel> channel =
121        std::make_unique<testing::StrictMock<MockClientChannel>>();
122    if (on_connect_callback_)
123      on_connect_callback_(channel.get());
124    return Status<std::unique_ptr<ClientChannel>>{std::move(channel)};
125  }
126
127  void OnConnectCallback(std::function<void(MockClientChannel*)> callback) {
128    on_connect_callback_ = callback;
129  }
130  void SetOnConnectError(int error) { on_connect_error_ = error; }
131  void ResetOnConnectError() { on_connect_error_ = 0; }
132
133  constexpr static int64_t kTimeout = 123;
134  std::unique_ptr<SimpleClient> client_;
135  std::function<void(MockClientChannel*)> on_connect_callback_;
136  int on_connect_error_{0};
137};
138
139constexpr int64_t ClientChannelFactoryTest::kTimeout;
140
141class ClientTransactionTest : public ClientChannelTest {
142 public:
143  ClientTransactionTest() : transaction_{*client_} {}
144
145  Transaction transaction_;
146};
147
148}  // anonymous namespace
149
150TEST_F(ClientChannelTest, IsInitialized) {
151  ASSERT_NE(client_.get(), nullptr);
152  EXPECT_TRUE(client_->IsInitialized());
153  EXPECT_TRUE(client_->IsConnected());
154}
155
156TEST_F(ClientChannelTest, CloseOnConstruction) {
157  FailingClient failed_client1{std::make_unique<MockClientChannel>(), EACCES};
158  ASSERT_FALSE(failed_client1.IsInitialized());
159  EXPECT_EQ(-EACCES, failed_client1.error());
160
161  FailingClient failed_client2{std::make_unique<MockClientChannel>(), -EACCES};
162  ASSERT_FALSE(failed_client2.IsInitialized());
163  EXPECT_EQ(-EACCES, failed_client2.error());
164
165  auto failed_client3 =
166      FailingClient::Create(std::make_unique<MockClientChannel>(), EIO);
167  ASSERT_EQ(failed_client3.get(), nullptr);
168}
169
170TEST_F(ClientChannelTest, IsConnected) {
171  EXPECT_TRUE(client_->IsConnected());
172  EXPECT_EQ(0, client_->error());
173  client_->Close(-EINVAL);
174  EXPECT_FALSE(client_->IsConnected());
175  EXPECT_EQ(-EINVAL, client_->error());
176}
177
178TEST_F(ClientChannelTest, event_fd) {
179  EXPECT_CALL(*mock_channel(), event_fd()).WillOnce(Return(12));
180  EXPECT_EQ(12, client_->event_fd());
181}
182
183TEST_F(ClientChannelTest, SendImpulse) {
184  EXPECT_CALL(*mock_channel(), SendImpulse(123, nullptr, 0))
185      .WillOnce(Return(Status<void>{}));
186  EXPECT_TRUE(client_->SendImpulse(123));
187
188  EXPECT_CALL(*mock_channel(), SendImpulse(17, nullptr, 0))
189      .WillOnce(Return(ErrorStatus{EIO}));
190  auto status = client_->SendImpulse(17);
191  ASSERT_FALSE(status);
192  EXPECT_EQ(EIO, status.error());
193
194  const void* const kTestPtr = IntToConstPtr(1234);
195  EXPECT_CALL(*mock_channel(), SendImpulse(1, kTestPtr, 17))
196      .WillOnce(Return(Status<void>{}));
197  EXPECT_TRUE(client_->SendImpulse(1, kTestPtr, 17));
198}
199
200TEST_F(ClientChannelTest, InvokeRemoteMethodNullTransactionState) {
201  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
202      .WillOnce(Return(nullptr));
203  EXPECT_CALL(*mock_channel(),
204              SendWithInt(nullptr, TestInterface::kOpAdd, _, _, nullptr, 0))
205      .WillOnce(Return(9));
206  EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr));
207  EXPECT_TRUE(client_->InvokeRemoteMethod<TestInterface::Add>(4, 5));
208}
209
210TEST_F(ClientChannelTest, InvokeRemoteMethodAddSuccess) {
211  void* const kTransactionState = IntToPtr(123);
212  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
213      .WillOnce(Return(kTransactionState));
214  EXPECT_CALL(
215      *mock_channel(),
216      SendWithInt(kTransactionState, TestInterface::kOpAdd, _, _, nullptr, 0))
217      .WillOnce(Return(3));
218  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
219  Status<int> status = client_->InvokeRemoteMethod<TestInterface::Add>(1, 2);
220  ASSERT_TRUE(status);
221  EXPECT_EQ(3, status.get());
222}
223
224TEST_F(ClientChannelTest, InvokeRemoteMethodAddFailure) {
225  void* const kTransactionState = IntToPtr(123);
226  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
227      .WillOnce(Return(kTransactionState));
228  EXPECT_CALL(
229      *mock_channel(),
230      SendWithInt(kTransactionState, TestInterface::kOpAdd, _, _, nullptr, 0))
231      .WillOnce(Return(ErrorStatus{EIO}));
232  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
233  Status<int> status = client_->InvokeRemoteMethod<TestInterface::Add>(1, 2);
234  ASSERT_FALSE(status);
235  EXPECT_EQ(EIO, status.error());
236}
237
238TEST_F(ClientChannelTest, InvokeRemoteMethodGetFileSuccess) {
239  void* const kTransactionState = IntToPtr(123);
240  int fd = eventfd(0, 0);
241  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
242      .WillOnce(Return(kTransactionState));
243  EXPECT_CALL(*mock_channel(),
244              SendWithFileHandle(kTransactionState, TestInterface::kOpGetFile,
245                                 _, _, nullptr, 0))
246      .WillOnce(Return(ByMove(LocalHandle{fd})));
247  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
248  Status<LocalHandle> status =
249      client_->InvokeRemoteMethod<TestInterface::GetFile>();
250  ASSERT_TRUE(status);
251  EXPECT_EQ(fd, status.get().Get());
252}
253
254TEST_F(ClientChannelTest, InvokeRemoteMethodGetFileFailure) {
255  void* const kTransactionState = IntToPtr(123);
256  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
257      .WillOnce(Return(kTransactionState));
258  EXPECT_CALL(*mock_channel(),
259              SendWithFileHandle(kTransactionState, TestInterface::kOpGetFile,
260                                 _, _, nullptr, 0))
261      .WillOnce(Return(ByMove(ErrorStatus{EACCES})));
262  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
263  Status<LocalHandle> status =
264      client_->InvokeRemoteMethod<TestInterface::GetFile>("file", 0);
265  ASSERT_FALSE(status);
266  EXPECT_EQ(EACCES, status.error());
267}
268
269TEST_F(ClientChannelTest, InvokeRemoteMethodPushChannelSuccess) {
270  void* const kTransactionState = IntToPtr(123);
271  const int32_t kHandleValue = 17;
272  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
273      .WillOnce(Return(kTransactionState));
274  EXPECT_CALL(
275      *mock_channel(),
276      SendWithChannelHandle(kTransactionState, TestInterface::kOpPushChannel, _,
277                            _, nullptr, 0))
278      .WillOnce(Return(ByMove(LocalChannelHandle{nullptr, kHandleValue})));
279  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
280  Status<LocalChannelHandle> status =
281      client_->InvokeRemoteMethod<TestInterface::PushChannel>();
282  ASSERT_TRUE(status);
283  EXPECT_EQ(kHandleValue, status.get().value());
284}
285
286TEST_F(ClientChannelTest, InvokeRemoteMethodPushChannelFailure) {
287  void* const kTransactionState = IntToPtr(123);
288  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
289      .WillOnce(Return(kTransactionState));
290  EXPECT_CALL(
291      *mock_channel(),
292      SendWithChannelHandle(kTransactionState, TestInterface::kOpPushChannel, _,
293                            _, nullptr, 0))
294      .WillOnce(Return(ByMove(ErrorStatus{EACCES})));
295  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
296  Status<LocalChannelHandle> status =
297      client_->InvokeRemoteMethod<TestInterface::PushChannel>();
298  ASSERT_FALSE(status);
299  EXPECT_EQ(EACCES, status.error());
300}
301
302TEST_F(ClientChannelTest, InvokeRemoteMethodSendFileSuccess) {
303  void* const kTransactionState = IntToPtr(123);
304  LocalHandle fd{eventfd(0, 0)};
305  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
306      .WillOnce(Return(kTransactionState));
307  EXPECT_CALL(*mock_channel(),
308              PushFileHandle(kTransactionState, A<const LocalHandle&>()))
309      .WillOnce(Return(1));
310  EXPECT_CALL(*mock_channel(),
311              SendWithInt(kTransactionState, TestInterface::kOpSendFile, _, _,
312                          nullptr, 0))
313      .WillOnce(Return(0));
314  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
315  EXPECT_TRUE(client_->InvokeRemoteMethod<TestInterface::SendFile>(fd));
316}
317
318TEST_F(ClientChannelTest, InvokeRemoteMethodSendFileFailure) {
319  void* const kTransactionState = IntToPtr(123);
320  LocalHandle fd{eventfd(0, 0)};
321  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
322      .WillOnce(Return(kTransactionState));
323  EXPECT_CALL(*mock_channel(),
324              PushFileHandle(kTransactionState, A<const LocalHandle&>()))
325      .WillOnce(Return(1));
326  EXPECT_CALL(*mock_channel(),
327              SendWithInt(kTransactionState, TestInterface::kOpSendFile, _, _,
328                          nullptr, 0))
329      .WillOnce(Return(ErrorStatus{EACCES}));
330  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
331  EXPECT_FALSE(client_->InvokeRemoteMethod<TestInterface::SendFile>(fd));
332}
333
334TEST_F(ClientChannelFactoryTest, IsInitialized) {
335  ASSERT_NE(client_.get(), nullptr);
336  EXPECT_TRUE(client_->IsInitialized());
337  EXPECT_TRUE(client_->IsConnected());
338}
339
340TEST_F(ClientChannelFactoryTest, NotConnectedButInitialized) {
341  auto factory =
342      std::make_unique<testing::NiceMock<MockClientChannelFactory>>();
343  EXPECT_CALL(*factory, Connect(kTimeout))
344      .WillOnce(Return(ByMove(ErrorStatus(ESHUTDOWN))))
345      .WillOnce(Invoke(this, &ClientChannelFactoryTest::OnConnect));
346  client_ = SimpleClient::Create(std::move(factory), kTimeout);
347  ASSERT_NE(client_.get(), nullptr);
348  EXPECT_TRUE(client_->IsInitialized());
349  EXPECT_FALSE(client_->IsConnected());
350  client_->DisableAutoReconnect();
351  ASSERT_FALSE(client_->SendImpulse(17));
352  EXPECT_FALSE(client_->IsConnected());
353  client_->EnableAutoReconnect(kTimeout);
354  EXPECT_CALL(*client_, OnConnect());
355  OnConnectCallback([](auto* mock) {
356    EXPECT_CALL(*mock, SendImpulse(17, nullptr, 0))
357        .WillOnce(Return(Status<void>{}));
358  });
359  ASSERT_TRUE(client_->SendImpulse(17));
360  EXPECT_TRUE(client_->IsConnected());
361}
362
363TEST_F(ClientChannelFactoryTest, CheckDisconnect) {
364  EXPECT_CALL(*mock_channel(), SendImpulse(17, nullptr, 0))
365      .WillOnce(Return(ErrorStatus{ESHUTDOWN}));
366  ASSERT_FALSE(client_->SendImpulse(17));
367  EXPECT_FALSE(client_->IsConnected());
368  EXPECT_EQ(-ESHUTDOWN, client_->error());
369}
370
371TEST_F(ClientChannelFactoryTest, CheckReconnect) {
372  client_->Close(ESHUTDOWN);
373  ASSERT_FALSE(client_->IsConnected());
374
375  EXPECT_CALL(*client_, OnConnect());
376  OnConnectCallback([](auto* mock) {
377    EXPECT_CALL(*mock, SendImpulse(17, nullptr, 0))
378        .WillOnce(Return(Status<void>{}));
379  });
380  ASSERT_TRUE(client_->SendImpulse(17));
381  EXPECT_TRUE(client_->IsConnected());
382}
383
384TEST_F(ClientChannelFactoryTest, CloseOnConnect) {
385  client_->Close(ESHUTDOWN);
386
387  EXPECT_CALL(*client_, OnConnect()).WillOnce(Invoke([this] {
388    client_->Close(EIO);
389  }));
390  auto status = client_->SendImpulse(17);
391  ASSERT_FALSE(status);
392  EXPECT_EQ(EIO, status.error());
393  EXPECT_FALSE(client_->IsConnected());
394  EXPECT_EQ(-EIO, client_->error());
395}
396
397TEST_F(ClientChannelFactoryTest, DisableAutoReconnect) {
398  client_->Close(EIO);
399  ASSERT_FALSE(client_->IsConnected());
400  client_->DisableAutoReconnect();
401  auto status = client_->SendImpulse(17);
402  ASSERT_FALSE(status);
403  EXPECT_EQ(ESHUTDOWN, status.error());
404  EXPECT_FALSE(client_->IsConnected());
405  client_->EnableAutoReconnect(kTimeout);
406  EXPECT_CALL(*client_, OnConnect());
407  OnConnectCallback([](auto* mock) {
408    EXPECT_CALL(*mock, SendImpulse(17, nullptr, 0))
409        .WillOnce(Return(Status<void>{}));
410  });
411  ASSERT_TRUE(client_->SendImpulse(17));
412  EXPECT_TRUE(client_->IsConnected());
413}
414
415TEST_F(ClientTransactionTest, SendNoData) {
416  void* const kTransactionState = IntToPtr(123);
417  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
418      .WillOnce(Return(kTransactionState));
419  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
420  EXPECT_CALL(*mock_channel(),
421              SendWithInt(kTransactionState, 1, nullptr, 0, nullptr, 0))
422      .WillOnce(Return(0));
423  EXPECT_TRUE(transaction_.Send<void>(1));
424  EXPECT_CALL(*mock_channel(),
425              SendWithFileHandle(kTransactionState, 2, nullptr, 0, nullptr, 0))
426      .WillOnce(Return(ByMove(LocalHandle{-1})));
427  EXPECT_TRUE(transaction_.Send<LocalHandle>(2));
428  EXPECT_CALL(*mock_channel(), SendWithChannelHandle(kTransactionState, 3,
429                                                     nullptr, 0, nullptr, 0))
430      .WillOnce(Return(ByMove(LocalChannelHandle{nullptr, 1})));
431  EXPECT_TRUE(transaction_.Send<LocalChannelHandle>(3));
432}
433
434TEST_F(ClientTransactionTest, SendNoState) {
435  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
436      .WillOnce(Return(nullptr));
437  EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 1, nullptr, 0, nullptr, 0))
438      .WillOnce(Return(0));
439  EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr));
440  EXPECT_TRUE(transaction_.Send<void>(1));
441}
442
443TEST_F(ClientTransactionTest, SendBuffers) {
444  const void* const kSendBuffer = IntToConstPtr(123);
445  const size_t kSendSize = 12;
446  void* const kReceiveBuffer = IntToPtr(456);
447  const size_t kReceiveSize = 34;
448
449  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
450      .WillOnce(Return(nullptr));
451  EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr));
452
453  EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 1, nullptr, 0, nullptr, 0))
454      .WillOnce(Return(0));
455  EXPECT_TRUE(transaction_.Send<void>(1, nullptr, 0, nullptr, 0));
456
457  EXPECT_CALL(*mock_channel(),
458              SendWithInt(nullptr, 2, Ne(nullptr), 1, nullptr, 0))
459      .WillOnce(Return(0));
460  EXPECT_TRUE(transaction_.Send<void>(2, kSendBuffer, kSendSize, nullptr, 0));
461
462  EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 3, nullptr, 0, nullptr, 0))
463      .WillOnce(Return(0));
464  EXPECT_TRUE(transaction_.Send<void>(3, kSendBuffer, 0, nullptr, 0));
465
466  EXPECT_CALL(*mock_channel(),
467              SendWithInt(nullptr, 4, nullptr, 0, Ne(nullptr), 1))
468      .WillOnce(Return(0));
469  EXPECT_TRUE(
470      transaction_.Send<void>(4, nullptr, 0, kReceiveBuffer, kReceiveSize));
471
472  EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 5, nullptr, 0, nullptr, 0))
473      .WillOnce(Return(0));
474  EXPECT_TRUE(transaction_.Send<void>(5, nullptr, 0, kReceiveBuffer, 0));
475
476  EXPECT_CALL(*mock_channel(),
477              SendWithInt(nullptr, 5, Ne(nullptr), 1, Ne(nullptr), 1))
478      .WillOnce(Return(0));
479  EXPECT_TRUE(transaction_.Send<void>(5, kSendBuffer, kSendSize, kReceiveBuffer,
480                                      kReceiveSize));
481}
482
483TEST_F(ClientTransactionTest, SendVector) {
484  iovec send[3] = {};
485  iovec recv[4] = {};
486
487  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
488      .WillOnce(Return(nullptr));
489  EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr));
490
491  EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 1, nullptr, 0, nullptr, 0))
492      .WillOnce(Return(0));
493  EXPECT_TRUE(transaction_.SendVector<void>(1, nullptr, 0, nullptr, 0));
494
495  EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 2, send, 3, recv, 4))
496      .WillOnce(Return(0));
497  EXPECT_TRUE(transaction_.SendVector<void>(2, send, 3, recv, 4));
498
499  EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 3, send, 3, nullptr, 0))
500      .WillOnce(Return(0));
501  EXPECT_TRUE(transaction_.SendVector<void>(3, send, nullptr));
502
503  EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 4, nullptr, 0, recv, 4))
504      .WillOnce(Return(0));
505  EXPECT_TRUE(transaction_.SendVector<void>(4, nullptr, recv));
506
507  EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 5, send, 3, recv, 4))
508      .WillOnce(Return(0));
509  EXPECT_TRUE(transaction_.SendVector<void>(5, send, recv));
510}
511
512TEST_F(ClientTransactionTest, PushHandle) {
513  void* const kTransactionState = IntToPtr(123);
514  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
515      .WillOnce(Return(kTransactionState));
516  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
517
518  EXPECT_CALL(*mock_channel(),
519              PushFileHandle(kTransactionState, A<const LocalHandle&>()))
520      .WillOnce(Return(1));
521  EXPECT_EQ(1, transaction_.PushFileHandle(LocalHandle{-1}).get());
522
523  EXPECT_CALL(*mock_channel(),
524              PushFileHandle(kTransactionState, A<const BorrowedHandle&>()))
525      .WillOnce(Return(2));
526  EXPECT_EQ(2, transaction_.PushFileHandle(BorrowedHandle{-1}).get());
527
528  EXPECT_EQ(3, transaction_.PushFileHandle(RemoteHandle{3}).get());
529
530  EXPECT_CALL(
531      *mock_channel(),
532      PushChannelHandle(kTransactionState, A<const LocalChannelHandle&>()))
533      .WillOnce(Return(11));
534  EXPECT_EQ(
535      11, transaction_.PushChannelHandle(LocalChannelHandle{nullptr, 1}).get());
536
537  EXPECT_CALL(
538      *mock_channel(),
539      PushChannelHandle(kTransactionState, A<const BorrowedChannelHandle&>()))
540      .WillOnce(Return(12));
541  EXPECT_EQ(12, transaction_.PushChannelHandle(BorrowedChannelHandle{2}).get());
542
543  EXPECT_EQ(13, transaction_.PushChannelHandle(RemoteChannelHandle{13}).get());
544}
545
546TEST_F(ClientTransactionTest, GetHandle) {
547  void* const kTransactionState = IntToPtr(123);
548  EXPECT_CALL(*mock_channel(), AllocateTransactionState())
549      .WillOnce(Return(kTransactionState));
550  EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState));
551
552  EXPECT_CALL(*mock_channel(), GetFileHandle(kTransactionState, 1, _))
553      .WillOnce(Return(false))
554      .WillOnce(Return(true));
555
556  LocalHandle file_handle;
557  EXPECT_FALSE(transaction_.GetFileHandle(1, &file_handle));
558  EXPECT_TRUE(transaction_.GetFileHandle(1, &file_handle));
559
560  EXPECT_CALL(*mock_channel(), GetChannelHandle(kTransactionState, 2, _))
561      .WillOnce(Return(false))
562      .WillOnce(Return(true));
563
564  LocalChannelHandle channel_handle;
565  EXPECT_FALSE(transaction_.GetChannelHandle(2, &channel_handle));
566  EXPECT_TRUE(transaction_.GetChannelHandle(2, &channel_handle));
567}
568