non-throwing, non-allocating exception_wrapper
[folly.git] / folly / test / PartialTest.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 <memory>
18
19 #include <folly/Function.h>
20 #include <folly/Partial.h>
21
22 #include <folly/portability/GTest.h>
23
24 using folly::partial;
25
26 int add3(int x, int y, int z) {
27   return 100 * x + 10 * y + z;
28 }
29
30 TEST(Partial, Simple) {
31   auto p0 = partial(&add3);
32   EXPECT_EQ(123, p0(1, 2, 3));
33
34   auto p1 = partial(&add3, 2);
35   EXPECT_EQ(234, p1(3, 4));
36
37   auto p2 = partial(&add3, 3, 4);
38   EXPECT_EQ(345, p2(5));
39
40   auto p3 = partial(&add3, 4, 5, 6);
41   EXPECT_EQ(456, p3());
42 }
43
44 struct Foo {
45   int method(int& x, int& y, int& z) {
46     return 1000 + 100 * x + 10 * y + z;
47   }
48   int constMethod(int const& x, int const& y, int const& z) const {
49     return 2000 + 100 * x + 10 * y + z;
50   }
51   int tempMethod(int&& x, int&& y, int&& z) {
52     return 3000 + 100 * x + 10 * y + z;
53   }
54 };
55
56 TEST(Partial, ReferenceArguments) {
57   auto p0 = partial(&Foo::method, Foo{}, 2, 3);
58   int four = 4;
59   EXPECT_EQ(1234, p0(four));
60
61   auto const p1 = partial(&Foo::constMethod, Foo{}, 3, 4);
62   EXPECT_EQ(2345, p1(5));
63
64   auto p2 = partial(&Foo::tempMethod, Foo{}, 4, 5);
65   EXPECT_EQ(3456, std::move(p2)(6));
66 }
67
68 struct RefQualifiers {
69   int operator()(int x, int y, int z) & {
70     return 1000 + 100 * x + 10 * y + z;
71   }
72   int operator()(int x, int y, int z) const& {
73     return 2000 + 100 * x + 10 * y + z;
74   }
75   int operator()(int x, int y, int z) && {
76     return 3000 + 100 * x + 10 * y + z;
77   }
78 };
79
80 TEST(Partial, RefQualifiers) {
81   auto p = partial(RefQualifiers{});
82   auto const& pconst = p;
83
84   EXPECT_EQ(1234, p(2, 3, 4));
85   EXPECT_EQ(2345, pconst(3, 4, 5));
86   EXPECT_EQ(3456, std::move(p)(4, 5, 6));
87 }
88
89 struct RefQualifiers2 {
90   int operator()(int& x, int const& y, int z) & {
91     return 1000 + 100 * x + 10 * y + z;
92   }
93   int operator()(int const& x, int y, int z) const& {
94     return 2000 + 100 * x + 10 * y + z;
95   }
96   int operator()(int&& x, int const& y, int z) && {
97     return 3000 + 100 * x + 10 * y + z;
98   }
99 };
100
101 TEST(Partial, RefQualifiers2) {
102   auto p = partial(RefQualifiers2{}, 9, 8);
103   auto const& pconst = p;
104
105   EXPECT_EQ(1984, p(4));
106   EXPECT_EQ(2985, pconst(5));
107   EXPECT_EQ(3986, std::move(p)(6));
108 }
109
110 std::unique_ptr<int> calc_uptr(std::unique_ptr<int> x, std::unique_ptr<int> y) {
111   *x = 100 * *x + 10 * *y;
112   return x;
113 }
114
115 TEST(Partial, MoveOnly) {
116   auto five = std::make_unique<int>(5);
117   auto six = std::make_unique<int>(6);
118
119   // create a partial object which holds a pointer to the `calc_uptr` function
120   // and a `unique_ptr<int>` for the first argument
121   auto p = partial(&calc_uptr, std::move(five));
122
123   // `five` should be moved out of
124   EXPECT_FALSE(five);
125
126   // call to the partial object as rvalue, which allows the call to consume
127   // captured data (here: the `unique_ptr<int>` storing 5), and pass it
128   // the other `unique_ptr`
129   auto result = std::move(p)(std::move(six));
130
131   // ...which now should be moved out of
132   EXPECT_FALSE(six);
133
134   EXPECT_EQ(560, *result);
135 }
136
137 TEST(Partial, WrapInStdFunction) {
138   auto p1 = partial(&add3, 2);
139   std::function<int(int, int)> func = p1;
140   EXPECT_EQ(234, func(3, 4));
141 }
142
143 TEST(Partial, WrapInFollyFunction) {
144   auto p1 = partial(&add3, 2);
145   folly::Function<int(int, int)> func = p1;
146   EXPECT_EQ(234, func(3, 4));
147 }