blob: 01ebe8c45c3ba9ce3ccd44d0c09b0b5920d7ad96 [file] [log] [blame]
Primiano Tuccied0ce252017-11-09 19:35:10 +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 "ipc/src/client_impl.h"
18
Primiano Tuccif54cae42017-11-21 19:37:13 +000019#include <stdio.h>
20#include <unistd.h>
21
Primiano Tucci3052b1a2017-11-14 10:51:01 +000022#include <string>
23
Primiano Tuccied0ce252017-11-09 19:35:10 +000024#include "base/test/test_task_runner.h"
Primiano Tucci3052b1a2017-11-14 10:51:01 +000025#include "base/utils.h"
Primiano Tuccied0ce252017-11-09 19:35:10 +000026#include "gmock/gmock.h"
27#include "gtest/gtest.h"
28#include "ipc/service_descriptor.h"
29#include "ipc/service_proxy.h"
30#include "ipc/src/buffered_frame_deserializer.h"
31#include "ipc/src/unix_socket.h"
32
Primiano Tucci2ee254a2017-11-15 00:38:48 +000033#include "ipc/src/test/client_unittest_messages.pb.h"
Primiano Tuccied0ce252017-11-09 19:35:10 +000034
35namespace perfetto {
36namespace ipc {
37namespace {
38
39using ::testing::_;
Primiano Tucci3052b1a2017-11-14 10:51:01 +000040using ::testing::InSequence;
Primiano Tuccied0ce252017-11-09 19:35:10 +000041using ::testing::Invoke;
Primiano Tucci3052b1a2017-11-14 10:51:01 +000042using ::testing::Mock;
Primiano Tuccied0ce252017-11-09 19:35:10 +000043
44constexpr char kSockName[] = "/tmp/perfetto_client_impl_unittest.sock";
45
Primiano Tucci3052b1a2017-11-14 10:51:01 +000046// A fake ServiceProxy. This fakes the client-side class that would be
47// auto-generated from .proto-files.
Primiano Tuccied0ce252017-11-09 19:35:10 +000048class FakeProxy : public ServiceProxy {
49 public:
Primiano Tuccied0ce252017-11-09 19:35:10 +000050 FakeProxy(const char* service_name, ServiceProxy::EventListener* el)
51 : ServiceProxy(el), service_name_(service_name) {}
52
53 const ServiceDescriptor& GetDescriptor() override {
Primiano Tucci3052b1a2017-11-14 10:51:01 +000054 auto reply_decoder = [](const std::string& proto) {
55 std::unique_ptr<ProtoMessage> reply(new ReplyProto());
56 EXPECT_TRUE(reply->ParseFromString(proto));
57 return reply;
58 };
Primiano Tuccied0ce252017-11-09 19:35:10 +000059 if (!descriptor_.service_name) {
60 descriptor_.service_name = service_name_;
Primiano Tucci3052b1a2017-11-14 10:51:01 +000061 descriptor_.methods.push_back({"FakeMethod1", nullptr, reply_decoder});
Primiano Tuccied0ce252017-11-09 19:35:10 +000062 }
63 return descriptor_;
64 }
65
66 const char* service_name_;
67 ServiceDescriptor descriptor_;
68};
69
70class MockEventListener : public ServiceProxy::EventListener {
71 public:
Primiano Tucci3052b1a2017-11-14 10:51:01 +000072 MOCK_METHOD0(OnConnect, void());
Primiano Tuccied0ce252017-11-09 19:35:10 +000073 MOCK_METHOD0(OnDisconnect, void());
74};
75
Primiano Tucci3052b1a2017-11-14 10:51:01 +000076// A fake host implementation. Listens on |kSockName| and replies to IPC
77// metohds like a real one.
Primiano Tuccied0ce252017-11-09 19:35:10 +000078class FakeHost : public UnixSocket::EventListener {
79 public:
Primiano Tucci3052b1a2017-11-14 10:51:01 +000080 struct FakeMethod {
81 MethodID id;
82 MOCK_METHOD2(OnInvoke,
83 void(const Frame::InvokeMethod&, Frame::InvokeMethodReply*));
84 }; // FakeMethod.
85
86 struct FakeService {
87 FakeMethod* AddFakeMethod(const std::string& name) {
88 auto it_and_inserted =
89 methods.emplace(name, std::unique_ptr<FakeMethod>(new FakeMethod()));
90 EXPECT_TRUE(it_and_inserted.second);
91 FakeMethod* method = it_and_inserted.first->second.get();
92 method->id = ++last_method_id;
93 return method;
94 }
95
96 ServiceID id;
97 std::map<std::string, std::unique_ptr<FakeMethod>> methods;
98 MethodID last_method_id = 0;
99 }; // FakeService.
Primiano Tuccied0ce252017-11-09 19:35:10 +0000100
101 explicit FakeHost(base::TaskRunner* task_runner) {
102 unlink(kSockName);
103 listening_sock = UnixSocket::Listen(kSockName, this, task_runner);
104 EXPECT_TRUE(listening_sock->is_listening());
105 }
Primiano Tuccied0ce252017-11-09 19:35:10 +0000106 ~FakeHost() override { unlink(kSockName); }
107
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000108 FakeService* AddFakeService(const std::string& name) {
109 auto it_and_inserted =
110 services.emplace(name, std::unique_ptr<FakeService>(new FakeService()));
111 EXPECT_TRUE(it_and_inserted.second);
112 FakeService* svc = it_and_inserted.first->second.get();
113 svc->id = ++last_service_id;
114 return svc;
115 }
116
Primiano Tuccied0ce252017-11-09 19:35:10 +0000117 // UnixSocket::EventListener implementation.
118 void OnNewIncomingConnection(
119 UnixSocket*,
120 std::unique_ptr<UnixSocket> new_connection) override {
121 ASSERT_FALSE(client_sock);
122 client_sock = std::move(new_connection);
123 }
124
Primiano Tuccied0ce252017-11-09 19:35:10 +0000125 void OnDataAvailable(UnixSocket* sock) override {
126 if (sock != client_sock.get())
127 return;
128 auto buf = frame_deserializer.BeginReceive();
129 size_t rsize = client_sock->Receive(buf.data, buf.size);
130 EXPECT_TRUE(frame_deserializer.EndReceive(rsize));
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000131 while (std::unique_ptr<Frame> frame = frame_deserializer.PopNextFrame())
132 OnFrameReceived(*frame);
133 }
134
135 void OnFrameReceived(const Frame& req) {
136 if (req.msg_case() == Frame::kMsgBindService) {
137 auto svc_it = services.find(req.msg_bind_service().service_name());
138 ASSERT_NE(services.end(), svc_it);
139 const FakeService& svc = *svc_it->second.get();
140 Frame reply;
141 reply.set_request_id(req.request_id());
142 reply.mutable_msg_bind_service_reply()->set_success(true);
143 reply.mutable_msg_bind_service_reply()->set_service_id(svc.id);
144 for (const auto& method_it : svc.methods) {
145 auto* method = reply.mutable_msg_bind_service_reply()->add_methods();
146 method->set_name(method_it.first);
147 method->set_id(method_it.second->id);
148 }
149 return Reply(reply);
150 } else if (req.msg_case() == Frame::kMsgInvokeMethod) {
151 // Lookup the service and method.
Primiano Tuccic2025af2017-11-20 12:47:49 +0000152 bool has_more = false;
153 do {
154 Frame reply;
155 reply.set_request_id(req.request_id());
156 for (const auto& svc : services) {
157 if (svc.second->id != req.msg_invoke_method().service_id())
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000158 continue;
Primiano Tuccic2025af2017-11-20 12:47:49 +0000159 for (const auto& method : svc.second->methods) {
160 if (method.second->id != req.msg_invoke_method().method_id())
161 continue;
162 method.second->OnInvoke(req.msg_invoke_method(),
163 reply.mutable_msg_invoke_method_reply());
164 has_more = reply.mutable_msg_invoke_method_reply()->has_more();
165 }
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000166 }
Primiano Tuccic2025af2017-11-20 12:47:49 +0000167 // If either the method or the service are not found, |success| will be
168 // false by default.
169 Reply(reply);
170 } while (has_more);
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000171 } else {
172 FAIL() << "Unknown request";
Primiano Tuccied0ce252017-11-09 19:35:10 +0000173 }
174 }
175
176 void Reply(const Frame& frame) {
177 auto buf = BufferedFrameDeserializer::Serialize(frame);
178 ASSERT_TRUE(client_sock->is_connected());
Primiano Tuccif54cae42017-11-21 19:37:13 +0000179 EXPECT_TRUE(client_sock->Send(buf.data(), buf.size(), next_reply_fd));
180 next_reply_fd = -1;
Primiano Tuccied0ce252017-11-09 19:35:10 +0000181 }
182
183 BufferedFrameDeserializer frame_deserializer;
184 std::unique_ptr<UnixSocket> listening_sock;
185 std::unique_ptr<UnixSocket> client_sock;
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000186 std::map<std::string, std::unique_ptr<FakeService>> services;
187 ServiceID last_service_id = 0;
Primiano Tuccif54cae42017-11-21 19:37:13 +0000188 int next_reply_fd = -1;
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000189}; // FakeHost.
190
191class ClientImplTest : public ::testing::Test {
192 public:
193 void SetUp() override {
194 task_runner_.reset(new base::TestTaskRunner());
195 host_.reset(new FakeHost(task_runner_.get()));
196 cli_ = Client::CreateInstance(kSockName, task_runner_.get());
197 }
198
199 void TearDown() override {
200 cli_.reset();
201 host_.reset();
202 task_runner_->RunUntilIdle();
203 task_runner_.reset();
204 }
205
206 ::testing::StrictMock<MockEventListener> proxy_events_;
207 std::unique_ptr<base::TestTaskRunner> task_runner_;
208 std::unique_ptr<FakeHost> host_;
209 std::unique_ptr<Client> cli_;
Primiano Tuccied0ce252017-11-09 19:35:10 +0000210};
211
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000212TEST_F(ClientImplTest, BindAndInvokeMethod) {
213 auto* host_svc = host_->AddFakeService("FakeSvc");
214 auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
Primiano Tuccied0ce252017-11-09 19:35:10 +0000215
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000216 std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
Primiano Tuccied0ce252017-11-09 19:35:10 +0000217
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000218 // Bind |proxy| to the fake host.
219 cli_->BindService(proxy->GetWeakPtr());
220 auto on_connect = task_runner_->CreateCheckpoint("on_connect");
221 EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
222 task_runner_->RunUntilCheckpoint("on_connect");
Primiano Tuccied0ce252017-11-09 19:35:10 +0000223
224 // Invoke a valid method.
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000225 EXPECT_CALL(*host_method, OnInvoke(_, _))
226 .WillOnce(Invoke(
227 [](const Frame::InvokeMethod& req, Frame::InvokeMethodReply* reply) {
228 RequestProto req_args;
229 EXPECT_TRUE(req_args.ParseFromString(req.args_proto()));
230 EXPECT_EQ("req_data", req_args.data());
231 ReplyProto reply_args;
232 reply->set_reply_proto(reply_args.SerializeAsString());
233 reply->set_success(true);
234 }));
Primiano Tuccied0ce252017-11-09 19:35:10 +0000235
236 RequestProto req;
237 req.set_data("req_data");
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000238 auto on_invoke_reply = task_runner_->CreateCheckpoint("on_invoke_reply");
Primiano Tuccied0ce252017-11-09 19:35:10 +0000239 DeferredBase deferred_reply(
240 [on_invoke_reply](AsyncResult<ProtoMessage> reply) {
241 EXPECT_TRUE(reply.success());
242 on_invoke_reply();
243 });
244 proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000245 task_runner_->RunUntilCheckpoint("on_invoke_reply");
Primiano Tuccied0ce252017-11-09 19:35:10 +0000246
247 // Invoke an invalid method.
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000248 auto on_invalid_invoke = task_runner_->CreateCheckpoint("on_invalid_invoke");
Primiano Tuccied0ce252017-11-09 19:35:10 +0000249 DeferredBase deferred_reply2(
250 [on_invalid_invoke](AsyncResult<ProtoMessage> reply) {
251 EXPECT_FALSE(reply.success());
252 on_invalid_invoke();
253 });
254 RequestProto empty_req;
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000255 proxy->BeginInvoke("InvalidMethod", empty_req, std::move(deferred_reply2));
256 task_runner_->RunUntilCheckpoint("on_invalid_invoke");
Primiano Tuccied0ce252017-11-09 19:35:10 +0000257}
258
Primiano Tuccic2025af2017-11-20 12:47:49 +0000259// Like BindAndInvokeMethod, but this time invoke a streaming method that
260// provides > 1 reply per invocation.
261TEST_F(ClientImplTest, BindAndInvokeStreamingMethod) {
262 auto* host_svc = host_->AddFakeService("FakeSvc");
263 auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
264 const int kNumReplies = 3;
265
266 // Create and bind |proxy| to the fake host.
267 std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
268 cli_->BindService(proxy->GetWeakPtr());
269 auto on_connect = task_runner_->CreateCheckpoint("on_connect");
270 EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
271 task_runner_->RunUntilCheckpoint("on_connect");
272
273 // Invoke a valid method, reply kNumReplies times.
274 int replies_left = kNumReplies;
275 EXPECT_CALL(*host_method, OnInvoke(_, _))
276 .Times(kNumReplies)
277 .WillRepeatedly(Invoke([&replies_left](const Frame::InvokeMethod& req,
278 Frame::InvokeMethodReply* reply) {
279 RequestProto req_args;
280 EXPECT_TRUE(req_args.ParseFromString(req.args_proto()));
281 reply->set_reply_proto(ReplyProto().SerializeAsString());
282 reply->set_success(true);
283 reply->set_has_more(--replies_left > 0);
284 }));
285
286 RequestProto req;
287 req.set_data("req_data");
288 auto on_last_reply = task_runner_->CreateCheckpoint("on_last_reply");
289 int replies_seen = 0;
290 DeferredBase deferred_reply(
291 [on_last_reply, &replies_seen](AsyncResult<ProtoMessage> reply) {
292 EXPECT_TRUE(reply.success());
293 replies_seen++;
294 if (!reply.has_more())
295 on_last_reply();
296 });
297 proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
298 task_runner_->RunUntilCheckpoint("on_last_reply");
299 ASSERT_EQ(kNumReplies, replies_seen);
300}
301
Primiano Tuccif54cae42017-11-21 19:37:13 +0000302// Like BindAndInvokeMethod, but this time invoke a streaming method that
303// provides > 1 reply per invocation.
304TEST_F(ClientImplTest, ReceiveFileDescriptor) {
305 auto* host_svc = host_->AddFakeService("FakeSvc");
306 auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
307
308 // Create and bind |proxy| to the fake host.
309 std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
310 cli_->BindService(proxy->GetWeakPtr());
311 auto on_connect = task_runner_->CreateCheckpoint("on_connect");
312 EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
313 task_runner_->RunUntilCheckpoint("on_connect");
314
315 FILE* tx_file = tmpfile(); // Automatically unlinked from the filesystem.
316 static constexpr char kFileContent[] = "shared file";
317 fwrite(kFileContent, sizeof(kFileContent), 1, tx_file);
318 fflush(tx_file);
319 host_->next_reply_fd = fileno(tx_file);
320
321 // Invoke a valid method, reply kNumReplies times.
322 EXPECT_CALL(*host_method, OnInvoke(_, _))
323 .WillOnce(Invoke(
324 [](const Frame::InvokeMethod& req, Frame::InvokeMethodReply* reply) {
325 RequestProto req_args;
326 reply->set_reply_proto(ReplyProto().SerializeAsString());
327 reply->set_success(true);
328 }));
329
330 RequestProto req;
331 auto on_reply = task_runner_->CreateCheckpoint("on_reply");
332 DeferredBase deferred_reply([on_reply](AsyncResult<ProtoMessage> reply) {
333 EXPECT_TRUE(reply.success());
334 on_reply();
335 });
336 proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
337 task_runner_->RunUntilCheckpoint("on_reply");
338
339 fclose(tx_file);
340 base::ScopedFile rx_fd = cli_->TakeReceivedFD();
341 ASSERT_TRUE(rx_fd);
342 char buf[sizeof(kFileContent)] = {};
343 ASSERT_EQ(0, lseek(*rx_fd, 0, SEEK_SET));
344 ASSERT_EQ(sizeof(buf), PERFETTO_EINTR(read(*rx_fd, buf, sizeof(buf))));
345 ASSERT_STREQ(kFileContent, buf);
346}
347
Primiano Tucci3052b1a2017-11-14 10:51:01 +0000348TEST_F(ClientImplTest, BindSameServiceMultipleTimesShouldFail) {
349 host_->AddFakeService("FakeSvc");
350
351 std::unique_ptr<FakeProxy> proxy[3];
352 for (size_t i = 0; i < base::ArraySize(proxy); i++)
353 proxy[i].reset(new FakeProxy("FakeSvc", &proxy_events_));
354
355 // Bind to the host.
356 for (size_t i = 0; i < base::ArraySize(proxy); i++) {
357 auto checkpoint_name = "on_connect_or_disconnect" + std::to_string(i);
358 auto closure = task_runner_->CreateCheckpoint(checkpoint_name);
359 if (i == 0) {
360 // Only the first call should succeed.
361 EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(closure));
362 } else {
363 EXPECT_CALL(proxy_events_, OnDisconnect()).WillOnce(Invoke(closure));
364 }
365 cli_->BindService(proxy[i]->GetWeakPtr());
366 task_runner_->RunUntilCheckpoint(checkpoint_name);
367 }
368}
369
370TEST_F(ClientImplTest, BindRequestsAreQueuedIfNotConnected) {
371 host_->AddFakeService("FakeSvc1");
372 host_->AddFakeService("FakeSvc2");
373
374 std::unique_ptr<FakeProxy> proxy1(new FakeProxy("FakeSvc1", &proxy_events_));
375 std::unique_ptr<FakeProxy> proxy2(new FakeProxy("FakeSvc2", &proxy_events_));
376
377 // Bind the services (in opposite order of creation) before running any task.
378 cli_->BindService(proxy2->GetWeakPtr());
379 cli_->BindService(proxy1->GetWeakPtr());
380
381 InSequence seq;
382 auto on_connect1 = task_runner_->CreateCheckpoint("on_connect1");
383 EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect1));
384
385 auto on_connect2 = task_runner_->CreateCheckpoint("on_connect2");
386 EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect2));
387
388 task_runner_->RunUntilCheckpoint("on_connect1");
389 task_runner_->RunUntilCheckpoint("on_connect2");
390}
391
392// The deferred callbacks for both binding a service and invoking a method
393// should be dropped if the ServiceProxy object is destroyed prematurely.
394TEST_F(ClientImplTest, DropCallbacksIfServiceProxyIsDestroyed) {
395 auto* host_svc = host_->AddFakeService("FakeSvc");
396 auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
397
398 std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
399
400 // First bind the service but destroy it before ClientImpl manages to run any
401 // tasks. No OnConnect() should be called.
402 cli_->BindService(proxy->GetWeakPtr());
403 proxy.reset();
404 task_runner_->RunUntilIdle();
405 ASSERT_TRUE(Mock::VerifyAndClearExpectations(&proxy_events_));
406
407 // Now bind it successfully, invoke a method but destroy the proxy before
408 // the method reply is dispatched. The DeferredReply should be rejected,
409 // despite the fact that the host gave a successful reply.
410 proxy.reset(new FakeProxy("FakeSvc", &proxy_events_));
411 auto on_connect = task_runner_->CreateCheckpoint("on_connect");
412 EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
413 cli_->BindService(proxy->GetWeakPtr());
414 task_runner_->RunUntilCheckpoint("on_connect");
415
416 RequestProto req;
417 auto on_reply_sent = task_runner_->CreateCheckpoint("on_reply_sent");
418 EXPECT_CALL(*host_method, OnInvoke(_, _))
419 .WillOnce(Invoke([on_reply_sent](const Frame::InvokeMethod&,
420 Frame::InvokeMethodReply* reply) {
421 ReplyProto reply_args;
422 reply->set_success(true);
423 on_reply_sent();
424 }));
425
426 auto on_reject = task_runner_->CreateCheckpoint("on_reject");
427 DeferredBase deferred_reply([on_reject](AsyncResult<ProtoMessage> res) {
428 ASSERT_FALSE(res.success());
429 on_reject();
430 });
431 proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
432 proxy.reset();
433 task_runner_->RunUntilCheckpoint("on_reject");
434 task_runner_->RunUntilCheckpoint("on_reply_sent");
435}
436
437// If the Client object is destroyed before the ServiceProxy, the ServiceProxy
438// should see a Disconnect() call and any pending callback should be rejected.
439TEST_F(ClientImplTest, ClientDestroyedBeforeProxy) {
440 auto* host_svc = host_->AddFakeService("FakeSvc");
441 host_svc->AddFakeMethod("FakeMethod1");
442
443 std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
444 auto on_connect = task_runner_->CreateCheckpoint("on_connect");
445 EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
446 cli_->BindService(proxy->GetWeakPtr());
447 task_runner_->RunUntilCheckpoint("on_connect");
448
449 auto on_reject = task_runner_->CreateCheckpoint("on_reject");
450 DeferredBase deferred_reply([on_reject](AsyncResult<ProtoMessage> res) {
451 ASSERT_FALSE(res.success());
452 on_reject();
453 });
454 RequestProto req;
455 proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
456 EXPECT_CALL(proxy_events_, OnDisconnect());
457 cli_.reset();
458 task_runner_->RunUntilCheckpoint("on_reject");
459}
460
461// Test that OnDisconnect() is invoked if the host is not reachable.
462TEST_F(ClientImplTest, HostNotReachable) {
463 host_.reset();
464
465 std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
466
467 auto on_disconnect = task_runner_->CreateCheckpoint("on_disconnect");
468 EXPECT_CALL(proxy_events_, OnDisconnect()).WillOnce(Invoke(on_disconnect));
469 cli_->BindService(proxy->GetWeakPtr());
470 task_runner_->RunUntilCheckpoint("on_disconnect");
471}
472
473// Test that OnDisconnect() is invoked if the host shuts down prematurely.
474TEST_F(ClientImplTest, HostDisconnection) {
475 host_->AddFakeService("FakeSvc");
476
477 std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
478
479 // Bind |proxy| to the fake host.
480 cli_->BindService(proxy->GetWeakPtr());
481 auto on_connect = task_runner_->CreateCheckpoint("on_connect");
482 EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
483 task_runner_->RunUntilCheckpoint("on_connect");
484
485 auto on_disconnect = task_runner_->CreateCheckpoint("on_disconnect");
486 EXPECT_CALL(proxy_events_, OnDisconnect()).WillOnce(Invoke(on_disconnect));
487 host_.reset();
488 task_runner_->RunUntilCheckpoint("on_disconnect");
489}
490
491// TODO(primiano): add the tests below.
Primiano Tuccied0ce252017-11-09 19:35:10 +0000492// TEST(ClientImplTest, UnparsableReply) {}
Primiano Tuccied0ce252017-11-09 19:35:10 +0000493
494} // namespace
495} // namespace ipc
496} // namespace perfetto