util_expected_tests.cpp
1 // Copyright (c) The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or https://opensource.org/license/mit. 4 5 #include <test/util/setup_common.h> 6 #include <util/expected.h> 7 8 #include <boost/test/unit_test.hpp> 9 10 #include <memory> 11 #include <string> 12 #include <utility> 13 14 15 using namespace util; 16 17 BOOST_AUTO_TEST_SUITE(util_expected_tests) 18 19 BOOST_AUTO_TEST_CASE(expected_value) 20 { 21 struct Obj { 22 int x; 23 }; 24 Expected<Obj, int> e{}; 25 BOOST_CHECK_EQUAL(e.value().x, 0); 26 27 e = Obj{42}; 28 29 BOOST_CHECK(e.has_value()); 30 BOOST_CHECK(static_cast<bool>(e)); 31 BOOST_CHECK_EQUAL(e.value().x, 42); 32 BOOST_CHECK_EQUAL((*e).x, 42); 33 BOOST_CHECK_EQUAL(e->x, 42); 34 35 // modify value 36 e.value().x += 1; 37 (*e).x += 1; 38 e->x += 1; 39 40 const auto& read{e}; 41 BOOST_CHECK_EQUAL(read.value().x, 45); 42 BOOST_CHECK_EQUAL((*read).x, 45); 43 BOOST_CHECK_EQUAL(read->x, 45); 44 } 45 46 BOOST_AUTO_TEST_CASE(expected_value_rvalue) 47 { 48 Expected<std::unique_ptr<int>, int> no_copy{std::make_unique<int>(5)}; 49 const auto moved{std::move(no_copy).value()}; 50 BOOST_CHECK_EQUAL(*moved, 5); 51 } 52 53 BOOST_AUTO_TEST_CASE(expected_deref_rvalue) 54 { 55 Expected<std::unique_ptr<int>, int> no_copy{std::make_unique<int>(5)}; 56 const auto moved{*std::move(no_copy)}; 57 BOOST_CHECK_EQUAL(*moved, 5); 58 } 59 60 BOOST_AUTO_TEST_CASE(expected_value_or) 61 { 62 Expected<std::unique_ptr<int>, int> no_copy{std::make_unique<int>(1)}; 63 const int one{*std::move(no_copy).value_or(std::make_unique<int>(2))}; 64 BOOST_CHECK_EQUAL(one, 1); 65 66 const Expected<std::string, int> const_val{Unexpected{-1}}; 67 BOOST_CHECK_EQUAL(const_val.value_or("fallback"), "fallback"); 68 } 69 70 BOOST_AUTO_TEST_CASE(expected_value_throws) 71 { 72 const Expected<int, std::string> e{Unexpected{"fail"}}; 73 BOOST_CHECK_THROW(e.value(), BadExpectedAccess); 74 75 const Expected<void, std::string> void_e{Unexpected{"fail"}}; 76 BOOST_CHECK_THROW(void_e.value(), BadExpectedAccess); 77 } 78 79 BOOST_AUTO_TEST_CASE(expected_error) 80 { 81 Expected<void, std::string> e{}; 82 BOOST_CHECK(e.has_value()); 83 [&]() -> void { return e.value(); }(); // check value returns void and does not throw 84 [&]() -> void { return *e; }(); 85 86 e = Unexpected{"fail"}; 87 BOOST_CHECK(!e.has_value()); 88 BOOST_CHECK(!static_cast<bool>(e)); 89 BOOST_CHECK_EQUAL(e.error(), "fail"); 90 91 // modify error 92 e.error() += "1"; 93 94 const auto& read{e}; 95 BOOST_CHECK_EQUAL(read.error(), "fail1"); 96 } 97 98 BOOST_AUTO_TEST_CASE(expected_error_rvalue) 99 { 100 { 101 Expected<int, std::unique_ptr<int>> nocopy_err{Unexpected{std::make_unique<int>(7)}}; 102 const auto moved{std::move(nocopy_err).error()}; 103 BOOST_CHECK_EQUAL(*moved, 7); 104 } 105 { 106 Expected<void, std::unique_ptr<int>> void_nocopy_err{Unexpected{std::make_unique<int>(9)}}; 107 const auto moved{std::move(void_nocopy_err).error()}; 108 BOOST_CHECK_EQUAL(*moved, 9); 109 } 110 } 111 112 BOOST_AUTO_TEST_CASE(unexpected_error_accessors) 113 { 114 Unexpected u{std::make_unique<int>(-1)}; 115 BOOST_CHECK_EQUAL(*u.error(), -1); 116 117 *u.error() -= 1; 118 const auto& read{u}; 119 BOOST_CHECK_EQUAL(*read.error(), -2); 120 121 const auto moved{std::move(u).error()}; 122 BOOST_CHECK_EQUAL(*moved, -2); 123 } 124 125 BOOST_AUTO_TEST_CASE(expected_swap) 126 { 127 Expected<const char*, std::unique_ptr<int>> a{Unexpected{std::make_unique<int>(-1)}}; 128 Expected<const char*, std::unique_ptr<int>> b{"good"}; 129 a.swap(b); 130 BOOST_CHECK_EQUAL(a.value(), "good"); 131 BOOST_CHECK_EQUAL(*b.error(), -1); 132 } 133 134 BOOST_AUTO_TEST_SUITE_END()