util_expected_tests.cpp raw
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()
135