1/*
2 * Copyright 2016-present Facebook, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <list>
18
19#include <folly/Function.h>
20#include <folly/portability/GTest.h>
21
22using folly::Function;
23using folly::FunctionRef;
24
25TEST(FunctionRef, Traits) {
26 static_assert(std::is_literal_type<FunctionRef<int(int)>>::value, "");
27// Some earlier versions of libstdc++ lack these traits. Frustrating that
28// the value of __GLIBCXX__ doesn't increase with version, but rather reflects
29// release date, so some larger values of __GLIBCXX__ lack the traits while
30// some smaller values have them. Can't figure out how to reliably test for the
31// presence or absence of the traits. :-(
32#if !defined(__GLIBCXX__) || __GNUC__ >= 5
33 static_assert(
34 std::is_trivially_copy_constructible<FunctionRef<int(int)>>::value, "");
35 static_assert(
36 std::is_trivially_move_constructible<FunctionRef<int(int)>>::value, "");
37 static_assert(
38 std::is_trivially_constructible<
39 FunctionRef<int(int)>,
40 FunctionRef<int(int)>&>::value,
41 "");
42 static_assert(
43 std::is_trivially_copy_assignable<FunctionRef<int(int)>>::value, "");
44 static_assert(
45 std::is_trivially_move_assignable<FunctionRef<int(int)>>::value, "");
46 static_assert(
47 std::is_trivially_assignable<
48 FunctionRef<int(int)>,
49 FunctionRef<int(int)>&>::value,
50 "");
51#endif
52 static_assert(
53 std::is_nothrow_copy_constructible<FunctionRef<int(int)>>::value, "");
54 static_assert(
55 std::is_nothrow_move_constructible<FunctionRef<int(int)>>::value, "");
56 static_assert(
57 std::is_nothrow_constructible<
58 FunctionRef<int(int)>,
59 FunctionRef<int(int)>&>::value,
60 "");
61 static_assert(
62 std::is_nothrow_copy_assignable<FunctionRef<int(int)>>::value, "");
63 static_assert(
64 std::is_nothrow_move_assignable<FunctionRef<int(int)>>::value, "");
65 static_assert(
66 std::is_nothrow_assignable<
67 FunctionRef<int(int)>,
68 FunctionRef<int(int)>&>::value,
69 "");
70}
71
72TEST(FunctionRef, Simple) {
73 int x = 1000;
74 auto lambda = [&x](int v) { return x += v; };
75
76 FunctionRef<int(int)> fref = lambda;
77 EXPECT_EQ(1005, fref(5));
78 EXPECT_EQ(1011, fref(6));
79 EXPECT_EQ(1018, fref(7));
80
81 FunctionRef<int(int)> const cfref = lambda;
82 EXPECT_EQ(1023, cfref(5));
83 EXPECT_EQ(1029, cfref(6));
84 EXPECT_EQ(1036, cfref(7));
85
86 auto const& clambda = lambda;
87
88 FunctionRef<int(int)> fcref = clambda;
89 EXPECT_EQ(1041, fcref(5));
90 EXPECT_EQ(1047, fcref(6));
91 EXPECT_EQ(1054, fcref(7));
92
93 FunctionRef<int(int)> const cfcref = clambda;
94 EXPECT_EQ(1059, cfcref(5));
95 EXPECT_EQ(1065, cfcref(6));
96 EXPECT_EQ(1072, cfcref(7));
97}
98
99TEST(FunctionRef, FunctionPtr) {
100 int (*funcptr)(int) = [](int v) { return v * v; };
101
102 FunctionRef<int(int)> fref = funcptr;
103 EXPECT_EQ(100, fref(10));
104 EXPECT_EQ(121, fref(11));
105
106 FunctionRef<int(int)> const cfref = funcptr;
107 EXPECT_EQ(100, cfref(10));
108 EXPECT_EQ(121, cfref(11));
109}
110
111TEST(FunctionRef, OverloadedFunctor) {
112 struct OverloadedFunctor {
113 // variant 1
114 int operator()(int x) {
115 return 100 + 1 * x;
116 }
117
118 // variant 2 (const-overload of v1)
119 int operator()(int x) const {
120 return 100 + 2 * x;
121 }
122
123 // variant 3
124 int operator()(int x, int) {
125 return 100 + 3 * x;
126 }
127
128 // variant 4 (const-overload of v3)
129 int operator()(int x, int) const {
130 return 100 + 4 * x;
131 }
132
133 // variant 5 (non-const, has no const-overload)
134 int operator()(int x, char const*) {
135 return 100 + 5 * x;
136 }
137
138 // variant 6 (const only)
139 int operator()(int x, std::vector<int> const&) const {
140 return 100 + 6 * x;
141 }
142 };
143 OverloadedFunctor of;
144 auto const& cof = of;
145
146 FunctionRef<int(int)> variant1 = of;
147 EXPECT_EQ(100 + 1 * 15, variant1(15));
148 FunctionRef<int(int)> const cvariant1 = of;
149 EXPECT_EQ(100 + 1 * 15, cvariant1(15));
150
151 FunctionRef<int(int)> variant2 = cof;
152 EXPECT_EQ(100 + 2 * 16, variant2(16));
153 FunctionRef<int(int)> const cvariant2 = cof;
154 EXPECT_EQ(100 + 2 * 16, cvariant2(16));
155
156 FunctionRef<int(int, int)> variant3 = of;
157 EXPECT_EQ(100 + 3 * 17, variant3(17, 0));
158 FunctionRef<int(int, int)> const cvariant3 = of;
159 EXPECT_EQ(100 + 3 * 17, cvariant3(17, 0));
160
161 FunctionRef<int(int, int)> variant4 = cof;
162 EXPECT_EQ(100 + 4 * 18, variant4(18, 0));
163 FunctionRef<int(int, int)> const cvariant4 = cof;
164 EXPECT_EQ(100 + 4 * 18, cvariant4(18, 0));
165
166 FunctionRef<int(int, char const*)> variant5 = of;
167 EXPECT_EQ(100 + 5 * 19, variant5(19, "foo"));
168 FunctionRef<int(int, char const*)> const cvariant5 = of;
169 EXPECT_EQ(100 + 5 * 19, cvariant5(19, "foo"));
170
171 FunctionRef<int(int, std::vector<int> const&)> variant6 = of;
172 EXPECT_EQ(100 + 6 * 20, variant6(20, {}));
173 EXPECT_EQ(100 + 6 * 20, variant6(20, {1, 2, 3}));
174 FunctionRef<int(int, std::vector<int> const&)> const cvariant6 = of;
175 EXPECT_EQ(100 + 6 * 20, cvariant6(20, {}));
176 EXPECT_EQ(100 + 6 * 20, cvariant6(20, {1, 2, 3}));
177
178 FunctionRef<int(int, std::vector<int> const&)> variant6const = cof;
179 EXPECT_EQ(100 + 6 * 21, variant6const(21, {}));
180 FunctionRef<int(int, std::vector<int> const&)> const cvariant6const = cof;
181 EXPECT_EQ(100 + 6 * 21, cvariant6const(21, {}));
182}
183
184TEST(FunctionRef, DefaultConstructAndAssign) {
185 FunctionRef<int(int, int)> fref;
186
187 EXPECT_FALSE(fref);
188 EXPECT_THROW(fref(1, 2), std::bad_function_call);
189
190 int (*func)(int, int) = [](int x, int y) { return 10 * x + y; };
191 fref = func;
192
193 EXPECT_TRUE(fref);
194 EXPECT_EQ(42, fref(4, 2));
195}
196
197template <typename ValueType>
198class ForEach {
199 public:
200 template <typename InputIterator>
201 ForEach(InputIterator begin, InputIterator end)
202 : func_([begin, end](FunctionRef<void(ValueType)> f) {
203 for (auto it = begin; it != end; ++it) {
204 f(*it);
205 }
206 }) {}
207
208 void operator()(FunctionRef<void(ValueType)> f) const {
209 func_(f);
210 }
211
212 private:
213 Function<void(FunctionRef<void(ValueType)>) const> const func_;
214};
215
216TEST(FunctionRef, ForEach) {
217 std::list<int> s{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
218
219 int sum = 0;
220
221 ForEach<int> fe{s.begin(), s.end()};
222
223 fe([&](int x) { sum += x; });
224
225 EXPECT_EQ(55, sum);
226}
227