Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:11:35

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2019 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
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 }  // namespace
0033 
0034 namespace std {
0035 // register with STL
0036 template <>
0037 struct is_error_code_enum<MyError> : std::true_type {};
0038 }  // namespace std
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 }  // namespace Test
0340 }  // namespace Acts