1 /*
2  * Copyright (C) 2018 The Android Open Source 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 "perfetto/ext/base/file_utils.h"
22 #include "perfetto/ext/base/scoped_file.h"
23 #include "perfetto/ext/base/temp_file.h"
24 #include "perfetto/ext/base/unix_socket.h"
25 #include "perfetto/ext/base/utils.h"
26 #include "perfetto/ext/ipc/service.h"
27 #include "perfetto/ext/ipc/service_descriptor.h"
28 #include "src/base/test/test_task_runner.h"
29 #include "src/ipc/buffered_frame_deserializer.h"
30 #include "src/ipc/test/test_socket.h"
31 #include "test/gtest_and_gmock.h"
32 
33 #include "protos/perfetto/ipc/wire_protocol.gen.h"
34 #include "src/ipc/test/client_unittest_messages.gen.h"
35 
36 namespace perfetto {
37 namespace ipc {
38 namespace {
39 
40 using ::perfetto::ipc::gen::ReplyProto;
41 using ::perfetto::ipc::gen::RequestProto;
42 using ::testing::_;
43 using ::testing::Invoke;
44 using ::testing::InvokeWithoutArgs;
45 using ::testing::Return;
46 
47 ipc::TestSocket kTestSocket{"host_impl_unittest"};
48 
49 // RequestProto and ReplyProto are defined in client_unittest_messages.proto.
50 
51 class FakeService : public Service {
52  public:
53   MOCK_METHOD2(OnFakeMethod1, void(const RequestProto&, DeferredBase*));
54 
Invoker(Service * service,const ProtoMessage & req,DeferredBase deferred_reply)55   static void Invoker(Service* service,
56                       const ProtoMessage& req,
57                       DeferredBase deferred_reply) {
58     static_cast<FakeService*>(service)->OnFakeMethod1(
59         static_cast<const RequestProto&>(req), &deferred_reply);
60   }
61 
RequestDecoder(const std::string & proto)62   static std::unique_ptr<ProtoMessage> RequestDecoder(
63       const std::string& proto) {
64     std::unique_ptr<ProtoMessage> reply(new RequestProto());
65     EXPECT_TRUE(reply->ParseFromString(proto));
66     return reply;
67   }
68 
FakeService(const char * service_name)69   explicit FakeService(const char* service_name) {
70     descriptor_.service_name = service_name;
71     descriptor_.methods.push_back(
72         {"FakeMethod1", &RequestDecoder, nullptr, &Invoker});
73   }
74 
GetDescriptor()75   const ServiceDescriptor& GetDescriptor() override { return descriptor_; }
76 
TakeReceivedFD()77   base::ScopedFile TakeReceivedFD() { return ipc::Service::TakeReceivedFD(); }
78 
79   base::ScopedFile received_fd_;
80   ServiceDescriptor descriptor_;
81 };
82 
83 class FakeClient : public base::UnixSocket::EventListener {
84  public:
85   MOCK_METHOD0(OnConnect, void());
86   MOCK_METHOD0(OnDisconnect, void());
87   MOCK_METHOD1(OnServiceBound, void(const Frame::BindServiceReply&));
88   MOCK_METHOD1(OnInvokeMethodReply, void(const Frame::InvokeMethodReply&));
89   MOCK_METHOD1(OnFileDescriptorReceived, void(int));
90   MOCK_METHOD0(OnRequestError, void());
91 
FakeClient(base::TaskRunner * task_runner)92   explicit FakeClient(base::TaskRunner* task_runner) {
93     sock_ = base::UnixSocket::Connect(kTestSocket.name(), this, task_runner,
94                                       kTestSocket.family(),
95                                       base::SockType::kStream);
96   }
97 
98   ~FakeClient() override = default;
99 
BindService(const std::string & service_name)100   void BindService(const std::string& service_name) {
101     Frame frame;
102     uint64_t request_id = requests_.empty() ? 1 : requests_.rbegin()->first + 1;
103     requests_.emplace(request_id, 0);
104     frame.set_request_id(request_id);
105     frame.mutable_msg_bind_service()->set_service_name(service_name);
106     SendFrame(frame);
107   }
108 
InvokeMethod(ServiceID service_id,MethodID method_id,const ProtoMessage & args,bool drop_reply=false,int fd=-1)109   void InvokeMethod(ServiceID service_id,
110                     MethodID method_id,
111                     const ProtoMessage& args,
112                     bool drop_reply = false,
113                     int fd = -1) {
114     Frame frame;
115     uint64_t request_id = requests_.empty() ? 1 : requests_.rbegin()->first + 1;
116     requests_.emplace(request_id, 0);
117     frame.set_request_id(request_id);
118     frame.mutable_msg_invoke_method()->set_service_id(service_id);
119     frame.mutable_msg_invoke_method()->set_method_id(method_id);
120     frame.mutable_msg_invoke_method()->set_drop_reply(drop_reply);
121     frame.mutable_msg_invoke_method()->set_args_proto(args.SerializeAsString());
122     SendFrame(frame, fd);
123   }
124 
125   // base::UnixSocket::EventListener implementation.
OnConnect(base::UnixSocket *,bool success)126   void OnConnect(base::UnixSocket*, bool success) override {
127     ASSERT_TRUE(success);
128     OnConnect();
129   }
130 
OnDisconnect(base::UnixSocket *)131   void OnDisconnect(base::UnixSocket*) override { OnDisconnect(); }
132 
OnDataAvailable(base::UnixSocket * sock)133   void OnDataAvailable(base::UnixSocket* sock) override {
134     ASSERT_EQ(sock_.get(), sock);
135     auto buf = frame_deserializer_.BeginReceive();
136     base::ScopedFile fd;
137     size_t rsize = sock->Receive(buf.data, buf.size, &fd);
138     ASSERT_TRUE(frame_deserializer_.EndReceive(rsize));
139     if (fd)
140       OnFileDescriptorReceived(*fd);
141     while (std::unique_ptr<Frame> frame = frame_deserializer_.PopNextFrame()) {
142       ASSERT_EQ(1u, requests_.count(frame->request_id()));
143       EXPECT_EQ(0, requests_[frame->request_id()]++);
144       if (frame->has_msg_bind_service_reply()) {
145         if (frame->msg_bind_service_reply().success())
146           last_bound_service_id_ = frame->msg_bind_service_reply().service_id();
147         return OnServiceBound(frame->msg_bind_service_reply());
148       }
149       if (frame->has_msg_invoke_method_reply())
150         return OnInvokeMethodReply(frame->msg_invoke_method_reply());
151       if (frame->has_msg_request_error())
152         return OnRequestError();
153       FAIL() << "Unexpected frame received from host";
154     }
155   }
156 
SendFrame(const Frame & frame,int fd=-1)157   void SendFrame(const Frame& frame, int fd = -1) {
158     std::string buf = BufferedFrameDeserializer::Serialize(frame);
159     ASSERT_TRUE(sock_->Send(buf.data(), buf.size(), fd));
160   }
161 
162   BufferedFrameDeserializer frame_deserializer_;
163   std::unique_ptr<base::UnixSocket> sock_;
164   std::map<uint64_t /* request_id */, int /* num_replies_received */> requests_;
165   ServiceID last_bound_service_id_;
166 };
167 
168 class HostImplTest : public ::testing::Test {
169  public:
SetUp()170   void SetUp() override {
171     kTestSocket.Destroy();
172     task_runner_.reset(new base::TestTaskRunner());
173     Host* host =
174         Host::CreateInstance(kTestSocket.name(), task_runner_.get()).release();
175     ASSERT_NE(nullptr, host);
176     host_.reset(static_cast<HostImpl*>(host));
177     cli_.reset(new FakeClient(task_runner_.get()));
178     auto on_connect = task_runner_->CreateCheckpoint("on_connect");
179     EXPECT_CALL(*cli_, OnConnect()).WillOnce(Invoke(on_connect));
180     task_runner_->RunUntilCheckpoint("on_connect");
181   }
182 
TearDown()183   void TearDown() override {
184     task_runner_->RunUntilIdle();
185     cli_.reset();
186     host_.reset();
187     task_runner_->RunUntilIdle();
188     task_runner_.reset();
189     kTestSocket.Destroy();
190   }
191 
192   // ::testing::StrictMock<MockEventListener> proxy_events_;
193   std::unique_ptr<base::TestTaskRunner> task_runner_;
194   std::unique_ptr<HostImpl> host_;
195   std::unique_ptr<FakeClient> cli_;
196 };
197 
TEST_F(HostImplTest,BindService)198 TEST_F(HostImplTest, BindService) {
199   // First bind the service when it doesn't exists yet and check that the
200   // BindService() request fails.
201   cli_->BindService("FakeService");  // FakeService does not exist yet.
202   auto on_bind_failure = task_runner_->CreateCheckpoint("on_bind_failure");
203   EXPECT_CALL(*cli_, OnServiceBound(_))
204       .WillOnce(Invoke([on_bind_failure](const Frame::BindServiceReply& reply) {
205         ASSERT_FALSE(reply.success());
206         on_bind_failure();
207       }));
208   task_runner_->RunUntilCheckpoint("on_bind_failure");
209 
210   // Now expose the service and bind it.
211   ASSERT_TRUE(host_->ExposeService(
212       std::unique_ptr<Service>(new FakeService("FakeService"))));
213   auto on_bind_success = task_runner_->CreateCheckpoint("on_bind_success");
214   cli_->BindService("FakeService");
215   EXPECT_CALL(*cli_, OnServiceBound(_))
216       .WillOnce(Invoke([on_bind_success](const Frame::BindServiceReply& reply) {
217         ASSERT_TRUE(reply.success());
218         on_bind_success();
219       }));
220   task_runner_->RunUntilCheckpoint("on_bind_success");
221 }
222 
TEST_F(HostImplTest,InvokeNonExistingMethod)223 TEST_F(HostImplTest, InvokeNonExistingMethod) {
224   FakeService* fake_service = new FakeService("FakeService");
225   ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
226   auto on_bind = task_runner_->CreateCheckpoint("on_bind");
227   cli_->BindService("FakeService");
228   EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
229   task_runner_->RunUntilCheckpoint("on_bind");
230 
231   auto on_invoke_failure = task_runner_->CreateCheckpoint("on_invoke_failure");
232   cli_->InvokeMethod(cli_->last_bound_service_id_, 42, RequestProto());
233   EXPECT_CALL(*cli_, OnInvokeMethodReply(_))
234       .WillOnce(
235           Invoke([on_invoke_failure](const Frame::InvokeMethodReply& reply) {
236             ASSERT_FALSE(reply.success());
237             ASSERT_FALSE(reply.has_more());
238             on_invoke_failure();
239           }));
240   task_runner_->RunUntilCheckpoint("on_invoke_failure");
241 }
242 
TEST_F(HostImplTest,InvokeMethod)243 TEST_F(HostImplTest, InvokeMethod) {
244   FakeService* fake_service = new FakeService("FakeService");
245   ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
246   auto on_bind = task_runner_->CreateCheckpoint("on_bind");
247   cli_->BindService("FakeService");
248   EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
249   task_runner_->RunUntilCheckpoint("on_bind");
250 
251   RequestProto req_args;
252   req_args.set_data("foo");
253   cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args);
254   auto on_reply_sent = task_runner_->CreateCheckpoint("on_reply_sent");
255   EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
256       .WillOnce(
257           Invoke([on_reply_sent](const RequestProto& req, DeferredBase* reply) {
258             ASSERT_EQ("foo", req.data());
259             std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
260             reply_args->set_data("bar");
261             reply->Resolve(AsyncResult<ProtoMessage>(
262                 std::unique_ptr<ProtoMessage>(reply_args.release())));
263             on_reply_sent();
264           }));
265   task_runner_->RunUntilCheckpoint("on_reply_sent");
266 
267   auto on_reply_received = task_runner_->CreateCheckpoint("on_reply_received");
268   EXPECT_CALL(*cli_, OnInvokeMethodReply(_))
269       .WillOnce(
270           Invoke([on_reply_received](const Frame::InvokeMethodReply& reply) {
271             ASSERT_TRUE(reply.success());
272             ASSERT_FALSE(reply.has_more());
273             ReplyProto reply_args;
274             reply_args.ParseFromString(reply.reply_proto());
275             ASSERT_EQ("bar", reply_args.data());
276             on_reply_received();
277           }));
278   task_runner_->RunUntilCheckpoint("on_reply_received");
279 }
280 
TEST_F(HostImplTest,InvokeMethodDropReply)281 TEST_F(HostImplTest, InvokeMethodDropReply) {
282   FakeService* fake_service = new FakeService("FakeService");
283   ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
284   auto on_bind = task_runner_->CreateCheckpoint("on_bind");
285   cli_->BindService("FakeService");
286   EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
287   task_runner_->RunUntilCheckpoint("on_bind");
288 
289   // OnFakeMethod1 will:
290   // - Do nothing on the 1st call, when |drop_reply| == true.
291   // - Reply on the 2nd call, when |drop_reply| == false.
292   EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
293       .Times(2)
294       .WillRepeatedly(Invoke([](const RequestProto& req, DeferredBase* reply) {
295         if (req.data() == "drop_reply")
296           return;
297         std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
298         reply_args->set_data("the_reply");
299         reply->Resolve(AsyncResult<ProtoMessage>(
300             std::unique_ptr<ProtoMessage>(reply_args.release())));
301       }));
302 
303   auto on_reply_received = task_runner_->CreateCheckpoint("on_reply_received");
304   EXPECT_CALL(*cli_, OnInvokeMethodReply(_))
305       .WillOnce(
306           Invoke([on_reply_received](const Frame::InvokeMethodReply& reply) {
307             ASSERT_TRUE(reply.success());
308             ReplyProto reply_args;
309             reply_args.ParseFromString(reply.reply_proto());
310             ASSERT_EQ("the_reply", reply_args.data());
311             on_reply_received();
312           }));
313 
314   // Invoke the method first with |drop_reply|=true, then |drop_reply|=false.
315   RequestProto rp;
316   rp.set_data("drop_reply");
317   cli_->InvokeMethod(cli_->last_bound_service_id_, 1, rp, true /*drop_reply*/);
318   rp.set_data("do_reply");
319   cli_->InvokeMethod(cli_->last_bound_service_id_, 1, rp, false /*drop_reply*/);
320 
321   task_runner_->RunUntilCheckpoint("on_reply_received");
322 }
323 
324 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
325 // File descriptor sending over IPC is not supported on Windows.
TEST_F(HostImplTest,SendFileDescriptor)326 TEST_F(HostImplTest, SendFileDescriptor) {
327   FakeService* fake_service = new FakeService("FakeService");
328   ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
329   auto on_bind = task_runner_->CreateCheckpoint("on_bind");
330   cli_->BindService("FakeService");
331   EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
332   task_runner_->RunUntilCheckpoint("on_bind");
333 
334   static constexpr char kFileContent[] = "shared file";
335   RequestProto req_args;
336   cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args);
337   auto on_reply_sent = task_runner_->CreateCheckpoint("on_reply_sent");
338   base::TempFile tx_file = base::TempFile::CreateUnlinked();
339   ASSERT_EQ(static_cast<size_t>(base::WriteAll(tx_file.fd(), kFileContent,
340                                                sizeof(kFileContent))),
341             sizeof(kFileContent));
342   EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
343       .WillOnce(Invoke(
344           [on_reply_sent, &tx_file](const RequestProto&, DeferredBase* reply) {
345             std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
346             auto async_res = AsyncResult<ProtoMessage>(
347                 std::unique_ptr<ProtoMessage>(reply_args.release()));
348             async_res.set_fd(tx_file.fd());
349             reply->Resolve(std::move(async_res));
350             on_reply_sent();
351           }));
352   task_runner_->RunUntilCheckpoint("on_reply_sent");
353   tx_file.ReleaseFD();
354 
355   auto on_fd_received = task_runner_->CreateCheckpoint("on_fd_received");
356   EXPECT_CALL(*cli_, OnFileDescriptorReceived(_))
357       .WillOnce(Invoke([on_fd_received](int fd) {
358         char buf[sizeof(kFileContent)] = {};
359         ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
360         ASSERT_EQ(static_cast<int32_t>(sizeof(buf)),
361                   PERFETTO_EINTR(read(fd, buf, sizeof(buf))));
362         ASSERT_STREQ(kFileContent, buf);
363         on_fd_received();
364       }));
365   EXPECT_CALL(*cli_, OnInvokeMethodReply(_));
366   task_runner_->RunUntilCheckpoint("on_fd_received");
367 }
368 
TEST_F(HostImplTest,ReceiveFileDescriptor)369 TEST_F(HostImplTest, ReceiveFileDescriptor) {
370   auto received = task_runner_->CreateCheckpoint("received");
371   FakeService* fake_service = new FakeService("FakeService");
372   ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
373   auto on_bind = task_runner_->CreateCheckpoint("on_bind");
374   cli_->BindService("FakeService");
375   EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
376   task_runner_->RunUntilCheckpoint("on_bind");
377 
378   static constexpr char kFileContent[] = "shared file";
379   RequestProto req_args;
380   base::TempFile tx_file = base::TempFile::CreateUnlinked();
381   ASSERT_EQ(static_cast<size_t>(base::WriteAll(tx_file.fd(), kFileContent,
382                                                sizeof(kFileContent))),
383             sizeof(kFileContent));
384   cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args, false,
385                      tx_file.fd());
386   EXPECT_CALL(*cli_, OnInvokeMethodReply(_));
387   base::ScopedFile rx_fd;
388   EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
389       .WillOnce(Invoke([received, &fake_service, &rx_fd](const RequestProto&,
390                                                          DeferredBase*) {
391         rx_fd = fake_service->TakeReceivedFD();
392         received();
393       }));
394 
395   task_runner_->RunUntilCheckpoint("received");
396 
397   ASSERT_TRUE(rx_fd);
398   char buf[sizeof(kFileContent)] = {};
399   ASSERT_EQ(0, lseek(*rx_fd, 0, SEEK_SET));
400   ASSERT_EQ(static_cast<int32_t>(sizeof(buf)),
401             PERFETTO_EINTR(read(*rx_fd, buf, sizeof(buf))));
402   ASSERT_STREQ(kFileContent, buf);
403 }
404 #endif  // !OS_WIN
405 
406 // Invoke a method and immediately after disconnect the client.
TEST_F(HostImplTest,OnClientDisconnect)407 TEST_F(HostImplTest, OnClientDisconnect) {
408   FakeService* fake_service = new FakeService("FakeService");
409   ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
410   auto on_bind = task_runner_->CreateCheckpoint("on_bind");
411   cli_->BindService("FakeService");
412   EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
413   task_runner_->RunUntilCheckpoint("on_bind");
414 
415   RequestProto req_args;
416   req_args.set_data("foo");
417   cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args);
418   EXPECT_CALL(*cli_, OnInvokeMethodReply(_)).Times(0);
419   cli_.reset();  // Disconnect the client.
420   auto on_host_method = task_runner_->CreateCheckpoint("on_host_method");
421   EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
422       .WillOnce(
423           Invoke([on_host_method](const RequestProto& req, DeferredBase*) {
424             ASSERT_EQ("foo", req.data());
425             on_host_method();
426           }));
427   task_runner_->RunUntilCheckpoint("on_host_method");
428 }
429 
430 // Like InvokeMethod, but instead of resolving the Deferred reply within the
431 // call stack, std::move()-s it outside an replies
TEST_F(HostImplTest,MoveReplyObjectAndReplyAsynchronously)432 TEST_F(HostImplTest, MoveReplyObjectAndReplyAsynchronously) {
433   FakeService* fake_service = new FakeService("FakeService");
434   ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
435   auto on_bind = task_runner_->CreateCheckpoint("on_bind");
436   cli_->BindService("FakeService");
437   EXPECT_CALL(*cli_, OnServiceBound(_)).WillOnce(InvokeWithoutArgs(on_bind));
438   task_runner_->RunUntilCheckpoint("on_bind");
439 
440   // Invokes the remote method and waits that the FakeService sees it. The reply
441   // is not resolved but just moved into |moved_reply|.
442   RequestProto req_args;
443   cli_->InvokeMethod(cli_->last_bound_service_id_, 1, req_args);
444   auto on_invoke = task_runner_->CreateCheckpoint("on_invoke");
445   DeferredBase moved_reply;
446   EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
447       .WillOnce(Invoke(
448           [on_invoke, &moved_reply](const RequestProto&, DeferredBase* reply) {
449             moved_reply = std::move(*reply);
450             on_invoke();
451           }));
452   task_runner_->RunUntilCheckpoint("on_invoke");
453 
454   // Check that the FakeClient doesn't see any reply yet.
455   EXPECT_CALL(*cli_, OnInvokeMethodReply(_)).Times(0);
456   task_runner_->RunUntilIdle();
457   ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(cli_.get()));
458 
459   // Resolve the reply asynchronously in a deferred task.
460   task_runner_->PostTask([&moved_reply] {
461     std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
462     reply_args->set_data("bar");
463     moved_reply.Resolve(AsyncResult<ProtoMessage>(
464         std::unique_ptr<ProtoMessage>(reply_args.release())));
465   });
466 
467   auto on_reply_received = task_runner_->CreateCheckpoint("on_reply_received");
468   EXPECT_CALL(*cli_, OnInvokeMethodReply(_))
469       .WillOnce(
470           Invoke([on_reply_received](const Frame::InvokeMethodReply& reply) {
471             ASSERT_TRUE(reply.success());
472             ASSERT_FALSE(reply.has_more());
473             ReplyProto reply_args;
474             reply_args.ParseFromString(reply.reply_proto());
475             ASSERT_EQ("bar", reply_args.data());
476             on_reply_received();
477           }));
478   task_runner_->RunUntilCheckpoint("on_reply_received");
479 }
480 
481 // TODO(primiano): add the tests below in next CLs.
482 // TEST(HostImplTest, ManyClients) {}
483 // TEST(HostImplTest, OverlappingRequstsOutOfOrder) {}
484 // TEST(HostImplTest, StreamingRequest) {}
485 // TEST(HostImplTest, ManyDropReplyRequestsDontLeakMemory) {}
486 
487 }  // namespace
488 }  // namespace ipc
489 }  // namespace perfetto
490