File indexing completed on 2025-08-06 08:11:35
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Utilities/Result.hpp"
0012
0013 #include <stdexcept>
0014 #include <string>
0015 #include <system_error>
0016 #include <type_traits>
0017 #include <utility>
0018
0019 using namespace std::string_literals;
0020
0021 namespace {
0022
0023 enum class MyError {
0024 Failure = 1,
0025 SomethingElse,
0026 };
0027
0028 std::error_code make_error_code(MyError e) {
0029 return {static_cast<int>(e), std::generic_category()};
0030 }
0031
0032 }
0033
0034 namespace std {
0035
0036 template <>
0037 struct is_error_code_enum<MyError> : std::true_type {};
0038 }
0039
0040 namespace Acts {
0041
0042 namespace Test {
0043
0044 BOOST_AUTO_TEST_SUITE(Utilities)
0045
0046 BOOST_AUTO_TEST_CASE(TestConstruction) {
0047 {
0048 using Result = Result<int, char>;
0049
0050 Result res = Result::success(42);
0051 BOOST_CHECK_EQUAL(*res, 42);
0052 BOOST_CHECK_EQUAL(res.value(), 42);
0053 BOOST_CHECK(res.ok());
0054 res = Result::success('e');
0055 BOOST_CHECK_EQUAL(*res, 'e');
0056 BOOST_CHECK_EQUAL(res.value(), 'e');
0057 BOOST_CHECK(res.ok());
0058 res = Result::failure(42);
0059 BOOST_CHECK(!res.ok());
0060 BOOST_CHECK_EQUAL(res.error(), 42);
0061 BOOST_CHECK_THROW(res.value(), std::runtime_error);
0062 res = Result::failure('e');
0063 BOOST_CHECK(!res.ok());
0064 BOOST_CHECK_EQUAL(res.error(), 'e');
0065 BOOST_CHECK_THROW(res.value(), std::runtime_error);
0066 }
0067
0068 {
0069 using Result = Result<double, std::string>;
0070
0071 Result res1("hallo");
0072 BOOST_CHECK(!res1.ok());
0073 BOOST_CHECK_EQUAL(res1.error(), "hallo");
0074 BOOST_CHECK_THROW(res1.value(), std::runtime_error);
0075 res1 = Result::failure("hallo");
0076 BOOST_CHECK(!res1.ok());
0077 BOOST_CHECK_EQUAL(res1.error(), "hallo");
0078 BOOST_CHECK_THROW(res1.value(), std::runtime_error);
0079
0080 Result res2(4.5);
0081 BOOST_CHECK(res2.ok());
0082 BOOST_CHECK(*res2 == 4.5);
0083 BOOST_CHECK(res2.value() == 4.5);
0084 res2 = Result::success(4.5);
0085 BOOST_CHECK(res2.ok());
0086 BOOST_CHECK_EQUAL(*res2, 4.5);
0087 BOOST_CHECK_EQUAL(res2.value(), 4.5);
0088 }
0089 }
0090
0091 BOOST_AUTO_TEST_CASE(TestErrorCodes) {
0092 auto err1 = MyError::Failure;
0093
0094 std::error_code ec = err1;
0095
0096 {
0097 using Result = Result<double, MyError>;
0098
0099 Result res(42.);
0100 BOOST_CHECK(res.ok());
0101 BOOST_CHECK_EQUAL(*res, 42.);
0102
0103 Result res2(err1);
0104 BOOST_CHECK(!res2.ok());
0105 BOOST_CHECK_EQUAL(res2.error(), err1);
0106 BOOST_CHECK_THROW(res2.value(), std::runtime_error);
0107 }
0108
0109 {
0110 using Result = Result<double, std::error_code>;
0111
0112 Result res(42.);
0113 BOOST_CHECK(res.ok());
0114 BOOST_CHECK_EQUAL(*res, 42.);
0115 BOOST_CHECK_EQUAL(res.value(), 42u);
0116 res = 46.;
0117 BOOST_CHECK(res.ok());
0118 BOOST_CHECK_EQUAL(*res, 46.);
0119 BOOST_CHECK_EQUAL(res.value(), 46u);
0120
0121 Result res2(ec);
0122 BOOST_CHECK(!res2.ok());
0123 BOOST_CHECK_EQUAL(res2.error(), ec);
0124 BOOST_CHECK_EQUAL(res2.error(), err1);
0125
0126 res2 = MyError::SomethingElse;
0127 BOOST_CHECK(!res2.ok());
0128 BOOST_CHECK_EQUAL(res2.error(), MyError::SomethingElse);
0129 BOOST_CHECK_NE(res2.error(), MyError::Failure);
0130 }
0131
0132 {
0133 using Result = Result<double, const char*>;
0134 Result res{0.};
0135 BOOST_CHECK(res.ok());
0136 BOOST_CHECK_EQUAL(*res, 0.0);
0137
0138 res = 1.;
0139 BOOST_CHECK(res.ok());
0140 BOOST_CHECK_EQUAL(*res, 1.0);
0141
0142 Result res2{"blubb"};
0143 BOOST_CHECK(!res2.ok());
0144 BOOST_CHECK_EQUAL(res2.error(), "blubb");
0145 res2 = "sep";
0146 BOOST_CHECK(!res2.ok());
0147 BOOST_CHECK_EQUAL(res2.error(), "sep");
0148 }
0149
0150 {
0151 using Result = Result<const char*, double>;
0152 Result res{0.};
0153 BOOST_CHECK(!res.ok());
0154 BOOST_CHECK_EQUAL(res.error(), 0.0);
0155
0156 res = "blibb";
0157 BOOST_CHECK(res.ok());
0158 BOOST_CHECK_EQUAL(res.value(), "blibb");
0159
0160 Result res2{"blibb"};
0161 BOOST_CHECK(res2.ok());
0162 BOOST_CHECK_EQUAL(res2.value(), "blibb");
0163
0164 res2 = 0.;
0165 BOOST_CHECK(!res2.ok());
0166 BOOST_CHECK_EQUAL(res2.error(), 0.0);
0167 }
0168
0169 {
0170 using Result = Result<double, int>;
0171 Result res = Result::success(2);
0172 BOOST_CHECK(res.ok());
0173 BOOST_CHECK_EQUAL(res.value(), 2.0);
0174
0175 res = Result::failure(3);
0176 BOOST_CHECK(!res.ok());
0177 BOOST_CHECK_EQUAL(res.error(), 3);
0178
0179 Result res2 = Result::failure(2);
0180 BOOST_CHECK(!res2.ok());
0181 BOOST_CHECK_EQUAL(res2.error(), 2);
0182
0183 res2 = Result::success(3.3);
0184 BOOST_CHECK(res2.ok());
0185 BOOST_CHECK_EQUAL(res2.value(), 3.3);
0186 }
0187
0188 {
0189 using Result = Result<double>;
0190
0191 Result res(42.);
0192 BOOST_CHECK(res.ok());
0193 BOOST_CHECK_EQUAL(*res, 42.);
0194 BOOST_CHECK_EQUAL(res.value(), 42u);
0195 res = 46.;
0196 BOOST_CHECK(res.ok());
0197 BOOST_CHECK_EQUAL(*res, 46.);
0198 BOOST_CHECK_EQUAL(res.value(), 46u);
0199
0200 Result res2(ec);
0201 BOOST_CHECK(!res2.ok());
0202 BOOST_CHECK_EQUAL(res2.error(), ec);
0203 BOOST_CHECK_EQUAL(res2.error(), err1);
0204
0205 res2 = MyError::SomethingElse;
0206 BOOST_CHECK(!res2.ok());
0207 BOOST_CHECK_EQUAL(res2.error(), MyError::SomethingElse);
0208 BOOST_CHECK_NE(res2.error(), MyError::Failure);
0209 }
0210
0211 {
0212 using Result = Result<std::string>;
0213
0214 Result res("hallo");
0215
0216 BOOST_CHECK(res.ok());
0217 BOOST_CHECK_EQUAL(*res, "hallo");
0218 BOOST_CHECK_EQUAL(res.value(), "hallo");
0219
0220 res = "something else";
0221 BOOST_CHECK(res.ok());
0222 BOOST_CHECK_EQUAL(*res, "something else");
0223 BOOST_CHECK_EQUAL(res.value(), "something else");
0224
0225 res = MyError::SomethingElse;
0226 BOOST_CHECK(!res.ok());
0227 BOOST_CHECK_EQUAL(res.error(), MyError::SomethingElse);
0228 BOOST_CHECK_NE(res.error(), MyError::Failure);
0229 }
0230
0231 {
0232 using Result = Result<std::string, int>;
0233
0234 Result res{"hallo"};
0235 BOOST_CHECK(res.ok());
0236 BOOST_CHECK_EQUAL(res.value(), "hallo");
0237
0238 Result res2{4};
0239 BOOST_CHECK(!res2.ok());
0240 BOOST_CHECK_EQUAL(res2.error(), 4);
0241 }
0242 }
0243
0244 struct NoCopy {
0245 NoCopy(int i) : num(i) {}
0246 NoCopy(const NoCopy&) = delete;
0247 NoCopy& operator=(const NoCopy&) = delete;
0248 NoCopy(NoCopy&&) = default;
0249 NoCopy& operator=(NoCopy&&) = default;
0250
0251 int num;
0252 };
0253
0254 Result<NoCopy> make_nocopy(int i, bool v = true) {
0255 if (!v) {
0256 return MyError::Failure;
0257 }
0258 return i;
0259 }
0260
0261 BOOST_AUTO_TEST_CASE(CopyBehaviour) {
0262 using Result = Result<NoCopy>;
0263
0264 NoCopy n(5);
0265 Result res = std::move(n);
0266 BOOST_CHECK(res.ok());
0267 BOOST_CHECK_EQUAL((*res).num, res.value().num);
0268
0269 res = make_nocopy(3);
0270 BOOST_CHECK(res.ok());
0271 BOOST_CHECK_EQUAL((*res).num, res.value().num);
0272 BOOST_CHECK_EQUAL((*res).num, 3);
0273
0274 res = NoCopy(-4);
0275 BOOST_CHECK(res.ok());
0276 BOOST_CHECK_EQUAL((*res).num, res.value().num);
0277 BOOST_CHECK_EQUAL((*res).num, -4.);
0278
0279 NoCopy n2 = make_nocopy(7).value();
0280 BOOST_CHECK_EQUAL(n2.num, 7);
0281 BOOST_REQUIRE_THROW(make_nocopy(6, false).value();, std::runtime_error);
0282
0283 Result n4r = make_nocopy(8);
0284 BOOST_CHECK(n4r.ok());
0285 BOOST_CHECK_EQUAL((*n4r).num, 8);
0286 NoCopy n4 = std::move(n4r.value());
0287 BOOST_CHECK_EQUAL(n4.num, 8);
0288 }
0289
0290 Result<void> void_res_func(int b) {
0291 if (b > 5) {
0292 return MyError::SomethingElse;
0293 }
0294 return {};
0295 }
0296
0297 BOOST_AUTO_TEST_CASE(VoidResult) {
0298 using Result = Result<void>;
0299
0300 Result res;
0301 BOOST_CHECK(res.ok());
0302
0303 Result res2 = Result::success();
0304 BOOST_CHECK(res2.ok());
0305
0306 res = MyError::Failure;
0307 BOOST_CHECK(!res.ok());
0308 BOOST_CHECK_EQUAL(res.error(), MyError::Failure);
0309
0310 Result res3 = Result::failure(MyError::SomethingElse);
0311 BOOST_CHECK(!res3.ok());
0312 BOOST_CHECK_EQUAL(res3.error(), MyError::SomethingElse);
0313
0314 Result res4 = void_res_func(4);
0315 BOOST_CHECK(res4.ok());
0316
0317 Result res5 = void_res_func(42);
0318 BOOST_CHECK(!res5.ok());
0319 BOOST_CHECK_EQUAL(res5.error(), MyError::SomethingElse);
0320 }
0321
0322 BOOST_AUTO_TEST_CASE(BoolResult) {
0323 using Result = Result<bool>;
0324
0325 Result res = Result::success(false);
0326 BOOST_CHECK(res.ok());
0327 BOOST_CHECK_EQUAL(*res, false);
0328
0329 res = Result::success(true);
0330 BOOST_CHECK(res.ok());
0331 BOOST_CHECK_EQUAL(*res, true);
0332
0333 res = Result::failure(MyError::Failure);
0334 BOOST_CHECK(!res.ok());
0335 BOOST_CHECK_EQUAL(res.error(), MyError::Failure);
0336 }
0337
0338 BOOST_AUTO_TEST_SUITE_END()
0339 }
0340 }