proxygen
FunctionRefTest.cpp
Go to the documentation of this file.
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>
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 
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) {
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:
214 };
215 
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 }
Definition: InvokeTest.cpp:58
auto f
std::atomic< int64_t > sum(0)
auto v
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
const int x
A reference wrapper for callable objects.
Definition: Function.h:893
auto begin(TestAdlIterable &instance)
Definition: ForeachTest.cpp:56
ForEach(InputIterator begin, InputIterator end)
TEST(FunctionRef, Traits)
auto end(TestAdlIterable &instance)
Definition: ForeachTest.cpp:62
static const char *const value
Definition: Conv.cpp:50
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
static set< string > s
Definition: InvokeTest.cpp:65
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
void operator()(FunctionRef< void(ValueType)> f) const