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