• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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/test/rectify_callback.h"
6 
7 #include <sstream>
8 #include <utility>
9 
10 #include "base/functional/bind.h"
11 #include "base/functional/callback.h"
12 #include "base/functional/callback_forward.h"
13 #include "base/functional/callback_helpers.h"
14 #include "base/test/bind.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace base {
18 
19 // Test rectifying functions with no return value.
20 
21 #define CALLBACK_TESTS_VOID(TestNameSuffix, Signature, LambdaToRectify, ...)  \
22   TEST(RectifyCallbackTest, RepeatingCallbackSignatureVoid##TestNameSuffix) { \
23     auto cb = RectifyCallback<Signature>(BindRepeating(LambdaToRectify));     \
24     cb.Run(__VA_ARGS__);                                                      \
25   }                                                                           \
26   TEST(RectifyCallbackTest, RepeatingCallbackTypeVoid##TestNameSuffix) {      \
27     auto cb = RectifyCallback<RepeatingCallback<Signature>>(                  \
28         BindRepeating(LambdaToRectify));                                      \
29     cb.Run(__VA_ARGS__);                                                      \
30   }                                                                           \
31   TEST(RectifyCallbackTest, RepeatingToOnceVoid##TestNameSuffix) {            \
32     auto cb = RectifyCallback<OnceCallback<Signature>>(                       \
33         BindRepeating(LambdaToRectify));                                      \
34     std::move(cb).Run(__VA_ARGS__);                                           \
35   }                                                                           \
36   TEST(RectifyCallbackTest, OnceCallbackSignatureVoid##TestNameSuffix) {      \
37     auto cb = RectifyCallback<Signature>(BindOnce(LambdaToRectify));          \
38     std::move(cb).Run(__VA_ARGS__);                                           \
39   }                                                                           \
40   TEST(RectifyCallbackTest, OnceCallbackTypeVoid##TestNameSuffix) {           \
41     auto cb =                                                                 \
42         RectifyCallback<OnceCallback<Signature>>(BindOnce(LambdaToRectify));  \
43     std::move(cb).Run(__VA_ARGS__);                                           \
44   }
45 
__anond27a09950102null46 CALLBACK_TESTS_VOID(NoArgsSameSignature, void(), [] {})
47 
__anond27a09950202null48 CALLBACK_TESTS_VOID(OneArgRemoveOneArg, void(int), [] {}, 1)
49 
__anond27a09950302null50 CALLBACK_TESTS_VOID(TwoArgsRemoveTwoArgs, void(float, int), [] {}, 0.25f, 1)
51 
52 CALLBACK_TESTS_VOID(
53     OneArgSameSignature,
54     void(int),
__anond27a09950402(int x) 55     [](int x) { EXPECT_EQ(1, x); },
56     1)
57 
58 CALLBACK_TESTS_VOID(
59     TwoArgsRemoveOneArg,
60     void(float, int),
__anond27a09950502(int x) 61     [](int x) { EXPECT_EQ(1, x); },
62     0.25f,
63     1)
64 
65 CALLBACK_TESTS_VOID(
66     ThreeArgsRemoveTwoArgs,
67     void(bool, float, int),
__anond27a09950602(int x) 68     [](int x) { EXPECT_EQ(1, x); },
69     true,
70     0.25f,
71     1)
72 
73 // Test rectifying functions that do return a value.
74 
75 #define CALLBACK_TESTS_RETURN(TestNameSuffix, Signature, LambdaToRectify,    \
76                               ExpectedReturn, ...)                           \
77   TEST(RectifyCallbackTest,                                                  \
78        RepeatingCallbackSignatureReturn##TestNameSuffix) {                   \
79     auto cb = RectifyCallback<Signature>(BindRepeating(LambdaToRectify));    \
80     EXPECT_EQ(ExpectedReturn, cb.Run(__VA_ARGS__));                          \
81   }                                                                          \
82   TEST(RectifyCallbackTest, RepeatingCallbackTypeReturn##TestNameSuffix) {   \
83     auto cb = RectifyCallback<RepeatingCallback<Signature>>(                 \
84         BindRepeating(LambdaToRectify));                                     \
85     EXPECT_EQ(ExpectedReturn, cb.Run(__VA_ARGS__));                          \
86   }                                                                          \
87   TEST(RectifyCallbackTest, RepeatingToOnceReturn##TestNameSuffix) {         \
88     auto cb = RectifyCallback<OnceCallback<Signature>>(                      \
89         BindRepeating(LambdaToRectify));                                     \
90     EXPECT_EQ(ExpectedReturn, std::move(cb).Run(__VA_ARGS__));               \
91   }                                                                          \
92   TEST(RectifyCallbackTest, OnceCallbackSignatureReturn##TestNameSuffix) {   \
93     auto cb = RectifyCallback<Signature>(BindOnce(LambdaToRectify));         \
94     EXPECT_EQ(ExpectedReturn, std::move(cb).Run(__VA_ARGS__));               \
95   }                                                                          \
96   TEST(RectifyCallbackTest, OnceCallbackTypeReturn##TestNameSuffix) {        \
97     auto cb =                                                                \
98         RectifyCallback<OnceCallback<Signature>>(BindOnce(LambdaToRectify)); \
99     EXPECT_EQ(ExpectedReturn, std::move(cb).Run(__VA_ARGS__));               \
100   }
101 
__anond27a09950702null102 CALLBACK_TESTS_RETURN(NoArgsSameSignature, int(), [] { return 2; }, 2)
103 
__anond27a09950802null104 CALLBACK_TESTS_RETURN(OneArgRemoveOneArg, int(int), [] { return 2; }, 2, 1)
105 
106 CALLBACK_TESTS_RETURN(
107     TwoArgsRemoveTwoArgs,
108     int(float, int),
__anond27a09950902null109     [] { return 2; },
110     2,
111     0.25f,
112     1)
113 
114 CALLBACK_TESTS_RETURN(
115     OneArgSameSignature,
116     int(int),
__anond27a09950a02(int x) 117     [](int x) { return x; },
118     2,
119     2)
120 
121 CALLBACK_TESTS_RETURN(
122     TwoArgsRemoveOneArg,
123     int(float, int),
__anond27a09950b02(int x) 124     [](int x) { return x; },
125     2,
126     0.25f,
127     2)
128 
129 CALLBACK_TESTS_RETURN(
130     ThreeArgsRemoveTwoArgs,
131     int(bool, float, int),
__anond27a09950c02(int x) 132     [](int x) { return x; },
133     2,
134     true,
135     0.25f,
136     2)
137 
138 // Test proper forwarding of move-only arguments.
139 
140 CALLBACK_TESTS_RETURN(
141     DiscardsMoveOnlyArgs,
142     bool(int, std::unique_ptr<int>),
__anond27a09950d02null143     [] { return true; },
144     true,
145     2,
146     std::make_unique<int>(3))
147 
148 CALLBACK_TESTS_RETURN(
149     UsesMoveOnlyArg,
150     int(float, int, std::unique_ptr<int>),
__anond27a09950e02(std::unique_ptr<int> p) 151     [](std::unique_ptr<int> p) { return *p; },
152     3,
153     0.25f,
154     2,
155     std::make_unique<int>(3))
156 
157 // Test rectifying DoNothing().
158 
159 #define CALLBACK_TESTS_DO_NOTHING(TestNameSuffix, Signature, ...)         \
160   TEST(RectifyCallbackTest, SignatureDoNothing##TestNameSuffix) {         \
161     auto cb = RectifyCallback<Signature>(DoNothing());                    \
162     cb.Run(__VA_ARGS__);                                                  \
163   }                                                                       \
164   TEST(RectifyCallbackTest, RepeatingCallbackDoNothing##TestNameSuffix) { \
165     auto cb = RectifyCallback<RepeatingCallback<Signature>>(DoNothing()); \
166     cb.Run(__VA_ARGS__);                                                  \
167   }                                                                       \
168   TEST(RectifyCallbackTest, OnceCallbackDoNothing##TestNameSuffix) {      \
169     auto cb = RectifyCallback<OnceCallback<Signature>>(DoNothing());      \
170     std::move(cb).Run(__VA_ARGS__);                                       \
171   }
172 
CALLBACK_TESTS_DO_NOTHING(NoArgs,void ())173 CALLBACK_TESTS_DO_NOTHING(NoArgs, void())
174 CALLBACK_TESTS_DO_NOTHING(OneArg, void(int), 2)
175 CALLBACK_TESTS_DO_NOTHING(TwoArgs, void(float, int), 0.25, 2)
176 CALLBACK_TESTS_DO_NOTHING(ThreeArgs, void(bool, float, int), false, 0.25, 2)
177 
178 // Test passing callbacks to RectifyCallback() in different ways.
179 
180 TEST(RectifyCallbackTest, RepeatingMove) {
181   auto cb = BindRepeating([](int x) { return x != 0; });
182   auto cb2 = RectifyCallback<bool(float, int)>(std::move(cb));
183   EXPECT_EQ(true, cb2.Run(1.0, 1));
184   EXPECT_EQ(false, cb2.Run(1.0, 0));
185 }
186 
TEST(RectifyCallbackTest,RepeatingCopy)187 TEST(RectifyCallbackTest, RepeatingCopy) {
188   const auto cb = BindRepeating([](int x) { return x != 0; });
189   auto cb2 = RectifyCallback<bool(float, int)>(cb);
190   EXPECT_EQ(true, cb2.Run(1.0, 1));
191   EXPECT_EQ(false, cb2.Run(1.0, 0));
192 }
193 
TEST(RectifyCallbackTest,RepeatingConstReference)194 TEST(RectifyCallbackTest, RepeatingConstReference) {
195   const auto cb = BindRepeating([](int x) { return x != 0; });
196   const auto& cb_ref = cb;
197   auto cb2 = RectifyCallback<bool(float, int)>(cb_ref);
198   EXPECT_EQ(true, cb2.Run(1.0, 1));
199   EXPECT_EQ(false, cb2.Run(1.0, 0));
200 }
201 
TEST(RectifyCallbackTest,OnceMove)202 TEST(RectifyCallbackTest, OnceMove) {
203   auto cb = BindOnce([](int x) { return x != 0; });
204   auto cb2 = RectifyCallback<bool(float, int)>(std::move(cb));
205   EXPECT_EQ(true, std::move(cb2).Run(1.0, 1));
206 }
207 
TEST(RectifyCallbackTest,OnceFromRepeating)208 TEST(RectifyCallbackTest, OnceFromRepeating) {
209   auto cb = BindRepeating([](int x) { return x != 0; });
210   auto cb2 = RectifyCallback<OnceCallback<bool(float, int)>>(std::move(cb));
211   EXPECT_EQ(true, std::move(cb2).Run(1.0, 1));
212 }
213 
214 // Test that we can write a function that can rectify its callback argument into
215 // the signature it wants.
216 //
217 // If this is implemented incorrectly, it can result in strange/bad behavior,
218 // even if it manages to compile.
219 
220 namespace {
221 
222 using ExampleRepeatingTargetType = RepeatingCallback<bool(double, int)>;
223 using ExampleOnceTargetType = OnceCallback<bool(double, int)>;
224 
225 // This is the call we'll be rectifying into the expected signature.
ExampleTargetFunction(int x)226 bool ExampleTargetFunction(int x) {
227   return x != 0;
228 }
229 
230 // Base version of the function that takes a repeating callback.
231 // This is the actual implementation.
ExampleFunctionRepeatingCallback(ExampleRepeatingTargetType callback)232 void ExampleFunctionRepeatingCallback(ExampleRepeatingTargetType callback) {
233   EXPECT_EQ(true, std::move(callback).Run(1.0, 1));
234 }
235 
236 // Template version of the function that wants a repeating callback; it will
237 // rectify its input and call the base version.
238 //
239 // If the rectify goes awry (e.g. the wrong kind of callback is generated),
240 // this can result in an infinite loop.
241 template <typename T>
ExampleFunctionRepeatingCallback(T && callback)242 void ExampleFunctionRepeatingCallback(T&& callback) {
243   ExampleFunctionRepeatingCallback(
244       RectifyCallback<ExampleRepeatingTargetType>(std::forward<T>(callback)));
245 }
246 
247 // Base version of the function that takes a once callback.
248 // This is the actual implementation.
ExampleFunctionOnceCallback(ExampleOnceTargetType callback)249 void ExampleFunctionOnceCallback(ExampleOnceTargetType callback) {
250   EXPECT_EQ(true, std::move(callback).Run(1.0, 1));
251 }
252 
253 // Template version of the function that wants a once callback; it will
254 // rectify its input and call the base version.
255 //
256 // If the rectify goes awry (e.g. the wrong kind of callback is generated),
257 // this can result in an infinite loop.
258 template <typename T>
ExampleFunctionOnceCallback(T && callback)259 void ExampleFunctionOnceCallback(T&& callback) {
260   ExampleFunctionOnceCallback(
261       RectifyCallback<ExampleOnceTargetType>(std::forward<T>(callback)));
262 }
263 
264 }  // namespace
265 
TEST(RectifyCallbackTest,TemplateOverloadRectifiesOnceCallback)266 TEST(RectifyCallbackTest, TemplateOverloadRectifiesOnceCallback) {
267   ExampleFunctionOnceCallback(BindOnce(&ExampleTargetFunction));
268   ExampleFunctionOnceCallback(BindOnce([] { return true; }));
269   ExampleFunctionOnceCallback(BindOnce([](double d, int i) { return d && i; }));
270   auto cb = BindOnce(&ExampleTargetFunction);
271   ExampleFunctionOnceCallback(std::move(cb));
272 }
273 
TEST(RectifyCallbackTest,TemplateOverloadRectifiesRepeatingCallback)274 TEST(RectifyCallbackTest, TemplateOverloadRectifiesRepeatingCallback) {
275   ExampleFunctionOnceCallback(BindRepeating(&ExampleTargetFunction));
276   ExampleFunctionOnceCallback(BindRepeating([] { return true; }));
277   ExampleFunctionOnceCallback(
278       BindRepeating([](double d, int i) { return d && i; }));
279   auto cb = BindRepeating(&ExampleTargetFunction);
280   ExampleFunctionOnceCallback(cb);
281   bool result = true;
282   ExampleFunctionOnceCallback(BindLambdaForTesting([&] { return result; }));
283 }
284 
TEST(RectifyCallbackTest,TemplateOverloadCoerceRepeatingTarget)285 TEST(RectifyCallbackTest, TemplateOverloadCoerceRepeatingTarget) {
286   ExampleFunctionRepeatingCallback(BindRepeating(&ExampleTargetFunction));
287   ExampleFunctionRepeatingCallback(BindRepeating([] { return true; }));
288   ExampleFunctionRepeatingCallback(
289       BindRepeating([](double d, int i) { return d && i; }));
290   auto cb = BindRepeating(&ExampleTargetFunction);
291   ExampleFunctionRepeatingCallback(cb);
292   bool result = true;
293   ExampleFunctionRepeatingCallback(
294       BindLambdaForTesting([&] { return result; }));
295 }
296 
TEST(RectifyCallbackTest,NullCallbackPassthrough)297 TEST(RectifyCallbackTest, NullCallbackPassthrough) {
298   {
299     OnceCallback<void()> once;
300     RepeatingCallback<void()> repeating;
301     EXPECT_TRUE(RectifyCallback<void()>(std::move(once)).is_null());
302     EXPECT_TRUE(RectifyCallback<void()>(repeating).is_null());
303     EXPECT_TRUE(RectifyCallback<void()>(NullCallback()).is_null());
304   }
305 
306   {
307     OnceCallback<void()> once;
308     RepeatingCallback<void()> repeating;
309     EXPECT_TRUE(RectifyCallback<void(int)>(std::move(once)).is_null());
310     EXPECT_TRUE(RectifyCallback<void(int)>(repeating).is_null());
311     EXPECT_TRUE(RectifyCallback<void(int)>(NullCallback()).is_null());
312   }
313 }
314 
315 }  // namespace base
316