xref: /aosp_15_r20/external/webrtc/third_party/abseil-cpp/absl/base/invoke_test.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/base/internal/invoke.h"
16 
17 #include <functional>
18 #include <memory>
19 #include <string>
20 #include <utility>
21 
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/memory/memory.h"
25 #include "absl/strings/str_cat.h"
26 
27 namespace absl {
28 ABSL_NAMESPACE_BEGIN
29 namespace base_internal {
30 namespace {
31 
Function(int a,int b)32 int Function(int a, int b) { return a - b; }
33 
VoidFunction(int & a,int & b)34 void VoidFunction(int& a, int& b) {
35   a += b;
36   b = a - b;
37   a -= b;
38 }
39 
ZeroArgFunction()40 int ZeroArgFunction() { return -1937; }
41 
Sink(std::unique_ptr<int> p)42 int Sink(std::unique_ptr<int> p) {
43   return *p;
44 }
45 
Factory(int n)46 std::unique_ptr<int> Factory(int n) {
47   return make_unique<int>(n);
48 }
49 
NoOp()50 void NoOp() {}
51 
52 struct ConstFunctor {
operator ()absl::base_internal::__anon2b2eb2bf0111::ConstFunctor53   int operator()(int a, int b) const { return a - b; }
54 };
55 
56 struct MutableFunctor {
operator ()absl::base_internal::__anon2b2eb2bf0111::MutableFunctor57   int operator()(int a, int b) { return a - b; }
58 };
59 
60 struct EphemeralFunctor {
operator ()absl::base_internal::__anon2b2eb2bf0111::EphemeralFunctor61   int operator()(int a, int b) && { return a - b; }
62 };
63 
64 struct OverloadedFunctor {
65   template <typename... Args>
operator ()absl::base_internal::__anon2b2eb2bf0111::OverloadedFunctor66   std::string operator()(const Args&... args) & {
67     return StrCat("&", args...);
68   }
69   template <typename... Args>
operator ()absl::base_internal::__anon2b2eb2bf0111::OverloadedFunctor70   std::string operator()(const Args&... args) const& {
71     return StrCat("const&", args...);
72   }
73   template <typename... Args>
operator ()absl::base_internal::__anon2b2eb2bf0111::OverloadedFunctor74   std::string operator()(const Args&... args) && {
75     return StrCat("&&", args...);
76   }
77 };
78 
79 struct Class {
Methodabsl::base_internal::__anon2b2eb2bf0111::Class80   int Method(int a, int b) { return a - b; }
ConstMethodabsl::base_internal::__anon2b2eb2bf0111::Class81   int ConstMethod(int a, int b) const { return a - b; }
RefMethodabsl::base_internal::__anon2b2eb2bf0111::Class82   int RefMethod(int a, int b) & { return a - b; }
RefRefMethodabsl::base_internal::__anon2b2eb2bf0111::Class83   int RefRefMethod(int a, int b) && { return a - b; }
NoExceptMethodabsl::base_internal::__anon2b2eb2bf0111::Class84   int NoExceptMethod(int a, int b) noexcept { return a - b; }
VolatileMethodabsl::base_internal::__anon2b2eb2bf0111::Class85   int VolatileMethod(int a, int b) volatile { return a - b; }
86 
87   int member;
88 };
89 
90 struct FlipFlop {
ConstMethodabsl::base_internal::__anon2b2eb2bf0111::FlipFlop91   int ConstMethod() const { return member; }
operator *absl::base_internal::__anon2b2eb2bf0111::FlipFlop92   FlipFlop operator*() const { return {-member}; }
93 
94   int member;
95 };
96 
97 // CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
98 // on which one is valid.
99 template <typename F>
invoke(std::declval<const F &> ())100 decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
101     const F& f) {
102   return base_internal::invoke(f);
103 }
104 
105 template <typename F>
CallMaybeWithArg(const F & f)106 decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
107     const F& f) {
108   return base_internal::invoke(f, 42);
109 }
110 
TEST(InvokeTest,Function)111 TEST(InvokeTest, Function) {
112   EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
113   EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
114 }
115 
TEST(InvokeTest,NonCopyableArgument)116 TEST(InvokeTest, NonCopyableArgument) {
117   EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
118 }
119 
TEST(InvokeTest,NonCopyableResult)120 TEST(InvokeTest, NonCopyableResult) {
121   EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
122 }
123 
TEST(InvokeTest,VoidResult)124 TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
125 
TEST(InvokeTest,ConstFunctor)126 TEST(InvokeTest, ConstFunctor) {
127   EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
128 }
129 
TEST(InvokeTest,MutableFunctor)130 TEST(InvokeTest, MutableFunctor) {
131   MutableFunctor f;
132   EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
133   EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
134 }
135 
TEST(InvokeTest,EphemeralFunctor)136 TEST(InvokeTest, EphemeralFunctor) {
137   EphemeralFunctor f;
138   EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
139   EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
140 }
141 
TEST(InvokeTest,OverloadedFunctor)142 TEST(InvokeTest, OverloadedFunctor) {
143   OverloadedFunctor f;
144   const OverloadedFunctor& cf = f;
145 
146   EXPECT_EQ("&", base_internal::invoke(f));
147   EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
148 
149   EXPECT_EQ("const&", base_internal::invoke(cf));
150   EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
151 
152   EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
153 
154   OverloadedFunctor f2;
155   EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
156 }
157 
TEST(InvokeTest,ReferenceWrapper)158 TEST(InvokeTest, ReferenceWrapper) {
159   ConstFunctor cf;
160   MutableFunctor mf;
161   EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
162   EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
163   EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
164 }
165 
TEST(InvokeTest,MemberFunction)166 TEST(InvokeTest, MemberFunction) {
167   std::unique_ptr<Class> p(new Class);
168   std::unique_ptr<const Class> cp(new Class);
169   std::unique_ptr<volatile Class> vp(new Class);
170 
171   EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
172   EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
173   EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
174   EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
175   EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
176   EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
177   EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
178                                      2));  // NOLINT
179   EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
180   EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
181   EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));
182 
183   EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
184   EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
185   EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));
186 
187   EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
188   EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
189   EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));
190 
191   EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
192   EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
193   EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
194   EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
195   EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
196   EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));
197 
198   EXPECT_EQ(1,
199             base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
200   EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
201                                      3, 2));
202   EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
203                                      make_unique<const Class>(), 3, 2));
204 }
205 
TEST(InvokeTest,DataMember)206 TEST(InvokeTest, DataMember) {
207   std::unique_ptr<Class> p(new Class{42});
208   std::unique_ptr<const Class> cp(new Class{42});
209   EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
210   EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
211   EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));
212 
213   base_internal::invoke(&Class::member, p) = 42;
214   base_internal::invoke(&Class::member, p.get()) = 42;
215 
216   EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
217   EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
218   EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
219 }
220 
TEST(InvokeTest,FlipFlop)221 TEST(InvokeTest, FlipFlop) {
222   FlipFlop obj = {42};
223   // This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
224   // ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
225   EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
226   EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
227 }
228 
TEST(InvokeTest,SfinaeFriendly)229 TEST(InvokeTest, SfinaeFriendly) {
230   CallMaybeWithArg(NoOp);
231   EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
232 }
233 
TEST(IsInvocableRTest,CallableExactMatch)234 TEST(IsInvocableRTest, CallableExactMatch) {
235   static_assert(
236       base_internal::is_invocable_r<int, decltype(Function), int, int>::value,
237       "Should be true for exact match of types on a free function");
238 }
239 
TEST(IsInvocableRTest,CallableArgumentConversionMatch)240 TEST(IsInvocableRTest, CallableArgumentConversionMatch) {
241   static_assert(
242       base_internal::is_invocable_r<int, decltype(Function), char, int>::value,
243       "Should be true for convertible argument type");
244 }
245 
TEST(IsInvocableRTest,CallableReturnConversionMatch)246 TEST(IsInvocableRTest, CallableReturnConversionMatch) {
247   static_assert(base_internal::is_invocable_r<double, decltype(Function), int,
248                                               int>::value,
249                 "Should be true for convertible return type");
250 }
251 
TEST(IsInvocableRTest,CallableReturnVoid)252 TEST(IsInvocableRTest, CallableReturnVoid) {
253   static_assert(base_internal::is_invocable_r<void, decltype(VoidFunction),
254                                               int&, int&>::value,
255                 "Should be true for void expected and actual return types");
256   static_assert(
257       base_internal::is_invocable_r<void, decltype(Function), int, int>::value,
258       "Should be true for void expected and non-void actual return types");
259 }
260 
TEST(IsInvocableRTest,CallableRefQualifierMismatch)261 TEST(IsInvocableRTest, CallableRefQualifierMismatch) {
262   static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
263                                                int&, const int&>::value,
264                 "Should be false for reference constness mismatch");
265   static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
266                                                int&&, int&>::value,
267                 "Should be false for reference value category mismatch");
268 }
269 
TEST(IsInvocableRTest,CallableArgumentTypeMismatch)270 TEST(IsInvocableRTest, CallableArgumentTypeMismatch) {
271   static_assert(!base_internal::is_invocable_r<int, decltype(Function),
272                                                std::string, int>::value,
273                 "Should be false for argument type mismatch");
274 }
275 
TEST(IsInvocableRTest,CallableReturnTypeMismatch)276 TEST(IsInvocableRTest, CallableReturnTypeMismatch) {
277   static_assert(!base_internal::is_invocable_r<std::string, decltype(Function),
278                                                int, int>::value,
279                 "Should be false for return type mismatch");
280 }
281 
TEST(IsInvocableRTest,CallableTooFewArgs)282 TEST(IsInvocableRTest, CallableTooFewArgs) {
283   static_assert(
284       !base_internal::is_invocable_r<int, decltype(Function), int>::value,
285       "Should be false for too few arguments");
286 }
287 
TEST(IsInvocableRTest,CallableTooManyArgs)288 TEST(IsInvocableRTest, CallableTooManyArgs) {
289   static_assert(!base_internal::is_invocable_r<int, decltype(Function), int,
290                                                int, int>::value,
291                 "Should be false for too many arguments");
292 }
293 
TEST(IsInvocableRTest,MemberFunctionAndReference)294 TEST(IsInvocableRTest, MemberFunctionAndReference) {
295   static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
296                                               Class&, int, int>::value,
297                 "Should be true for exact match of types on a member function "
298                 "and class reference");
299 }
300 
TEST(IsInvocableRTest,MemberFunctionAndPointer)301 TEST(IsInvocableRTest, MemberFunctionAndPointer) {
302   static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
303                                               Class*, int, int>::value,
304                 "Should be true for exact match of types on a member function "
305                 "and class pointer");
306 }
307 
TEST(IsInvocableRTest,DataMemberAndReference)308 TEST(IsInvocableRTest, DataMemberAndReference) {
309   static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
310                                               Class&>::value,
311                 "Should be true for exact match of types on a data member and "
312                 "class reference");
313 }
314 
TEST(IsInvocableRTest,DataMemberAndPointer)315 TEST(IsInvocableRTest, DataMemberAndPointer) {
316   static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
317                                               Class*>::value,
318                 "Should be true for exact match of types on a data member and "
319                 "class pointer");
320 }
321 
TEST(IsInvocableRTest,CallableZeroArgs)322 TEST(IsInvocableRTest, CallableZeroArgs) {
323   static_assert(
324       base_internal::is_invocable_r<int, decltype(ZeroArgFunction)>::value,
325       "Should be true for exact match for a zero-arg free function");
326 }
327 
328 }  // namespace
329 }  // namespace base_internal
330 ABSL_NAMESPACE_END
331 }  // namespace absl
332