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
__anon8df38ecf0102() 46 CALLBACK_TESTS_VOID(NoArgsSameSignature, void(), []() {})
47
48 CALLBACK_TESTS_VOID(
49 OneArgRemoveOneArg,
50 void(int),
__anon8df38ecf0202() 51 []() {},
52 1)
53
54 CALLBACK_TESTS_VOID(
55 TwoArgsRemoveTwoArgs,
56 void(float, int),
__anon8df38ecf0302() 57 []() {},
58 0.25f,
59 1)
60
61 CALLBACK_TESTS_VOID(
62 OneArgSameSignature,
63 void(int),
__anon8df38ecf0402(int x) 64 [](int x) { EXPECT_EQ(1, x); },
65 1)
66
67 CALLBACK_TESTS_VOID(
68 TwoArgsRemoveOneArg,
69 void(float, int),
__anon8df38ecf0502(int x) 70 [](int x) { EXPECT_EQ(1, x); },
71 0.25f,
72 1)
73
74 CALLBACK_TESTS_VOID(
75 ThreeArgsRemoveTwoArgs,
76 void(bool, float, int),
__anon8df38ecf0602(int x) 77 [](int x) { EXPECT_EQ(1, x); },
78 true,
79 0.25f,
80 1)
81
82 // Test rectifying functions that do return a value.
83
84 #define CALLBACK_TESTS_RETURN(TestNameSuffix, Signature, LambdaToRectify, \
85 ExpectedReturn, ...) \
86 TEST(RectifyCallbackTest, \
87 RepeatingCallbackSignatureReturn##TestNameSuffix) { \
88 auto cb = RectifyCallback<Signature>(BindRepeating(LambdaToRectify)); \
89 EXPECT_EQ(ExpectedReturn, cb.Run(__VA_ARGS__)); \
90 } \
91 TEST(RectifyCallbackTest, RepeatingCallbackTypeReturn##TestNameSuffix) { \
92 auto cb = RectifyCallback<RepeatingCallback<Signature>>( \
93 BindRepeating(LambdaToRectify)); \
94 EXPECT_EQ(ExpectedReturn, cb.Run(__VA_ARGS__)); \
95 } \
96 TEST(RectifyCallbackTest, RepeatingToOnceReturn##TestNameSuffix) { \
97 auto cb = RectifyCallback<OnceCallback<Signature>>( \
98 BindRepeating(LambdaToRectify)); \
99 EXPECT_EQ(ExpectedReturn, std::move(cb).Run(__VA_ARGS__)); \
100 } \
101 TEST(RectifyCallbackTest, OnceCallbackSignatureReturn##TestNameSuffix) { \
102 auto cb = RectifyCallback<Signature>(BindOnce(LambdaToRectify)); \
103 EXPECT_EQ(ExpectedReturn, std::move(cb).Run(__VA_ARGS__)); \
104 } \
105 TEST(RectifyCallbackTest, OnceCallbackTypeReturn##TestNameSuffix) { \
106 auto cb = \
107 RectifyCallback<OnceCallback<Signature>>(BindOnce(LambdaToRectify)); \
108 EXPECT_EQ(ExpectedReturn, std::move(cb).Run(__VA_ARGS__)); \
109 }
110
111 CALLBACK_TESTS_RETURN(
112 NoArgsSameSignature,
113 int(),
__anon8df38ecf0702() 114 []() { return 2; },
115 2)
116
117 CALLBACK_TESTS_RETURN(
118 OneArgRemoveOneArg,
119 int(int),
__anon8df38ecf0802() 120 []() { return 2; },
121 2,
122 1)
123
124 CALLBACK_TESTS_RETURN(
125 TwoArgsRemoveTwoArgs,
126 int(float, int),
__anon8df38ecf0902() 127 []() { return 2; },
128 2,
129 0.25f,
130 1)
131
132 CALLBACK_TESTS_RETURN(
133 OneArgSameSignature,
134 int(int),
__anon8df38ecf0a02(int x) 135 [](int x) { return x; },
136 2,
137 2)
138
139 CALLBACK_TESTS_RETURN(
140 TwoArgsRemoveOneArg,
141 int(float, int),
__anon8df38ecf0b02(int x) 142 [](int x) { return x; },
143 2,
144 0.25f,
145 2)
146
147 CALLBACK_TESTS_RETURN(
148 ThreeArgsRemoveTwoArgs,
149 int(bool, float, int),
__anon8df38ecf0c02(int x) 150 [](int x) { return x; },
151 2,
152 true,
153 0.25f,
154 2)
155
156 // Test proper forwarding of move-only arguments.
157
158 CALLBACK_TESTS_RETURN(
159 DiscardsMoveOnlyArgs,
160 bool(int, std::unique_ptr<int>),
__anon8df38ecf0d02() 161 []() { return true; },
162 true,
163 2,
164 std::make_unique<int>(3))
165
166 CALLBACK_TESTS_RETURN(
167 UsesMoveOnlyArg,
168 int(float, int, std::unique_ptr<int>),
__anon8df38ecf0e02(std::unique_ptr<int> p) 169 [](std::unique_ptr<int> p) { return *p; },
170 3,
171 0.25f,
172 2,
173 std::make_unique<int>(3))
174
175 // Test rectifying DoNothing().
176
177 #define CALLBACK_TESTS_DO_NOTHING(TestNameSuffix, Signature, ...) \
178 TEST(RectifyCallbackTest, SignatureDoNothing##TestNameSuffix) { \
179 auto cb = RectifyCallback<Signature>(DoNothing()); \
180 cb.Run(__VA_ARGS__); \
181 } \
182 TEST(RectifyCallbackTest, RepeatingCallbackDoNothing##TestNameSuffix) { \
183 auto cb = RectifyCallback<RepeatingCallback<Signature>>(DoNothing()); \
184 cb.Run(__VA_ARGS__); \
185 } \
186 TEST(RectifyCallbackTest, OnceCallbackDoNothing##TestNameSuffix) { \
187 auto cb = RectifyCallback<OnceCallback<Signature>>(DoNothing()); \
188 std::move(cb).Run(__VA_ARGS__); \
189 }
190
CALLBACK_TESTS_DO_NOTHING(NoArgs,void ())191 CALLBACK_TESTS_DO_NOTHING(NoArgs, void())
192 CALLBACK_TESTS_DO_NOTHING(OneArg, void(int), 2)
193 CALLBACK_TESTS_DO_NOTHING(TwoArgs, void(float, int), 0.25, 2)
194 CALLBACK_TESTS_DO_NOTHING(ThreeArgs, void(bool, float, int), false, 0.25, 2)
195
196 // Test passing callbacks to RectifyCallback() in different ways.
197
198 TEST(RectifyCallbackTest, RepeatingMove) {
199 auto cb = BindRepeating([](int x) { return x != 0; });
200 auto cb2 = RectifyCallback<bool(float, int)>(std::move(cb));
201 EXPECT_EQ(true, cb2.Run(1.0, 1));
202 EXPECT_EQ(false, cb2.Run(1.0, 0));
203 }
204
TEST(RectifyCallbackTest,RepeatingCopy)205 TEST(RectifyCallbackTest, RepeatingCopy) {
206 const auto cb = BindRepeating([](int x) { return x != 0; });
207 auto cb2 = RectifyCallback<bool(float, int)>(cb);
208 EXPECT_EQ(true, cb2.Run(1.0, 1));
209 EXPECT_EQ(false, cb2.Run(1.0, 0));
210 }
211
TEST(RectifyCallbackTest,RepeatingConstReference)212 TEST(RectifyCallbackTest, RepeatingConstReference) {
213 const auto cb = BindRepeating([](int x) { return x != 0; });
214 const auto& cb_ref = cb;
215 auto cb2 = RectifyCallback<bool(float, int)>(cb_ref);
216 EXPECT_EQ(true, cb2.Run(1.0, 1));
217 EXPECT_EQ(false, cb2.Run(1.0, 0));
218 }
219
TEST(RectifyCallbackTest,OnceMove)220 TEST(RectifyCallbackTest, OnceMove) {
221 auto cb = BindOnce([](int x) { return x != 0; });
222 auto cb2 = RectifyCallback<bool(float, int)>(std::move(cb));
223 EXPECT_EQ(true, std::move(cb2).Run(1.0, 1));
224 }
225
TEST(RectifyCallbackTest,OnceFromRepeating)226 TEST(RectifyCallbackTest, OnceFromRepeating) {
227 auto cb = BindRepeating([](int x) { return x != 0; });
228 auto cb2 = RectifyCallback<OnceCallback<bool(float, int)>>(std::move(cb));
229 EXPECT_EQ(true, std::move(cb2).Run(1.0, 1));
230 }
231
232 // Test that we can write a function that can rectify its callback argument into
233 // the signature it wants.
234 //
235 // If this is implemented incorrectly, it can result in strange/bad behavior,
236 // even if it manages to compile.
237
238 namespace {
239
240 using ExampleRepeatingTargetType = RepeatingCallback<bool(double, int)>;
241 using ExampleOnceTargetType = OnceCallback<bool(double, int)>;
242
243 // This is the call we'll be rectifying into the expected signature.
ExampleTargetFunction(int x)244 bool ExampleTargetFunction(int x) {
245 return x != 0;
246 }
247
248 // Base version of the function that takes a repeating callback.
249 // This is the actual implementation.
ExampleFunctionRepeatingCallback(ExampleRepeatingTargetType callback)250 void ExampleFunctionRepeatingCallback(ExampleRepeatingTargetType callback) {
251 EXPECT_EQ(true, std::move(callback).Run(1.0, 1));
252 }
253
254 // Template version of the function that wants a repeating callback; it will
255 // rectify its input and call the base version.
256 //
257 // If the rectify goes awry (e.g. the wrong kind of callback is generated),
258 // this can result in an infinite loop.
259 template <typename T>
ExampleFunctionRepeatingCallback(T && callback)260 void ExampleFunctionRepeatingCallback(T&& callback) {
261 ExampleFunctionRepeatingCallback(
262 RectifyCallback<ExampleRepeatingTargetType>(std::forward<T>(callback)));
263 }
264
265 // Base version of the function that takes a once callback.
266 // This is the actual implementation.
ExampleFunctionOnceCallback(ExampleOnceTargetType callback)267 void ExampleFunctionOnceCallback(ExampleOnceTargetType callback) {
268 EXPECT_EQ(true, std::move(callback).Run(1.0, 1));
269 }
270
271 // Template version of the function that wants a once callback; it will
272 // rectify its input and call the base version.
273 //
274 // If the rectify goes awry (e.g. the wrong kind of callback is generated),
275 // this can result in an infinite loop.
276 template <typename T>
ExampleFunctionOnceCallback(T && callback)277 void ExampleFunctionOnceCallback(T&& callback) {
278 ExampleFunctionOnceCallback(
279 RectifyCallback<ExampleOnceTargetType>(std::forward<T>(callback)));
280 }
281
282 } // namespace
283
TEST(RectifyCallbackTest,TemplateOverloadRectifiesOnceCallback)284 TEST(RectifyCallbackTest, TemplateOverloadRectifiesOnceCallback) {
285 ExampleFunctionOnceCallback(BindOnce(&ExampleTargetFunction));
286 ExampleFunctionOnceCallback(BindOnce([]() { return true; }));
287 ExampleFunctionOnceCallback(BindOnce([](double d, int i) { return d && i; }));
288 auto cb = BindOnce(&ExampleTargetFunction);
289 ExampleFunctionOnceCallback(std::move(cb));
290 }
291
TEST(RectifyCallbackTest,TemplateOverloadRectifiesRepeatingCallback)292 TEST(RectifyCallbackTest, TemplateOverloadRectifiesRepeatingCallback) {
293 ExampleFunctionOnceCallback(BindRepeating(&ExampleTargetFunction));
294 ExampleFunctionOnceCallback(BindRepeating([]() { return true; }));
295 ExampleFunctionOnceCallback(
296 BindRepeating([](double d, int i) { return d && i; }));
297 auto cb = BindRepeating(&ExampleTargetFunction);
298 ExampleFunctionOnceCallback(cb);
299 bool result = true;
300 ExampleFunctionOnceCallback(BindLambdaForTesting([&]() { return result; }));
301 }
302
TEST(RectifyCallbackTest,TemplateOverloadCoerceRepeatingTarget)303 TEST(RectifyCallbackTest, TemplateOverloadCoerceRepeatingTarget) {
304 ExampleFunctionRepeatingCallback(BindRepeating(&ExampleTargetFunction));
305 ExampleFunctionRepeatingCallback(BindRepeating([]() { return true; }));
306 ExampleFunctionRepeatingCallback(
307 BindRepeating([](double d, int i) { return d && i; }));
308 auto cb = BindRepeating(&ExampleTargetFunction);
309 ExampleFunctionRepeatingCallback(cb);
310 bool result = true;
311 ExampleFunctionRepeatingCallback(
312 BindLambdaForTesting([&]() { return result; }));
313 }
314
TEST(RectifyCallbackTest,NullCallbackPassthrough)315 TEST(RectifyCallbackTest, NullCallbackPassthrough) {
316 {
317 OnceCallback<void()> once;
318 RepeatingCallback<void()> repeating;
319 EXPECT_TRUE(RectifyCallback<void()>(std::move(once)).is_null());
320 EXPECT_TRUE(RectifyCallback<void()>(repeating).is_null());
321 EXPECT_TRUE(RectifyCallback<void()>(NullCallback()).is_null());
322 }
323
324 {
325 OnceCallback<void()> once;
326 RepeatingCallback<void()> repeating;
327 EXPECT_TRUE(RectifyCallback<void(int)>(std::move(once)).is_null());
328 EXPECT_TRUE(RectifyCallback<void(int)>(repeating).is_null());
329 EXPECT_TRUE(RectifyCallback<void(int)>(NullCallback()).is_null());
330 }
331 }
332
333 } // namespace base
334