blob: 3aa59745873d94488f0368715448677e4fce25e2 [file] [log] [blame]
Austin Schuhb4691e92020-12-31 12:37:18 -08001// 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
24namespace absl {
25ABSL_NAMESPACE_BEGIN
26namespace {
27
28void RunFun(FunctionRef<void()> f) { f(); }
29
30TEST(FunctionRefTest, Lambda) {
31 bool ran = false;
32 RunFun([&] { ran = true; });
33 EXPECT_TRUE(ran);
34}
35
36int Function() { return 1337; }
37
38TEST(FunctionRefTest, Function1) {
39 FunctionRef<int()> ref(&Function);
40 EXPECT_EQ(1337, ref());
41}
42
43TEST(FunctionRefTest, Function2) {
44 FunctionRef<int()> ref(Function);
45 EXPECT_EQ(1337, ref());
46}
47
48int NoExceptFunction() noexcept { return 1337; }
49
50// TODO(jdennett): Add a test for noexcept member functions.
51TEST(FunctionRefTest, NoExceptFunction) {
52 FunctionRef<int()> ref(NoExceptFunction);
53 EXPECT_EQ(1337, ref());
54}
55
56TEST(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
62TEST(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
68TEST(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
74TEST(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
85TEST(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
99TEST(FunctionRef, VoidResultFromNonVoidFuncton) {
100 FunctionRef<void()> ref(Function);
101 ref();
102}
103
104TEST(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
115TEST(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
127TEST(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
140TEST(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
150TEST(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
161TEST(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
171TEST(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
181TEST(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
191TEST(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
201TEST(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
256ABSL_NAMESPACE_END
257} // namespace absl