1 // Copyright 2019 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/functional/function_ref.h"
16 
17 #include <memory>
18 
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include "absl/container/internal/test_instance_tracker.h"
22 #include "absl/memory/memory.h"
23 
24 namespace absl {
25 ABSL_NAMESPACE_BEGIN
26 namespace {
27 
RunFun(FunctionRef<void ()> f)28 void RunFun(FunctionRef<void()> f) { f(); }
29 
TEST(FunctionRefTest,Lambda)30 TEST(FunctionRefTest, Lambda) {
31   bool ran = false;
32   RunFun([&] { ran = true; });
33   EXPECT_TRUE(ran);
34 }
35 
Function()36 int Function() { return 1337; }
37 
TEST(FunctionRefTest,Function1)38 TEST(FunctionRefTest, Function1) {
39   FunctionRef<int()> ref(&Function);
40   EXPECT_EQ(1337, ref());
41 }
42 
TEST(FunctionRefTest,Function2)43 TEST(FunctionRefTest, Function2) {
44   FunctionRef<int()> ref(Function);
45   EXPECT_EQ(1337, ref());
46 }
47 
NoExceptFunction()48 int NoExceptFunction() noexcept { return 1337; }
49 
50 // TODO(jdennett): Add a test for noexcept member functions.
TEST(FunctionRefTest,NoExceptFunction)51 TEST(FunctionRefTest, NoExceptFunction) {
52   FunctionRef<int()> ref(NoExceptFunction);
53   EXPECT_EQ(1337, ref());
54 }
55 
TEST(FunctionRefTest,ForwardsArgs)56 TEST(FunctionRefTest, ForwardsArgs) {
57   auto l = [](std::unique_ptr<int> i) { return *i; };
58   FunctionRef<int(std::unique_ptr<int>)> ref(l);
59   EXPECT_EQ(42, ref(absl::make_unique<int>(42)));
60 }
61 
TEST(FunctionRef,ReturnMoveOnly)62 TEST(FunctionRef, ReturnMoveOnly) {
63   auto l = [] { return absl::make_unique<int>(29); };
64   FunctionRef<std::unique_ptr<int>()> ref(l);
65   EXPECT_EQ(29, *ref());
66 }
67 
TEST(FunctionRef,ManyArgs)68 TEST(FunctionRef, ManyArgs) {
69   auto l = [](int a, int b, int c) { return a + b + c; };
70   FunctionRef<int(int, int, int)> ref(l);
71   EXPECT_EQ(6, ref(1, 2, 3));
72 }
73 
TEST(FunctionRef,VoidResultFromNonVoidFunctor)74 TEST(FunctionRef, VoidResultFromNonVoidFunctor) {
75   bool ran = false;
76   auto l = [&]() -> int {
77     ran = true;
78     return 2;
79   };
80   FunctionRef<void()> ref(l);
81   ref();
82   EXPECT_TRUE(ran);
83 }
84 
TEST(FunctionRef,CastFromDerived)85 TEST(FunctionRef, CastFromDerived) {
86   struct Base {};
87   struct Derived : public Base {};
88 
89   Derived d;
90   auto l1 = [&](Base* b) { EXPECT_EQ(&d, b); };
91   FunctionRef<void(Derived*)> ref1(l1);
92   ref1(&d);
93 
94   auto l2 = [&]() -> Derived* { return &d; };
95   FunctionRef<Base*()> ref2(l2);
96   EXPECT_EQ(&d, ref2());
97 }
98 
TEST(FunctionRef,VoidResultFromNonVoidFuncton)99 TEST(FunctionRef, VoidResultFromNonVoidFuncton) {
100   FunctionRef<void()> ref(Function);
101   ref();
102 }
103 
TEST(FunctionRef,MemberPtr)104 TEST(FunctionRef, MemberPtr) {
105   struct S {
106     int i;
107   };
108 
109   S s{1100111};
110   auto mem_ptr = &S::i;
111   FunctionRef<int(const S& s)> ref(mem_ptr);
112   EXPECT_EQ(1100111, ref(s));
113 }
114 
TEST(FunctionRef,MemberFun)115 TEST(FunctionRef, MemberFun) {
116   struct S {
117     int i;
118     int get_i() const { return i; }
119   };
120 
121   S s{22};
122   auto mem_fun_ptr = &S::get_i;
123   FunctionRef<int(const S& s)> ref(mem_fun_ptr);
124   EXPECT_EQ(22, ref(s));
125 }
126 
TEST(FunctionRef,MemberFunRefqualified)127 TEST(FunctionRef, MemberFunRefqualified) {
128   struct S {
129     int i;
130     int get_i() && { return i; }
131   };
132   auto mem_fun_ptr = &S::get_i;
133   S s{22};
134   FunctionRef<int(S && s)> ref(mem_fun_ptr);
135   EXPECT_EQ(22, ref(std::move(s)));
136 }
137 
138 #if !defined(_WIN32) && defined(GTEST_HAS_DEATH_TEST)
139 
TEST(FunctionRef,MemberFunRefqualifiedNull)140 TEST(FunctionRef, MemberFunRefqualifiedNull) {
141   struct S {
142     int i;
143     int get_i() && { return i; }
144   };
145   auto mem_fun_ptr = &S::get_i;
146   mem_fun_ptr = nullptr;
147   EXPECT_DEBUG_DEATH({ FunctionRef<int(S && s)> ref(mem_fun_ptr); }, "");
148 }
149 
TEST(FunctionRef,NullMemberPtrAssertFails)150 TEST(FunctionRef, NullMemberPtrAssertFails) {
151   struct S {
152     int i;
153   };
154   using MemberPtr = int S::*;
155   MemberPtr mem_ptr = nullptr;
156   EXPECT_DEBUG_DEATH({ FunctionRef<int(const S& s)> ref(mem_ptr); }, "");
157 }
158 
159 #endif  // GTEST_HAS_DEATH_TEST
160 
TEST(FunctionRef,CopiesAndMovesPerPassByValue)161 TEST(FunctionRef, CopiesAndMovesPerPassByValue) {
162   absl::test_internal::InstanceTracker tracker;
163   absl::test_internal::CopyableMovableInstance instance(0);
164   auto l = [](absl::test_internal::CopyableMovableInstance) {};
165   FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
166   ref(instance);
167   EXPECT_EQ(tracker.copies(), 1);
168   EXPECT_EQ(tracker.moves(), 1);
169 }
170 
TEST(FunctionRef,CopiesAndMovesPerPassByRef)171 TEST(FunctionRef, CopiesAndMovesPerPassByRef) {
172   absl::test_internal::InstanceTracker tracker;
173   absl::test_internal::CopyableMovableInstance instance(0);
174   auto l = [](const absl::test_internal::CopyableMovableInstance&) {};
175   FunctionRef<void(const absl::test_internal::CopyableMovableInstance&)> ref(l);
176   ref(instance);
177   EXPECT_EQ(tracker.copies(), 0);
178   EXPECT_EQ(tracker.moves(), 0);
179 }
180 
TEST(FunctionRef,CopiesAndMovesPerPassByValueCallByMove)181 TEST(FunctionRef, CopiesAndMovesPerPassByValueCallByMove) {
182   absl::test_internal::InstanceTracker tracker;
183   absl::test_internal::CopyableMovableInstance instance(0);
184   auto l = [](absl::test_internal::CopyableMovableInstance) {};
185   FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
186   ref(std::move(instance));
187   EXPECT_EQ(tracker.copies(), 0);
188   EXPECT_EQ(tracker.moves(), 2);
189 }
190 
TEST(FunctionRef,CopiesAndMovesPerPassByValueToRef)191 TEST(FunctionRef, CopiesAndMovesPerPassByValueToRef) {
192   absl::test_internal::InstanceTracker tracker;
193   absl::test_internal::CopyableMovableInstance instance(0);
194   auto l = [](const absl::test_internal::CopyableMovableInstance&) {};
195   FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
196   ref(std::move(instance));
197   EXPECT_EQ(tracker.copies(), 0);
198   EXPECT_EQ(tracker.moves(), 1);
199 }
200 
TEST(FunctionRef,PassByValueTypes)201 TEST(FunctionRef, PassByValueTypes) {
202   using absl::functional_internal::Invoker;
203   using absl::functional_internal::VoidPtr;
204   using absl::test_internal::CopyableMovableInstance;
205   struct Trivial {
206     void* p[2];
207   };
208   struct LargeTrivial {
209     void* p[3];
210   };
211 
212   static_assert(std::is_same<Invoker<void, int>, void (*)(VoidPtr, int)>::value,
213                 "Scalar types should be passed by value");
214   static_assert(
215       std::is_same<Invoker<void, Trivial>, void (*)(VoidPtr, Trivial)>::value,
216       "Small trivial types should be passed by value");
217   static_assert(std::is_same<Invoker<void, LargeTrivial>,
218                              void (*)(VoidPtr, LargeTrivial &&)>::value,
219                 "Large trivial types should be passed by rvalue reference");
220   static_assert(
221       std::is_same<Invoker<void, CopyableMovableInstance>,
222                    void (*)(VoidPtr, CopyableMovableInstance &&)>::value,
223       "Types with copy/move ctor should be passed by rvalue reference");
224 
225   // References are passed as references.
226   static_assert(
227       std::is_same<Invoker<void, int&>, void (*)(VoidPtr, int&)>::value,
228       "Reference types should be preserved");
229   static_assert(
230       std::is_same<Invoker<void, CopyableMovableInstance&>,
231                    void (*)(VoidPtr, CopyableMovableInstance&)>::value,
232       "Reference types should be preserved");
233   static_assert(
234       std::is_same<Invoker<void, CopyableMovableInstance&&>,
235                    void (*)(VoidPtr, CopyableMovableInstance &&)>::value,
236       "Reference types should be preserved");
237 
238   // Make sure the address of an object received by reference is the same as the
239   // addess of the object passed by the caller.
240   {
241     LargeTrivial obj;
242     auto test = [&obj](LargeTrivial& input) { ASSERT_EQ(&input, &obj); };
243     absl::FunctionRef<void(LargeTrivial&)> ref(test);
244     ref(obj);
245   }
246 
247   {
248     Trivial obj;
249     auto test = [&obj](Trivial& input) { ASSERT_EQ(&input, &obj); };
250     absl::FunctionRef<void(Trivial&)> ref(test);
251     ref(obj);
252   }
253 }
254 
255 }  // namespace
256 ABSL_NAMESPACE_END
257 }  // namespace absl
258