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 
10 using android::pdx::BorrowedChannelHandle;
11 using android::pdx::BorrowedHandle;
12 using android::pdx::ClientBase;
13 using android::pdx::ClientChannel;
14 using android::pdx::ClientChannelFactory;
15 using android::pdx::ErrorStatus;
16 using android::pdx::LocalChannelHandle;
17 using android::pdx::LocalHandle;
18 using android::pdx::MockClientChannel;
19 using android::pdx::MockClientChannelFactory;
20 using android::pdx::RemoteChannelHandle;
21 using android::pdx::RemoteHandle;
22 using android::pdx::Status;
23 using android::pdx::Transaction;
24 using android::pdx::rpc::Void;
25 
26 using testing::A;
27 using testing::AnyNumber;
28 using testing::ByMove;
29 using testing::Invoke;
30 using testing::Ne;
31 using testing::Return;
32 using testing::_;
33 
34 namespace {
35 
IntToPtr(intptr_t addr)36 inline void* IntToPtr(intptr_t addr) { return reinterpret_cast<void*>(addr); }
IntToConstPtr(intptr_t addr)37 inline const void* IntToConstPtr(intptr_t addr) {
38   return reinterpret_cast<const void*>(addr);
39 }
40 
41 struct 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 
59 class SimpleClient : public ClientBase<SimpleClient> {
60  public:
SimpleClient(std::unique_ptr<ClientChannel> channel)61   explicit SimpleClient(std::unique_ptr<ClientChannel> channel)
62       : BASE{std::move(channel)} {}
SimpleClient(std::unique_ptr<ClientChannelFactory> channel_factory,int64_t timeout_ms)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 
82 class FailingClient : public ClientBase<FailingClient> {
83  public:
FailingClient(std::unique_ptr<ClientChannel> channel,int error_code)84   explicit FailingClient(std::unique_ptr<ClientChannel> channel, int error_code)
85       : BASE{std::move(channel)} {
86     Close(error_code);
87   }
88 };
89 
90 class ClientChannelTest : public testing::Test {
91  public:
ClientChannelTest()92   ClientChannelTest()
93       : client_{SimpleClient::Create(
94             std::make_unique<testing::StrictMock<MockClientChannel>>())} {}
95 
mock_channel()96   MockClientChannel* mock_channel() {
97     return static_cast<MockClientChannel*>(client_->GetChannel());
98   }
99 
100   std::unique_ptr<SimpleClient> client_;
101 };
102 
103 class ClientChannelFactoryTest : public testing::Test {
104  public:
ClientChannelFactoryTest()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 
mock_channel()113   MockClientChannel* mock_channel() {
114     return static_cast<MockClientChannel*>(client_->GetChannel());
115   }
116 
OnConnect(int64_t)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 
OnConnectCallback(std::function<void (MockClientChannel *)> callback)127   void OnConnectCallback(std::function<void(MockClientChannel*)> callback) {
128     on_connect_callback_ = callback;
129   }
SetOnConnectError(int error)130   void SetOnConnectError(int error) { on_connect_error_ = error; }
ResetOnConnectError()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 
139 constexpr int64_t ClientChannelFactoryTest::kTimeout;
140 
141 class ClientTransactionTest : public ClientChannelTest {
142  public:
ClientTransactionTest()143   ClientTransactionTest() : transaction_{*client_} {}
144 
145   Transaction transaction_;
146 };
147 
148 }  // anonymous namespace
149 
TEST_F(ClientChannelTest,IsInitialized)150 TEST_F(ClientChannelTest, IsInitialized) {
151   ASSERT_NE(client_.get(), nullptr);
152   EXPECT_TRUE(client_->IsInitialized());
153   EXPECT_TRUE(client_->IsConnected());
154 }
155 
TEST_F(ClientChannelTest,CloseOnConstruction)156 TEST_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 
TEST_F(ClientChannelTest,IsConnected)170 TEST_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 
TEST_F(ClientChannelTest,event_fd)178 TEST_F(ClientChannelTest, event_fd) {
179   EXPECT_CALL(*mock_channel(), event_fd()).WillOnce(Return(12));
180   EXPECT_EQ(12, client_->event_fd());
181 }
182 
TEST_F(ClientChannelTest,SendImpulse)183 TEST_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 
TEST_F(ClientChannelTest,InvokeRemoteMethodNullTransactionState)200 TEST_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 
TEST_F(ClientChannelTest,InvokeRemoteMethodAddSuccess)210 TEST_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 
TEST_F(ClientChannelTest,InvokeRemoteMethodAddFailure)224 TEST_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 
TEST_F(ClientChannelTest,InvokeRemoteMethodGetFileSuccess)238 TEST_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 
TEST_F(ClientChannelTest,InvokeRemoteMethodGetFileFailure)254 TEST_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 
TEST_F(ClientChannelTest,InvokeRemoteMethodPushChannelSuccess)269 TEST_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 
TEST_F(ClientChannelTest,InvokeRemoteMethodPushChannelFailure)286 TEST_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 
TEST_F(ClientChannelTest,InvokeRemoteMethodSendFileSuccess)302 TEST_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 
TEST_F(ClientChannelTest,InvokeRemoteMethodSendFileFailure)318 TEST_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 
TEST_F(ClientChannelFactoryTest,IsInitialized)334 TEST_F(ClientChannelFactoryTest, IsInitialized) {
335   ASSERT_NE(client_.get(), nullptr);
336   EXPECT_TRUE(client_->IsInitialized());
337   EXPECT_TRUE(client_->IsConnected());
338 }
339 
TEST_F(ClientChannelFactoryTest,NotConnectedButInitialized)340 TEST_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 
TEST_F(ClientChannelFactoryTest,CheckDisconnect)363 TEST_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 
TEST_F(ClientChannelFactoryTest,CheckReconnect)371 TEST_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 
TEST_F(ClientChannelFactoryTest,CloseOnConnect)384 TEST_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 
TEST_F(ClientChannelFactoryTest,DisableAutoReconnect)397 TEST_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 
TEST_F(ClientTransactionTest,SendNoData)415 TEST_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 
TEST_F(ClientTransactionTest,SendNoState)434 TEST_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 
TEST_F(ClientTransactionTest,SendBuffers)443 TEST_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 
TEST_F(ClientTransactionTest,SendVector)483 TEST_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 
TEST_F(ClientTransactionTest,PushHandle)512 TEST_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 
TEST_F(ClientTransactionTest,GetHandle)546 TEST_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