blob: cbf8d0a8176552ab2ac38ad548f9e89dc2ac4f60 [file] [log] [blame]
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001/*
2 * Copyright (C) 2017 The Android Open foo Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "src/ipc/host_impl.h"
18
19#include <memory>
20
21#include "gmock/gmock.h"
22#include "gtest/gtest.h"
23#include "perfetto/base/scoped_file.h"
Primiano Tucci941b2212018-03-14 22:46:31 +000024#include "perfetto/base/temp_file.h"
Primiano Tucci55e73f32018-03-15 07:32:02 +000025#include "perfetto/base/utils.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000026#include "perfetto/ipc/service.h"
27#include "perfetto/ipc/service_descriptor.h"
28#include "src/base/test/test_task_runner.h"
29#include "src/ipc/buffered_frame_deserializer.h"
Primiano Tuccib03ba362017-12-06 09:47:41 +000030#include "src/ipc/test/test_socket.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000031#include "src/ipc/unix_socket.h"
32
33#include "src/ipc/test/client_unittest_messages.pb.h"
34#include "src/ipc/wire_protocol.pb.h"
35
36namespace perfetto {
37namespace ipc {
38namespace {
39
40using ::testing::_;
41using ::testing::Invoke;
42using ::testing::InvokeWithoutArgs;
Primiano Tucci2d0b2252018-01-25 13:37:50 +000043using ::testing::Return;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000044
Primiano Tuccib03ba362017-12-06 09:47:41 +000045constexpr char kSockName[] = TEST_SOCK_NAME("host_impl_unittest.sock");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000046
47// RequestProto and ReplyProto are defined in client_unittest_messages.proto.
48
49class FakeService : public Service {
50 public:
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000051 MOCK_METHOD2(OnFakeMethod1, void(const RequestProto&, DeferredBase*));
52
53 static void Invoker(Service* service,
54 const ProtoMessage& req,
55 DeferredBase deferred_reply) {
56 static_cast<FakeService*>(service)->OnFakeMethod1(
57 static_cast<const RequestProto&>(req), &deferred_reply);
58 }
59
60 static std::unique_ptr<ProtoMessage> RequestDecoder(
61 const std::string& proto) {
62 std::unique_ptr<ProtoMessage> reply(new RequestProto());
63 EXPECT_TRUE(reply->ParseFromString(proto));
64 return reply;
65 }
66
Florian Mayeraab53552018-01-24 14:13:55 +000067 explicit FakeService(const char* service_name) {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000068 descriptor_.service_name = service_name;
69 descriptor_.methods.push_back(
70 {"FakeMethod1", &RequestDecoder, nullptr, &Invoker});
71 }
72
73 const ServiceDescriptor& GetDescriptor() override { return descriptor_; }
74
Florian Mayerd16508e2018-03-02 17:06:40 +000075 base::ScopedFile TakeReceivedFD() { return ipc::Service::TakeReceivedFD(); }
76
77 base::ScopedFile received_fd_;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000078 ServiceDescriptor descriptor_;
79};
80
81class FakeClient : public UnixSocket::EventListener {
82 public:
83 MOCK_METHOD0(OnConnect, void());
84 MOCK_METHOD0(OnDisconnect, void());
85 MOCK_METHOD1(OnServiceBound, void(const Frame::BindServiceReply&));
86 MOCK_METHOD1(OnInvokeMethodReply, void(const Frame::InvokeMethodReply&));
87 MOCK_METHOD1(OnFileDescriptorReceived, void(int));
88 MOCK_METHOD0(OnRequestError, void());
89
90 explicit FakeClient(base::TaskRunner* task_runner) {
91 sock_ = UnixSocket::Connect(kSockName, this, task_runner);
92 }
93
94 ~FakeClient() override = default;
95
96 void BindService(const std::string& service_name) {
97 Frame frame;
98 uint64_t request_id = requests_.empty() ? 1 : requests_.rbegin()->first + 1;
99 requests_.emplace(request_id, 0);
100 frame.set_request_id(request_id);
101 frame.mutable_msg_bind_service()->set_service_name(service_name);
102 SendFrame(frame);
103 }
104
105 void InvokeMethod(ServiceID service_id,
106 MethodID method_id,
Primiano Tucci2d0b2252018-01-25 13:37:50 +0000107 const ProtoMessage& args,
Florian Mayerd16508e2018-03-02 17:06:40 +0000108 bool drop_reply = false,
109 int fd = -1) {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000110 Frame frame;
111 uint64_t request_id = requests_.empty() ? 1 : requests_.rbegin()->first + 1;
112 requests_.emplace(request_id, 0);
113 frame.set_request_id(request_id);
114 frame.mutable_msg_invoke_method()->set_service_id(service_id);
115 frame.mutable_msg_invoke_method()->set_method_id(method_id);
Primiano Tucci2d0b2252018-01-25 13:37:50 +0000116 frame.mutable_msg_invoke_method()->set_drop_reply(drop_reply);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000117 frame.mutable_msg_invoke_method()->set_args_proto(args.SerializeAsString());
Florian Mayerd16508e2018-03-02 17:06:40 +0000118 SendFrame(frame, fd);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000119 }
120
121 // UnixSocket::EventListener implementation.
122 void OnConnect(UnixSocket*, bool success) override {
123 ASSERT_TRUE(success);
124 OnConnect();
125 }
126
127 void OnDisconnect(UnixSocket*) override { OnDisconnect(); }
128
129 void OnDataAvailable(UnixSocket* sock) override {
130 ASSERT_EQ(sock_.get(), sock);
131 auto buf = frame_deserializer_.BeginReceive();
132 base::ScopedFile fd;
133 size_t rsize = sock->Receive(buf.data, buf.size, &fd);
134 ASSERT_TRUE(frame_deserializer_.EndReceive(rsize));
135 if (fd)
136 OnFileDescriptorReceived(*fd);
137 while (std::unique_ptr<Frame> frame = frame_deserializer_.PopNextFrame()) {
138 ASSERT_EQ(1u, requests_.count(frame->request_id()));
139 EXPECT_EQ(0, requests_[frame->request_id()]++);
140 if (frame->msg_case() == Frame::kMsgBindServiceReply) {
141 if (frame->msg_bind_service_reply().success())
142 last_bound_service_id_ = frame->msg_bind_service_reply().service_id();
143 return OnServiceBound(frame->msg_bind_service_reply());
144 }
145 if (frame->msg_case() == Frame::kMsgInvokeMethodReply)
146 return OnInvokeMethodReply(frame->msg_invoke_method_reply());
147 if (frame->msg_case() == Frame::kMsgRequestError)
148 return OnRequestError();
149 FAIL() << "Unexpected frame received from host " << frame->msg_case();
150 }
151 }
152
Florian Mayerd16508e2018-03-02 17:06:40 +0000153 void SendFrame(const Frame& frame, int fd = -1) {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000154 std::string buf = BufferedFrameDeserializer::Serialize(frame);
Florian Mayerd16508e2018-03-02 17:06:40 +0000155 ASSERT_TRUE(sock_->Send(buf.data(), buf.size(), fd));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000156 }
157
158 BufferedFrameDeserializer frame_deserializer_;
159 std::unique_ptr<UnixSocket> sock_;
160 std::map<uint64_t /* request_id */, int /* num_replies_received */> requests_;
161 ServiceID last_bound_service_id_;
162};
163
164class HostImplTest : public ::testing::Test {
165 public:
166 void SetUp() override {
Primiano Tuccib03ba362017-12-06 09:47:41 +0000167 DESTROY_TEST_SOCK(kSockName);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000168 task_runner_.reset(new base::TestTaskRunner());
169 Host* host = Host::CreateInstance(kSockName, task_runner_.get()).release();
170 ASSERT_NE(nullptr, host);
171 host_.reset(static_cast<HostImpl*>(host));
172 cli_.reset(new FakeClient(task_runner_.get()));
173 auto on_connect = task_runner_->CreateCheckpoint("on_connect");
174 EXPECT_CALL(*cli_, OnConnect()).WillOnce(Invoke(on_connect));
175 task_runner_->RunUntilCheckpoint("on_connect");
176 }
177
178 void TearDown() override {
179 task_runner_->RunUntilIdle();
180 cli_.reset();
181 host_.reset();
182 task_runner_->RunUntilIdle();
183 task_runner_.reset();
Primiano Tuccib03ba362017-12-06 09:47:41 +0000184 DESTROY_TEST_SOCK(kSockName);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000185 }
186
187 // ::testing::StrictMock<MockEventListener> proxy_events_;
188 std::unique_ptr<base::TestTaskRunner> task_runner_;
189 std::unique_ptr<HostImpl> host_;
190 std::unique_ptr<FakeClient> cli_;
191};
192
193TEST_F(HostImplTest, BindService) {
194 // First bind the service when it doesn't exists yet and check that the
195 // BindService() request fails.
196 cli_->BindService("FakeService"); // FakeService does not exist yet.
197 auto on_bind_failure = task_runner_->CreateCheckpoint("on_bind_failure");
198 EXPECT_CALL(*cli_, OnServiceBound(_))
199 .WillOnce(Invoke([on_bind_failure](const Frame::BindServiceReply& reply) {
200 ASSERT_FALSE(reply.success());
201 on_bind_failure();
202 }));
203 task_runner_->RunUntilCheckpoint("on_bind_failure");
204
205 // Now expose the service and bind it.
206 ASSERT_TRUE(host_->ExposeService(
207 std::unique_ptr<Service>(new FakeService("FakeService"))));
208 auto on_bind_success = task_runner_->CreateCheckpoint("on_bind_success");
209 cli_->BindService("FakeService");
210 EXPECT_CALL(*cli_, OnServiceBound(_))
211 .WillOnce(Invoke([on_bind_success](const Frame::BindServiceReply& reply) {
212 ASSERT_TRUE(reply.success());
213 on_bind_success();
214 }));
215 task_runner_->RunUntilCheckpoint("on_bind_success");
216}
217
218TEST_F(HostImplTest, InvokeNonExistingMethod) {
219 FakeService* fake_service = new FakeService("FakeService");
220 ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
221 auto on_bind = task_runner_->CreateCheckpoint("on_bind");
222 cli_->BindService("FakeService");
223 EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
224 task_runner_->RunUntilCheckpoint("on_bind");
225
226 auto on_invoke_failure = task_runner_->CreateCheckpoint("on_invoke_failure");
227 cli_->InvokeMethod(cli_->last_bound_service_id_, 42, RequestProto());
228 EXPECT_CALL(*cli_, OnInvokeMethodReply(_))
229 .WillOnce(
230 Invoke([on_invoke_failure](const Frame::InvokeMethodReply& reply) {
231 ASSERT_FALSE(reply.success());
232 ASSERT_FALSE(reply.has_more());
233 on_invoke_failure();
234 }));
235 task_runner_->RunUntilCheckpoint("on_invoke_failure");
236}
237
238TEST_F(HostImplTest, InvokeMethod) {
239 FakeService* fake_service = new FakeService("FakeService");
240 ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
241 auto on_bind = task_runner_->CreateCheckpoint("on_bind");
242 cli_->BindService("FakeService");
243 EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
244 task_runner_->RunUntilCheckpoint("on_bind");
245
246 RequestProto req_args;
247 req_args.set_data("foo");
248 cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args);
249 auto on_reply_sent = task_runner_->CreateCheckpoint("on_reply_sent");
250 EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
251 .WillOnce(
252 Invoke([on_reply_sent](const RequestProto& req, DeferredBase* reply) {
253 ASSERT_EQ("foo", req.data());
254 std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
255 reply_args->set_data("bar");
256 reply->Resolve(AsyncResult<ProtoMessage>(
257 std::unique_ptr<ProtoMessage>(reply_args.release())));
258 on_reply_sent();
259 }));
260 task_runner_->RunUntilCheckpoint("on_reply_sent");
261
262 auto on_reply_received = task_runner_->CreateCheckpoint("on_reply_received");
263 EXPECT_CALL(*cli_, OnInvokeMethodReply(_))
264 .WillOnce(
265 Invoke([on_reply_received](const Frame::InvokeMethodReply& reply) {
266 ASSERT_TRUE(reply.success());
267 ASSERT_FALSE(reply.has_more());
268 ReplyProto reply_args;
269 reply_args.ParseFromString(reply.reply_proto());
270 ASSERT_EQ("bar", reply_args.data());
271 on_reply_received();
272 }));
273 task_runner_->RunUntilCheckpoint("on_reply_received");
274}
275
Primiano Tucci2d0b2252018-01-25 13:37:50 +0000276TEST_F(HostImplTest, InvokeMethodDropReply) {
277 FakeService* fake_service = new FakeService("FakeService");
278 ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
279 auto on_bind = task_runner_->CreateCheckpoint("on_bind");
280 cli_->BindService("FakeService");
281 EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
282 task_runner_->RunUntilCheckpoint("on_bind");
283
284 // OnFakeMethod1 will:
285 // - Do nothing on the 1st call, when |drop_reply| == true.
286 // - Reply on the the 2nd call, when |drop_reply| == false.
287 EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
288 .Times(2)
289 .WillRepeatedly(Invoke([](const RequestProto& req, DeferredBase* reply) {
290 if (req.data() == "drop_reply")
291 return;
292 std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
293 reply_args->set_data("the_reply");
294 reply->Resolve(AsyncResult<ProtoMessage>(
295 std::unique_ptr<ProtoMessage>(reply_args.release())));
296 }));
297
298 auto on_reply_received = task_runner_->CreateCheckpoint("on_reply_received");
299 EXPECT_CALL(*cli_, OnInvokeMethodReply(_))
300 .WillOnce(
301 Invoke([on_reply_received](const Frame::InvokeMethodReply& reply) {
302 ASSERT_TRUE(reply.success());
303 ReplyProto reply_args;
304 reply_args.ParseFromString(reply.reply_proto());
305 ASSERT_EQ("the_reply", reply_args.data());
306 on_reply_received();
307 }));
308
309 // Invoke the method first with |drop_reply|=true, then |drop_reply|=false.
310 RequestProto rp;
311 rp.set_data("drop_reply");
312 cli_->InvokeMethod(cli_->last_bound_service_id_, 1, rp, true /*drop_reply*/);
313 rp.set_data("do_reply");
314 cli_->InvokeMethod(cli_->last_bound_service_id_, 1, rp, false /*drop_reply*/);
315
316 task_runner_->RunUntilCheckpoint("on_reply_received");
317}
318
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000319TEST_F(HostImplTest, SendFileDescriptor) {
320 FakeService* fake_service = new FakeService("FakeService");
321 ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
322 auto on_bind = task_runner_->CreateCheckpoint("on_bind");
323 cli_->BindService("FakeService");
324 EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
325 task_runner_->RunUntilCheckpoint("on_bind");
326
327 static constexpr char kFileContent[] = "shared file";
328 RequestProto req_args;
329 cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args);
330 auto on_reply_sent = task_runner_->CreateCheckpoint("on_reply_sent");
Primiano Tucci941b2212018-03-14 22:46:31 +0000331 base::TempFile tx_file = base::TempFile::CreateUnlinked();
Primiano Tucci55e73f32018-03-15 07:32:02 +0000332 base::ignore_result(write(tx_file.fd(), kFileContent, sizeof(kFileContent)));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000333 EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100334 .WillOnce(Invoke([on_reply_sent, &tx_file](const RequestProto&,
Primiano Tucci941b2212018-03-14 22:46:31 +0000335 DeferredBase* reply) {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000336 std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
337 auto async_res = AsyncResult<ProtoMessage>(
338 std::unique_ptr<ProtoMessage>(reply_args.release()));
Primiano Tucci941b2212018-03-14 22:46:31 +0000339 async_res.set_fd(tx_file.fd());
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000340 reply->Resolve(std::move(async_res));
341 on_reply_sent();
342 }));
343 task_runner_->RunUntilCheckpoint("on_reply_sent");
Primiano Tucci941b2212018-03-14 22:46:31 +0000344 tx_file.ReleaseFD();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000345
346 auto on_fd_received = task_runner_->CreateCheckpoint("on_fd_received");
347 EXPECT_CALL(*cli_, OnFileDescriptorReceived(_))
348 .WillOnce(Invoke([on_fd_received](int fd) {
349 char buf[sizeof(kFileContent)] = {};
350 ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
351 ASSERT_EQ(static_cast<int32_t>(sizeof(buf)),
352 PERFETTO_EINTR(read(fd, buf, sizeof(buf))));
353 ASSERT_STREQ(kFileContent, buf);
354 on_fd_received();
355 }));
356 EXPECT_CALL(*cli_, OnInvokeMethodReply(_));
357 task_runner_->RunUntilCheckpoint("on_fd_received");
358}
359
Florian Mayerd16508e2018-03-02 17:06:40 +0000360TEST_F(HostImplTest, ReceiveFileDescriptor) {
361 auto received = task_runner_->CreateCheckpoint("received");
362 FakeService* fake_service = new FakeService("FakeService");
363 ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
364 auto on_bind = task_runner_->CreateCheckpoint("on_bind");
365 cli_->BindService("FakeService");
366 EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
367 task_runner_->RunUntilCheckpoint("on_bind");
368
369 static constexpr char kFileContent[] = "shared file";
370 RequestProto req_args;
Primiano Tucci941b2212018-03-14 22:46:31 +0000371 base::TempFile tx_file = base::TempFile::CreateUnlinked();
Primiano Tucci55e73f32018-03-15 07:32:02 +0000372 base::ignore_result(write(tx_file.fd(), kFileContent, sizeof(kFileContent)));
Florian Mayerd16508e2018-03-02 17:06:40 +0000373 cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args, false,
Primiano Tucci941b2212018-03-14 22:46:31 +0000374 tx_file.fd());
Florian Mayerd16508e2018-03-02 17:06:40 +0000375 EXPECT_CALL(*cli_, OnInvokeMethodReply(_));
376 base::ScopedFile rx_fd;
377 EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100378 .WillOnce(Invoke([received, &fake_service, &rx_fd](const RequestProto&,
379 DeferredBase*) {
Florian Mayerd16508e2018-03-02 17:06:40 +0000380 rx_fd = fake_service->TakeReceivedFD();
381 received();
382 }));
383
384 task_runner_->RunUntilCheckpoint("received");
385
386 ASSERT_TRUE(rx_fd);
387 char buf[sizeof(kFileContent)] = {};
388 ASSERT_EQ(0, lseek(*rx_fd, 0, SEEK_SET));
389 ASSERT_EQ(static_cast<int32_t>(sizeof(buf)),
390 PERFETTO_EINTR(read(*rx_fd, buf, sizeof(buf))));
391 ASSERT_STREQ(kFileContent, buf);
392}
393
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000394// Invoke a method and immediately after disconnect the client.
395TEST_F(HostImplTest, OnClientDisconnect) {
396 FakeService* fake_service = new FakeService("FakeService");
397 ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
398 auto on_bind = task_runner_->CreateCheckpoint("on_bind");
399 cli_->BindService("FakeService");
400 EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
401 task_runner_->RunUntilCheckpoint("on_bind");
402
403 RequestProto req_args;
404 req_args.set_data("foo");
405 cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args);
406 EXPECT_CALL(*cli_, OnInvokeMethodReply(_)).Times(0);
407 cli_.reset(); // Disconnect the client.
408 auto on_host_method = task_runner_->CreateCheckpoint("on_host_method");
409 EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100410 .WillOnce(
411 Invoke([on_host_method](const RequestProto& req, DeferredBase*) {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000412 ASSERT_EQ("foo", req.data());
413 on_host_method();
414 }));
415 task_runner_->RunUntilCheckpoint("on_host_method");
416}
417
418// Like InvokeMethod, but instead of resolving the Deferred reply within the
419// call stack, std::move()-s it outside an replies
420TEST_F(HostImplTest, MoveReplyObjectAndReplyAsynchronously) {
421 FakeService* fake_service = new FakeService("FakeService");
422 ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
423 auto on_bind = task_runner_->CreateCheckpoint("on_bind");
424 cli_->BindService("FakeService");
425 EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
426 task_runner_->RunUntilCheckpoint("on_bind");
427
428 // Invokes the remote method and waits that the FakeService sees it. The reply
429 // is not resolved but just moved into |moved_reply|.
430 RequestProto req_args;
431 cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args);
432 auto on_invoke = task_runner_->CreateCheckpoint("on_invoke");
433 DeferredBase moved_reply;
434 EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100435 .WillOnce(Invoke(
436 [on_invoke, &moved_reply](const RequestProto&, DeferredBase* reply) {
437 moved_reply = std::move(*reply);
438 on_invoke();
439 }));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000440 task_runner_->RunUntilCheckpoint("on_invoke");
441
442 // Check that the FakeClient doesn't see any reply yet.
443 EXPECT_CALL(*cli_, OnInvokeMethodReply(_)).Times(0);
444 task_runner_->RunUntilIdle();
445 ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(cli_.get()));
446
447 // Resolve the reply asynchronously in a deferred task.
448 task_runner_->PostTask([&moved_reply] {
449 std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
450 reply_args->set_data("bar");
451 moved_reply.Resolve(AsyncResult<ProtoMessage>(
452 std::unique_ptr<ProtoMessage>(reply_args.release())));
453 });
454
455 auto on_reply_received = task_runner_->CreateCheckpoint("on_reply_received");
456 EXPECT_CALL(*cli_, OnInvokeMethodReply(_))
457 .WillOnce(
458 Invoke([on_reply_received](const Frame::InvokeMethodReply& reply) {
459 ASSERT_TRUE(reply.success());
460 ASSERT_FALSE(reply.has_more());
461 ReplyProto reply_args;
462 reply_args.ParseFromString(reply.reply_proto());
463 ASSERT_EQ("bar", reply_args.data());
464 on_reply_received();
465 }));
466 task_runner_->RunUntilCheckpoint("on_reply_received");
467}
468
469// TODO(primiano): add the tests below in next CLs.
470// TEST(HostImplTest, ManyClients) {}
471// TEST(HostImplTest, OverlappingRequstsOutOfOrder) {}
472// TEST(HostImplTest, StreamingRequest) {}
Primiano Tucci2d0b2252018-01-25 13:37:50 +0000473// TEST(HostImplTest, ManyDropReplyRequestsDontLeakMemory) {}
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000474
475} // namespace
476} // namespace ipc
477} // namespace perfetto