2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <folly/Try.h>
19 #include <glog/logging.h>
21 #include <folly/Memory.h>
22 #include <folly/Traits.h>
23 #include <folly/portability/GTest.h>
25 using namespace folly;
31 explicit A(int x) : x_(x) {}
43 Try<A> t_a(std::move(a));
47 EXPECT_EQ(5, t_a.value().x());
51 Try<A> t_a(in_place, 5);
53 EXPECT_EQ(5, t_a.value().x());
56 TEST(Try, in_place_nested) {
57 Try<Try<A>> t_t_a(in_place, in_place, 5);
59 EXPECT_EQ(5, t_t_a.value().value().x());
62 // Make sure we can copy Trys for copyable types
68 // But don't choke on move-only types
70 Try<std::unique_ptr<int>> t;
71 std::vector<Try<std::unique_ptr<int>>> v;
75 TEST(Try, makeTryWith) {
77 return std::make_unique<int>(1);
80 auto result = makeTryWith(func);
81 EXPECT_TRUE(result.hasValue());
82 EXPECT_EQ(*result.value(), 1);
85 TEST(Try, makeTryWithThrow) {
86 auto func = []() -> std::unique_ptr<int> {
87 throw std::runtime_error("Runtime");
90 auto result = makeTryWith(func);
91 EXPECT_TRUE(result.hasException<std::runtime_error>());
94 TEST(Try, makeTryWithVoid) {
99 auto result = makeTryWith(func);
100 EXPECT_TRUE(result.hasValue());
103 TEST(Try, makeTryWithVoidThrow) {
105 throw std::runtime_error("Runtime");
108 auto result = makeTryWith(func);
109 EXPECT_TRUE(result.hasException<std::runtime_error>());
112 TEST(Try, exception) {
113 using ML = exception_wrapper&;
114 using MR = exception_wrapper&&;
115 using CL = exception_wrapper const&;
116 using CR = exception_wrapper const&&;
119 auto obj = Try<int>();
120 using ActualML = decltype(obj.exception());
121 using ActualMR = decltype(std::move(obj).exception());
122 using ActualCL = decltype(as_const(obj).exception());
123 using ActualCR = decltype(std::move(as_const(obj)).exception());
124 EXPECT_TRUE((std::is_same<ML, ActualML>::value));
125 EXPECT_TRUE((std::is_same<MR, ActualMR>::value));
126 EXPECT_TRUE((std::is_same<CL, ActualCL>::value));
127 EXPECT_TRUE((std::is_same<CR, ActualCR>::value));
131 auto obj = Try<int>(3);
132 EXPECT_THROW(obj.exception(), TryException);
133 EXPECT_THROW(std::move(obj).exception(), TryException);
134 EXPECT_THROW(as_const(obj).exception(), TryException);
135 EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
139 auto obj = Try<int>(make_exception_wrapper<int>(-3));
140 EXPECT_EQ(-3, *obj.exception().get_exception<int>());
141 EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
142 EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
143 EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
147 auto obj = Try<void>();
148 using ActualML = decltype(obj.exception());
149 using ActualMR = decltype(std::move(obj).exception());
150 using ActualCL = decltype(as_const(obj).exception());
151 using ActualCR = decltype(std::move(as_const(obj)).exception());
152 EXPECT_TRUE((std::is_same<ML, ActualML>::value));
153 EXPECT_TRUE((std::is_same<MR, ActualMR>::value));
154 EXPECT_TRUE((std::is_same<CL, ActualCL>::value));
155 EXPECT_TRUE((std::is_same<CR, ActualCR>::value));
159 auto obj = Try<void>();
160 EXPECT_THROW(obj.exception(), TryException);
161 EXPECT_THROW(std::move(obj).exception(), TryException);
162 EXPECT_THROW(as_const(obj).exception(), TryException);
163 EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
167 auto obj = Try<void>(make_exception_wrapper<int>(-3));
168 EXPECT_EQ(-3, *obj.exception().get_exception<int>());
169 EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
170 EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
171 EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
175 template <typename E>
176 static E* get_exception(std::exception_ptr eptr) {
178 std::rethrow_exception(eptr);
186 TEST(Try, tryGetExceptionObject) {
187 auto epexn = std::make_exception_ptr(std::range_error("oops"));
188 auto epnum = std::make_exception_ptr(17);
190 auto exn = CHECK_NOTNULL(get_exception<std::range_error>(epexn));
191 auto num = CHECK_NOTNULL(get_exception<int>(epnum));
194 auto t = Try<bool>(true);
195 EXPECT_EQ(nullptr, t.tryGetExceptionObject());
196 EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
197 EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
201 auto t = Try<bool>(exception_wrapper(epexn, *exn));
202 EXPECT_EQ(exn, t.tryGetExceptionObject());
203 EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
204 EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
208 auto t = Try<bool>(exception_wrapper(epnum, *num));
209 EXPECT_EQ(nullptr, t.tryGetExceptionObject());
210 EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
211 EXPECT_EQ(num, t.tryGetExceptionObject<int>());
215 auto t = Try<void>();
216 EXPECT_EQ(nullptr, t.tryGetExceptionObject());
217 EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
218 EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
222 auto t = Try<void>(exception_wrapper(epexn, *exn));
223 EXPECT_EQ(exn, t.tryGetExceptionObject());
224 EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
225 EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
229 auto t = Try<void>(exception_wrapper(epnum, *num));
230 EXPECT_EQ(nullptr, t.tryGetExceptionObject());
231 EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
232 EXPECT_EQ(num, t.tryGetExceptionObject<int>());
236 auto const t = Try<bool>(true);
237 EXPECT_EQ(nullptr, t.tryGetExceptionObject());
238 EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
239 EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
243 auto const t = Try<bool>(exception_wrapper(epexn, *exn));
244 EXPECT_EQ(exn, t.tryGetExceptionObject());
245 EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
246 EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
250 auto const t = Try<bool>(exception_wrapper(epnum, *num));
251 EXPECT_EQ(nullptr, t.tryGetExceptionObject());
252 EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
253 EXPECT_EQ(num, t.tryGetExceptionObject<int>());
257 auto const t = Try<void>();
258 EXPECT_EQ(nullptr, t.tryGetExceptionObject());
259 EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
260 EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
264 auto const t = Try<void>(exception_wrapper(epexn, *exn));
265 EXPECT_EQ(exn, t.tryGetExceptionObject());
266 EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
267 EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
271 auto const t = Try<void>(exception_wrapper(epnum, *num));
272 EXPECT_EQ(nullptr, t.tryGetExceptionObject());
273 EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
274 EXPECT_EQ(num, t.tryGetExceptionObject<int>());
278 TEST(Try, withException) {
279 auto ew = make_exception_wrapper<std::range_error>("oops");
282 auto t = Try<bool>(true);
283 EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
284 EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
285 EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
286 EXPECT_FALSE(t.withException([](std::logic_error&) {}));
290 auto t = Try<bool>(ew);
291 EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
292 EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
293 EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
294 EXPECT_FALSE(t.withException([](std::logic_error&) {}));
298 auto t = Try<void>();
299 EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
300 EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
301 EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
302 EXPECT_FALSE(t.withException([](std::logic_error&) {}));
306 auto t = Try<void>(ew);
307 EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
308 EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
309 EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
310 EXPECT_FALSE(t.withException([](std::logic_error&) {}));
314 auto const t = Try<bool>(true);
315 EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
316 EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
317 EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
318 EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
322 auto const t = Try<bool>(ew);
323 EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
324 EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
325 EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
326 EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
330 auto const t = Try<void>();
331 EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
332 EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
333 EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
334 EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
338 auto const t = Try<void>(ew);
339 EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
340 EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
341 EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
342 EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
346 TEST(Try, TestUnwrapTuple) {
347 auto original = std::make_tuple(Try<int>{1}, Try<int>{2});
348 EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(original));
349 EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(folly::copy(original)));
350 EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(folly::as_const(original)));
353 TEST(Try, TestUnwrapPair) {
354 auto original = std::make_pair(Try<int>{1}, Try<int>{2});
355 EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(original));
356 EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::copy(original)));
357 EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::as_const(original)));
360 TEST(Try, TestUnwrapForward) {
361 using UPtr_t = std::unique_ptr<int>;
362 auto original = std::make_tuple(Try<UPtr_t>{std::make_unique<int>(1)});
363 auto unwrapped = unwrapTryTuple(std::move(original));
364 EXPECT_EQ(*std::get<0>(unwrapped), 1);