xref: /aosp_15_r20/external/cronet/base/test/rectify_callback_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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