• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(CallbackHelpersTest,IsOnceCallback)132 TEST(CallbackHelpersTest, IsOnceCallback) {
133   // Check that base::OnceClosures and references to them are considered
134   // base::OnceCallbacks, but base::RepeatingClosures are not.
135   static_assert(base::IsOnceCallback<base::OnceClosure>);
136   static_assert(!base::IsOnceCallback<base::RepeatingClosure>);
137   static_assert(base::IsOnceCallback<base::OnceClosure&&>);
138   static_assert(!base::IsOnceCallback<const base::RepeatingClosure&>);
139 
140   // Check that base::OnceCallbacks with a given RunType and references to them
141   // are considered base::OnceCallbacks, but base::RepeatingCallbacks are not.
142   static_assert(base::IsOnceCallback<base::OnceCallback<int(int)>>);
143   static_assert(!base::IsOnceCallback<base::RepeatingCallback<int(int)>>);
144   static_assert(base::IsOnceCallback<base::OnceCallback<int(int)>&&>);
145   static_assert(
146       !base::IsOnceCallback<const base::RepeatingCallback<int(int)>&>);
147 
148   // Check that POD types are not considered base::OnceCallbacks.
149   static_assert(!base::IsOnceCallback<bool>);
150   static_assert(!base::IsOnceCallback<int>);
151   static_assert(!base::IsOnceCallback<double>);
152 
153   // Check that the closely related std::function is not considered a
154   // base::OnceCallback.
155   static_assert(!base::IsOnceCallback<std::function<void()>>);
156   static_assert(!base::IsOnceCallback<const std::function<void()>&>);
157   static_assert(!base::IsOnceCallback<std::function<void()>&&>);
158 
159   // Check that the result of BindOnce is a OnceCallback.
160   auto cb = base::BindOnce([](int* count) { ++*count; });
161   static_assert(base::IsOnceCallback<decltype(cb)>);
162 }
163 
Increment(int * value)164 void Increment(int* value) {
165   (*value)++;
166 }
167 
IncrementWithRef(int & value)168 void IncrementWithRef(int& value) {
169   value++;
170 }
171 
TEST(CallbackHelpersTest,ScopedClosureRunnerHasClosure)172 TEST(CallbackHelpersTest, ScopedClosureRunnerHasClosure) {
173   base::ScopedClosureRunner runner1;
174   EXPECT_FALSE(runner1);
175 
176   base::ScopedClosureRunner runner2{base::DoNothing()};
177   EXPECT_TRUE(runner2);
178 }
179 
TEST(CallbackHelpersTest,ScopedClosureRunnerExitScope)180 TEST(CallbackHelpersTest, ScopedClosureRunnerExitScope) {
181   int run_count = 0;
182   {
183     base::ScopedClosureRunner runner(base::BindOnce(&Increment, &run_count));
184     EXPECT_EQ(0, run_count);
185   }
186   EXPECT_EQ(1, run_count);
187 }
188 
TEST(CallbackHelpersTest,ScopedClosureRunnerRelease)189 TEST(CallbackHelpersTest, ScopedClosureRunnerRelease) {
190   int run_count = 0;
191   base::OnceClosure c;
192   {
193     base::ScopedClosureRunner runner(base::BindOnce(&Increment, &run_count));
194     c = runner.Release();
195     EXPECT_EQ(0, run_count);
196   }
197   EXPECT_EQ(0, run_count);
198   std::move(c).Run();
199   EXPECT_EQ(1, run_count);
200 }
201 
TEST(CallbackHelpersTest,ScopedClosureRunnerReplaceClosure)202 TEST(CallbackHelpersTest, ScopedClosureRunnerReplaceClosure) {
203   int run_count_1 = 0;
204   int run_count_2 = 0;
205   {
206     base::ScopedClosureRunner runner;
207     runner.ReplaceClosure(base::BindOnce(&Increment, &run_count_1));
208     runner.ReplaceClosure(base::BindOnce(&Increment, &run_count_2));
209     EXPECT_EQ(0, run_count_1);
210     EXPECT_EQ(0, run_count_2);
211   }
212   EXPECT_EQ(0, run_count_1);
213   EXPECT_EQ(1, run_count_2);
214 }
215 
TEST(CallbackHelpersTest,ScopedClosureRunnerRunAndResetNonNull)216 TEST(CallbackHelpersTest, ScopedClosureRunnerRunAndResetNonNull) {
217   int run_count_3 = 0;
218   {
219     base::ScopedClosureRunner runner(base::BindOnce(&Increment, &run_count_3));
220     EXPECT_EQ(0, run_count_3);
221     runner.RunAndReset();
222     EXPECT_EQ(1, run_count_3);
223   }
224   EXPECT_EQ(1, run_count_3);
225 }
226 
TEST(CallbackHelpersTest,ScopedClosureRunnerRunAndResetNull)227 TEST(CallbackHelpersTest, ScopedClosureRunnerRunAndResetNull) {
228   base::ScopedClosureRunner runner;
229   runner.RunAndReset();  // Should not crash.
230 }
231 
TEST(CallbackHelpersTest,ScopedClosureRunnerMoveConstructor)232 TEST(CallbackHelpersTest, ScopedClosureRunnerMoveConstructor) {
233   int run_count = 0;
234   {
235     std::unique_ptr<base::ScopedClosureRunner> runner(
236         new base::ScopedClosureRunner(base::BindOnce(&Increment, &run_count)));
237     base::ScopedClosureRunner runner2(std::move(*runner));
238     runner.reset();
239     EXPECT_EQ(0, run_count);
240   }
241   EXPECT_EQ(1, run_count);
242 }
243 
TEST(CallbackHelpersTest,ScopedClosureRunnerMoveAssignment)244 TEST(CallbackHelpersTest, ScopedClosureRunnerMoveAssignment) {
245   int run_count_1 = 0;
246   int run_count_2 = 0;
247   {
248     base::ScopedClosureRunner runner(base::BindOnce(&Increment, &run_count_1));
249     {
250       base::ScopedClosureRunner runner2(
251           base::BindOnce(&Increment, &run_count_2));
252       runner = std::move(runner2);
253       EXPECT_EQ(1, run_count_1);
254       EXPECT_EQ(0, run_count_2);
255     }
256     EXPECT_EQ(1, run_count_1);
257     EXPECT_EQ(0, run_count_2);
258   }
259   EXPECT_EQ(1, run_count_1);
260   EXPECT_EQ(1, run_count_2);
261 }
262 
TEST(CallbackHelpersTest,SplitOnceCallback_EmptyCallback)263 TEST(CallbackHelpersTest, SplitOnceCallback_EmptyCallback) {
264   base::OnceCallback<void(int*)> cb = base::NullCallback();
265   EXPECT_FALSE(cb);
266 
267   auto split = base::SplitOnceCallback(std::move(cb));
268 
269   static_assert(std::is_same_v<decltype(split),
270                                std::pair<base::OnceCallback<void(int*)>,
271                                          base::OnceCallback<void(int*)>>>,
272                 "");
273   EXPECT_FALSE(split.first);
274   EXPECT_FALSE(split.second);
275 }
276 
TEST(CallbackHelpersTest,SplitOnceCallback_FirstCallback)277 TEST(CallbackHelpersTest, SplitOnceCallback_FirstCallback) {
278   int count = 0;
279   base::OnceCallback<void(int*)> cb =
280       base::BindOnce([](int* count) { ++*count; });
281 
282   auto split = base::SplitOnceCallback(std::move(cb));
283 
284   static_assert(std::is_same_v<decltype(split),
285                                std::pair<base::OnceCallback<void(int*)>,
286                                          base::OnceCallback<void(int*)>>>,
287                 "");
288 
289   EXPECT_EQ(0, count);
290   std::move(split.first).Run(&count);
291   EXPECT_EQ(1, count);
292 
293 #if GTEST_HAS_DEATH_TEST
294   EXPECT_CHECK_DEATH(std::move(split.second).Run(&count));
295 #endif  // GTEST_HAS_DEATH_TEST
296 }
297 
TEST(CallbackHelpersTest,SplitOnceCallback_SecondCallback)298 TEST(CallbackHelpersTest, SplitOnceCallback_SecondCallback) {
299   int count = 0;
300   base::OnceCallback<void(int*)> cb =
301       base::BindOnce([](int* count) { ++*count; });
302 
303   auto split = base::SplitOnceCallback(std::move(cb));
304 
305   static_assert(std::is_same_v<decltype(split),
306                                std::pair<base::OnceCallback<void(int*)>,
307                                          base::OnceCallback<void(int*)>>>,
308                 "");
309 
310   EXPECT_EQ(0, count);
311   std::move(split.second).Run(&count);
312   EXPECT_EQ(1, count);
313 
314   EXPECT_CHECK_DEATH(std::move(split.first).Run(&count));
315 }
316 
TEST(CallbackHelpersTest,SplitSplitOnceCallback_FirstSplit)317 TEST(CallbackHelpersTest, SplitSplitOnceCallback_FirstSplit) {
318   int count = 0;
319   base::OnceCallback<void(int*)> cb =
320       base::BindOnce([](int* count) { ++*count; });
321 
322   auto split = base::SplitOnceCallback(std::move(cb));
323   base::OnceCallback<void(int*)> cb1 = std::move(split.first);
324   split = base::SplitOnceCallback(std::move(split.second));
325   base::OnceCallback<void(int*)> cb2 = std::move(split.first);
326   base::OnceCallback<void(int*)> cb3 = std::move(split.second);
327 
328   EXPECT_EQ(0, count);
329   std::move(cb1).Run(&count);
330   EXPECT_EQ(1, count);
331 
332   EXPECT_CHECK_DEATH(std::move(cb3).Run(&count));
333 }
334 
TEST(CallbackHelpersTest,SplitSplitOnceCallback_SecondSplit)335 TEST(CallbackHelpersTest, SplitSplitOnceCallback_SecondSplit) {
336   int count = 0;
337   base::OnceCallback<void(int*)> cb =
338       base::BindOnce([](int* count) { ++*count; });
339 
340   auto split = base::SplitOnceCallback(std::move(cb));
341   base::OnceCallback<void(int*)> cb1 = std::move(split.first);
342   split = base::SplitOnceCallback(std::move(split.second));
343   base::OnceCallback<void(int*)> cb2 = std::move(split.first);
344   base::OnceCallback<void(int*)> cb3 = std::move(split.second);
345 
346   EXPECT_EQ(0, count);
347   std::move(cb2).Run(&count);
348   EXPECT_EQ(1, count);
349 
350   EXPECT_CHECK_DEATH(std::move(cb1).Run(&count));
351 }
352 
TEST(CallbackHelpersTest,IgnoreArgs)353 TEST(CallbackHelpersTest, IgnoreArgs) {
354   int count = 0;
355   base::RepeatingClosure repeating_closure =
356       base::BindRepeating(&Increment, &count);
357   base::OnceClosure once_closure = base::BindOnce(&Increment, &count);
358 
359   base::RepeatingCallback<void(int)> repeating_int_cb =
360       base::IgnoreArgs<int>(repeating_closure);
361   EXPECT_EQ(0, count);
362   repeating_int_cb.Run(42);
363   EXPECT_EQ(1, count);
364   repeating_int_cb.Run(42);
365   EXPECT_EQ(2, count);
366 
367   base::OnceCallback<void(int)> once_int_cb =
368       base::IgnoreArgs<int>(std::move(once_closure));
369   EXPECT_EQ(2, count);
370   std::move(once_int_cb).Run(42);
371   EXPECT_EQ(3, count);
372 
373   // Ignore only some (one) argument and forward the rest.
374   auto repeating_callback = base::BindRepeating(&Increment);
375   auto repeating_cb_with_extra_arg = base::IgnoreArgs<bool>(repeating_callback);
376   repeating_cb_with_extra_arg.Run(false, &count);
377   EXPECT_EQ(4, count);
378 
379   // Ignore two arguments and forward the rest.
380   auto once_callback = base::BindOnce(&Increment);
381   auto once_cb_with_extra_arg =
382       base::IgnoreArgs<char, bool>(repeating_callback);
383   std::move(once_cb_with_extra_arg).Run('d', false, &count);
384   EXPECT_EQ(5, count);
385 }
386 
TEST(CallbackHelpersTest,IgnoreArgs_EmptyCallback)387 TEST(CallbackHelpersTest, IgnoreArgs_EmptyCallback) {
388   base::RepeatingCallback<void(int)> repeating_int_cb =
389       base::IgnoreArgs<int>(base::RepeatingClosure());
390   EXPECT_FALSE(repeating_int_cb);
391 
392   base::OnceCallback<void(int)> once_int_cb =
393       base::IgnoreArgs<int>(base::OnceClosure());
394   EXPECT_FALSE(once_int_cb);
395 }
396 
TEST(CallbackHelpersTest,ForwardRepeatingCallbacks)397 TEST(CallbackHelpersTest, ForwardRepeatingCallbacks) {
398   int count = 0;
399   auto tie_cb =
400       base::ForwardRepeatingCallbacks({base::BindRepeating(&IncrementWithRef),
401                                        base::BindRepeating(&IncrementWithRef)});
402 
403   tie_cb.Run(count);
404   EXPECT_EQ(count, 2);
405 
406   tie_cb.Run(count);
407   EXPECT_EQ(count, 4);
408 }
409 
TEST(CallbackHelpersTest,ReturnValueOnce)410 TEST(CallbackHelpersTest, ReturnValueOnce) {
411   // Check that copyable types are supported.
412   auto string_factory = base::ReturnValueOnce(std::string("test"));
413   static_assert(std::is_same_v<decltype(string_factory),
414                                base::OnceCallback<std::string(void)>>);
415   EXPECT_EQ(std::move(string_factory).Run(), "test");
416 
417   // Check that move-only types are supported.
418   auto unique_ptr_factory = base::ReturnValueOnce(std::make_unique<int>(42));
419   static_assert(std::is_same_v<decltype(unique_ptr_factory),
420                                base::OnceCallback<std::unique_ptr<int>(void)>>);
421   EXPECT_EQ(*std::move(unique_ptr_factory).Run(), 42);
422 }
423 
424 }  // namespace
425