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