xref: /aosp_15_r20/external/perfetto/src/ipc/deferred_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 "perfetto/ext/ipc/deferred.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
20*6dbdd20aSAndroid Build Coastguard Worker #include "test/gtest_and_gmock.h"
21*6dbdd20aSAndroid Build Coastguard Worker 
22*6dbdd20aSAndroid Build Coastguard Worker #include "src/ipc/test/deferred_unittest_messages.gen.h"
23*6dbdd20aSAndroid Build Coastguard Worker 
24*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
25*6dbdd20aSAndroid Build Coastguard Worker namespace ipc {
26*6dbdd20aSAndroid Build Coastguard Worker namespace {
27*6dbdd20aSAndroid Build Coastguard Worker 
28*6dbdd20aSAndroid Build Coastguard Worker using ::perfetto::ipc::gen::TestMessage;
29*6dbdd20aSAndroid Build Coastguard Worker 
30*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_DCHECK_IS_ON()
31*6dbdd20aSAndroid Build Coastguard Worker #define EXPECT_DCHECK(x) EXPECT_DEATH_IF_SUPPORTED((x), ".*")
32*6dbdd20aSAndroid Build Coastguard Worker #else
33*6dbdd20aSAndroid Build Coastguard Worker #define EXPECT_DCHECK(x) x
34*6dbdd20aSAndroid Build Coastguard Worker #endif
35*6dbdd20aSAndroid Build Coastguard Worker 
TEST(DeferredTest,BindAndResolve)36*6dbdd20aSAndroid Build Coastguard Worker TEST(DeferredTest, BindAndResolve) {
37*6dbdd20aSAndroid Build Coastguard Worker   Deferred<TestMessage> deferred;
38*6dbdd20aSAndroid Build Coastguard Worker   std::shared_ptr<int> num_callbacks(new int{0});
39*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind([num_callbacks](AsyncResult<TestMessage> msg) {
40*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_TRUE(msg.success());
41*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_TRUE(msg);
42*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(42, msg->num());
43*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(13, msg.fd());
44*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ("foo", msg->str());
45*6dbdd20aSAndroid Build Coastguard Worker     (*num_callbacks)++;
46*6dbdd20aSAndroid Build Coastguard Worker   });
47*6dbdd20aSAndroid Build Coastguard Worker 
48*6dbdd20aSAndroid Build Coastguard Worker   AsyncResult<TestMessage> res = AsyncResult<TestMessage>::Create();
49*6dbdd20aSAndroid Build Coastguard Worker   res->set_num(42);
50*6dbdd20aSAndroid Build Coastguard Worker   res.set_fd(13);
51*6dbdd20aSAndroid Build Coastguard Worker   (*res).set_str("foo");
52*6dbdd20aSAndroid Build Coastguard Worker   deferred.Resolve(std::move(res));
53*6dbdd20aSAndroid Build Coastguard Worker 
54*6dbdd20aSAndroid Build Coastguard Worker   // A second call to Resolve() or Reject() shouldn't have any effect beause we
55*6dbdd20aSAndroid Build Coastguard Worker   // didn't set has_more.
56*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_DCHECK(deferred.Resolve(std::move(res)));
57*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_DCHECK(deferred.Reject());
58*6dbdd20aSAndroid Build Coastguard Worker 
59*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, *num_callbacks);
60*6dbdd20aSAndroid Build Coastguard Worker }
61*6dbdd20aSAndroid Build Coastguard Worker 
62*6dbdd20aSAndroid Build Coastguard Worker // In case of a Reject() a callback with a nullptr should be received.
TEST(DeferredTest,BindAndFail)63*6dbdd20aSAndroid Build Coastguard Worker TEST(DeferredTest, BindAndFail) {
64*6dbdd20aSAndroid Build Coastguard Worker   Deferred<TestMessage> deferred;
65*6dbdd20aSAndroid Build Coastguard Worker   std::shared_ptr<int> num_callbacks(new int{0});
66*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind([num_callbacks](AsyncResult<TestMessage> msg) {
67*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(-1, msg.fd());
68*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_FALSE(msg.success());
69*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_FALSE(msg);
70*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(nullptr, msg.operator->());
71*6dbdd20aSAndroid Build Coastguard Worker     (*num_callbacks)++;
72*6dbdd20aSAndroid Build Coastguard Worker   });
73*6dbdd20aSAndroid Build Coastguard Worker 
74*6dbdd20aSAndroid Build Coastguard Worker   AsyncResult<TestMessage> res = AsyncResult<TestMessage>::Create();
75*6dbdd20aSAndroid Build Coastguard Worker   res.set_fd(42);
76*6dbdd20aSAndroid Build Coastguard Worker   deferred.Reject();
77*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_DCHECK(deferred.Resolve(std::move(res)));
78*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_DCHECK(deferred.Reject());
79*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, *num_callbacks);
80*6dbdd20aSAndroid Build Coastguard Worker }
81*6dbdd20aSAndroid Build Coastguard Worker 
82*6dbdd20aSAndroid Build Coastguard Worker // Test the RAII behavior.
TEST(DeferredTest,AutoRejectIfOutOfScope)83*6dbdd20aSAndroid Build Coastguard Worker TEST(DeferredTest, AutoRejectIfOutOfScope) {
84*6dbdd20aSAndroid Build Coastguard Worker   std::shared_ptr<int> num_callbacks(new int{0});
85*6dbdd20aSAndroid Build Coastguard Worker   {
86*6dbdd20aSAndroid Build Coastguard Worker     Deferred<TestMessage> deferred;
87*6dbdd20aSAndroid Build Coastguard Worker     deferred.Bind([num_callbacks](AsyncResult<TestMessage> msg) {
88*6dbdd20aSAndroid Build Coastguard Worker       ASSERT_FALSE(msg.success());
89*6dbdd20aSAndroid Build Coastguard Worker       (*num_callbacks)++;
90*6dbdd20aSAndroid Build Coastguard Worker     });
91*6dbdd20aSAndroid Build Coastguard Worker   }
92*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, *num_callbacks);
93*6dbdd20aSAndroid Build Coastguard Worker }
94*6dbdd20aSAndroid Build Coastguard Worker 
95*6dbdd20aSAndroid Build Coastguard Worker // Binds two callbacks one after the other and tests that the bind state of the
96*6dbdd20aSAndroid Build Coastguard Worker // first callback is released.
TEST(DeferredTest,BindTwiceDoesNotHoldBindState)97*6dbdd20aSAndroid Build Coastguard Worker TEST(DeferredTest, BindTwiceDoesNotHoldBindState) {
98*6dbdd20aSAndroid Build Coastguard Worker   // Use shared_ptr's use_count() to infer the bind state of the callback.
99*6dbdd20aSAndroid Build Coastguard Worker   std::shared_ptr<int> num_callbacks(new int{0});
100*6dbdd20aSAndroid Build Coastguard Worker   Deferred<TestMessage> deferred;
101*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind(
102*6dbdd20aSAndroid Build Coastguard Worker       [num_callbacks](AsyncResult<TestMessage>) { (*num_callbacks)++; });
103*6dbdd20aSAndroid Build Coastguard Worker 
104*6dbdd20aSAndroid Build Coastguard Worker   // At this point both the shared_ptr above and the callback in |deferred| are
105*6dbdd20aSAndroid Build Coastguard Worker   // refcounting the bind state.
106*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_GE(num_callbacks.use_count(), 2);
107*6dbdd20aSAndroid Build Coastguard Worker 
108*6dbdd20aSAndroid Build Coastguard Worker   // Re-binding the callback should release the bind state, without invoking the
109*6dbdd20aSAndroid Build Coastguard Worker   // old callback.
110*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind([](AsyncResult<TestMessage>) {});
111*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, num_callbacks.use_count());
112*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(0, *num_callbacks);
113*6dbdd20aSAndroid Build Coastguard Worker 
114*6dbdd20aSAndroid Build Coastguard Worker   // Test that the new callback is invoked when re-bindings.
115*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind([num_callbacks](AsyncResult<TestMessage> msg) {
116*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_TRUE(msg.success());
117*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(4242, msg->num());
118*6dbdd20aSAndroid Build Coastguard Worker     (*num_callbacks)++;
119*6dbdd20aSAndroid Build Coastguard Worker   });
120*6dbdd20aSAndroid Build Coastguard Worker   AsyncResult<TestMessage> res = AsyncResult<TestMessage>::Create();
121*6dbdd20aSAndroid Build Coastguard Worker   res->set_num(4242);
122*6dbdd20aSAndroid Build Coastguard Worker   deferred.Resolve(std::move(res));
123*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, *num_callbacks);
124*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, num_callbacks.use_count());
125*6dbdd20aSAndroid Build Coastguard Worker }
126*6dbdd20aSAndroid Build Coastguard Worker 
TEST(DeferredTest,MoveOperators)127*6dbdd20aSAndroid Build Coastguard Worker TEST(DeferredTest, MoveOperators) {
128*6dbdd20aSAndroid Build Coastguard Worker   Deferred<TestMessage> deferred;
129*6dbdd20aSAndroid Build Coastguard Worker   std::shared_ptr<int> num_callbacks(new int{0});
130*6dbdd20aSAndroid Build Coastguard Worker   std::function<void(AsyncResult<TestMessage>)> callback =
131*6dbdd20aSAndroid Build Coastguard Worker       [num_callbacks](AsyncResult<TestMessage> msg) {
132*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_TRUE(msg.success());
133*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_GE(msg->num(), 42);
134*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_LE(msg->num(), 43);
135*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_EQ(msg->num() * 10, msg.fd());
136*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_EQ(std::to_string(msg->num()), msg->str());
137*6dbdd20aSAndroid Build Coastguard Worker         (*num_callbacks)++;
138*6dbdd20aSAndroid Build Coastguard Worker       };
139*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind(callback);
140*6dbdd20aSAndroid Build Coastguard Worker 
141*6dbdd20aSAndroid Build Coastguard Worker   // Do a bit of std::move() dance with both the Deferred and the AsyncResult.
142*6dbdd20aSAndroid Build Coastguard Worker   AsyncResult<TestMessage> res = AsyncResult<TestMessage>::Create();
143*6dbdd20aSAndroid Build Coastguard Worker   res.set_fd(420);
144*6dbdd20aSAndroid Build Coastguard Worker   res->set_num(42);
145*6dbdd20aSAndroid Build Coastguard Worker   AsyncResult<TestMessage> res_moved(std::move(res));
146*6dbdd20aSAndroid Build Coastguard Worker   res = std::move(res_moved);
147*6dbdd20aSAndroid Build Coastguard Worker   res->set_str("42");
148*6dbdd20aSAndroid Build Coastguard Worker   res_moved = std::move(res);
149*6dbdd20aSAndroid Build Coastguard Worker 
150*6dbdd20aSAndroid Build Coastguard Worker   Deferred<TestMessage> deferred_moved(std::move(deferred));
151*6dbdd20aSAndroid Build Coastguard Worker   deferred = std::move(deferred_moved);
152*6dbdd20aSAndroid Build Coastguard Worker   deferred_moved = std::move(deferred);
153*6dbdd20aSAndroid Build Coastguard Worker 
154*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_DCHECK(deferred.Reject());  // |deferred| has been cleared.
155*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(0, *num_callbacks);
156*6dbdd20aSAndroid Build Coastguard Worker 
157*6dbdd20aSAndroid Build Coastguard Worker   deferred_moved.Resolve(std::move(res_moved));  // This, instead, should fire.
158*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, *num_callbacks);
159*6dbdd20aSAndroid Build Coastguard Worker 
160*6dbdd20aSAndroid Build Coastguard Worker   // |deferred| and |res| have lost their state but should remain reusable.
161*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind(callback);
162*6dbdd20aSAndroid Build Coastguard Worker   res = AsyncResult<TestMessage>::Create();
163*6dbdd20aSAndroid Build Coastguard Worker   res.set_fd(430);
164*6dbdd20aSAndroid Build Coastguard Worker   res->set_num(43);
165*6dbdd20aSAndroid Build Coastguard Worker   res->set_str("43");
166*6dbdd20aSAndroid Build Coastguard Worker   deferred.Resolve(std::move(res));
167*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(2, *num_callbacks);
168*6dbdd20aSAndroid Build Coastguard Worker 
169*6dbdd20aSAndroid Build Coastguard Worker   // Finally re-bind |deferred|, move it to a new scoped Deferred and verify
170*6dbdd20aSAndroid Build Coastguard Worker   // that the moved-into object still auto-nacks the callback.
171*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind([num_callbacks](AsyncResult<TestMessage> msg) {
172*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_FALSE(msg.success());
173*6dbdd20aSAndroid Build Coastguard Worker     (*num_callbacks)++;
174*6dbdd20aSAndroid Build Coastguard Worker   });
175*6dbdd20aSAndroid Build Coastguard Worker   { Deferred<TestMessage> scoped_deferred(std::move(deferred)); }
176*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(3, *num_callbacks);
177*6dbdd20aSAndroid Build Coastguard Worker   callback = nullptr;
178*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, num_callbacks.use_count());
179*6dbdd20aSAndroid Build Coastguard Worker }
180*6dbdd20aSAndroid Build Coastguard Worker 
181*6dbdd20aSAndroid Build Coastguard Worker // Covers the case of a streaming reply, where the deferred keeps being resolved
182*6dbdd20aSAndroid Build Coastguard Worker // until has_more == true.
TEST(DeferredTest,StreamingReply)183*6dbdd20aSAndroid Build Coastguard Worker TEST(DeferredTest, StreamingReply) {
184*6dbdd20aSAndroid Build Coastguard Worker   Deferred<TestMessage> deferred;
185*6dbdd20aSAndroid Build Coastguard Worker   std::shared_ptr<int> num_callbacks(new int{0});
186*6dbdd20aSAndroid Build Coastguard Worker   std::function<void(AsyncResult<TestMessage>)> callback =
187*6dbdd20aSAndroid Build Coastguard Worker       [num_callbacks](AsyncResult<TestMessage> msg) {
188*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_TRUE(msg.success());
189*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_EQ(*num_callbacks == 0 ? 13 : -1, msg.fd());
190*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_EQ(*num_callbacks, msg->num());
191*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_EQ(std::to_string(*num_callbacks), msg->str());
192*6dbdd20aSAndroid Build Coastguard Worker         ASSERT_EQ(msg->num() < 3, msg.has_more());
193*6dbdd20aSAndroid Build Coastguard Worker         (*num_callbacks)++;
194*6dbdd20aSAndroid Build Coastguard Worker       };
195*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind(callback);
196*6dbdd20aSAndroid Build Coastguard Worker 
197*6dbdd20aSAndroid Build Coastguard Worker   for (int i = 0; i < 3; i++) {
198*6dbdd20aSAndroid Build Coastguard Worker     AsyncResult<TestMessage> res = AsyncResult<TestMessage>::Create();
199*6dbdd20aSAndroid Build Coastguard Worker     res.set_fd(i == 0 ? 13 : -1);
200*6dbdd20aSAndroid Build Coastguard Worker     res->set_num(i);
201*6dbdd20aSAndroid Build Coastguard Worker     res->set_str(std::to_string(i));
202*6dbdd20aSAndroid Build Coastguard Worker     res.set_has_more(true);
203*6dbdd20aSAndroid Build Coastguard Worker     AsyncResult<TestMessage> res_moved(std::move(res));
204*6dbdd20aSAndroid Build Coastguard Worker     deferred.Resolve(std::move(res_moved));
205*6dbdd20aSAndroid Build Coastguard Worker   }
206*6dbdd20aSAndroid Build Coastguard Worker 
207*6dbdd20aSAndroid Build Coastguard Worker   Deferred<TestMessage> deferred_moved(std::move(deferred));
208*6dbdd20aSAndroid Build Coastguard Worker   AsyncResult<TestMessage> res = AsyncResult<TestMessage>::Create();
209*6dbdd20aSAndroid Build Coastguard Worker   res->set_num(3);
210*6dbdd20aSAndroid Build Coastguard Worker   res->set_str(std::to_string(3));
211*6dbdd20aSAndroid Build Coastguard Worker   res.set_has_more(false);
212*6dbdd20aSAndroid Build Coastguard Worker   deferred_moved.Resolve(std::move(res));
213*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(4, *num_callbacks);
214*6dbdd20aSAndroid Build Coastguard Worker 
215*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_DCHECK(deferred_moved.Reject());
216*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(4, *num_callbacks);
217*6dbdd20aSAndroid Build Coastguard Worker   callback = nullptr;
218*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, num_callbacks.use_count());
219*6dbdd20aSAndroid Build Coastguard Worker }
220*6dbdd20aSAndroid Build Coastguard Worker 
221*6dbdd20aSAndroid Build Coastguard Worker // Similar to the above, but checks that destroying a Deferred without having
222*6dbdd20aSAndroid Build Coastguard Worker // resolved with has_more == true automatically rejects once out of scope.
TEST(DeferredTest,StreamingReplyIsRejectedOutOfScope)223*6dbdd20aSAndroid Build Coastguard Worker TEST(DeferredTest, StreamingReplyIsRejectedOutOfScope) {
224*6dbdd20aSAndroid Build Coastguard Worker   std::shared_ptr<int> num_callbacks(new int{0});
225*6dbdd20aSAndroid Build Coastguard Worker 
226*6dbdd20aSAndroid Build Coastguard Worker   {
227*6dbdd20aSAndroid Build Coastguard Worker     Deferred<TestMessage> deferred;
228*6dbdd20aSAndroid Build Coastguard Worker     deferred.Bind([num_callbacks](AsyncResult<TestMessage> msg) {
229*6dbdd20aSAndroid Build Coastguard Worker       ASSERT_EQ((*num_callbacks) < 3, msg.success());
230*6dbdd20aSAndroid Build Coastguard Worker       ASSERT_EQ(msg.success(), msg.has_more());
231*6dbdd20aSAndroid Build Coastguard Worker       (*num_callbacks)++;
232*6dbdd20aSAndroid Build Coastguard Worker     });
233*6dbdd20aSAndroid Build Coastguard Worker 
234*6dbdd20aSAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++) {
235*6dbdd20aSAndroid Build Coastguard Worker       AsyncResult<TestMessage> res = AsyncResult<TestMessage>::Create();
236*6dbdd20aSAndroid Build Coastguard Worker       res.set_has_more(true);
237*6dbdd20aSAndroid Build Coastguard Worker       deferred.Resolve(std::move(res));
238*6dbdd20aSAndroid Build Coastguard Worker     }
239*6dbdd20aSAndroid Build Coastguard Worker 
240*6dbdd20aSAndroid Build Coastguard Worker     // |deferred_moved| going out of scope should cause a Reject().
241*6dbdd20aSAndroid Build Coastguard Worker     { Deferred<TestMessage> deferred_moved = std::move(deferred); }
242*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(4, *num_callbacks);
243*6dbdd20aSAndroid Build Coastguard Worker   }
244*6dbdd20aSAndroid Build Coastguard Worker 
245*6dbdd20aSAndroid Build Coastguard Worker   // |deferred| going out of scope should do noting, it has been std::move()'d.
246*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(4, *num_callbacks);
247*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, num_callbacks.use_count());
248*6dbdd20aSAndroid Build Coastguard Worker }
249*6dbdd20aSAndroid Build Coastguard Worker 
250*6dbdd20aSAndroid Build Coastguard Worker // Tests that a Deferred<Specialized> still behaves sanely after it has been
251*6dbdd20aSAndroid Build Coastguard Worker // moved into a DeferredBase.
TEST(DeferredTest,MoveAsBase)252*6dbdd20aSAndroid Build Coastguard Worker TEST(DeferredTest, MoveAsBase) {
253*6dbdd20aSAndroid Build Coastguard Worker   Deferred<TestMessage> deferred;
254*6dbdd20aSAndroid Build Coastguard Worker   std::shared_ptr<int> num_callbacks(new int{0});
255*6dbdd20aSAndroid Build Coastguard Worker   deferred.Bind([num_callbacks](AsyncResult<TestMessage> msg) {
256*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_TRUE(msg.success());
257*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(13, msg.fd());
258*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(42, msg->num());
259*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ("foo", msg->str());
260*6dbdd20aSAndroid Build Coastguard Worker     (*num_callbacks)++;
261*6dbdd20aSAndroid Build Coastguard Worker   });
262*6dbdd20aSAndroid Build Coastguard Worker 
263*6dbdd20aSAndroid Build Coastguard Worker   DeferredBase deferred_base(std::move(deferred));
264*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_FALSE(deferred.IsBound());
265*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_TRUE(deferred_base.IsBound());
266*6dbdd20aSAndroid Build Coastguard Worker 
267*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<TestMessage> msg(new TestMessage());
268*6dbdd20aSAndroid Build Coastguard Worker   msg->set_num(42);
269*6dbdd20aSAndroid Build Coastguard Worker   msg->set_str("foo");
270*6dbdd20aSAndroid Build Coastguard Worker 
271*6dbdd20aSAndroid Build Coastguard Worker   AsyncResult<ProtoMessage> async_result_base(std::move(msg));
272*6dbdd20aSAndroid Build Coastguard Worker   async_result_base.set_fd(13);
273*6dbdd20aSAndroid Build Coastguard Worker   deferred_base.Resolve(std::move(async_result_base));
274*6dbdd20aSAndroid Build Coastguard Worker 
275*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_DCHECK(deferred_base.Resolve(std::move(async_result_base)));
276*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_DCHECK(deferred_base.Reject());
277*6dbdd20aSAndroid Build Coastguard Worker 
278*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(1, *num_callbacks);
279*6dbdd20aSAndroid Build Coastguard Worker }
280*6dbdd20aSAndroid Build Coastguard Worker 
281*6dbdd20aSAndroid Build Coastguard Worker }  // namespace
282*6dbdd20aSAndroid Build Coastguard Worker }  // namespace ipc
283*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
284