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