Introducing folly::Function
[folly.git] / folly / test / FunctionTest.cpp
1 /*
2  * Copyright 2016 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 <cstdarg>
18
19 #include <folly/Function.h>
20
21 #include <folly/Memory.h>
22 #include <gtest/gtest.h>
23
24 using folly::FunctionMoveCtor;
25 using folly::Function;
26
27 namespace {
28 int func_int_int_add_25(int x) {
29   return x + 25;
30 }
31 int func_int_int_add_111(int x) {
32   return x + 111;
33 }
34 int func_int_return_987() {
35   return 987;
36 }
37 float floatMult(float a, float b) {
38   return a * b;
39 }
40
41 template <class T, size_t S>
42 struct Functor {
43   std::array<T, S> data = {{0}};
44
45   // Two operator() with different argument types.
46   // The InvokeReference tests use both
47   T const& operator()(size_t index) const {
48     return data[index];
49   }
50   T operator()(size_t index, T const& value) {
51     T oldvalue = data[index];
52     data[index] = value;
53     return oldvalue;
54   }
55 };
56
57 // TEST =====================================================================
58 // NoExceptMovable
59
60 struct MoveMayThrow {
61   bool doThrow{false};
62
63   MoveMayThrow() = default;
64   MoveMayThrow(MoveMayThrow const&) = default;
65   MoveMayThrow& operator=(MoveMayThrow const&) = default;
66   MoveMayThrow(MoveMayThrow&&) noexcept(false) {
67     if (doThrow) {
68       throw std::runtime_error("MoveMayThrow(MoveMayThrow&&)");
69     }
70   }
71   MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) {
72     if (doThrow) {
73       throw std::runtime_error("MoveMayThrow::operator=(MoveMayThrow&&)");
74     }
75     return *this;
76   }
77 };
78 }
79
80 TEST(Function, NoExceptMovable) {
81   // callable_noexcept is noexcept-movable
82   auto callable_noexcept = [](int x) { return x + 1; };
83   EXPECT_TRUE(
84       std::is_nothrow_move_constructible<decltype(callable_noexcept)>::value);
85
86   // callable_throw may throw when moved
87   MoveMayThrow mmt;
88   auto callable_throw = [mmt](int x) { return x + 10; };
89   EXPECT_FALSE(
90       std::is_nothrow_move_constructible<decltype(callable_throw)>::value);
91
92   // callable_noexcept can be stored in the Function object
93   Function<int(int), FunctionMoveCtor::NO_THROW> func(callable_noexcept);
94   EXPECT_EQ(func(42), 43);
95   EXPECT_FALSE(func.hasAllocatedMemory());
96   EXPECT_TRUE(std::is_nothrow_move_constructible<decltype(func)>::value);
97
98   // callable_throw cannot be stored in the Function object,
99   // because Function guarantees noexcept-movability, but
100   // callable_throw may throw when moved
101   Function<int(int), FunctionMoveCtor::NO_THROW> func_safe_move(callable_throw);
102   EXPECT_EQ(func_safe_move(42), 52);
103   EXPECT_TRUE(func_safe_move.hasAllocatedMemory());
104   EXPECT_TRUE(
105       std::is_nothrow_move_constructible<decltype(func_safe_move)>::value);
106
107   // callable_throw can be stored in the Function object when
108   // the NoExceptMovable template parameter is set to NO
109   Function<int(int), FunctionMoveCtor::MAY_THROW> func_movethrows(
110       callable_throw);
111   EXPECT_EQ(func_movethrows(42), 52);
112   EXPECT_FALSE(func_movethrows.hasAllocatedMemory());
113   EXPECT_FALSE(
114       std::is_nothrow_move_constructible<decltype(func_movethrows)>::value);
115 }
116
117 // TEST =====================================================================
118 // InvokeFunctor & InvokeReference
119
120 template <FunctionMoveCtor NEM, size_t S>
121 void invoke_functor_test() {
122   Functor<int, 100> func;
123   func(5, 123);
124
125   // Try Functions with differently sized storage areas
126   // S=0: request storage for functors of size 0. The storage size
127   // will be actually larger, because there is a lower limit which
128   // still allows to store at least pointers to functors on the heap.
129   // S=1: request minimum storage size of 0.5x the sizeof(func)
130   // S=2: request sizeof(func)
131   // S=3: request 1.5*sizeof(func)
132   Function<int(size_t) const, NEM, sizeof(func)* S / 2> getter =
133       std::move(func);
134
135   // Function will allocate memory on the heap to store
136   // the functor object if the internal storage area is smaller than
137   // sizeof(func).
138   EXPECT_EQ(getter.hasAllocatedMemory(), S < 2);
139
140   EXPECT_EQ(getter(5), 123);
141 }
142 TEST(Function, InvokeFunctor_T0) {
143   invoke_functor_test<FunctionMoveCtor::MAY_THROW, 0>();
144 }
145 TEST(Function, InvokeFunctor_N0) {
146   invoke_functor_test<FunctionMoveCtor::NO_THROW, 0>();
147 }
148 TEST(Function, InvokeFunctor_T1) {
149   invoke_functor_test<FunctionMoveCtor::MAY_THROW, 1>();
150 }
151 TEST(Function, InvokeFunctor_N1) {
152   invoke_functor_test<FunctionMoveCtor::NO_THROW, 1>();
153 }
154 TEST(Function, InvokeFunctor_T2) {
155   invoke_functor_test<FunctionMoveCtor::MAY_THROW, 2>();
156 }
157 TEST(Function, InvokeFunctor_N2) {
158   invoke_functor_test<FunctionMoveCtor::NO_THROW, 2>();
159 }
160 TEST(Function, InvokeFunctor_T3) {
161   invoke_functor_test<FunctionMoveCtor::MAY_THROW, 3>();
162 }
163 TEST(Function, InvokeFunctor_N3) {
164   invoke_functor_test<FunctionMoveCtor::NO_THROW, 3>();
165 }
166
167 template <FunctionMoveCtor NEM>
168 void invoke_reference_test() {
169   Functor<int, 10> func;
170   func(5, 123);
171
172   // Have Functions for getter and setter, both referencing the
173   // same funtor
174   Function<int(size_t) const, NEM, 0> getter = std::ref(func);
175   Function<int(size_t, int), NEM, 0> setter = std::ref(func);
176
177   EXPECT_EQ(getter(5), 123);
178   EXPECT_EQ(setter(5, 456), 123);
179   EXPECT_EQ(setter(5, 567), 456);
180   EXPECT_EQ(getter(5), 567);
181 }
182 TEST(Function, InvokeReference_T) {
183   invoke_reference_test<FunctionMoveCtor::MAY_THROW>();
184 }
185 TEST(Function, InvokeReference_N) {
186   invoke_reference_test<FunctionMoveCtor::NO_THROW>();
187 }
188
189 // TEST =====================================================================
190 // Emptiness
191
192 template <FunctionMoveCtor NEM>
193 void emptiness_test() {
194   Function<int(int), NEM> f;
195   EXPECT_EQ(f, nullptr);
196   EXPECT_EQ(nullptr, f);
197   EXPECT_FALSE(f);
198   EXPECT_THROW(f(98), std::bad_function_call);
199
200   Function<int(int), NEM> g([](int x) { return x + 1; });
201   EXPECT_NE(g, nullptr);
202   EXPECT_NE(nullptr, g);
203   EXPECT_TRUE(g);
204   EXPECT_EQ(g(99), 100);
205
206   Function<int(int), NEM> h(&func_int_int_add_25);
207   EXPECT_NE(h, nullptr);
208   EXPECT_NE(nullptr, h);
209   EXPECT_TRUE(h);
210   EXPECT_EQ(h(100), 125);
211
212   h = {};
213   EXPECT_EQ(h, nullptr);
214   EXPECT_EQ(nullptr, h);
215   EXPECT_FALSE(h);
216   EXPECT_THROW(h(101), std::bad_function_call);
217 }
218
219 TEST(Function, Emptiness_T) {
220   emptiness_test<FunctionMoveCtor::MAY_THROW>();
221 }
222 TEST(Function, Emptiness_N) {
223   emptiness_test<FunctionMoveCtor::NO_THROW>();
224 }
225
226 // TEST =====================================================================
227 // Types
228
229 TEST(Function, Types) {
230   EXPECT_TRUE((
231       !std::is_base_of<std::unary_function<int, int>, Function<int()>>::value));
232   EXPECT_TRUE(
233       (!std::is_base_of<std::binary_function<int, int, int>, Function<int()>>::
234            value));
235   EXPECT_TRUE((std::is_same<Function<int()>::ResultType, int>::value));
236
237   EXPECT_TRUE((
238       std::is_base_of<std::unary_function<int, double>, Function<double(int)>>::
239           value));
240   EXPECT_TRUE((!std::is_base_of<
241                std::binary_function<int, int, double>,
242                Function<double(int)>>::value));
243   EXPECT_TRUE((std::is_same<Function<double(int)>::ResultType, double>::value));
244   EXPECT_TRUE(
245       (std::is_same<Function<double(int)>::result_type, double>::value));
246   EXPECT_TRUE((std::is_same<Function<double(int)>::argument_type, int>::value));
247
248   EXPECT_TRUE((!std::is_base_of<
249                std::unary_function<int, double>,
250                Function<double(int, char)>>::value));
251   EXPECT_TRUE((std::is_base_of<
252                std::binary_function<int, char, double>,
253                Function<double(int, char)>>::value));
254   EXPECT_TRUE(
255       (std::is_same<Function<double(int, char)>::ResultType, double>::value));
256   EXPECT_TRUE(
257       (std::is_same<Function<double(int, char)>::result_type, double>::value));
258   EXPECT_TRUE(
259       (std::is_same<Function<double(int, char)>::first_argument_type, int>::
260            value));
261   EXPECT_TRUE(
262       (std::is_same<Function<double(int, char)>::second_argument_type, char>::
263            value));
264 }
265
266 // TEST =====================================================================
267 // Swap
268
269 template <FunctionMoveCtor NEM1, FunctionMoveCtor NEM2>
270 void swap_test() {
271   Function<int(int), NEM1> mf1(func_int_int_add_25);
272   Function<int(int), NEM2> mf2(func_int_int_add_111);
273
274   EXPECT_EQ(mf1(100), 125);
275   EXPECT_EQ(mf2(100), 211);
276
277   mf1.swap(mf2);
278
279   EXPECT_EQ(mf2(100), 125);
280   EXPECT_EQ(mf1(100), 211);
281
282   Function<int(int)> mf3(nullptr);
283   EXPECT_EQ(mf3, nullptr);
284
285   mf1.swap(mf3);
286
287   EXPECT_EQ(mf3(100), 211);
288   EXPECT_EQ(mf1, nullptr);
289
290   Function<int(int)> mf4([](int x) { return x + 222; });
291   EXPECT_EQ(mf4(100), 322);
292
293   mf4.swap(mf3);
294   EXPECT_EQ(mf4(100), 211);
295   EXPECT_EQ(mf3(100), 322);
296
297   mf3.swap(mf1);
298   EXPECT_EQ(mf3, nullptr);
299   EXPECT_EQ(mf1(100), 322);
300 }
301 TEST(Function, Swap_TT) {
302   swap_test<FunctionMoveCtor::MAY_THROW, FunctionMoveCtor::MAY_THROW>();
303 }
304 TEST(Function, Swap_TN) {
305   swap_test<FunctionMoveCtor::MAY_THROW, FunctionMoveCtor::NO_THROW>();
306 }
307 TEST(Function, Swap_NT) {
308   swap_test<FunctionMoveCtor::NO_THROW, FunctionMoveCtor::MAY_THROW>();
309 }
310 TEST(Function, Swap_NN) {
311   swap_test<FunctionMoveCtor::NO_THROW, FunctionMoveCtor::NO_THROW>();
312 }
313
314 // TEST =====================================================================
315 // Bind
316
317 template <FunctionMoveCtor NEM>
318 void bind_test() {
319   Function<float(float, float), NEM> fnc = floatMult;
320   auto task = std::bind(std::move(fnc), 2.f, 4.f);
321   EXPECT_THROW(fnc(0, 0), std::bad_function_call);
322   EXPECT_EQ(task(), 8);
323   auto task2(std::move(task));
324   EXPECT_THROW(task(), std::bad_function_call);
325   EXPECT_EQ(task2(), 8);
326 }
327 TEST(Function, Bind_T) {
328   bind_test<FunctionMoveCtor::MAY_THROW>();
329 }
330 TEST(Function, Bind_N) {
331   bind_test<FunctionMoveCtor::NO_THROW>();
332 }
333
334 // TEST =====================================================================
335 // NonCopyableLambda
336
337 template <FunctionMoveCtor NEM, size_t S>
338 void non_copyable_lambda_test() {
339   auto unique_ptr_int = folly::make_unique<int>(900);
340   EXPECT_EQ(*unique_ptr_int, 900);
341
342   char fooData[64] = {0};
343   EXPECT_EQ(fooData[0], 0); // suppress gcc warning about fooData not being used
344
345   auto functor = std::bind(
346       [fooData](std::unique_ptr<int>& up) mutable { return ++*up; },
347       std::move(unique_ptr_int));
348
349   EXPECT_EQ(functor(), 901);
350
351   Function<int(void), NEM, sizeof(functor)* S / 2> func = std::move(functor);
352   EXPECT_EQ(
353       func.hasAllocatedMemory(),
354       S < 2 || (NEM == FunctionMoveCtor::NO_THROW &&
355                 !std::is_nothrow_move_constructible<decltype(functor)>::value));
356
357   EXPECT_EQ(func(), 902);
358 }
359 TEST(Function, NonCopyableLambda_T0) {
360   non_copyable_lambda_test<FunctionMoveCtor::MAY_THROW, 0>();
361 }
362 TEST(Function, NonCopyableLambda_N0) {
363   non_copyable_lambda_test<FunctionMoveCtor::NO_THROW, 0>();
364 }
365 TEST(Function, NonCopyableLambda_T1) {
366   non_copyable_lambda_test<FunctionMoveCtor::MAY_THROW, 1>();
367 }
368 TEST(Function, NonCopyableLambda_N1) {
369   non_copyable_lambda_test<FunctionMoveCtor::NO_THROW, 1>();
370 }
371 TEST(Function, NonCopyableLambda_T2) {
372   non_copyable_lambda_test<FunctionMoveCtor::MAY_THROW, 2>();
373 }
374 TEST(Function, NonCopyableLambda_N2) {
375   non_copyable_lambda_test<FunctionMoveCtor::NO_THROW, 2>();
376 }
377 TEST(Function, NonCopyableLambda_T3) {
378   non_copyable_lambda_test<FunctionMoveCtor::MAY_THROW, 3>();
379 }
380 TEST(Function, NonCopyableLambda_N3) {
381   non_copyable_lambda_test<FunctionMoveCtor::NO_THROW, 3>();
382 }
383
384 // TEST =====================================================================
385 // Downsize
386
387 template <FunctionMoveCtor NEM>
388 void downsize_test() {
389   Functor<int, 10> functor;
390
391   // set element 3
392   functor(3, 123);
393   EXPECT_EQ(functor(3), 123);
394
395   // Function with large callable storage area (twice the size of
396   // the functor)
397   Function<int(size_t, int), NEM, sizeof(functor)* 2> func2x =
398       std::move(functor);
399   EXPECT_FALSE(func2x.hasAllocatedMemory());
400   EXPECT_EQ(func2x(3, 200), 123);
401   EXPECT_EQ(func2x(3, 201), 200);
402
403   // Function with sufficient callable storage area (equal to
404   // size of the functor)
405   Function<int(size_t, int), NEM, sizeof(functor)> func1x = std::move(func2x);
406   EXPECT_THROW(func2x(0, 0), std::bad_function_call);
407   EXPECT_FALSE(func2x);
408   EXPECT_FALSE(func1x.hasAllocatedMemory());
409   EXPECT_EQ(func1x(3, 202), 201);
410   EXPECT_EQ(func1x(3, 203), 202);
411
412   // Function with minimal callable storage area (functor does
413   // not fit and will be moved to memory on the heap)
414   Function<int(size_t, int), NEM, 0> func0x = std::move(func1x);
415   EXPECT_THROW(func1x(0, 0), std::bad_function_call);
416   EXPECT_FALSE(func1x);
417   EXPECT_TRUE(func0x.hasAllocatedMemory());
418   EXPECT_EQ(func0x(3, 204), 203);
419   EXPECT_EQ(func0x(3, 205), 204);
420
421   // bonus test: move to Function with opposite NoExceptMovable
422   // setting
423   Function<
424       int(size_t, int),
425       NEM == FunctionMoveCtor::NO_THROW ? FunctionMoveCtor::MAY_THROW
426                                         : FunctionMoveCtor::NO_THROW,
427       0>
428       funcnot = std::move(func0x);
429   EXPECT_THROW(func0x(0, 0), std::bad_function_call);
430   EXPECT_FALSE(func0x);
431   EXPECT_TRUE(funcnot.hasAllocatedMemory());
432   EXPECT_EQ(funcnot(3, 206), 205);
433   EXPECT_EQ(funcnot(3, 207), 206);
434 }
435 TEST(Function, Downsize_T) {
436   downsize_test<FunctionMoveCtor::MAY_THROW>();
437 }
438 TEST(Function, Downsize_N) {
439   downsize_test<FunctionMoveCtor::NO_THROW>();
440 }
441
442 // TEST =====================================================================
443 // Refcount
444
445 template <FunctionMoveCtor NEM>
446 void refcount_test() {
447   Functor<int, 100> functor;
448   functor(3, 999);
449   auto shared_int = std::make_shared<int>(100);
450
451   EXPECT_EQ(*shared_int, 100);
452   EXPECT_EQ(shared_int.use_count(), 1);
453
454   Function<int(void), NEM> func1 = [shared_int]() { return ++*shared_int; };
455   EXPECT_EQ(shared_int.use_count(), 2);
456   EXPECT_EQ(func1(), 101);
457   EXPECT_EQ(*shared_int, 101);
458
459   // func2: made to not fit functor.
460   Function<int(void), NEM, sizeof(functor) / 2> func2 = std::move(func1);
461   EXPECT_THROW(func1(), std::bad_function_call);
462   EXPECT_EQ(shared_int.use_count(), 2);
463   EXPECT_FALSE(func1);
464   EXPECT_EQ(func2(), 102);
465   EXPECT_EQ(*shared_int, 102);
466
467   func2 = [shared_int]() { return ++*shared_int; };
468   EXPECT_EQ(shared_int.use_count(), 2);
469   EXPECT_EQ(func2(), 103);
470   EXPECT_EQ(*shared_int, 103);
471
472   // We set func2 to a lambda that captures 'functor', which forces it on
473   // the heap
474   func2 = [functor]() { return functor(3); };
475   EXPECT_TRUE(func2.hasAllocatedMemory());
476   EXPECT_EQ(func2(), 999);
477   EXPECT_EQ(shared_int.use_count(), 1);
478   EXPECT_EQ(*shared_int, 103);
479
480   func2 = [shared_int]() { return ++*shared_int; };
481   EXPECT_EQ(shared_int.use_count(), 2);
482   EXPECT_EQ(func2(), 104);
483   EXPECT_EQ(*shared_int, 104);
484
485   // We set func2 to function pointer, which always fits into the
486   // Function object and is no-except-movable
487   func2 = &func_int_return_987;
488   EXPECT_FALSE(func2.hasAllocatedMemory());
489   EXPECT_EQ(func2(), 987);
490   EXPECT_EQ(shared_int.use_count(), 1);
491   EXPECT_EQ(*shared_int, 104);
492 }
493 TEST(Function, Refcount_T) {
494   refcount_test<FunctionMoveCtor::MAY_THROW>();
495 }
496 TEST(Function, Refcount_N) {
497   refcount_test<FunctionMoveCtor::NO_THROW>();
498 }
499
500 // TEST =====================================================================
501 // Target
502
503 template <FunctionMoveCtor NEM>
504 void target_test() {
505   std::function<int(int)> func = [](int x) { return x + 25; };
506   EXPECT_EQ(func(100), 125);
507
508   Function<int(int), NEM> ufunc = std::move(func);
509   EXPECT_THROW(func(0), std::bad_function_call);
510   EXPECT_EQ(ufunc(200), 225);
511
512   EXPECT_EQ(ufunc.target_type(), typeid(std::function<int(int)>));
513
514   EXPECT_FALSE(ufunc.template target<int>());
515   EXPECT_FALSE(ufunc.template target<std::function<void(void)>>());
516
517   std::function<int(int)>& ufunc_target =
518       *ufunc.template target<std::function<int(int)>>();
519
520   EXPECT_EQ(ufunc_target(300), 325);
521 }
522
523 TEST(Function, Target_T) {
524   target_test<FunctionMoveCtor::MAY_THROW>();
525 }
526 TEST(Function, Target_N) {
527   target_test<FunctionMoveCtor::NO_THROW>();
528 }
529
530 // TEST =====================================================================
531 // OverloadedFunctor
532
533 TEST(Function, OverloadedFunctor) {
534   struct OverloadedFunctor {
535     // variant 1
536     int operator()(int x) {
537       return 100 + 1 * x;
538     }
539
540     // variant 2 (const-overload of v1)
541     int operator()(int x) const {
542       return 100 + 2 * x;
543     }
544
545     // variant 3
546     int operator()(int x, int) {
547       return 100 + 3 * x;
548     }
549
550     // variant 4 (const-overload of v3)
551     int operator()(int x, int) const {
552       return 100 + 4 * x;
553     }
554
555     // variant 5 (non-const, has no const-overload)
556     int operator()(int x, char const*) {
557       return 100 + 5 * x;
558     }
559
560     // variant 6 (const only)
561     int operator()(int x, std::vector<int> const&) const {
562       return 100 + 6 * x;
563     }
564   };
565   OverloadedFunctor of;
566
567   Function<int(int)> variant1 = of;
568   EXPECT_EQ(variant1(15), 100 + 1 * 15);
569
570   Function<int(int) const> variant2 = of;
571   EXPECT_EQ(variant2(16), 100 + 2 * 16);
572
573   Function<int(int, int)> variant3 = of;
574   EXPECT_EQ(variant3(17, 0), 100 + 3 * 17);
575
576   Function<int(int, int) const> variant4 = of;
577   EXPECT_EQ(variant4(18, 0), 100 + 4 * 18);
578
579   Function<int(int, char const*)> variant5 = of;
580   EXPECT_EQ(variant5(19, "foo"), 100 + 5 * 19);
581
582   Function<int(int, std::vector<int> const&)> variant6 = of;
583   EXPECT_EQ(variant6(20, {}), 100 + 6 * 20);
584   EXPECT_EQ(variant6(20, {1, 2, 3}), 100 + 6 * 20);
585
586   Function<int(int, std::vector<int> const&) const> variant6const = of;
587   EXPECT_EQ(variant6const(21, {}), 100 + 6 * 21);
588
589   // Cast const-functions to non-const and the other way around: if the functor
590   // has both const and non-const operator()s for a given parameter signature,
591   // constructing a Function must select one of them, depending on
592   // whether the function type template parameter is const-qualified or not.
593   // When the const-ness is later changed (by moving the
594   // Function<R(Args...)const> into a Function<R(Args...)> or by
595   // calling the folly::constCastFunction which moves it into a
596   // Function<R(Args...)const>), the Function must still execute
597   // the initially selected function.
598
599   auto variant1_const = folly::constCastFunction(std::move(variant1));
600   EXPECT_THROW(variant1(0), std::bad_function_call);
601   EXPECT_EQ(variant1_const(22), 100 + 1 * 22);
602
603   Function<int(int)> variant2_nonconst = std::move(variant2);
604   EXPECT_THROW(variant2(0), std::bad_function_call);
605   EXPECT_EQ(variant2_nonconst(23), 100 + 2 * 23);
606
607   auto variant3_const = folly::constCastFunction(std::move(variant3));
608   EXPECT_THROW(variant3(0, 0), std::bad_function_call);
609   EXPECT_EQ(variant3_const(24, 0), 100 + 3 * 24);
610
611   Function<int(int, int)> variant4_nonconst = std::move(variant4);
612   EXPECT_THROW(variant4(0, 0), std::bad_function_call);
613   EXPECT_EQ(variant4_nonconst(25, 0), 100 + 4 * 25);
614
615   auto variant5_const = folly::constCastFunction(std::move(variant5));
616   EXPECT_THROW(variant5(0, ""), std::bad_function_call);
617   EXPECT_EQ(variant5_const(26, "foo"), 100 + 5 * 26);
618
619   auto variant6_const = folly::constCastFunction(std::move(variant6));
620   EXPECT_THROW(variant6(0, {}), std::bad_function_call);
621   EXPECT_EQ(variant6_const(27, {}), 100 + 6 * 27);
622
623   Function<int(int, std::vector<int> const&)> variant6const_nonconst =
624       std::move(variant6const);
625   EXPECT_THROW(variant6const(0, {}), std::bad_function_call);
626   EXPECT_EQ(variant6const_nonconst(28, {}), 100 + 6 * 28);
627 }
628
629 // TEST =====================================================================
630 // Lambda
631
632 TEST(Function, Lambda) {
633   // Non-mutable lambdas: can be stored in a non-const...
634   Function<int(int)> func = [](int x) { return 1000 + x; };
635   EXPECT_EQ(func(1), 1001);
636
637   // ...as well as in a const Function
638   Function<int(int) const> func_const = [](int x) { return 2000 + x; };
639   EXPECT_EQ(func_const(1), 2001);
640
641   // Mutable lambda: can only be stored in a const Function:
642   int number = 3000;
643   Function<int()> func_mutable = [number]() mutable { return ++number; };
644   EXPECT_EQ(func_mutable(), 3001);
645   EXPECT_EQ(func_mutable(), 3002);
646
647   // test after const-casting
648
649   Function<int(int) const> func_made_const =
650       folly::constCastFunction(std::move(func));
651   EXPECT_EQ(func_made_const(2), 1002);
652   EXPECT_THROW(func(0), std::bad_function_call);
653
654   Function<int(int)> func_const_made_nonconst = std::move(func_const);
655   EXPECT_EQ(func_const_made_nonconst(2), 2002);
656   EXPECT_THROW(func_const(0), std::bad_function_call);
657
658   Function<int() const> func_mutable_made_const =
659       folly::constCastFunction(std::move(func_mutable));
660   EXPECT_EQ(func_mutable_made_const(), 3003);
661   EXPECT_EQ(func_mutable_made_const(), 3004);
662   EXPECT_THROW(func_mutable(), std::bad_function_call);
663 }
664
665 // TEST =====================================================================
666 // DataMember & MemberFunction
667
668 struct MemberFunc {
669   int x;
670   int getX() const {
671     return x;
672   }
673   void setX(int xx) {
674     x = xx;
675   }
676 };
677
678 TEST(Function, DataMember) {
679   MemberFunc mf;
680   MemberFunc const& cmf = mf;
681   mf.x = 123;
682
683   Function<int(MemberFunc const*)> data_getter1 = &MemberFunc::x;
684   EXPECT_EQ(data_getter1(&cmf), 123);
685   Function<int(MemberFunc*)> data_getter2 = &MemberFunc::x;
686   EXPECT_EQ(data_getter2(&mf), 123);
687   Function<int(MemberFunc const&)> data_getter3 = &MemberFunc::x;
688   EXPECT_EQ(data_getter3(cmf), 123);
689   Function<int(MemberFunc&)> data_getter4 = &MemberFunc::x;
690   EXPECT_EQ(data_getter4(mf), 123);
691 }
692
693 TEST(Function, MemberFunction) {
694   MemberFunc mf;
695   MemberFunc const& cmf = mf;
696   mf.x = 123;
697
698   Function<int(MemberFunc const*)> getter1 = &MemberFunc::getX;
699   EXPECT_EQ(getter1(&cmf), 123);
700   Function<int(MemberFunc*)> getter2 = &MemberFunc::getX;
701   EXPECT_EQ(getter2(&mf), 123);
702   Function<int(MemberFunc const&)> getter3 = &MemberFunc::getX;
703   EXPECT_EQ(getter3(cmf), 123);
704   Function<int(MemberFunc&)> getter4 = &MemberFunc::getX;
705   EXPECT_EQ(getter4(mf), 123);
706
707   Function<void(MemberFunc*, int)> setter1 = &MemberFunc::setX;
708   setter1(&mf, 234);
709   EXPECT_EQ(mf.x, 234);
710
711   Function<void(MemberFunc&, int)> setter2 = &MemberFunc::setX;
712   setter2(mf, 345);
713   EXPECT_EQ(mf.x, 345);
714 }
715
716 // TEST =====================================================================
717 // CaptureCopyMoveCount & ParameterCopyMoveCount
718
719 class CopyMoveTracker {
720  public:
721   struct ConstructorTag {};
722
723   CopyMoveTracker() = delete;
724   explicit CopyMoveTracker(ConstructorTag)
725       : data_(std::make_shared<std::pair<size_t, size_t>>(0, 0)) {}
726
727   CopyMoveTracker(CopyMoveTracker const& o) noexcept : data_(o.data_) {
728     ++data_->first;
729   }
730   CopyMoveTracker& operator=(CopyMoveTracker const& o) noexcept {
731     data_ = o.data_;
732     ++data_->first;
733     return *this;
734   }
735
736   CopyMoveTracker(CopyMoveTracker&& o) noexcept : data_(o.data_) {
737     ++data_->second;
738   }
739   CopyMoveTracker& operator=(CopyMoveTracker&& o) noexcept {
740     data_ = o.data_;
741     ++data_->second;
742     return *this;
743   }
744
745   size_t copyCount() const {
746     return data_->first;
747   }
748   size_t moveCount() const {
749     return data_->second;
750   }
751   size_t refCount() const {
752     return data_.use_count();
753   }
754   void resetCounters() {
755     data_->first = data_->second = 0;
756   }
757
758  private:
759   // copy, move
760   std::shared_ptr<std::pair<size_t, size_t>> data_;
761 };
762
763 TEST(Function, CaptureCopyMoveCount) {
764   // This test checks that no unnecessary copies/moves are made.
765
766   CopyMoveTracker cmt(CopyMoveTracker::ConstructorTag{});
767   EXPECT_EQ(cmt.copyCount(), 0);
768   EXPECT_EQ(cmt.moveCount(), 0);
769   EXPECT_EQ(cmt.refCount(), 1);
770
771   // Move into lambda, move lambda into Function
772   auto lambda1 = [cmt = std::move(cmt)]() {
773     return cmt.moveCount();
774   };
775   Function<size_t(void)> uf1 = std::move(lambda1);
776
777   // Max copies: 0. Max copy+moves: 2.
778   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
779   EXPECT_LE(cmt.copyCount(), 0);
780
781   cmt.resetCounters();
782
783   // Move into lambda, copy lambda into Function
784   auto lambda2 = [cmt = std::move(cmt)]() {
785     return cmt.moveCount();
786   };
787   Function<size_t(void)> uf2 = lambda2;
788
789   // Max copies: 1. Max copy+moves: 2.
790   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
791   EXPECT_LE(cmt.copyCount(), 1);
792
793   // Invoking Function must not make copies/moves of the callable
794   cmt.resetCounters();
795   uf1();
796   uf2();
797   EXPECT_EQ(cmt.copyCount(), 0);
798   EXPECT_EQ(cmt.moveCount(), 0);
799 }
800
801 TEST(Function, ParameterCopyMoveCount) {
802   // This test checks that no unnecessary copies/moves are made.
803
804   CopyMoveTracker cmt(CopyMoveTracker::ConstructorTag{});
805   EXPECT_EQ(cmt.copyCount(), 0);
806   EXPECT_EQ(cmt.moveCount(), 0);
807   EXPECT_EQ(cmt.refCount(), 1);
808
809   // pass by value
810   Function<size_t(CopyMoveTracker)> uf1 = [](CopyMoveTracker c) {
811     return c.moveCount();
812   };
813
814   cmt.resetCounters();
815   uf1(cmt);
816   // Max copies: 1. Max copy+moves: 2.
817   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
818   EXPECT_LE(cmt.copyCount(), 1);
819
820   cmt.resetCounters();
821   uf1(std::move(cmt));
822   // Max copies: 1. Max copy+moves: 2.
823   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
824   EXPECT_LE(cmt.copyCount(), 0);
825
826   // pass by reference
827   Function<size_t(CopyMoveTracker&)> uf2 = [](CopyMoveTracker& c) {
828     return c.moveCount();
829   };
830
831   cmt.resetCounters();
832   uf2(cmt);
833   // Max copies: 0. Max copy+moves: 0.
834   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 0);
835   EXPECT_LE(cmt.copyCount(), 0);
836
837   // pass by const reference
838   Function<size_t(CopyMoveTracker const&)> uf3 = [](CopyMoveTracker const& c) {
839     return c.moveCount();
840   };
841
842   cmt.resetCounters();
843   uf3(cmt);
844   // Max copies: 0. Max copy+moves: 0.
845   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 0);
846   EXPECT_LE(cmt.copyCount(), 0);
847
848   // pass by rvalue reference
849   Function<size_t(CopyMoveTracker &&)> uf4 = [](CopyMoveTracker&& c) {
850     return c.moveCount();
851   };
852
853   cmt.resetCounters();
854   uf4(std::move(cmt));
855   // Max copies: 0. Max copy+moves: 0.
856   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 0);
857   EXPECT_LE(cmt.copyCount(), 0);
858 }
859
860 // TEST =====================================================================
861 // CopyMoveThrows
862
863 enum ExceptionType { COPY, MOVE };
864
865 template <ExceptionType ET>
866 class CopyMoveException : public std::runtime_error {
867  public:
868   using std::runtime_error::runtime_error;
869 };
870
871 template <bool CopyThrows, bool MoveThrows>
872 struct CopyMoveThrowsCallable {
873   int allowCopyOperations{0};
874   int allowMoveOperations{0};
875
876   CopyMoveThrowsCallable() = default;
877   CopyMoveThrowsCallable(CopyMoveThrowsCallable const& o) noexcept(
878       !CopyThrows) {
879     *this = o;
880   }
881   CopyMoveThrowsCallable& operator=(CopyMoveThrowsCallable const& o) noexcept(
882       !CopyThrows) {
883     allowCopyOperations = o.allowCopyOperations;
884     allowMoveOperations = o.allowMoveOperations;
885
886     if (allowCopyOperations > 0) {
887       --allowCopyOperations;
888     } else if (CopyThrows) {
889       throw CopyMoveException<COPY>("CopyMoveThrowsCallable copy");
890     }
891     return *this;
892   }
893   CopyMoveThrowsCallable(CopyMoveThrowsCallable&& o) noexcept(!MoveThrows) {
894     *this = std::move(o);
895   }
896   CopyMoveThrowsCallable& operator=(CopyMoveThrowsCallable&& o) noexcept(
897       !MoveThrows) {
898     allowCopyOperations = o.allowCopyOperations;
899     allowMoveOperations = o.allowMoveOperations;
900
901     if (o.allowMoveOperations > 0) {
902       --allowMoveOperations;
903     } else if (MoveThrows) {
904       throw CopyMoveException<MOVE>("CopyMoveThrowsCallable move");
905     }
906     return *this;
907   }
908
909   void operator()() const {}
910 };
911
912 TEST(Function, CopyMoveThrowsCallable) {
913   EXPECT_TRUE((std::is_nothrow_move_constructible<
914                CopyMoveThrowsCallable<false, false>>::value));
915   EXPECT_TRUE((std::is_nothrow_move_constructible<
916                CopyMoveThrowsCallable<true, false>>::value));
917   EXPECT_FALSE((std::is_nothrow_move_constructible<
918                 CopyMoveThrowsCallable<false, true>>::value));
919   EXPECT_FALSE((std::is_nothrow_move_constructible<
920                 CopyMoveThrowsCallable<true, true>>::value));
921
922   EXPECT_TRUE((std::is_nothrow_copy_constructible<
923                CopyMoveThrowsCallable<false, false>>::value));
924   EXPECT_FALSE((std::is_nothrow_copy_constructible<
925                 CopyMoveThrowsCallable<true, false>>::value));
926   EXPECT_TRUE((std::is_nothrow_copy_constructible<
927                CopyMoveThrowsCallable<false, true>>::value));
928   EXPECT_FALSE((std::is_nothrow_copy_constructible<
929                 CopyMoveThrowsCallable<true, true>>::value));
930 }
931
932 template <FunctionMoveCtor NEM, bool CopyThrows, bool MoveThrows>
933 void copy_and_move_throws_test() {
934   CopyMoveThrowsCallable<CopyThrows, MoveThrows> c;
935   Function<void(void), NEM> uf;
936
937   if (CopyThrows) {
938     EXPECT_THROW((uf = c), CopyMoveException<COPY>);
939   } else {
940     EXPECT_NO_THROW((uf = c));
941   }
942
943   if (MoveThrows) {
944     EXPECT_THROW((uf = std::move(c)), CopyMoveException<MOVE>);
945   } else {
946     EXPECT_NO_THROW((uf = std::move(c)));
947   }
948
949   c.allowMoveOperations = 1;
950   uf = std::move(c);
951   if (NEM == FunctionMoveCtor::MAY_THROW && MoveThrows) {
952     Function<void(void), NEM> uf2;
953     EXPECT_THROW((uf2 = std::move(uf)), CopyMoveException<MOVE>);
954   } else {
955     Function<void(void), NEM> uf2;
956     EXPECT_NO_THROW((uf2 = std::move(uf)));
957   }
958
959   c.allowMoveOperations = 0;
960   c.allowCopyOperations = 1;
961   uf = c;
962   if (NEM == FunctionMoveCtor::MAY_THROW && MoveThrows) {
963     Function<void(void), NEM> uf2;
964     EXPECT_THROW((uf2 = std::move(uf)), CopyMoveException<MOVE>);
965   } else {
966     Function<void(void), NEM> uf2;
967     EXPECT_NO_THROW((uf2 = std::move(uf)));
968   }
969 }
970
971 TEST(Function, CopyAndMoveThrows_TNN) {
972   copy_and_move_throws_test<FunctionMoveCtor::MAY_THROW, false, false>();
973 }
974
975 TEST(Function, CopyAndMoveThrows_NNN) {
976   copy_and_move_throws_test<FunctionMoveCtor::NO_THROW, false, false>();
977 }
978
979 TEST(Function, CopyAndMoveThrows_TTN) {
980   copy_and_move_throws_test<FunctionMoveCtor::MAY_THROW, true, false>();
981 }
982
983 TEST(Function, CopyAndMoveThrows_NTN) {
984   copy_and_move_throws_test<FunctionMoveCtor::NO_THROW, true, false>();
985 }
986
987 TEST(Function, CopyAndMoveThrows_TNT) {
988   copy_and_move_throws_test<FunctionMoveCtor::MAY_THROW, false, true>();
989 }
990
991 TEST(Function, CopyAndMoveThrows_NNT) {
992   copy_and_move_throws_test<FunctionMoveCtor::NO_THROW, false, true>();
993 }
994
995 TEST(Function, CopyAndMoveThrows_TTT) {
996   copy_and_move_throws_test<FunctionMoveCtor::MAY_THROW, true, true>();
997 }
998
999 TEST(Function, CopyAndMoveThrows_NTT) {
1000   copy_and_move_throws_test<FunctionMoveCtor::NO_THROW, true, true>();
1001 }
1002
1003 // TEST =====================================================================
1004 // VariadicTemplate & VariadicArguments
1005
1006 struct VariadicTemplateSum {
1007   int operator()() const {
1008     return 0;
1009   }
1010   template <class... Args>
1011   int operator()(int x, Args... args) const {
1012     return x + (*this)(args...);
1013   }
1014 };
1015
1016 TEST(Function, VariadicTemplate) {
1017   Function<int(int)> uf1 = VariadicTemplateSum();
1018   Function<int(int, int)> uf2 = VariadicTemplateSum();
1019   Function<int(int, int, int)> uf3 = VariadicTemplateSum();
1020
1021   EXPECT_EQ(uf1(66), 66);
1022   EXPECT_EQ(uf2(55, 44), 99);
1023   EXPECT_EQ(uf3(33, 22, 11), 66);
1024 }
1025
1026 struct VariadicArgumentsSum {
1027   int operator()(int count, ...) const {
1028     int result = 0;
1029     va_list args;
1030     va_start(args, count);
1031     for (int i = 0; i < count; ++i) {
1032       result += va_arg(args, int);
1033     }
1034     va_end(args);
1035     return result;
1036   }
1037 };
1038
1039 TEST(Function, VariadicArguments) {
1040   Function<int(int)> uf1 = VariadicArgumentsSum();
1041   Function<int(int, int)> uf2 = VariadicArgumentsSum();
1042   Function<int(int, int, int)> uf3 = VariadicArgumentsSum();
1043
1044   EXPECT_EQ(uf1(0), 0);
1045   EXPECT_EQ(uf2(1, 66), 66);
1046   EXPECT_EQ(uf3(2, 55, 44), 99);
1047 }
1048
1049 // TEST =====================================================================
1050 // SafeCaptureByReference
1051
1052 // A function can use Function const& as a parameter to signal that it
1053 // is safe to pass a lambda that captures local variables by reference.
1054 // It is safe because we know the function called can only invoke the
1055 // Function until it returns. It can't store a copy of the Function
1056 // (because it's not copyable), and it can't move the Function somewhere
1057 // else (because it gets only a const&).
1058
1059 template <typename T>
1060 void for_each(
1061     T const& range,
1062     Function<void(typename T::value_type const&) const> const& func) {
1063   for (auto const& elem : range) {
1064     func(elem);
1065   }
1066 }
1067
1068 TEST(Function, SafeCaptureByReference) {
1069   std::vector<int> const vec = {20, 30, 40, 2, 3, 4, 200, 300, 400};
1070
1071   int sum = 0;
1072
1073   // for_each's second parameter is of type Function<...> const&.
1074   // Hence we know we can safely pass it a lambda that references local
1075   // variables. There is no way the reference to x will be stored anywhere.
1076   for_each<std::vector<int>>(vec, [&sum](int x) { sum += x; });
1077
1078   // gcc versions before 4.9 cannot deduce the type T in the above call
1079   // to for_each. Modern compiler versions can compile the following line:
1080   //   for_each(vec, [&sum](int x) { sum += x; });
1081
1082   EXPECT_EQ(sum, 999);
1083 }