xref: /aosp_15_r20/external/cronet/base/functional/callback_helpers_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/functional/callback_helpers.h"
6 
7 #include <functional>
8 #include <type_traits>
9 
10 #include "base/functional/bind.h"
11 #include "base/functional/callback.h"
12 #include "base/test/gtest_util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace {
16 
17 struct BadArg {};
18 
19 template <typename TagType, typename CallbackType>
20 struct TestConversionAndAssignmentImpl {
21   static constexpr bool kSupportsConversion =
22       std::is_convertible_v<TagType, CallbackType>;
23   static constexpr bool kSupportsAssignment =
24       std::is_assignable_v<CallbackType, TagType>;
25   static_assert(kSupportsConversion == kSupportsAssignment);
26 
27   static constexpr bool kValue = kSupportsConversion;
28 };
29 
30 template <typename T, typename U>
31 constexpr bool TestConversionAndAssignment =
32     TestConversionAndAssignmentImpl<T, U>::kValue;
33 
34 #define VOID_RETURN_CALLBACK_TAG_TEST(CallbackType, Sig, BadSig, BoundArg)   \
35   static_assert(TestConversionAndAssignment<decltype(base::NullCallback()),  \
36                                             CallbackType<Sig>>);             \
37   static_assert(                                                             \
38       TestConversionAndAssignment<decltype(base::NullCallbackAs<Sig>()),     \
39                                   CallbackType<Sig>>);                       \
40   static_assert(TestConversionAndAssignment<decltype(base::DoNothing()),     \
41                                             CallbackType<Sig>>);             \
42   static_assert(                                                             \
43       TestConversionAndAssignment<decltype(base::DoNothingAs<Sig>()),        \
44                                   CallbackType<Sig>>);                       \
45   static_assert(TestConversionAndAssignment<                                 \
46                 decltype(base::DoNothingWithBoundArgs(BoundArg)),            \
47                 CallbackType<Sig>>);                                         \
48                                                                              \
49   static_assert(                                                             \
50       !TestConversionAndAssignment<decltype(base::NullCallbackAs<BadSig>()), \
51                                    CallbackType<Sig>>);                      \
52   static_assert(                                                             \
53       !TestConversionAndAssignment<decltype(base::DoNothingAs<BadSig>()),    \
54                                    CallbackType<Sig>>);                      \
55   static_assert(TestConversionAndAssignment<                                 \
56                 decltype(base::DoNothingWithBoundArgs(BadArg())),            \
57                 CallbackType<Sig>>)
58 
59 #define NON_VOID_RETURN_CALLBACK_TAG_TEST(CallbackType, Sig, BadSig, BoundArg) \
60   static_assert(TestConversionAndAssignment<decltype(base::NullCallback()),    \
61                                             CallbackType<Sig>>);               \
62   static_assert(                                                               \
63       TestConversionAndAssignment<decltype(base::NullCallbackAs<Sig>()),       \
64                                   CallbackType<Sig>>);                         \
65                                                                                \
66   /* Unlike callbacks that return void, callbacks that return non-void      */ \
67   /* should not be implicitly convertible from DoNothingCallbackTag since   */ \
68   /* this would require guessing what the callback should return.           */ \
69   static_assert(!TestConversionAndAssignment<decltype(base::DoNothing()),      \
70                                              CallbackType<Sig>>);              \
71   static_assert(                                                               \
72       !TestConversionAndAssignment<decltype(base::DoNothingAs<Sig>()),         \
73                                    CallbackType<Sig>>);                        \
74   static_assert(!TestConversionAndAssignment<                                  \
75                 decltype(base::DoNothingWithBoundArgs(BoundArg)),              \
76                 CallbackType<Sig>>);                                           \
77                                                                                \
78   static_assert(                                                               \
79       !TestConversionAndAssignment<decltype(base::NullCallbackAs<BadSig>()),   \
80                                    CallbackType<Sig>>);                        \
81   static_assert(                                                               \
82       !TestConversionAndAssignment<decltype(base::DoNothingAs<BadSig>()),      \
83                                    CallbackType<Sig>>);                        \
84   static_assert(!TestConversionAndAssignment<                                  \
85                 decltype(base::DoNothingWithBoundArgs(BadArg())),              \
86                 CallbackType<Sig>>)
87 
88 VOID_RETURN_CALLBACK_TAG_TEST(base::OnceCallback, void(), void(char), );
89 VOID_RETURN_CALLBACK_TAG_TEST(base::OnceCallback, void(int), void(char), 8);
90 NON_VOID_RETURN_CALLBACK_TAG_TEST(base::OnceCallback, int(int), char(int), 8);
91 
92 VOID_RETURN_CALLBACK_TAG_TEST(base::RepeatingCallback, void(), void(char), );
93 VOID_RETURN_CALLBACK_TAG_TEST(base::RepeatingCallback,
94                               void(int),
95                               void(char),
96                               8);
97 NON_VOID_RETURN_CALLBACK_TAG_TEST(base::RepeatingCallback,
98                                   int(int),
99                                   char(int),
100                                   8);
101 
102 #undef VOID_RETURN_CALLBACK_TAG_TEST
103 #undef NON_VOID_RETURN_CALLBACK_TAG_TEST
104 
TEST(CallbackHelpersTest,IsBaseCallback)105 TEST(CallbackHelpersTest, IsBaseCallback) {
106   // Check that base::{Once,Repeating}Closures and references to them are
107   // considered base::{Once,Repeating}Callbacks.
108   static_assert(base::IsBaseCallback<base::OnceClosure>);
109   static_assert(base::IsBaseCallback<base::RepeatingClosure>);
110   static_assert(base::IsBaseCallback<base::OnceClosure&&>);
111   static_assert(base::IsBaseCallback<const base::RepeatingClosure&>);
112 
113   // Check that base::{Once, Repeating}Callbacks with a given RunType and
114   // references to them are considered base::{Once, Repeating}Callbacks.
115   static_assert(base::IsBaseCallback<base::OnceCallback<int(int)>>);
116   static_assert(base::IsBaseCallback<base::RepeatingCallback<int(int)>>);
117   static_assert(base::IsBaseCallback<base::OnceCallback<int(int)>&&>);
118   static_assert(base::IsBaseCallback<const base::RepeatingCallback<int(int)>&>);
119 
120   // Check that POD types are not considered base::{Once, Repeating}Callbacks.
121   static_assert(!base::IsBaseCallback<bool>);
122   static_assert(!base::IsBaseCallback<int>);
123   static_assert(!base::IsBaseCallback<double>);
124 
125   // Check that the closely related std::function is not considered a
126   // base::{Once, Repeating}Callback.
127   static_assert(!base::IsBaseCallback<std::function<void()>>);
128   static_assert(!base::IsBaseCallback<const std::function<void()>&>);
129   static_assert(!base::IsBaseCallback<std::function<void()>&&>);
130 }
131 
Increment(int * value)132 void Increment(int* value) {
133   (*value)++;
134 }
135 
IncrementWithRef(int & value)136 void IncrementWithRef(int& value) {
137   value++;
138 }
139 
TEST(CallbackHelpersTest,ScopedClosureRunnerHasClosure)140 TEST(CallbackHelpersTest, ScopedClosureRunnerHasClosure) {
141   base::ScopedClosureRunner runner1;
142   EXPECT_FALSE(runner1);
143 
144   base::ScopedClosureRunner runner2{base::DoNothing()};
145   EXPECT_TRUE(runner2);
146 }
147 
TEST(CallbackHelpersTest,ScopedClosureRunnerExitScope)148 TEST(CallbackHelpersTest, ScopedClosureRunnerExitScope) {
149   int run_count = 0;
150   {
151     base::ScopedClosureRunner runner(base::BindOnce(&Increment, &run_count));
152     EXPECT_EQ(0, run_count);
153   }
154   EXPECT_EQ(1, run_count);
155 }
156 
TEST(CallbackHelpersTest,ScopedClosureRunnerRelease)157 TEST(CallbackHelpersTest, ScopedClosureRunnerRelease) {
158   int run_count = 0;
159   base::OnceClosure c;
160   {
161     base::ScopedClosureRunner runner(base::BindOnce(&Increment, &run_count));
162     c = runner.Release();
163     EXPECT_EQ(0, run_count);
164   }
165   EXPECT_EQ(0, run_count);
166   std::move(c).Run();
167   EXPECT_EQ(1, run_count);
168 }
169 
TEST(CallbackHelpersTest,ScopedClosureRunnerReplaceClosure)170 TEST(CallbackHelpersTest, ScopedClosureRunnerReplaceClosure) {
171   int run_count_1 = 0;
172   int run_count_2 = 0;
173   {
174     base::ScopedClosureRunner runner;
175     runner.ReplaceClosure(base::BindOnce(&Increment, &run_count_1));
176     runner.ReplaceClosure(base::BindOnce(&Increment, &run_count_2));
177     EXPECT_EQ(0, run_count_1);
178     EXPECT_EQ(0, run_count_2);
179   }
180   EXPECT_EQ(0, run_count_1);
181   EXPECT_EQ(1, run_count_2);
182 }
183 
TEST(CallbackHelpersTest,ScopedClosureRunnerRunAndResetNonNull)184 TEST(CallbackHelpersTest, ScopedClosureRunnerRunAndResetNonNull) {
185   int run_count_3 = 0;
186   {
187     base::ScopedClosureRunner runner(base::BindOnce(&Increment, &run_count_3));
188     EXPECT_EQ(0, run_count_3);
189     runner.RunAndReset();
190     EXPECT_EQ(1, run_count_3);
191   }
192   EXPECT_EQ(1, run_count_3);
193 }
194 
TEST(CallbackHelpersTest,ScopedClosureRunnerRunAndResetNull)195 TEST(CallbackHelpersTest, ScopedClosureRunnerRunAndResetNull) {
196   base::ScopedClosureRunner runner;
197   runner.RunAndReset();  // Should not crash.
198 }
199 
TEST(CallbackHelpersTest,ScopedClosureRunnerMoveConstructor)200 TEST(CallbackHelpersTest, ScopedClosureRunnerMoveConstructor) {
201   int run_count = 0;
202   {
203     std::unique_ptr<base::ScopedClosureRunner> runner(
204         new base::ScopedClosureRunner(base::BindOnce(&Increment, &run_count)));
205     base::ScopedClosureRunner runner2(std::move(*runner));
206     runner.reset();
207     EXPECT_EQ(0, run_count);
208   }
209   EXPECT_EQ(1, run_count);
210 }
211 
TEST(CallbackHelpersTest,ScopedClosureRunnerMoveAssignment)212 TEST(CallbackHelpersTest, ScopedClosureRunnerMoveAssignment) {
213   int run_count_1 = 0;
214   int run_count_2 = 0;
215   {
216     base::ScopedClosureRunner runner(base::BindOnce(&Increment, &run_count_1));
217     {
218       base::ScopedClosureRunner runner2(
219           base::BindOnce(&Increment, &run_count_2));
220       runner = std::move(runner2);
221       EXPECT_EQ(1, run_count_1);
222       EXPECT_EQ(0, run_count_2);
223     }
224     EXPECT_EQ(1, run_count_1);
225     EXPECT_EQ(0, run_count_2);
226   }
227   EXPECT_EQ(1, run_count_1);
228   EXPECT_EQ(1, run_count_2);
229 }
230 
TEST(CallbackHelpersTest,SplitOnceCallback_EmptyCallback)231 TEST(CallbackHelpersTest, SplitOnceCallback_EmptyCallback) {
232   base::OnceCallback<void(int*)> cb = base::NullCallback();
233   EXPECT_FALSE(cb);
234 
235   auto split = base::SplitOnceCallback(std::move(cb));
236 
237   static_assert(std::is_same_v<decltype(split),
238                                std::pair<base::OnceCallback<void(int*)>,
239                                          base::OnceCallback<void(int*)>>>,
240                 "");
241   EXPECT_FALSE(split.first);
242   EXPECT_FALSE(split.second);
243 }
244 
TEST(CallbackHelpersTest,SplitOnceCallback_FirstCallback)245 TEST(CallbackHelpersTest, SplitOnceCallback_FirstCallback) {
246   int count = 0;
247   base::OnceCallback<void(int*)> cb =
248       base::BindOnce([](int* count) { ++*count; });
249 
250   auto split = base::SplitOnceCallback(std::move(cb));
251 
252   static_assert(std::is_same_v<decltype(split),
253                                std::pair<base::OnceCallback<void(int*)>,
254                                          base::OnceCallback<void(int*)>>>,
255                 "");
256 
257   EXPECT_EQ(0, count);
258   std::move(split.first).Run(&count);
259   EXPECT_EQ(1, count);
260 
261 #if GTEST_HAS_DEATH_TEST
262   EXPECT_CHECK_DEATH(std::move(split.second).Run(&count));
263 #endif  // GTEST_HAS_DEATH_TEST
264 }
265 
TEST(CallbackHelpersTest,SplitOnceCallback_SecondCallback)266 TEST(CallbackHelpersTest, SplitOnceCallback_SecondCallback) {
267   int count = 0;
268   base::OnceCallback<void(int*)> cb =
269       base::BindOnce([](int* count) { ++*count; });
270 
271   auto split = base::SplitOnceCallback(std::move(cb));
272 
273   static_assert(std::is_same_v<decltype(split),
274                                std::pair<base::OnceCallback<void(int*)>,
275                                          base::OnceCallback<void(int*)>>>,
276                 "");
277 
278   EXPECT_EQ(0, count);
279   std::move(split.second).Run(&count);
280   EXPECT_EQ(1, count);
281 
282   EXPECT_CHECK_DEATH(std::move(split.first).Run(&count));
283 }
284 
TEST(CallbackHelpersTest,SplitSplitOnceCallback_FirstSplit)285 TEST(CallbackHelpersTest, SplitSplitOnceCallback_FirstSplit) {
286   int count = 0;
287   base::OnceCallback<void(int*)> cb =
288       base::BindOnce([](int* count) { ++*count; });
289 
290   auto split = base::SplitOnceCallback(std::move(cb));
291   base::OnceCallback<void(int*)> cb1 = std::move(split.first);
292   split = base::SplitOnceCallback(std::move(split.second));
293   base::OnceCallback<void(int*)> cb2 = std::move(split.first);
294   base::OnceCallback<void(int*)> cb3 = std::move(split.second);
295 
296   EXPECT_EQ(0, count);
297   std::move(cb1).Run(&count);
298   EXPECT_EQ(1, count);
299 
300   EXPECT_CHECK_DEATH(std::move(cb3).Run(&count));
301 }
302 
TEST(CallbackHelpersTest,SplitSplitOnceCallback_SecondSplit)303 TEST(CallbackHelpersTest, SplitSplitOnceCallback_SecondSplit) {
304   int count = 0;
305   base::OnceCallback<void(int*)> cb =
306       base::BindOnce([](int* count) { ++*count; });
307 
308   auto split = base::SplitOnceCallback(std::move(cb));
309   base::OnceCallback<void(int*)> cb1 = std::move(split.first);
310   split = base::SplitOnceCallback(std::move(split.second));
311   base::OnceCallback<void(int*)> cb2 = std::move(split.first);
312   base::OnceCallback<void(int*)> cb3 = std::move(split.second);
313 
314   EXPECT_EQ(0, count);
315   std::move(cb2).Run(&count);
316   EXPECT_EQ(1, count);
317 
318   EXPECT_CHECK_DEATH(std::move(cb1).Run(&count));
319 }
320 
TEST(CallbackHelpersTest,IgnoreArgs)321 TEST(CallbackHelpersTest, IgnoreArgs) {
322   int count = 0;
323   base::RepeatingClosure repeating_closure =
324       base::BindRepeating(&Increment, &count);
325   base::OnceClosure once_closure = base::BindOnce(&Increment, &count);
326 
327   base::RepeatingCallback<void(int)> repeating_int_cb =
328       base::IgnoreArgs<int>(repeating_closure);
329   EXPECT_EQ(0, count);
330   repeating_int_cb.Run(42);
331   EXPECT_EQ(1, count);
332   repeating_int_cb.Run(42);
333   EXPECT_EQ(2, count);
334 
335   base::OnceCallback<void(int)> once_int_cb =
336       base::IgnoreArgs<int>(std::move(once_closure));
337   EXPECT_EQ(2, count);
338   std::move(once_int_cb).Run(42);
339   EXPECT_EQ(3, count);
340 
341   // Ignore only some (one) argument and forward the rest.
342   auto repeating_callback = base::BindRepeating(&Increment);
343   auto repeating_cb_with_extra_arg = base::IgnoreArgs<bool>(repeating_callback);
344   repeating_cb_with_extra_arg.Run(false, &count);
345   EXPECT_EQ(4, count);
346 
347   // Ignore two arguments and forward the rest.
348   auto once_callback = base::BindOnce(&Increment);
349   auto once_cb_with_extra_arg =
350       base::IgnoreArgs<char, bool>(repeating_callback);
351   std::move(once_cb_with_extra_arg).Run('d', false, &count);
352   EXPECT_EQ(5, count);
353 }
354 
TEST(CallbackHelpersTest,IgnoreArgs_EmptyCallback)355 TEST(CallbackHelpersTest, IgnoreArgs_EmptyCallback) {
356   base::RepeatingCallback<void(int)> repeating_int_cb =
357       base::IgnoreArgs<int>(base::RepeatingClosure());
358   EXPECT_FALSE(repeating_int_cb);
359 
360   base::OnceCallback<void(int)> once_int_cb =
361       base::IgnoreArgs<int>(base::OnceClosure());
362   EXPECT_FALSE(once_int_cb);
363 }
364 
TEST(CallbackHelpersTest,ForwardRepeatingCallbacks)365 TEST(CallbackHelpersTest, ForwardRepeatingCallbacks) {
366   int count = 0;
367   auto tie_cb =
368       base::ForwardRepeatingCallbacks({base::BindRepeating(&IncrementWithRef),
369                                        base::BindRepeating(&IncrementWithRef)});
370 
371   tie_cb.Run(count);
372   EXPECT_EQ(count, 2);
373 
374   tie_cb.Run(count);
375   EXPECT_EQ(count, 4);
376 }
377 
TEST(CallbackHelpersTest,ReturnValueOnce)378 TEST(CallbackHelpersTest, ReturnValueOnce) {
379   // Check that copyable types are supported.
380   auto string_factory = base::ReturnValueOnce(std::string("test"));
381   static_assert(std::is_same_v<decltype(string_factory),
382                                base::OnceCallback<std::string(void)>>);
383   EXPECT_EQ(std::move(string_factory).Run(), "test");
384 
385   // Check that move-only types are supported.
386   auto unique_ptr_factory = base::ReturnValueOnce(std::make_unique<int>(42));
387   static_assert(std::is_same_v<decltype(unique_ptr_factory),
388                                base::OnceCallback<std::unique_ptr<int>(void)>>);
389   EXPECT_EQ(*std::move(unique_ptr_factory).Run(), 42);
390 }
391 
392 }  // namespace
393