Try::tryGetExceptionObject
[folly.git] / folly / test / TryTest.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 <folly/Try.h>
18
19 #include <glog/logging.h>
20
21 #include <folly/Memory.h>
22 #include <folly/portability/GTest.h>
23
24 using namespace folly;
25
26 TEST(Try, basic) {
27   class A {
28    public:
29     A(int x) : x_(x) {}
30
31     int x() const {
32       return x_;
33     }
34    private:
35     int x_;
36   };
37
38   A a(5);
39   Try<A> t_a(std::move(a));
40
41   Try<Unit> t_void;
42
43   EXPECT_EQ(5, t_a.value().x());
44 }
45
46 // Make sure we can copy Trys for copyable types
47 TEST(Try, copy) {
48   Try<int> t;
49   auto t2 = t;
50 }
51
52 // But don't choke on move-only types
53 TEST(Try, moveOnly) {
54   Try<std::unique_ptr<int>> t;
55   std::vector<Try<std::unique_ptr<int>>> v;
56   v.reserve(10);
57 }
58
59 TEST(Try, makeTryWith) {
60   auto func = []() {
61     return std::make_unique<int>(1);
62   };
63
64   auto result = makeTryWith(func);
65   EXPECT_TRUE(result.hasValue());
66   EXPECT_EQ(*result.value(), 1);
67 }
68
69 TEST(Try, makeTryWithThrow) {
70   auto func = []() -> std::unique_ptr<int> {
71     throw std::runtime_error("Runtime");
72   };
73
74   auto result = makeTryWith(func);
75   EXPECT_TRUE(result.hasException<std::runtime_error>());
76 }
77
78 TEST(Try, makeTryWithVoid) {
79   auto func = []() {
80     return;
81   };
82
83   auto result = makeTryWith(func);
84   EXPECT_TRUE(result.hasValue());
85 }
86
87 TEST(Try, makeTryWithVoidThrow) {
88   auto func = []() {
89     throw std::runtime_error("Runtime");
90   };
91
92   auto result = makeTryWith(func);
93   EXPECT_TRUE(result.hasException<std::runtime_error>());
94 }
95
96 template <typename E>
97 static E* get_exception(std::exception_ptr eptr) {
98   try {
99     std::rethrow_exception(eptr);
100   } catch (E& e) {
101     return &e;
102   } catch (...) {
103     return nullptr;
104   }
105 }
106
107 TEST(Try, tryGetExceptionObject) {
108   auto epexn = std::make_exception_ptr(std::range_error("oops"));
109   auto epnum = std::make_exception_ptr(17);
110
111   auto exn = CHECK_NOTNULL(get_exception<std::range_error>(epexn));
112   auto num = CHECK_NOTNULL(get_exception<int>(epnum));
113
114   {
115     auto t = Try<bool>(true);
116     EXPECT_EQ(nullptr, t.tryGetExceptionObject());
117     EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
118     EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
119   }
120
121   {
122     auto t = Try<bool>(exception_wrapper(epexn, *exn));
123     EXPECT_EQ(exn, t.tryGetExceptionObject());
124     EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
125     EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
126   }
127
128   {
129     auto t = Try<bool>(exception_wrapper(epnum, *num));
130     EXPECT_EQ(nullptr, t.tryGetExceptionObject());
131     EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
132     EXPECT_EQ(num, t.tryGetExceptionObject<int>());
133   }
134
135   {
136     auto t = Try<void>();
137     EXPECT_EQ(nullptr, t.tryGetExceptionObject());
138     EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
139     EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
140   }
141
142   {
143     auto t = Try<void>(exception_wrapper(epexn, *exn));
144     EXPECT_EQ(exn, t.tryGetExceptionObject());
145     EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
146     EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
147   }
148
149   {
150     auto t = Try<void>(exception_wrapper(epnum, *num));
151     EXPECT_EQ(nullptr, t.tryGetExceptionObject());
152     EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
153     EXPECT_EQ(num, t.tryGetExceptionObject<int>());
154   }
155
156   {
157     auto const t = Try<bool>(true);
158     EXPECT_EQ(nullptr, t.tryGetExceptionObject());
159     EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
160     EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
161   }
162
163   {
164     auto const t = Try<bool>(exception_wrapper(epexn, *exn));
165     EXPECT_EQ(exn, t.tryGetExceptionObject());
166     EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
167     EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
168   }
169
170   {
171     auto const t = Try<bool>(exception_wrapper(epnum, *num));
172     EXPECT_EQ(nullptr, t.tryGetExceptionObject());
173     EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
174     EXPECT_EQ(num, t.tryGetExceptionObject<int>());
175   }
176
177   {
178     auto const t = Try<void>();
179     EXPECT_EQ(nullptr, t.tryGetExceptionObject());
180     EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
181     EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
182   }
183
184   {
185     auto const t = Try<void>(exception_wrapper(epexn, *exn));
186     EXPECT_EQ(exn, t.tryGetExceptionObject());
187     EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
188     EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
189   }
190
191   {
192     auto const t = Try<void>(exception_wrapper(epnum, *num));
193     EXPECT_EQ(nullptr, t.tryGetExceptionObject());
194     EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
195     EXPECT_EQ(num, t.tryGetExceptionObject<int>());
196   }
197 }