Fix copyright lines for Bits.h and move BitsBenchmark.cpp
[folly.git] / folly / test / FunctionRefTest.cpp
1 /*
2  * Copyright 2017 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
22 using folly::Function;
23 using folly::FunctionRef;
24
25 TEST(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
72 TEST(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
99 TEST(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
111 TEST(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
184 TEST(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
197 template <typename ValueType>
198 class 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
216 TEST(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 }