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
__anon1bbdabf90102null46 CALLBACK_TESTS_VOID(NoArgsSameSignature, void(), [] {})
47
__anon1bbdabf90202null48 CALLBACK_TESTS_VOID(OneArgRemoveOneArg, void(int), [] {}, 1)
49
__anon1bbdabf90302null50 CALLBACK_TESTS_VOID(TwoArgsRemoveTwoArgs, void(float, int), [] {}, 0.25f, 1)
51
52 CALLBACK_TESTS_VOID(
53 OneArgSameSignature,
54 void(int),
__anon1bbdabf90402(int x) 55 [](int x) { EXPECT_EQ(1, x); },
56 1)
57
58 CALLBACK_TESTS_VOID(
59 TwoArgsRemoveOneArg,
60 void(float, int),
__anon1bbdabf90502(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),
__anon1bbdabf90602(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
__anon1bbdabf90702null102 CALLBACK_TESTS_RETURN(NoArgsSameSignature, int(), [] { return 2; }, 2)
103
__anon1bbdabf90802null104 CALLBACK_TESTS_RETURN(OneArgRemoveOneArg, int(int), [] { return 2; }, 2, 1)
105
106 CALLBACK_TESTS_RETURN(
107 TwoArgsRemoveTwoArgs,
108 int(float, int),
__anon1bbdabf90902null109 [] { return 2; },
110 2,
111 0.25f,
112 1)
113
114 CALLBACK_TESTS_RETURN(
115 OneArgSameSignature,
116 int(int),
__anon1bbdabf90a02(int x) 117 [](int x) { return x; },
118 2,
119 2)
120
121 CALLBACK_TESTS_RETURN(
122 TwoArgsRemoveOneArg,
123 int(float, int),
__anon1bbdabf90b02(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),
__anon1bbdabf90c02(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>),
__anon1bbdabf90d02null143 [] { 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>),
__anon1bbdabf90e02(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