xref: /aosp_15_r20/external/perfetto/src/ipc/client_impl_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "src/ipc/client_impl.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include <stdio.h>
20*6dbdd20aSAndroid Build Coastguard Worker 
21*6dbdd20aSAndroid Build Coastguard Worker #include <string>
22*6dbdd20aSAndroid Build Coastguard Worker 
23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/file_utils.h"
24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/temp_file.h"
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/unix_socket.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/ipc/service_descriptor.h"
28*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/ipc/service_proxy.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "src/base/test/test_task_runner.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "src/ipc/buffered_frame_deserializer.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "src/ipc/test/test_socket.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "test/gtest_and_gmock.h"
33*6dbdd20aSAndroid Build Coastguard Worker 
34*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/ipc/wire_protocol.gen.h"
35*6dbdd20aSAndroid Build Coastguard Worker #include "src/ipc/test/client_unittest_messages.gen.h"
36*6dbdd20aSAndroid Build Coastguard Worker 
37*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
38*6dbdd20aSAndroid Build Coastguard Worker namespace ipc {
39*6dbdd20aSAndroid Build Coastguard Worker namespace {
40*6dbdd20aSAndroid Build Coastguard Worker 
41*6dbdd20aSAndroid Build Coastguard Worker using ::perfetto::ipc::gen::ReplyProto;
42*6dbdd20aSAndroid Build Coastguard Worker using ::perfetto::ipc::gen::RequestProto;
43*6dbdd20aSAndroid Build Coastguard Worker using ::testing::_;
44*6dbdd20aSAndroid Build Coastguard Worker using ::testing::InSequence;
45*6dbdd20aSAndroid Build Coastguard Worker using ::testing::Invoke;
46*6dbdd20aSAndroid Build Coastguard Worker using ::testing::Mock;
47*6dbdd20aSAndroid Build Coastguard Worker 
48*6dbdd20aSAndroid Build Coastguard Worker ipc::TestSocket kTestSocket{"client_impl_unittest"};
49*6dbdd20aSAndroid Build Coastguard Worker 
50*6dbdd20aSAndroid Build Coastguard Worker // A fake ServiceProxy. This fakes the client-side class that would be
51*6dbdd20aSAndroid Build Coastguard Worker // auto-generated from .proto-files.
52*6dbdd20aSAndroid Build Coastguard Worker class FakeProxy : public ServiceProxy {
53*6dbdd20aSAndroid Build Coastguard Worker  public:
FakeProxy(const char * service_name,ServiceProxy::EventListener * el)54*6dbdd20aSAndroid Build Coastguard Worker   FakeProxy(const char* service_name, ServiceProxy::EventListener* el)
55*6dbdd20aSAndroid Build Coastguard Worker       : ServiceProxy(el), service_name_(service_name) {}
56*6dbdd20aSAndroid Build Coastguard Worker 
GetDescriptor()57*6dbdd20aSAndroid Build Coastguard Worker   const ServiceDescriptor& GetDescriptor() override {
58*6dbdd20aSAndroid Build Coastguard Worker     auto reply_decoder = [](const std::string& proto) {
59*6dbdd20aSAndroid Build Coastguard Worker       std::unique_ptr<ProtoMessage> reply(new ReplyProto());
60*6dbdd20aSAndroid Build Coastguard Worker       EXPECT_TRUE(reply->ParseFromString(proto));
61*6dbdd20aSAndroid Build Coastguard Worker       return reply;
62*6dbdd20aSAndroid Build Coastguard Worker     };
63*6dbdd20aSAndroid Build Coastguard Worker     if (!descriptor_.service_name) {
64*6dbdd20aSAndroid Build Coastguard Worker       descriptor_.service_name = service_name_;
65*6dbdd20aSAndroid Build Coastguard Worker       descriptor_.methods.push_back(
66*6dbdd20aSAndroid Build Coastguard Worker           {"FakeMethod1", nullptr, reply_decoder, nullptr});
67*6dbdd20aSAndroid Build Coastguard Worker     }
68*6dbdd20aSAndroid Build Coastguard Worker     return descriptor_;
69*6dbdd20aSAndroid Build Coastguard Worker   }
70*6dbdd20aSAndroid Build Coastguard Worker 
71*6dbdd20aSAndroid Build Coastguard Worker   const char* service_name_;
72*6dbdd20aSAndroid Build Coastguard Worker   ServiceDescriptor descriptor_;
73*6dbdd20aSAndroid Build Coastguard Worker };
74*6dbdd20aSAndroid Build Coastguard Worker 
75*6dbdd20aSAndroid Build Coastguard Worker class MockEventListener : public ServiceProxy::EventListener {
76*6dbdd20aSAndroid Build Coastguard Worker  public:
77*6dbdd20aSAndroid Build Coastguard Worker   MOCK_METHOD(void, OnConnect, (), (override));
78*6dbdd20aSAndroid Build Coastguard Worker   MOCK_METHOD(void, OnDisconnect, (), (override));
79*6dbdd20aSAndroid Build Coastguard Worker };
80*6dbdd20aSAndroid Build Coastguard Worker 
81*6dbdd20aSAndroid Build Coastguard Worker // A fake host implementation. Listens on |kTestSocket.name()| and replies to
82*6dbdd20aSAndroid Build Coastguard Worker // IPC metohds like a real one.
83*6dbdd20aSAndroid Build Coastguard Worker class FakeHost : public base::UnixSocket::EventListener {
84*6dbdd20aSAndroid Build Coastguard Worker  public:
85*6dbdd20aSAndroid Build Coastguard Worker   struct FakeMethod {
86*6dbdd20aSAndroid Build Coastguard Worker     MethodID id;
87*6dbdd20aSAndroid Build Coastguard Worker     MOCK_METHOD(void,
88*6dbdd20aSAndroid Build Coastguard Worker                 OnInvoke,
89*6dbdd20aSAndroid Build Coastguard Worker                 (const Frame::InvokeMethod&, Frame::InvokeMethodReply*));
90*6dbdd20aSAndroid Build Coastguard Worker   };  // FakeMethod.
91*6dbdd20aSAndroid Build Coastguard Worker 
92*6dbdd20aSAndroid Build Coastguard Worker   struct FakeService {
AddFakeMethodperfetto::ipc::__anon03c600040111::FakeHost::FakeService93*6dbdd20aSAndroid Build Coastguard Worker     FakeMethod* AddFakeMethod(const std::string& name) {
94*6dbdd20aSAndroid Build Coastguard Worker       auto it_and_inserted =
95*6dbdd20aSAndroid Build Coastguard Worker           methods.emplace(name, std::unique_ptr<FakeMethod>(new FakeMethod()));
96*6dbdd20aSAndroid Build Coastguard Worker       EXPECT_TRUE(it_and_inserted.second);
97*6dbdd20aSAndroid Build Coastguard Worker       FakeMethod* method = it_and_inserted.first->second.get();
98*6dbdd20aSAndroid Build Coastguard Worker       method->id = ++last_method_id;
99*6dbdd20aSAndroid Build Coastguard Worker       return method;
100*6dbdd20aSAndroid Build Coastguard Worker     }
101*6dbdd20aSAndroid Build Coastguard Worker 
102*6dbdd20aSAndroid Build Coastguard Worker     ServiceID id;
103*6dbdd20aSAndroid Build Coastguard Worker     std::map<std::string, std::unique_ptr<FakeMethod>> methods;
104*6dbdd20aSAndroid Build Coastguard Worker     MethodID last_method_id = 0;
105*6dbdd20aSAndroid Build Coastguard Worker   };  // FakeService.
106*6dbdd20aSAndroid Build Coastguard Worker 
107*6dbdd20aSAndroid Build Coastguard Worker   // If |should_listen| is set, then a listening socket is created.
108*6dbdd20aSAndroid Build Coastguard Worker   // Otherwise, incoming connections should be delivered via
109*6dbdd20aSAndroid Build Coastguard Worker   // OnNewIncomingConnection().
FakeHost(bool should_listen,base::TaskRunner * task_runner)110*6dbdd20aSAndroid Build Coastguard Worker   FakeHost(bool should_listen, base::TaskRunner* task_runner) {
111*6dbdd20aSAndroid Build Coastguard Worker     if (should_listen) {
112*6dbdd20aSAndroid Build Coastguard Worker       kTestSocket.Destroy();
113*6dbdd20aSAndroid Build Coastguard Worker       listening_sock_ = base::UnixSocket::Listen(
114*6dbdd20aSAndroid Build Coastguard Worker           kTestSocket.name(), this, task_runner, kTestSocket.family(),
115*6dbdd20aSAndroid Build Coastguard Worker           base::SockType::kStream);
116*6dbdd20aSAndroid Build Coastguard Worker       EXPECT_TRUE(listening_sock_->is_listening());
117*6dbdd20aSAndroid Build Coastguard Worker     }
118*6dbdd20aSAndroid Build Coastguard Worker   }
119*6dbdd20aSAndroid Build Coastguard Worker 
~FakeHost()120*6dbdd20aSAndroid Build Coastguard Worker   ~FakeHost() override { kTestSocket.Destroy(); }
121*6dbdd20aSAndroid Build Coastguard Worker 
AddFakeService(const std::string & name)122*6dbdd20aSAndroid Build Coastguard Worker   FakeService* AddFakeService(const std::string& name) {
123*6dbdd20aSAndroid Build Coastguard Worker     auto it_and_inserted = services_.emplace(
124*6dbdd20aSAndroid Build Coastguard Worker         name, std::unique_ptr<FakeService>(new FakeService()));
125*6dbdd20aSAndroid Build Coastguard Worker     EXPECT_TRUE(it_and_inserted.second);
126*6dbdd20aSAndroid Build Coastguard Worker     FakeService* svc = it_and_inserted.first->second.get();
127*6dbdd20aSAndroid Build Coastguard Worker     svc->id = ++last_service_id_;
128*6dbdd20aSAndroid Build Coastguard Worker     return svc;
129*6dbdd20aSAndroid Build Coastguard Worker   }
130*6dbdd20aSAndroid Build Coastguard Worker 
131*6dbdd20aSAndroid Build Coastguard Worker   // base::UnixSocket::EventListener implementation.
OnNewIncomingConnection(base::UnixSocket *,std::unique_ptr<base::UnixSocket> new_connection)132*6dbdd20aSAndroid Build Coastguard Worker   void OnNewIncomingConnection(
133*6dbdd20aSAndroid Build Coastguard Worker       base::UnixSocket*,
134*6dbdd20aSAndroid Build Coastguard Worker       std::unique_ptr<base::UnixSocket> new_connection) override {
135*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_FALSE(client_sock_);
136*6dbdd20aSAndroid Build Coastguard Worker     client_sock_ = std::move(new_connection);
137*6dbdd20aSAndroid Build Coastguard Worker   }
138*6dbdd20aSAndroid Build Coastguard Worker 
OnDataAvailable(base::UnixSocket * sock)139*6dbdd20aSAndroid Build Coastguard Worker   void OnDataAvailable(base::UnixSocket* sock) override {
140*6dbdd20aSAndroid Build Coastguard Worker     if (sock != client_sock_.get())
141*6dbdd20aSAndroid Build Coastguard Worker       return;
142*6dbdd20aSAndroid Build Coastguard Worker     auto buf = frame_deserializer_.BeginReceive();
143*6dbdd20aSAndroid Build Coastguard Worker     base::ScopedFile fd;
144*6dbdd20aSAndroid Build Coastguard Worker     size_t rsize = client_sock_->Receive(buf.data, buf.size, &fd);
145*6dbdd20aSAndroid Build Coastguard Worker     if (fd)
146*6dbdd20aSAndroid Build Coastguard Worker       received_fd_ = std::move(fd);
147*6dbdd20aSAndroid Build Coastguard Worker     EXPECT_TRUE(frame_deserializer_.EndReceive(rsize));
148*6dbdd20aSAndroid Build Coastguard Worker     while (std::unique_ptr<Frame> frame = frame_deserializer_.PopNextFrame())
149*6dbdd20aSAndroid Build Coastguard Worker       OnFrameReceived(*frame);
150*6dbdd20aSAndroid Build Coastguard Worker   }
151*6dbdd20aSAndroid Build Coastguard Worker 
OnFrameReceived(const Frame & req)152*6dbdd20aSAndroid Build Coastguard Worker   void OnFrameReceived(const Frame& req) {
153*6dbdd20aSAndroid Build Coastguard Worker     if (req.has_msg_bind_service()) {
154*6dbdd20aSAndroid Build Coastguard Worker       auto svc_it = services_.find(req.msg_bind_service().service_name());
155*6dbdd20aSAndroid Build Coastguard Worker       ASSERT_NE(services_.end(), svc_it);
156*6dbdd20aSAndroid Build Coastguard Worker       const FakeService& svc = *svc_it->second;
157*6dbdd20aSAndroid Build Coastguard Worker       Frame reply;
158*6dbdd20aSAndroid Build Coastguard Worker       reply.set_request_id(req.request_id());
159*6dbdd20aSAndroid Build Coastguard Worker       reply.mutable_msg_bind_service_reply()->set_success(true);
160*6dbdd20aSAndroid Build Coastguard Worker       reply.mutable_msg_bind_service_reply()->set_service_id(svc.id);
161*6dbdd20aSAndroid Build Coastguard Worker       for (const auto& method_it : svc.methods) {
162*6dbdd20aSAndroid Build Coastguard Worker         auto* method = reply.mutable_msg_bind_service_reply()->add_methods();
163*6dbdd20aSAndroid Build Coastguard Worker         method->set_name(method_it.first);
164*6dbdd20aSAndroid Build Coastguard Worker         method->set_id(method_it.second->id);
165*6dbdd20aSAndroid Build Coastguard Worker       }
166*6dbdd20aSAndroid Build Coastguard Worker       Reply(reply);
167*6dbdd20aSAndroid Build Coastguard Worker     } else if (req.has_msg_invoke_method()) {
168*6dbdd20aSAndroid Build Coastguard Worker       // Lookup the service and method.
169*6dbdd20aSAndroid Build Coastguard Worker       bool has_more = false;
170*6dbdd20aSAndroid Build Coastguard Worker       do {
171*6dbdd20aSAndroid Build Coastguard Worker         Frame reply;
172*6dbdd20aSAndroid Build Coastguard Worker         reply.set_request_id(req.request_id());
173*6dbdd20aSAndroid Build Coastguard Worker         for (const auto& svc : services_) {
174*6dbdd20aSAndroid Build Coastguard Worker           if (svc.second->id != req.msg_invoke_method().service_id())
175*6dbdd20aSAndroid Build Coastguard Worker             continue;
176*6dbdd20aSAndroid Build Coastguard Worker           for (const auto& method : svc.second->methods) {
177*6dbdd20aSAndroid Build Coastguard Worker             if (method.second->id != req.msg_invoke_method().method_id())
178*6dbdd20aSAndroid Build Coastguard Worker               continue;
179*6dbdd20aSAndroid Build Coastguard Worker             method.second->OnInvoke(req.msg_invoke_method(),
180*6dbdd20aSAndroid Build Coastguard Worker                                     reply.mutable_msg_invoke_method_reply());
181*6dbdd20aSAndroid Build Coastguard Worker             has_more = reply.mutable_msg_invoke_method_reply()->has_more();
182*6dbdd20aSAndroid Build Coastguard Worker           }
183*6dbdd20aSAndroid Build Coastguard Worker         }
184*6dbdd20aSAndroid Build Coastguard Worker         // If either the method or the service are not found, |success| will be
185*6dbdd20aSAndroid Build Coastguard Worker         // false by default.
186*6dbdd20aSAndroid Build Coastguard Worker         Reply(reply);
187*6dbdd20aSAndroid Build Coastguard Worker       } while (has_more);
188*6dbdd20aSAndroid Build Coastguard Worker     } else {
189*6dbdd20aSAndroid Build Coastguard Worker       FAIL() << "Unknown request";
190*6dbdd20aSAndroid Build Coastguard Worker     }
191*6dbdd20aSAndroid Build Coastguard Worker   }
192*6dbdd20aSAndroid Build Coastguard Worker 
Reply(const Frame & frame)193*6dbdd20aSAndroid Build Coastguard Worker   void Reply(const Frame& frame) {
194*6dbdd20aSAndroid Build Coastguard Worker     if (suppress_replies_)
195*6dbdd20aSAndroid Build Coastguard Worker       return;
196*6dbdd20aSAndroid Build Coastguard Worker     auto buf = BufferedFrameDeserializer::Serialize(frame);
197*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_TRUE(client_sock_->is_connected());
198*6dbdd20aSAndroid Build Coastguard Worker     EXPECT_TRUE(client_sock_->Send(buf.data(), buf.size(), next_reply_fd_));
199*6dbdd20aSAndroid Build Coastguard Worker     next_reply_fd_ = -1;
200*6dbdd20aSAndroid Build Coastguard Worker   }
201*6dbdd20aSAndroid Build Coastguard Worker 
202*6dbdd20aSAndroid Build Coastguard Worker   BufferedFrameDeserializer frame_deserializer_;
203*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<base::UnixSocket> listening_sock_;
204*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<base::UnixSocket> client_sock_;
205*6dbdd20aSAndroid Build Coastguard Worker   std::map<std::string, std::unique_ptr<FakeService>> services_;
206*6dbdd20aSAndroid Build Coastguard Worker   ServiceID last_service_id_ = 0;
207*6dbdd20aSAndroid Build Coastguard Worker   int next_reply_fd_ = -1;
208*6dbdd20aSAndroid Build Coastguard Worker   base::ScopedFile received_fd_;
209*6dbdd20aSAndroid Build Coastguard Worker   // This flag can be set to true to prevent the host from sending replies.
210*6dbdd20aSAndroid Build Coastguard Worker   // Useful to test race conditions in ClientImpl.
211*6dbdd20aSAndroid Build Coastguard Worker   bool suppress_replies_ = false;
212*6dbdd20aSAndroid Build Coastguard Worker };  // FakeHost.
213*6dbdd20aSAndroid Build Coastguard Worker 
214*6dbdd20aSAndroid Build Coastguard Worker class ClientImplTest : public ::testing::Test {
215*6dbdd20aSAndroid Build Coastguard Worker  public:
SetUp()216*6dbdd20aSAndroid Build Coastguard Worker   void SetUp() override {
217*6dbdd20aSAndroid Build Coastguard Worker     task_runner_.reset(new base::TestTaskRunner());
218*6dbdd20aSAndroid Build Coastguard Worker 
219*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
220*6dbdd20aSAndroid Build Coastguard Worker     auto socket_pair = base::UnixSocketRaw::CreatePairPosix(
221*6dbdd20aSAndroid Build Coastguard Worker         base::SockFamily::kUnix, base::SockType::kStream);
222*6dbdd20aSAndroid Build Coastguard Worker     host_.reset(new FakeHost(false, task_runner_.get()));
223*6dbdd20aSAndroid Build Coastguard Worker     host_->OnNewIncomingConnection(
224*6dbdd20aSAndroid Build Coastguard Worker         nullptr,
225*6dbdd20aSAndroid Build Coastguard Worker         base::UnixSocket::AdoptConnected(
226*6dbdd20aSAndroid Build Coastguard Worker             socket_pair.first.ReleaseFd(), host_.get(), task_runner_.get(),
227*6dbdd20aSAndroid Build Coastguard Worker             kTestSocket.family(), base::SockType::kStream));
228*6dbdd20aSAndroid Build Coastguard Worker     cli_ = Client::CreateInstance(Client::ConnArgs(base::ScopedSocketHandle(
229*6dbdd20aSAndroid Build Coastguard Worker                                       socket_pair.second.ReleaseFd())),
230*6dbdd20aSAndroid Build Coastguard Worker                                   task_runner_.get());
231*6dbdd20aSAndroid Build Coastguard Worker #else
232*6dbdd20aSAndroid Build Coastguard Worker     host_.reset(new FakeHost(true, task_runner_.get()));
233*6dbdd20aSAndroid Build Coastguard Worker     cli_ = Client::CreateInstance({kTestSocket.name(), /*retry=*/false},
234*6dbdd20aSAndroid Build Coastguard Worker                                   task_runner_.get());
235*6dbdd20aSAndroid Build Coastguard Worker #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
236*6dbdd20aSAndroid Build Coastguard Worker   }
237*6dbdd20aSAndroid Build Coastguard Worker 
TearDown()238*6dbdd20aSAndroid Build Coastguard Worker   void TearDown() override {
239*6dbdd20aSAndroid Build Coastguard Worker     cli_.reset();
240*6dbdd20aSAndroid Build Coastguard Worker     host_.reset();
241*6dbdd20aSAndroid Build Coastguard Worker     task_runner_->RunUntilIdle();
242*6dbdd20aSAndroid Build Coastguard Worker     task_runner_.reset();
243*6dbdd20aSAndroid Build Coastguard Worker   }
244*6dbdd20aSAndroid Build Coastguard Worker 
245*6dbdd20aSAndroid Build Coastguard Worker   ::testing::StrictMock<MockEventListener> proxy_events_;
246*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<base::TestTaskRunner> task_runner_;
247*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeHost> host_;
248*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<Client> cli_;
249*6dbdd20aSAndroid Build Coastguard Worker };
250*6dbdd20aSAndroid Build Coastguard Worker 
TEST_F(ClientImplTest,BindAndInvokeMethod)251*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, BindAndInvokeMethod) {
252*6dbdd20aSAndroid Build Coastguard Worker   auto* host_svc = host_->AddFakeService("FakeSvc");
253*6dbdd20aSAndroid Build Coastguard Worker   auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
254*6dbdd20aSAndroid Build Coastguard Worker 
255*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
256*6dbdd20aSAndroid Build Coastguard Worker 
257*6dbdd20aSAndroid Build Coastguard Worker   // Bind |proxy| to the fake host.
258*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
259*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect = task_runner_->CreateCheckpoint("on_connect");
260*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
261*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect");
262*6dbdd20aSAndroid Build Coastguard Worker 
263*6dbdd20aSAndroid Build Coastguard Worker   // Invoke a valid method.
264*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(*host_method, OnInvoke(_, _))
265*6dbdd20aSAndroid Build Coastguard Worker       .WillOnce(Invoke(
266*6dbdd20aSAndroid Build Coastguard Worker           [](const Frame::InvokeMethod& req, Frame::InvokeMethodReply* reply) {
267*6dbdd20aSAndroid Build Coastguard Worker             RequestProto req_args;
268*6dbdd20aSAndroid Build Coastguard Worker             EXPECT_TRUE(req_args.ParseFromString(req.args_proto()));
269*6dbdd20aSAndroid Build Coastguard Worker             EXPECT_EQ("req_data", req_args.data());
270*6dbdd20aSAndroid Build Coastguard Worker             ReplyProto reply_args;
271*6dbdd20aSAndroid Build Coastguard Worker             reply->set_reply_proto(reply_args.SerializeAsString());
272*6dbdd20aSAndroid Build Coastguard Worker             reply->set_success(true);
273*6dbdd20aSAndroid Build Coastguard Worker           }));
274*6dbdd20aSAndroid Build Coastguard Worker 
275*6dbdd20aSAndroid Build Coastguard Worker   RequestProto req;
276*6dbdd20aSAndroid Build Coastguard Worker   req.set_data("req_data");
277*6dbdd20aSAndroid Build Coastguard Worker   auto on_invoke_reply = task_runner_->CreateCheckpoint("on_invoke_reply");
278*6dbdd20aSAndroid Build Coastguard Worker   Deferred<ProtoMessage> deferred_reply(
279*6dbdd20aSAndroid Build Coastguard Worker       [on_invoke_reply](AsyncResult<ProtoMessage> reply) {
280*6dbdd20aSAndroid Build Coastguard Worker         EXPECT_TRUE(reply.success());
281*6dbdd20aSAndroid Build Coastguard Worker         on_invoke_reply();
282*6dbdd20aSAndroid Build Coastguard Worker       });
283*6dbdd20aSAndroid Build Coastguard Worker   proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
284*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_invoke_reply");
285*6dbdd20aSAndroid Build Coastguard Worker 
286*6dbdd20aSAndroid Build Coastguard Worker   // Invoke an invalid method.
287*6dbdd20aSAndroid Build Coastguard Worker   auto on_invalid_invoke = task_runner_->CreateCheckpoint("on_invalid_invoke");
288*6dbdd20aSAndroid Build Coastguard Worker   Deferred<ProtoMessage> deferred_reply2(
289*6dbdd20aSAndroid Build Coastguard Worker       [on_invalid_invoke](AsyncResult<ProtoMessage> reply) {
290*6dbdd20aSAndroid Build Coastguard Worker         EXPECT_FALSE(reply.success());
291*6dbdd20aSAndroid Build Coastguard Worker         on_invalid_invoke();
292*6dbdd20aSAndroid Build Coastguard Worker       });
293*6dbdd20aSAndroid Build Coastguard Worker   RequestProto empty_req;
294*6dbdd20aSAndroid Build Coastguard Worker   proxy->BeginInvoke("InvalidMethod", empty_req, std::move(deferred_reply2));
295*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_invalid_invoke");
296*6dbdd20aSAndroid Build Coastguard Worker }
297*6dbdd20aSAndroid Build Coastguard Worker 
298*6dbdd20aSAndroid Build Coastguard Worker // Tests that when invoking a method without binding a callback, the resulting
299*6dbdd20aSAndroid Build Coastguard Worker // request has the |drop_reply| flag set.
TEST_F(ClientImplTest,InvokeMethodDropReply)300*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, InvokeMethodDropReply) {
301*6dbdd20aSAndroid Build Coastguard Worker   auto* host_svc = host_->AddFakeService("FakeSvc");
302*6dbdd20aSAndroid Build Coastguard Worker   auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
303*6dbdd20aSAndroid Build Coastguard Worker 
304*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
305*6dbdd20aSAndroid Build Coastguard Worker 
306*6dbdd20aSAndroid Build Coastguard Worker   // Bind |proxy| to the fake host.
307*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
308*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect = task_runner_->CreateCheckpoint("on_connect");
309*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
310*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect");
311*6dbdd20aSAndroid Build Coastguard Worker 
312*6dbdd20aSAndroid Build Coastguard Worker   auto on_req_received = task_runner_->CreateCheckpoint("on_req_received");
313*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(*host_method, OnInvoke(_, _))
314*6dbdd20aSAndroid Build Coastguard Worker       .WillOnce(Invoke([on_req_received](const Frame::InvokeMethod& req,
315*6dbdd20aSAndroid Build Coastguard Worker                                          Frame::InvokeMethodReply*) {
316*6dbdd20aSAndroid Build Coastguard Worker         RequestProto req_args;
317*6dbdd20aSAndroid Build Coastguard Worker         EXPECT_TRUE(req.drop_reply());
318*6dbdd20aSAndroid Build Coastguard Worker         on_req_received();
319*6dbdd20aSAndroid Build Coastguard Worker       }));
320*6dbdd20aSAndroid Build Coastguard Worker 
321*6dbdd20aSAndroid Build Coastguard Worker   // Invoke a method without binding any callback to the Deferred object.
322*6dbdd20aSAndroid Build Coastguard Worker   Deferred<ProtoMessage> no_callback;
323*6dbdd20aSAndroid Build Coastguard Worker   proxy->BeginInvoke("FakeMethod1", RequestProto(), std::move(no_callback));
324*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_req_received");
325*6dbdd20aSAndroid Build Coastguard Worker }
326*6dbdd20aSAndroid Build Coastguard Worker 
327*6dbdd20aSAndroid Build Coastguard Worker // Like BindAndInvokeMethod, but this time invoke a streaming method that
328*6dbdd20aSAndroid Build Coastguard Worker // provides > 1 reply per invocation.
TEST_F(ClientImplTest,BindAndInvokeStreamingMethod)329*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, BindAndInvokeStreamingMethod) {
330*6dbdd20aSAndroid Build Coastguard Worker   auto* host_svc = host_->AddFakeService("FakeSvc");
331*6dbdd20aSAndroid Build Coastguard Worker   auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
332*6dbdd20aSAndroid Build Coastguard Worker   const int kNumReplies = 3;
333*6dbdd20aSAndroid Build Coastguard Worker 
334*6dbdd20aSAndroid Build Coastguard Worker   // Create and bind |proxy| to the fake host.
335*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
336*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
337*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect = task_runner_->CreateCheckpoint("on_connect");
338*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
339*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect");
340*6dbdd20aSAndroid Build Coastguard Worker 
341*6dbdd20aSAndroid Build Coastguard Worker   // Invoke a valid method, reply kNumReplies times.
342*6dbdd20aSAndroid Build Coastguard Worker   int replies_left = kNumReplies;
343*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(*host_method, OnInvoke(_, _))
344*6dbdd20aSAndroid Build Coastguard Worker       .Times(kNumReplies)
345*6dbdd20aSAndroid Build Coastguard Worker       .WillRepeatedly(Invoke([&replies_left](const Frame::InvokeMethod& req,
346*6dbdd20aSAndroid Build Coastguard Worker                                              Frame::InvokeMethodReply* reply) {
347*6dbdd20aSAndroid Build Coastguard Worker         RequestProto req_args;
348*6dbdd20aSAndroid Build Coastguard Worker         EXPECT_TRUE(req_args.ParseFromString(req.args_proto()));
349*6dbdd20aSAndroid Build Coastguard Worker         reply->set_reply_proto(ReplyProto().SerializeAsString());
350*6dbdd20aSAndroid Build Coastguard Worker         reply->set_success(true);
351*6dbdd20aSAndroid Build Coastguard Worker         reply->set_has_more(--replies_left > 0);
352*6dbdd20aSAndroid Build Coastguard Worker       }));
353*6dbdd20aSAndroid Build Coastguard Worker 
354*6dbdd20aSAndroid Build Coastguard Worker   RequestProto req;
355*6dbdd20aSAndroid Build Coastguard Worker   req.set_data("req_data");
356*6dbdd20aSAndroid Build Coastguard Worker   auto on_last_reply = task_runner_->CreateCheckpoint("on_last_reply");
357*6dbdd20aSAndroid Build Coastguard Worker   int replies_seen = 0;
358*6dbdd20aSAndroid Build Coastguard Worker   Deferred<ProtoMessage> deferred_reply(
359*6dbdd20aSAndroid Build Coastguard Worker       [on_last_reply, &replies_seen](AsyncResult<ProtoMessage> reply) {
360*6dbdd20aSAndroid Build Coastguard Worker         EXPECT_TRUE(reply.success());
361*6dbdd20aSAndroid Build Coastguard Worker         replies_seen++;
362*6dbdd20aSAndroid Build Coastguard Worker         if (!reply.has_more())
363*6dbdd20aSAndroid Build Coastguard Worker           on_last_reply();
364*6dbdd20aSAndroid Build Coastguard Worker       });
365*6dbdd20aSAndroid Build Coastguard Worker   proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
366*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_last_reply");
367*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(kNumReplies, replies_seen);
368*6dbdd20aSAndroid Build Coastguard Worker }
369*6dbdd20aSAndroid Build Coastguard Worker 
370*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
371*6dbdd20aSAndroid Build Coastguard Worker     !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
372*6dbdd20aSAndroid Build Coastguard Worker // File descriptor sending over IPC is not supported on Windows or Fuchsia.
TEST_F(ClientImplTest,ReceiveFileDescriptor)373*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, ReceiveFileDescriptor) {
374*6dbdd20aSAndroid Build Coastguard Worker   auto* host_svc = host_->AddFakeService("FakeSvc");
375*6dbdd20aSAndroid Build Coastguard Worker   auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
376*6dbdd20aSAndroid Build Coastguard Worker 
377*6dbdd20aSAndroid Build Coastguard Worker   // Create and bind |proxy| to the fake host.
378*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
379*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
380*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect = task_runner_->CreateCheckpoint("on_connect");
381*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
382*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect");
383*6dbdd20aSAndroid Build Coastguard Worker 
384*6dbdd20aSAndroid Build Coastguard Worker   base::TempFile tx_file = base::TempFile::CreateUnlinked();
385*6dbdd20aSAndroid Build Coastguard Worker   static constexpr char kFileContent[] = "shared file";
386*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(base::WriteAll(tx_file.fd(), kFileContent,
387*6dbdd20aSAndroid Build Coastguard Worker                                                sizeof(kFileContent))),
388*6dbdd20aSAndroid Build Coastguard Worker             sizeof(kFileContent));
389*6dbdd20aSAndroid Build Coastguard Worker   host_->next_reply_fd_ = tx_file.fd();
390*6dbdd20aSAndroid Build Coastguard Worker 
391*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(*host_method, OnInvoke(_, _))
392*6dbdd20aSAndroid Build Coastguard Worker       .WillOnce(Invoke(
393*6dbdd20aSAndroid Build Coastguard Worker           [](const Frame::InvokeMethod&, Frame::InvokeMethodReply* reply) {
394*6dbdd20aSAndroid Build Coastguard Worker             RequestProto req_args;
395*6dbdd20aSAndroid Build Coastguard Worker             reply->set_reply_proto(ReplyProto().SerializeAsString());
396*6dbdd20aSAndroid Build Coastguard Worker             reply->set_success(true);
397*6dbdd20aSAndroid Build Coastguard Worker           }));
398*6dbdd20aSAndroid Build Coastguard Worker 
399*6dbdd20aSAndroid Build Coastguard Worker   RequestProto req;
400*6dbdd20aSAndroid Build Coastguard Worker   auto on_reply = task_runner_->CreateCheckpoint("on_reply");
401*6dbdd20aSAndroid Build Coastguard Worker   Deferred<ProtoMessage> deferred_reply(
402*6dbdd20aSAndroid Build Coastguard Worker       [on_reply](AsyncResult<ProtoMessage> reply) {
403*6dbdd20aSAndroid Build Coastguard Worker         EXPECT_TRUE(reply.success());
404*6dbdd20aSAndroid Build Coastguard Worker         on_reply();
405*6dbdd20aSAndroid Build Coastguard Worker       });
406*6dbdd20aSAndroid Build Coastguard Worker   proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
407*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_reply");
408*6dbdd20aSAndroid Build Coastguard Worker 
409*6dbdd20aSAndroid Build Coastguard Worker   tx_file.ReleaseFD();
410*6dbdd20aSAndroid Build Coastguard Worker   base::ScopedFile rx_fd = cli_->TakeReceivedFD();
411*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_TRUE(rx_fd);
412*6dbdd20aSAndroid Build Coastguard Worker   char buf[sizeof(kFileContent)] = {};
413*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(0, lseek(*rx_fd, 0, SEEK_SET));
414*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<long>(sizeof(buf)),
415*6dbdd20aSAndroid Build Coastguard Worker             PERFETTO_EINTR(read(*rx_fd, buf, sizeof(buf))));
416*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_STREQ(kFileContent, buf);
417*6dbdd20aSAndroid Build Coastguard Worker }
418*6dbdd20aSAndroid Build Coastguard Worker 
TEST_F(ClientImplTest,SendFileDescriptor)419*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, SendFileDescriptor) {
420*6dbdd20aSAndroid Build Coastguard Worker   auto* host_svc = host_->AddFakeService("FakeSvc");
421*6dbdd20aSAndroid Build Coastguard Worker   auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
422*6dbdd20aSAndroid Build Coastguard Worker 
423*6dbdd20aSAndroid Build Coastguard Worker   // Create and bind |proxy| to the fake host.
424*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
425*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
426*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect = task_runner_->CreateCheckpoint("on_connect");
427*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
428*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect");
429*6dbdd20aSAndroid Build Coastguard Worker 
430*6dbdd20aSAndroid Build Coastguard Worker   base::TempFile tx_file = base::TempFile::CreateUnlinked();
431*6dbdd20aSAndroid Build Coastguard Worker   static constexpr char kFileContent[] = "shared file";
432*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(base::WriteAll(tx_file.fd(), kFileContent,
433*6dbdd20aSAndroid Build Coastguard Worker                                                sizeof(kFileContent))),
434*6dbdd20aSAndroid Build Coastguard Worker             sizeof(kFileContent));
435*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(*host_method, OnInvoke(_, _))
436*6dbdd20aSAndroid Build Coastguard Worker       .WillOnce(Invoke(
437*6dbdd20aSAndroid Build Coastguard Worker           [](const Frame::InvokeMethod&, Frame::InvokeMethodReply* reply) {
438*6dbdd20aSAndroid Build Coastguard Worker             RequestProto req_args;
439*6dbdd20aSAndroid Build Coastguard Worker             reply->set_reply_proto(ReplyProto().SerializeAsString());
440*6dbdd20aSAndroid Build Coastguard Worker             reply->set_success(true);
441*6dbdd20aSAndroid Build Coastguard Worker           }));
442*6dbdd20aSAndroid Build Coastguard Worker 
443*6dbdd20aSAndroid Build Coastguard Worker   RequestProto req;
444*6dbdd20aSAndroid Build Coastguard Worker   auto on_reply = task_runner_->CreateCheckpoint("on_reply");
445*6dbdd20aSAndroid Build Coastguard Worker   Deferred<ProtoMessage> deferred_reply(
446*6dbdd20aSAndroid Build Coastguard Worker       [on_reply](AsyncResult<ProtoMessage> reply) {
447*6dbdd20aSAndroid Build Coastguard Worker         EXPECT_TRUE(reply.success());
448*6dbdd20aSAndroid Build Coastguard Worker         on_reply();
449*6dbdd20aSAndroid Build Coastguard Worker       });
450*6dbdd20aSAndroid Build Coastguard Worker   proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply),
451*6dbdd20aSAndroid Build Coastguard Worker                      tx_file.fd());
452*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_reply");
453*6dbdd20aSAndroid Build Coastguard Worker 
454*6dbdd20aSAndroid Build Coastguard Worker   base::ScopedFile rx_fd = std::move(host_->received_fd_);
455*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_TRUE(rx_fd);
456*6dbdd20aSAndroid Build Coastguard Worker   char buf[sizeof(kFileContent)] = {};
457*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(0, lseek(*rx_fd, 0, SEEK_SET));
458*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<long>(sizeof(buf)),
459*6dbdd20aSAndroid Build Coastguard Worker             PERFETTO_EINTR(read(*rx_fd, buf, sizeof(buf))));
460*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_STREQ(kFileContent, buf);
461*6dbdd20aSAndroid Build Coastguard Worker }
462*6dbdd20aSAndroid Build Coastguard Worker #endif  // !OS_WIN
463*6dbdd20aSAndroid Build Coastguard Worker 
TEST_F(ClientImplTest,BindSameServiceMultipleTimesShouldFail)464*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, BindSameServiceMultipleTimesShouldFail) {
465*6dbdd20aSAndroid Build Coastguard Worker   host_->AddFakeService("FakeSvc");
466*6dbdd20aSAndroid Build Coastguard Worker 
467*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy[3];
468*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; i < base::ArraySize(proxy); i++)
469*6dbdd20aSAndroid Build Coastguard Worker     proxy[i].reset(new FakeProxy("FakeSvc", &proxy_events_));
470*6dbdd20aSAndroid Build Coastguard Worker 
471*6dbdd20aSAndroid Build Coastguard Worker   // Bind to the host.
472*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; i < base::ArraySize(proxy); i++) {
473*6dbdd20aSAndroid Build Coastguard Worker     auto checkpoint_name = "on_connect_or_disconnect" + std::to_string(i);
474*6dbdd20aSAndroid Build Coastguard Worker     auto closure = task_runner_->CreateCheckpoint(checkpoint_name);
475*6dbdd20aSAndroid Build Coastguard Worker     if (i == 0) {
476*6dbdd20aSAndroid Build Coastguard Worker       // Only the first call should succeed.
477*6dbdd20aSAndroid Build Coastguard Worker       EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(closure));
478*6dbdd20aSAndroid Build Coastguard Worker     } else {
479*6dbdd20aSAndroid Build Coastguard Worker       EXPECT_CALL(proxy_events_, OnDisconnect()).WillOnce(Invoke(closure));
480*6dbdd20aSAndroid Build Coastguard Worker     }
481*6dbdd20aSAndroid Build Coastguard Worker     cli_->BindService(proxy[i]->GetWeakPtr());
482*6dbdd20aSAndroid Build Coastguard Worker     task_runner_->RunUntilCheckpoint(checkpoint_name);
483*6dbdd20aSAndroid Build Coastguard Worker   }
484*6dbdd20aSAndroid Build Coastguard Worker }
485*6dbdd20aSAndroid Build Coastguard Worker 
TEST_F(ClientImplTest,BindRequestsAreQueuedIfNotConnected)486*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, BindRequestsAreQueuedIfNotConnected) {
487*6dbdd20aSAndroid Build Coastguard Worker   host_->AddFakeService("FakeSvc1");
488*6dbdd20aSAndroid Build Coastguard Worker   host_->AddFakeService("FakeSvc2");
489*6dbdd20aSAndroid Build Coastguard Worker 
490*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy1(new FakeProxy("FakeSvc1", &proxy_events_));
491*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy2(new FakeProxy("FakeSvc2", &proxy_events_));
492*6dbdd20aSAndroid Build Coastguard Worker 
493*6dbdd20aSAndroid Build Coastguard Worker   // Bind the services (in opposite order of creation) before running any task.
494*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy2->GetWeakPtr());
495*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy1->GetWeakPtr());
496*6dbdd20aSAndroid Build Coastguard Worker 
497*6dbdd20aSAndroid Build Coastguard Worker   InSequence seq;
498*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect1 = task_runner_->CreateCheckpoint("on_connect1");
499*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect1));
500*6dbdd20aSAndroid Build Coastguard Worker 
501*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect2 = task_runner_->CreateCheckpoint("on_connect2");
502*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect2));
503*6dbdd20aSAndroid Build Coastguard Worker 
504*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect1");
505*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect2");
506*6dbdd20aSAndroid Build Coastguard Worker }
507*6dbdd20aSAndroid Build Coastguard Worker 
508*6dbdd20aSAndroid Build Coastguard Worker // The deferred callbacks for both binding a service and invoking a method
509*6dbdd20aSAndroid Build Coastguard Worker // should be dropped if the ServiceProxy object is destroyed prematurely.
TEST_F(ClientImplTest,DropCallbacksIfServiceProxyIsDestroyed)510*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, DropCallbacksIfServiceProxyIsDestroyed) {
511*6dbdd20aSAndroid Build Coastguard Worker   auto* host_svc = host_->AddFakeService("FakeSvc");
512*6dbdd20aSAndroid Build Coastguard Worker   auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
513*6dbdd20aSAndroid Build Coastguard Worker 
514*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
515*6dbdd20aSAndroid Build Coastguard Worker 
516*6dbdd20aSAndroid Build Coastguard Worker   // First bind the service but destroy it before ClientImpl manages to run any
517*6dbdd20aSAndroid Build Coastguard Worker   // tasks. No OnConnect() should be called.
518*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
519*6dbdd20aSAndroid Build Coastguard Worker   proxy.reset();
520*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilIdle();
521*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_TRUE(Mock::VerifyAndClearExpectations(&proxy_events_));
522*6dbdd20aSAndroid Build Coastguard Worker 
523*6dbdd20aSAndroid Build Coastguard Worker   // Now bind it successfully, invoke a method but destroy the proxy before
524*6dbdd20aSAndroid Build Coastguard Worker   // the method reply is dispatched. The DeferredReply should be rejected,
525*6dbdd20aSAndroid Build Coastguard Worker   // despite the fact that the host gave a successful reply.
526*6dbdd20aSAndroid Build Coastguard Worker   proxy.reset(new FakeProxy("FakeSvc", &proxy_events_));
527*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect = task_runner_->CreateCheckpoint("on_connect");
528*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
529*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
530*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect");
531*6dbdd20aSAndroid Build Coastguard Worker 
532*6dbdd20aSAndroid Build Coastguard Worker   RequestProto req;
533*6dbdd20aSAndroid Build Coastguard Worker   auto on_reply_sent = task_runner_->CreateCheckpoint("on_reply_sent");
534*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(*host_method, OnInvoke(_, _))
535*6dbdd20aSAndroid Build Coastguard Worker       .WillOnce(Invoke([on_reply_sent](const Frame::InvokeMethod&,
536*6dbdd20aSAndroid Build Coastguard Worker                                        Frame::InvokeMethodReply* reply) {
537*6dbdd20aSAndroid Build Coastguard Worker         ReplyProto reply_args;
538*6dbdd20aSAndroid Build Coastguard Worker         reply->set_success(true);
539*6dbdd20aSAndroid Build Coastguard Worker         on_reply_sent();
540*6dbdd20aSAndroid Build Coastguard Worker       }));
541*6dbdd20aSAndroid Build Coastguard Worker 
542*6dbdd20aSAndroid Build Coastguard Worker   auto on_reject = task_runner_->CreateCheckpoint("on_reject");
543*6dbdd20aSAndroid Build Coastguard Worker   Deferred<ProtoMessage> deferred_reply(
544*6dbdd20aSAndroid Build Coastguard Worker       [on_reject](AsyncResult<ProtoMessage> res) {
545*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_FALSE(res.success());
546*6dbdd20aSAndroid Build Coastguard Worker         on_reject();
547*6dbdd20aSAndroid Build Coastguard Worker       });
548*6dbdd20aSAndroid Build Coastguard Worker   proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
549*6dbdd20aSAndroid Build Coastguard Worker   proxy.reset();
550*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_reject");
551*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_reply_sent");
552*6dbdd20aSAndroid Build Coastguard Worker }
553*6dbdd20aSAndroid Build Coastguard Worker 
554*6dbdd20aSAndroid Build Coastguard Worker // If the Client object is destroyed before the ServiceProxy, the ServiceProxy
555*6dbdd20aSAndroid Build Coastguard Worker // should see a Disconnect() call and any pending callback should be rejected.
TEST_F(ClientImplTest,ClientDestroyedBeforeProxy)556*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, ClientDestroyedBeforeProxy) {
557*6dbdd20aSAndroid Build Coastguard Worker   auto* host_svc = host_->AddFakeService("FakeSvc");
558*6dbdd20aSAndroid Build Coastguard Worker   host_svc->AddFakeMethod("FakeMethod1");
559*6dbdd20aSAndroid Build Coastguard Worker 
560*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
561*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect = task_runner_->CreateCheckpoint("on_connect");
562*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
563*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
564*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect");
565*6dbdd20aSAndroid Build Coastguard Worker 
566*6dbdd20aSAndroid Build Coastguard Worker   auto on_reject = task_runner_->CreateCheckpoint("on_reject");
567*6dbdd20aSAndroid Build Coastguard Worker   DeferredBase deferred_reply([on_reject](AsyncResult<ProtoMessage> res) {
568*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_FALSE(res.success());
569*6dbdd20aSAndroid Build Coastguard Worker     on_reject();
570*6dbdd20aSAndroid Build Coastguard Worker   });
571*6dbdd20aSAndroid Build Coastguard Worker   RequestProto req;
572*6dbdd20aSAndroid Build Coastguard Worker   proxy->BeginInvoke("FakeMethod1", req, std::move(deferred_reply));
573*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnDisconnect());
574*6dbdd20aSAndroid Build Coastguard Worker   cli_.reset();
575*6dbdd20aSAndroid Build Coastguard Worker   host_.reset();  // Prevent spurious OnInvoke callbacks on the fake host.
576*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_reject");
577*6dbdd20aSAndroid Build Coastguard Worker }
578*6dbdd20aSAndroid Build Coastguard Worker 
579*6dbdd20aSAndroid Build Coastguard Worker // Test that OnDisconnect() is invoked if the host is not reachable.
TEST_F(ClientImplTest,HostNotReachable)580*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, HostNotReachable) {
581*6dbdd20aSAndroid Build Coastguard Worker   host_.reset();
582*6dbdd20aSAndroid Build Coastguard Worker 
583*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
584*6dbdd20aSAndroid Build Coastguard Worker 
585*6dbdd20aSAndroid Build Coastguard Worker   auto on_disconnect = task_runner_->CreateCheckpoint("on_disconnect");
586*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnDisconnect()).WillOnce(Invoke(on_disconnect));
587*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
588*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_disconnect");
589*6dbdd20aSAndroid Build Coastguard Worker }
590*6dbdd20aSAndroid Build Coastguard Worker 
591*6dbdd20aSAndroid Build Coastguard Worker // Test that OnDisconnect() is invoked if the host shuts down prematurely.
TEST_F(ClientImplTest,HostDisconnection)592*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, HostDisconnection) {
593*6dbdd20aSAndroid Build Coastguard Worker   host_->AddFakeService("FakeSvc");
594*6dbdd20aSAndroid Build Coastguard Worker 
595*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
596*6dbdd20aSAndroid Build Coastguard Worker 
597*6dbdd20aSAndroid Build Coastguard Worker   // Bind |proxy| to the fake host.
598*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
599*6dbdd20aSAndroid Build Coastguard Worker   auto on_connect = task_runner_->CreateCheckpoint("on_connect");
600*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
601*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_connect");
602*6dbdd20aSAndroid Build Coastguard Worker 
603*6dbdd20aSAndroid Build Coastguard Worker   auto on_disconnect = task_runner_->CreateCheckpoint("on_disconnect");
604*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnDisconnect()).WillOnce(Invoke(on_disconnect));
605*6dbdd20aSAndroid Build Coastguard Worker   host_.reset();
606*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_disconnect");
607*6dbdd20aSAndroid Build Coastguard Worker }
608*6dbdd20aSAndroid Build Coastguard Worker 
609*6dbdd20aSAndroid Build Coastguard Worker // Test that OnDisconnect() is invoked if the host shuts down prematurely.
TEST_F(ClientImplTest,HostDisconnectionBeforeBindReply)610*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, HostDisconnectionBeforeBindReply) {
611*6dbdd20aSAndroid Build Coastguard Worker   host_->AddFakeService("FakeSvc");
612*6dbdd20aSAndroid Build Coastguard Worker 
613*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
614*6dbdd20aSAndroid Build Coastguard Worker 
615*6dbdd20aSAndroid Build Coastguard Worker   // Prevent the host from replying
616*6dbdd20aSAndroid Build Coastguard Worker   host_->suppress_replies_ = true;
617*6dbdd20aSAndroid Build Coastguard Worker 
618*6dbdd20aSAndroid Build Coastguard Worker   // Bind |proxy| to the fake host. The host will receive the request, but it
619*6dbdd20aSAndroid Build Coastguard Worker   // will not reply.
620*6dbdd20aSAndroid Build Coastguard Worker   cli_->BindService(proxy->GetWeakPtr());
621*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilIdle();
622*6dbdd20aSAndroid Build Coastguard Worker   auto on_disconnect = task_runner_->CreateCheckpoint("on_disconnect");
623*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnDisconnect()).WillOnce(Invoke(on_disconnect));
624*6dbdd20aSAndroid Build Coastguard Worker   // Shutdown the host before it's able to send the Bind reply. The ClientImpl
625*6dbdd20aSAndroid Build Coastguard Worker   // should receive an OnDisconnect() callback and propagate that to the service
626*6dbdd20aSAndroid Build Coastguard Worker   // proxy.
627*6dbdd20aSAndroid Build Coastguard Worker   host_.reset();
628*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_disconnect");
629*6dbdd20aSAndroid Build Coastguard Worker }
630*6dbdd20aSAndroid Build Coastguard Worker 
631*6dbdd20aSAndroid Build Coastguard Worker // Disabled on Fuchsia because Fuchsia kernel sockets are non-addressable
632*6dbdd20aSAndroid Build Coastguard Worker // so there is no connect() step which may fail.
633*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
TEST_F(ClientImplTest,HostConnectionFailure)634*6dbdd20aSAndroid Build Coastguard Worker TEST_F(ClientImplTest, HostConnectionFailure) {
635*6dbdd20aSAndroid Build Coastguard Worker   ipc::TestSocket kNonexistentSock{"client_impl_unittest_nonexistent"};
636*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<Client> client = Client::CreateInstance(
637*6dbdd20aSAndroid Build Coastguard Worker       {kNonexistentSock.name(), /*retry=*/false}, task_runner_.get());
638*6dbdd20aSAndroid Build Coastguard Worker 
639*6dbdd20aSAndroid Build Coastguard Worker   // Connect a client to a non-existent socket, which will always fail. The
640*6dbdd20aSAndroid Build Coastguard Worker   // client will notify the proxy of disconnection.
641*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
642*6dbdd20aSAndroid Build Coastguard Worker   client->BindService(proxy->GetWeakPtr());
643*6dbdd20aSAndroid Build Coastguard Worker 
644*6dbdd20aSAndroid Build Coastguard Worker   // Make sure the client copes with being deleted by the disconnection
645*6dbdd20aSAndroid Build Coastguard Worker   // callback.
646*6dbdd20aSAndroid Build Coastguard Worker   auto on_disconnect_reached = task_runner_->CreateCheckpoint("on_disconnect");
647*6dbdd20aSAndroid Build Coastguard Worker   auto on_disconnect = [&] {
648*6dbdd20aSAndroid Build Coastguard Worker     client.reset();
649*6dbdd20aSAndroid Build Coastguard Worker     on_disconnect_reached();
650*6dbdd20aSAndroid Build Coastguard Worker   };
651*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_CALL(proxy_events_, OnDisconnect()).WillOnce(Invoke(on_disconnect));
652*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->RunUntilCheckpoint("on_disconnect");
653*6dbdd20aSAndroid Build Coastguard Worker }
654*6dbdd20aSAndroid Build Coastguard Worker #endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
655*6dbdd20aSAndroid Build Coastguard Worker 
656*6dbdd20aSAndroid Build Coastguard Worker // TODO(primiano): add the tests below.
657*6dbdd20aSAndroid Build Coastguard Worker // TEST(ClientImplTest, UnparsableReply) {}
658*6dbdd20aSAndroid Build Coastguard Worker 
659*6dbdd20aSAndroid Build Coastguard Worker }  // namespace
660*6dbdd20aSAndroid Build Coastguard Worker }  // namespace ipc
661*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
662