rippled
Loading...
Searching...
No Matches
Expected_test.cpp
1#include <xrpl/basics/Expected.h>
2#include <xrpl/beast/unit_test.h>
3#include <xrpl/protocol/TER.h>
4
5#if BOOST_VERSION >= 107500
6#include <boost/json.hpp> // Not part of boost before version 1.75
7#endif // BOOST_VERSION
8#include <array>
9#include <cstdint>
10
11namespace xrpl {
12namespace test {
13
15{
16 void
17 run() override
18 {
19 // Test non-error const construction.
20 {
21 auto const expected = []() -> Expected<std::string, TER> { return "Valid value"; }();
22 BEAST_EXPECT(expected);
23 BEAST_EXPECT(expected.has_value());
24 BEAST_EXPECT(expected.value() == "Valid value");
25 BEAST_EXPECT(*expected == "Valid value");
26 BEAST_EXPECT(expected->at(0) == 'V');
27
28 bool throwOccurred = false;
29 try
30 {
31 // There's no error, so should throw.
32 [[maybe_unused]] TER const t = expected.error();
33 }
34 catch (std::runtime_error const& e)
35 {
36 BEAST_EXPECT(e.what() == std::string("bad expected access"));
37 throwOccurred = true;
38 }
39 BEAST_EXPECT(throwOccurred);
40 }
41 // Test non-error non-const construction.
42 {
43 auto expected = []() -> Expected<std::string, TER> { return "Valid value"; }();
44 BEAST_EXPECT(expected);
45 BEAST_EXPECT(expected.has_value());
46 BEAST_EXPECT(expected.value() == "Valid value");
47 BEAST_EXPECT(*expected == "Valid value");
48 BEAST_EXPECT(expected->at(0) == 'V');
49 std::string mv = std::move(*expected);
50 BEAST_EXPECT(mv == "Valid value");
51
52 bool throwOccurred = false;
53 try
54 {
55 // There's no error, so should throw.
56 [[maybe_unused]] TER const t = expected.error();
57 }
58 catch (std::runtime_error const& e)
59 {
60 BEAST_EXPECT(e.what() == std::string("bad expected access"));
61 throwOccurred = true;
62 }
63 BEAST_EXPECT(throwOccurred);
64 }
65 // Test non-error overlapping type construction.
66 {
67 auto expected = []() -> Expected<std::uint32_t, std::uint16_t> { return 1; }();
68 BEAST_EXPECT(expected);
69 BEAST_EXPECT(expected.has_value());
70 BEAST_EXPECT(expected.value() == 1);
71 BEAST_EXPECT(*expected == 1);
72
73 bool throwOccurred = false;
74 try
75 {
76 // There's no error, so should throw.
77 [[maybe_unused]] std::uint16_t const t = expected.error();
78 }
79 catch (std::runtime_error const& e)
80 {
81 BEAST_EXPECT(e.what() == std::string("bad expected access"));
82 throwOccurred = true;
83 }
84 BEAST_EXPECT(throwOccurred);
85 }
86 // Test error construction from rvalue.
87 {
88 auto const expected = []() -> Expected<std::string, TER> { return Unexpected(telLOCAL_ERROR); }();
89 BEAST_EXPECT(!expected);
90 BEAST_EXPECT(!expected.has_value());
91 BEAST_EXPECT(expected.error() == telLOCAL_ERROR);
92
93 bool throwOccurred = false;
94 try
95 {
96 // There's no result, so should throw.
97 [[maybe_unused]] std::string const s = *expected;
98 }
99 catch (std::runtime_error const& e)
100 {
101 BEAST_EXPECT(e.what() == std::string("bad expected access"));
102 throwOccurred = true;
103 }
104 BEAST_EXPECT(throwOccurred);
105 }
106 // Test error construction from lvalue.
107 {
108 auto const err(telLOCAL_ERROR);
109 auto expected = [&err]() -> Expected<std::string, TER> { return Unexpected(err); }();
110 BEAST_EXPECT(!expected);
111 BEAST_EXPECT(!expected.has_value());
112 BEAST_EXPECT(expected.error() == telLOCAL_ERROR);
113
114 bool throwOccurred = false;
115 try
116 {
117 // There's no result, so should throw.
118 [[maybe_unused]] std::size_t const s = expected->size();
119 }
120 catch (std::runtime_error const& e)
121 {
122 BEAST_EXPECT(e.what() == std::string("bad expected access"));
123 throwOccurred = true;
124 }
125 BEAST_EXPECT(throwOccurred);
126 }
127 // Test error construction from const char*.
128 {
129 auto const expected = []() -> Expected<int, char const*> { return Unexpected("Not what is expected!"); }();
130 BEAST_EXPECT(!expected);
131 BEAST_EXPECT(!expected.has_value());
132 BEAST_EXPECT(expected.error() == std::string("Not what is expected!"));
133 }
134 // Test error construction of string from const char*.
135 {
136 auto expected = []() -> Expected<int, std::string> { return Unexpected("Not what is expected!"); }();
137 BEAST_EXPECT(!expected);
138 BEAST_EXPECT(!expected.has_value());
139 BEAST_EXPECT(expected.error() == "Not what is expected!");
140 std::string const s(std::move(expected.error()));
141 BEAST_EXPECT(s == "Not what is expected!");
142 }
143 // Test non-error const construction of Expected<void, T>.
144 {
145 auto const expected = []() -> Expected<void, std::string> { return {}; }();
146 BEAST_EXPECT(expected);
147 bool throwOccurred = false;
148 try
149 {
150 // There's no error, so should throw.
151 [[maybe_unused]] std::size_t const s = expected.error().size();
152 }
153 catch (std::runtime_error const& e)
154 {
155 BEAST_EXPECT(e.what() == std::string("bad expected access"));
156 throwOccurred = true;
157 }
158 BEAST_EXPECT(throwOccurred);
159 }
160 // Test non-error non-const construction of Expected<void, T>.
161 {
162 auto expected = []() -> Expected<void, std::string> { return {}; }();
163 BEAST_EXPECT(expected);
164 bool throwOccurred = false;
165 try
166 {
167 // There's no error, so should throw.
168 [[maybe_unused]] std::size_t const s = expected.error().size();
169 }
170 catch (std::runtime_error const& e)
171 {
172 BEAST_EXPECT(e.what() == std::string("bad expected access"));
173 throwOccurred = true;
174 }
175 BEAST_EXPECT(throwOccurred);
176 }
177 // Test error const construction of Expected<void, T>.
178 {
179 auto const expected = []() -> Expected<void, std::string> { return Unexpected("Not what is expected!"); }();
180 BEAST_EXPECT(!expected);
181 BEAST_EXPECT(expected.error() == "Not what is expected!");
182 }
183 // Test error non-const construction of Expected<void, T>.
184 {
185 auto expected = []() -> Expected<void, std::string> { return Unexpected("Not what is expected!"); }();
186 BEAST_EXPECT(!expected);
187 BEAST_EXPECT(expected.error() == "Not what is expected!");
188 std::string const s(std::move(expected.error()));
189 BEAST_EXPECT(s == "Not what is expected!");
190 }
191 // Test a case that previously unintentionally returned an array.
192#if BOOST_VERSION >= 107500
193 {
194 auto expected = []() -> Expected<boost::json::value, std::string> {
195 return boost::json::object{{"oops", "me array now"}};
196 }();
197 BEAST_EXPECT(expected);
198 BEAST_EXPECT(!expected.value().is_array());
199 }
200#endif // BOOST_VERSION
201 }
202};
203
204BEAST_DEFINE_TESTSUITE(Expected, basics, xrpl);
205
206} // namespace test
207} // namespace xrpl
A testsuite class.
Definition suite.h:52
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
@ telLOCAL_ERROR
Definition TER.h:33
void run() override
Runs the suite.
T what(T... args)