TryTest.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. /*
  2. * Copyright 2014-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. #include <folly/Try.h>
  17. #include <glog/logging.h>
  18. #include <folly/Memory.h>
  19. #include <folly/Traits.h>
  20. #include <folly/portability/GTest.h>
  21. using namespace folly;
  22. namespace {
  23. class A {
  24. public:
  25. explicit A(int x) : x_(x) {}
  26. int x() const {
  27. return x_;
  28. }
  29. private:
  30. int x_;
  31. };
  32. template <bool Nothrow>
  33. class HasCtors {
  34. public:
  35. explicit HasCtors(int) noexcept(Nothrow) {}
  36. HasCtors(HasCtors&&) noexcept(Nothrow) {}
  37. HasCtors& operator=(HasCtors&&) noexcept(Nothrow) {}
  38. HasCtors(HasCtors const&) noexcept(Nothrow) {}
  39. HasCtors& operator=(HasCtors const&) noexcept(Nothrow) {}
  40. };
  41. class MoveConstructOnly {
  42. public:
  43. MoveConstructOnly() = default;
  44. MoveConstructOnly(const MoveConstructOnly&) = delete;
  45. MoveConstructOnly(MoveConstructOnly&&) = default;
  46. };
  47. class MutableContainer {
  48. public:
  49. mutable MoveConstructOnly val;
  50. };
  51. } // namespace
  52. TEST(Try, basic) {
  53. A a(5);
  54. Try<A> t_a(std::move(a));
  55. Try<Unit> t_void;
  56. EXPECT_EQ(5, t_a.value().x());
  57. }
  58. TEST(Try, in_place) {
  59. Try<A> t_a(in_place, 5);
  60. EXPECT_EQ(5, t_a.value().x());
  61. }
  62. TEST(Try, in_place_nested) {
  63. Try<Try<A>> t_t_a(in_place, in_place, 5);
  64. EXPECT_EQ(5, t_t_a.value().value().x());
  65. }
  66. TEST(Try, assignmentWithThrowingCopyConstructor) {
  67. struct MyException : std::exception {};
  68. struct ThrowingCopyConstructor {
  69. int& counter_;
  70. explicit ThrowingCopyConstructor(int& counter) : counter_(counter) {
  71. ++counter_;
  72. }
  73. [[noreturn]] ThrowingCopyConstructor(
  74. const ThrowingCopyConstructor& other) noexcept(false)
  75. : counter_(other.counter_) {
  76. throw MyException{};
  77. }
  78. ThrowingCopyConstructor& operator=(const ThrowingCopyConstructor&) = delete;
  79. ~ThrowingCopyConstructor() {
  80. --counter_;
  81. }
  82. };
  83. int counter = 0;
  84. {
  85. Try<ThrowingCopyConstructor> t1{in_place, counter};
  86. Try<ThrowingCopyConstructor> t2{in_place, counter};
  87. EXPECT_EQ(2, counter);
  88. EXPECT_THROW(t2 = t1, MyException);
  89. EXPECT_EQ(1, counter);
  90. EXPECT_FALSE(t2.hasValue());
  91. EXPECT_TRUE(t1.hasValue());
  92. }
  93. EXPECT_EQ(0, counter);
  94. {
  95. Try<ThrowingCopyConstructor> t1{in_place, counter};
  96. Try<ThrowingCopyConstructor> t2;
  97. EXPECT_EQ(1, counter);
  98. EXPECT_THROW(t2 = t1, MyException);
  99. EXPECT_EQ(1, counter);
  100. EXPECT_FALSE(t2.hasValue());
  101. EXPECT_TRUE(t1.hasValue());
  102. }
  103. EXPECT_EQ(0, counter);
  104. }
  105. TEST(Try, assignmentWithThrowingMoveConstructor) {
  106. struct MyException : std::exception {};
  107. struct ThrowingMoveConstructor {
  108. int& counter_;
  109. explicit ThrowingMoveConstructor(int& counter) : counter_(counter) {
  110. ++counter_;
  111. }
  112. [[noreturn]] ThrowingMoveConstructor(
  113. ThrowingMoveConstructor&& other) noexcept(false)
  114. : counter_(other.counter_) {
  115. throw MyException{};
  116. }
  117. ThrowingMoveConstructor& operator=(ThrowingMoveConstructor&&) = delete;
  118. ~ThrowingMoveConstructor() {
  119. --counter_;
  120. }
  121. };
  122. int counter = 0;
  123. {
  124. Try<ThrowingMoveConstructor> t1{in_place, counter};
  125. Try<ThrowingMoveConstructor> t2{in_place, counter};
  126. EXPECT_EQ(2, counter);
  127. EXPECT_THROW(t2 = std::move(t1), MyException);
  128. EXPECT_EQ(1, counter);
  129. EXPECT_FALSE(t2.hasValue());
  130. EXPECT_TRUE(t1.hasValue());
  131. }
  132. EXPECT_EQ(0, counter);
  133. {
  134. Try<ThrowingMoveConstructor> t1{in_place, counter};
  135. Try<ThrowingMoveConstructor> t2;
  136. EXPECT_EQ(1, counter);
  137. EXPECT_THROW(t2 = std::move(t1), MyException);
  138. EXPECT_EQ(1, counter);
  139. EXPECT_FALSE(t2.hasValue());
  140. EXPECT_TRUE(t1.hasValue());
  141. }
  142. EXPECT_EQ(0, counter);
  143. }
  144. TEST(Try, emplace) {
  145. Try<A> t;
  146. A& t_a = t.emplace(10);
  147. EXPECT_TRUE(t.hasValue());
  148. EXPECT_EQ(t_a.x(), 10);
  149. }
  150. TEST(Try, emplaceWithThrowingConstructor) {
  151. struct MyException : std::exception {};
  152. struct ThrowingConstructor {
  153. explicit ThrowingConstructor(bool shouldThrow) {
  154. if (shouldThrow) {
  155. throw MyException{};
  156. }
  157. }
  158. };
  159. {
  160. // Try constructing from empty state to new value and constructor throws.
  161. Try<ThrowingConstructor> t;
  162. EXPECT_FALSE(t.hasValue());
  163. EXPECT_FALSE(t.hasException());
  164. EXPECT_THROW(t.emplace(true), MyException);
  165. EXPECT_FALSE(t.hasValue());
  166. EXPECT_FALSE(t.hasException());
  167. }
  168. {
  169. // Initialise to value, then re-emplace with throwing constructor.
  170. // This should reset the object back to empty.
  171. Try<ThrowingConstructor> t{in_place, false};
  172. EXPECT_TRUE(t.hasValue());
  173. EXPECT_THROW(t.emplace(true), MyException);
  174. EXPECT_FALSE(t.hasValue());
  175. EXPECT_FALSE(t.hasException());
  176. }
  177. }
  178. TEST(Try, tryEmplace) {
  179. Try<A> t;
  180. A* a = tryEmplace(t, 10);
  181. EXPECT_EQ(&t.value(), a);
  182. EXPECT_TRUE(t.hasValue());
  183. EXPECT_EQ(10, t.value().x());
  184. }
  185. TEST(Try, tryEmplaceWithThrowingConstructor) {
  186. struct MyException : std::exception {};
  187. struct NonInheritingException {};
  188. struct ThrowingConstructor {
  189. [[noreturn]] ThrowingConstructor() noexcept(false) {
  190. throw NonInheritingException{}; // @nolint
  191. }
  192. explicit ThrowingConstructor(bool shouldThrow) {
  193. if (shouldThrow) {
  194. throw MyException{};
  195. }
  196. }
  197. };
  198. {
  199. Try<ThrowingConstructor> t;
  200. EXPECT_EQ(nullptr, tryEmplace(t, true));
  201. EXPECT_TRUE(t.hasException());
  202. EXPECT_NE(t.tryGetExceptionObject<MyException>(), nullptr);
  203. }
  204. {
  205. Try<ThrowingConstructor> t;
  206. EXPECT_EQ(nullptr, tryEmplace(t));
  207. EXPECT_TRUE(t.hasException());
  208. EXPECT_NE(t.tryGetExceptionObject<NonInheritingException>(), nullptr);
  209. }
  210. {
  211. Try<ThrowingConstructor> t;
  212. EXPECT_NE(nullptr, tryEmplace(t, false));
  213. EXPECT_TRUE(t.hasValue());
  214. EXPECT_EQ(nullptr, tryEmplace(t, true));
  215. EXPECT_TRUE(t.hasException());
  216. EXPECT_NE(t.tryGetExceptionObject<MyException>(), nullptr);
  217. }
  218. }
  219. TEST(Try, emplaceVoidTry) {
  220. struct MyException : std::exception {};
  221. Try<void> t;
  222. t.emplace();
  223. EXPECT_TRUE(t.hasValue());
  224. t.emplaceException(folly::in_place_type<MyException>);
  225. EXPECT_FALSE(t.hasValue());
  226. EXPECT_TRUE(t.hasException());
  227. EXPECT_TRUE(t.hasException<MyException>());
  228. t.emplace();
  229. EXPECT_TRUE(t.hasValue());
  230. EXPECT_FALSE(t.hasException());
  231. }
  232. TEST(Try, tryEmplaceVoidTry) {
  233. struct MyException : std::exception {};
  234. Try<void> t;
  235. tryEmplace(t);
  236. EXPECT_TRUE(t.hasValue());
  237. t.emplaceException(folly::in_place_type<MyException>);
  238. EXPECT_FALSE(t.hasValue());
  239. EXPECT_TRUE(t.hasException());
  240. EXPECT_TRUE(t.hasException<MyException>());
  241. t.emplace();
  242. EXPECT_TRUE(t.hasValue());
  243. EXPECT_FALSE(t.hasException());
  244. }
  245. TEST(Try, tryEmplaceWith) {
  246. Try<std::string> t;
  247. tryEmplaceWith(t, [] { return "hello"; });
  248. EXPECT_EQ("hello", t.value());
  249. }
  250. TEST(Try, tryEmplaceWithFunctionThrows) {
  251. struct MyException : std::exception {};
  252. Try<int> t;
  253. tryEmplaceWith(t, []() -> int { throw MyException{}; });
  254. EXPECT_TRUE(t.hasException());
  255. EXPECT_TRUE(t.hasException<MyException>());
  256. }
  257. TEST(Try, tryEmplaceWithConstructorThrows) {
  258. struct MyException : std::exception {};
  259. struct ThrowingConstructor {
  260. int value_;
  261. explicit ThrowingConstructor(bool shouldThrow) noexcept(false) : value_(0) {
  262. if (shouldThrow) {
  263. throw MyException{};
  264. }
  265. }
  266. };
  267. Try<ThrowingConstructor> t;
  268. tryEmplaceWith(t, [] { return false; });
  269. EXPECT_TRUE(t.hasValue());
  270. tryEmplaceWith(t, [] { return true; });
  271. EXPECT_TRUE(t.hasException());
  272. EXPECT_TRUE(t.hasException<MyException>());
  273. }
  274. TEST(Try, tryEmplaceWithVoidTry) {
  275. Try<void> t;
  276. bool hasRun = false;
  277. tryEmplaceWith(t, [&] { hasRun = true; });
  278. EXPECT_TRUE(t.hasValue());
  279. EXPECT_TRUE(hasRun);
  280. struct MyException : std::exception {};
  281. tryEmplaceWith(t, [&] { throw MyException{}; });
  282. EXPECT_TRUE(t.hasException());
  283. EXPECT_TRUE(t.hasException<MyException>());
  284. }
  285. TEST(Try, nothrow) {
  286. using F = HasCtors<false>;
  287. using T = HasCtors<true>;
  288. // default ctor
  289. EXPECT_TRUE(std::is_nothrow_default_constructible<Try<F>>::value);
  290. EXPECT_TRUE(std::is_nothrow_default_constructible<Try<T>>::value);
  291. EXPECT_TRUE(std::is_nothrow_default_constructible<Try<void>>::value);
  292. // inner ctor - no void
  293. EXPECT_FALSE((std::is_nothrow_constructible<Try<F>, F&&>::value));
  294. EXPECT_TRUE((std::is_nothrow_constructible<Try<T>, T&&>::value));
  295. EXPECT_FALSE((std::is_nothrow_constructible<Try<F>, F const&>::value));
  296. EXPECT_TRUE((std::is_nothrow_constructible<Try<T>, T const&>::value));
  297. // emplacing ctor - no void
  298. EXPECT_FALSE((std::is_nothrow_constructible<Try<F>, in_place_t, int>::value));
  299. EXPECT_TRUE((std::is_nothrow_constructible<Try<T>, in_place_t, int>::value));
  300. // copy/move ctor/assign
  301. EXPECT_TRUE(std::is_nothrow_constructible<Try<void>>::value);
  302. EXPECT_FALSE(std::is_nothrow_move_constructible<Try<F>>::value);
  303. EXPECT_TRUE(std::is_nothrow_move_constructible<Try<T>>::value);
  304. EXPECT_TRUE(std::is_nothrow_move_constructible<Try<void>>::value);
  305. EXPECT_FALSE(std::is_nothrow_move_assignable<Try<F>>::value);
  306. EXPECT_TRUE(std::is_nothrow_move_assignable<Try<T>>::value);
  307. EXPECT_TRUE(std::is_nothrow_move_assignable<Try<void>>::value);
  308. EXPECT_FALSE(std::is_nothrow_copy_constructible<Try<F>>::value);
  309. EXPECT_TRUE(std::is_nothrow_copy_constructible<Try<T>>::value);
  310. EXPECT_TRUE(std::is_nothrow_copy_constructible<Try<void>>::value);
  311. EXPECT_FALSE(std::is_nothrow_copy_assignable<Try<F>>::value);
  312. EXPECT_TRUE(std::is_nothrow_copy_assignable<Try<T>>::value);
  313. EXPECT_TRUE(std::is_nothrow_copy_assignable<Try<void>>::value);
  314. // conversion ctor - void to unit
  315. EXPECT_TRUE((std::is_nothrow_constructible<Try<Unit>, Try<void>&&>::value));
  316. EXPECT_TRUE(
  317. (std::is_nothrow_constructible<Try<Unit>, Try<void> const&>::value));
  318. }
  319. TEST(Try, MoveDereference) {
  320. auto ptr = std::make_unique<int>(1);
  321. auto t = Try<std::unique_ptr<int>>{std::move(ptr)};
  322. auto result = *std::move(t);
  323. EXPECT_EQ(*result, 1);
  324. }
  325. TEST(Try, MoveConstRvalue) {
  326. // tests to see if Try returns a const Rvalue, this is required in the case
  327. // where for example MutableContainer has a mutable memebr that is move only
  328. // and you want to fetch the value from the Try and move it into a member
  329. {
  330. const Try<MutableContainer> t{in_place};
  331. auto val = MoveConstructOnly(std::move(t).value().val);
  332. static_cast<void>(val);
  333. }
  334. {
  335. const Try<MutableContainer> t{in_place};
  336. auto val = (*(std::move(t))).val;
  337. static_cast<void>(val);
  338. }
  339. }
  340. TEST(Try, ValueOverloads) {
  341. using ML = int&;
  342. using MR = int&&;
  343. using CL = const int&;
  344. using CR = const int&&;
  345. {
  346. auto obj = Try<int>{};
  347. using ActualML = decltype(obj.value());
  348. using ActualMR = decltype(std::move(obj).value());
  349. using ActualCL = decltype(as_const(obj).value());
  350. using ActualCR = decltype(std::move(as_const(obj)).value());
  351. EXPECT_TRUE((std::is_same<ML, ActualML>::value));
  352. EXPECT_TRUE((std::is_same<MR, ActualMR>::value));
  353. EXPECT_TRUE((std::is_same<CL, ActualCL>::value));
  354. EXPECT_TRUE((std::is_same<CR, ActualCR>::value));
  355. }
  356. {
  357. auto obj = Try<int>{3};
  358. EXPECT_EQ(obj.value(), 3);
  359. EXPECT_EQ(std::move(obj).value(), 3);
  360. EXPECT_EQ(as_const(obj).value(), 3);
  361. EXPECT_EQ(std::move(as_const(obj)).value(), 3);
  362. }
  363. {
  364. auto obj = Try<int>{make_exception_wrapper<std::range_error>("oops")};
  365. EXPECT_THROW(obj.value(), std::range_error);
  366. EXPECT_THROW(std::move(obj.value()), std::range_error);
  367. EXPECT_THROW(as_const(obj.value()), std::range_error);
  368. EXPECT_THROW(std::move(as_const(obj.value())), std::range_error);
  369. }
  370. }
  371. // Make sure we can copy Trys for copyable types
  372. TEST(Try, copy) {
  373. Try<int> t;
  374. auto t2 = t;
  375. }
  376. // But don't choke on move-only types
  377. TEST(Try, moveOnly) {
  378. Try<std::unique_ptr<int>> t;
  379. std::vector<Try<std::unique_ptr<int>>> v;
  380. v.reserve(10);
  381. }
  382. TEST(Try, makeTryWith) {
  383. auto func = []() { return std::make_unique<int>(1); };
  384. auto result = makeTryWith(func);
  385. EXPECT_TRUE(result.hasValue());
  386. EXPECT_EQ(*result.value(), 1);
  387. }
  388. TEST(Try, makeTryWithThrow) {
  389. auto func = []() -> std::unique_ptr<int> {
  390. throw std::runtime_error("Runtime");
  391. };
  392. auto result = makeTryWith(func);
  393. EXPECT_TRUE(result.hasException<std::runtime_error>());
  394. }
  395. TEST(Try, makeTryWithVoid) {
  396. auto func = []() { return; };
  397. auto result = makeTryWith(func);
  398. EXPECT_TRUE(result.hasValue());
  399. }
  400. TEST(Try, makeTryWithVoidThrow) {
  401. auto func = []() { throw std::runtime_error("Runtime"); };
  402. auto result = makeTryWith(func);
  403. EXPECT_TRUE(result.hasException<std::runtime_error>());
  404. }
  405. TEST(Try, exception) {
  406. using ML = exception_wrapper&;
  407. using MR = exception_wrapper&&;
  408. using CL = exception_wrapper const&;
  409. using CR = exception_wrapper const&&;
  410. {
  411. auto obj = Try<int>();
  412. using ActualML = decltype(obj.exception());
  413. using ActualMR = decltype(std::move(obj).exception());
  414. using ActualCL = decltype(as_const(obj).exception());
  415. using ActualCR = decltype(std::move(as_const(obj)).exception());
  416. EXPECT_TRUE((std::is_same<ML, ActualML>::value));
  417. EXPECT_TRUE((std::is_same<MR, ActualMR>::value));
  418. EXPECT_TRUE((std::is_same<CL, ActualCL>::value));
  419. EXPECT_TRUE((std::is_same<CR, ActualCR>::value));
  420. }
  421. {
  422. auto obj = Try<int>(3);
  423. EXPECT_THROW(obj.exception(), TryException);
  424. EXPECT_THROW(std::move(obj).exception(), TryException);
  425. EXPECT_THROW(as_const(obj).exception(), TryException);
  426. EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
  427. }
  428. {
  429. auto obj = Try<int>(make_exception_wrapper<int>(-3));
  430. EXPECT_EQ(-3, *obj.exception().get_exception<int>());
  431. EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
  432. EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
  433. EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
  434. }
  435. {
  436. auto obj = Try<void>();
  437. using ActualML = decltype(obj.exception());
  438. using ActualMR = decltype(std::move(obj).exception());
  439. using ActualCL = decltype(as_const(obj).exception());
  440. using ActualCR = decltype(std::move(as_const(obj)).exception());
  441. EXPECT_TRUE((std::is_same<ML, ActualML>::value));
  442. EXPECT_TRUE((std::is_same<MR, ActualMR>::value));
  443. EXPECT_TRUE((std::is_same<CL, ActualCL>::value));
  444. EXPECT_TRUE((std::is_same<CR, ActualCR>::value));
  445. }
  446. {
  447. auto obj = Try<void>();
  448. EXPECT_THROW(obj.exception(), TryException);
  449. EXPECT_THROW(std::move(obj).exception(), TryException);
  450. EXPECT_THROW(as_const(obj).exception(), TryException);
  451. EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
  452. }
  453. {
  454. auto obj = Try<void>(make_exception_wrapper<int>(-3));
  455. EXPECT_EQ(-3, *obj.exception().get_exception<int>());
  456. EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
  457. EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
  458. EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
  459. }
  460. }
  461. template <typename E>
  462. static E* get_exception(std::exception_ptr eptr) {
  463. try {
  464. std::rethrow_exception(eptr);
  465. } catch (E& e) {
  466. return &e;
  467. } catch (...) {
  468. return nullptr;
  469. }
  470. }
  471. TEST(Try, tryGetExceptionObject) {
  472. auto epexn = std::make_exception_ptr(std::range_error("oops"));
  473. auto epnum = std::make_exception_ptr(17);
  474. auto exn = CHECK_NOTNULL(get_exception<std::range_error>(epexn));
  475. auto num = CHECK_NOTNULL(get_exception<int>(epnum));
  476. {
  477. auto t = Try<bool>(true);
  478. EXPECT_EQ(nullptr, t.tryGetExceptionObject());
  479. EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
  480. EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
  481. }
  482. {
  483. auto t = Try<bool>(exception_wrapper(epexn, *exn));
  484. EXPECT_EQ(exn, t.tryGetExceptionObject());
  485. EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
  486. EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
  487. }
  488. {
  489. auto t = Try<bool>(exception_wrapper(epnum, *num));
  490. EXPECT_EQ(nullptr, t.tryGetExceptionObject());
  491. EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
  492. EXPECT_EQ(num, t.tryGetExceptionObject<int>());
  493. }
  494. {
  495. auto t = Try<void>();
  496. EXPECT_EQ(nullptr, t.tryGetExceptionObject());
  497. EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
  498. EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
  499. }
  500. {
  501. auto t = Try<void>(exception_wrapper(epexn, *exn));
  502. EXPECT_EQ(exn, t.tryGetExceptionObject());
  503. EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
  504. EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
  505. }
  506. {
  507. auto t = Try<void>(exception_wrapper(epnum, *num));
  508. EXPECT_EQ(nullptr, t.tryGetExceptionObject());
  509. EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
  510. EXPECT_EQ(num, t.tryGetExceptionObject<int>());
  511. }
  512. {
  513. auto const t = Try<bool>(true);
  514. EXPECT_EQ(nullptr, t.tryGetExceptionObject());
  515. EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
  516. EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
  517. }
  518. {
  519. auto const t = Try<bool>(exception_wrapper(epexn, *exn));
  520. EXPECT_EQ(exn, t.tryGetExceptionObject());
  521. EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
  522. EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
  523. }
  524. {
  525. auto const t = Try<bool>(exception_wrapper(epnum, *num));
  526. EXPECT_EQ(nullptr, t.tryGetExceptionObject());
  527. EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
  528. EXPECT_EQ(num, t.tryGetExceptionObject<int>());
  529. }
  530. {
  531. auto const t = Try<void>();
  532. EXPECT_EQ(nullptr, t.tryGetExceptionObject());
  533. EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
  534. EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
  535. }
  536. {
  537. auto const t = Try<void>(exception_wrapper(epexn, *exn));
  538. EXPECT_EQ(exn, t.tryGetExceptionObject());
  539. EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
  540. EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
  541. }
  542. {
  543. auto const t = Try<void>(exception_wrapper(epnum, *num));
  544. EXPECT_EQ(nullptr, t.tryGetExceptionObject());
  545. EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
  546. EXPECT_EQ(num, t.tryGetExceptionObject<int>());
  547. }
  548. }
  549. TEST(Try, withException) {
  550. auto ew = make_exception_wrapper<std::range_error>("oops");
  551. {
  552. auto t = Try<bool>(true);
  553. EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
  554. EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
  555. EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
  556. EXPECT_FALSE(t.withException([](std::logic_error&) {}));
  557. }
  558. {
  559. auto t = Try<bool>(ew);
  560. EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
  561. EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
  562. EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
  563. EXPECT_FALSE(t.withException([](std::logic_error&) {}));
  564. }
  565. {
  566. auto t = Try<void>();
  567. EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
  568. EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
  569. EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
  570. EXPECT_FALSE(t.withException([](std::logic_error&) {}));
  571. }
  572. {
  573. auto t = Try<void>(ew);
  574. EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
  575. EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
  576. EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
  577. EXPECT_FALSE(t.withException([](std::logic_error&) {}));
  578. }
  579. {
  580. auto const t = Try<bool>(true);
  581. EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
  582. EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
  583. EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
  584. EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
  585. }
  586. {
  587. auto const t = Try<bool>(ew);
  588. EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
  589. EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
  590. EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
  591. EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
  592. }
  593. {
  594. auto const t = Try<void>();
  595. EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
  596. EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
  597. EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
  598. EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
  599. }
  600. {
  601. auto const t = Try<void>(ew);
  602. EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
  603. EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
  604. EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
  605. EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
  606. }
  607. }
  608. TEST(Try, TestUnwrapTuple) {
  609. auto original = std::make_tuple(Try<int>{1}, Try<int>{2});
  610. EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(original));
  611. EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(folly::copy(original)));
  612. EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(folly::as_const(original)));
  613. }
  614. TEST(Try, TestUnwrapPair) {
  615. auto original = std::make_pair(Try<int>{1}, Try<int>{2});
  616. EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(original));
  617. EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::copy(original)));
  618. EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::as_const(original)));
  619. }
  620. TEST(Try, TestUnwrapForward) {
  621. using UPtr_t = std::unique_ptr<int>;
  622. auto original = std::make_tuple(Try<UPtr_t>{std::make_unique<int>(1)});
  623. auto unwrapped = unwrapTryTuple(std::move(original));
  624. EXPECT_EQ(*std::get<0>(unwrapped), 1);
  625. }