diff options
Diffstat (limited to 'src/boost/libs/outcome/test/tests')
37 files changed, 4186 insertions, 0 deletions
diff --git a/src/boost/libs/outcome/test/tests/comparison.cpp b/src/boost/libs/outcome/test/tests/comparison.cpp new file mode 100644 index 000000000..1c093ffd2 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/comparison.cpp @@ -0,0 +1,102 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (6 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#ifdef _MSC_VER +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4244) // conversion from int to short +#endif + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_comparison, "Tests that the outcome can compare to compatible outcomes") +{ +#if !defined(__APPLE__) || defined(__cpp_exceptions) + using namespace BOOST_OUTCOME_V2_NAMESPACE; + auto p = boost::copy_exception(std::runtime_error("hi")); + // value comparison + { + outcome<int> a(1), b(2), c(2); + BOOST_CHECK(a == a); + BOOST_CHECK(b == b); + BOOST_CHECK(c == c); + BOOST_CHECK(a != b); + BOOST_CHECK(b == c); + } + // homogeneous outcome comparison + { + outcome<int> a(1), b(2), c(boost::system::errc::invalid_argument), d(p); + BOOST_CHECK(a == a); + BOOST_CHECK(a != b); + BOOST_CHECK(a != c); + BOOST_CHECK(a != d); + BOOST_CHECK(b == b); + BOOST_CHECK(b != c); + BOOST_CHECK(b != d); + BOOST_CHECK(c == c); + BOOST_CHECK(c != d); + BOOST_CHECK(d == d); + outcome<int> e(boost::system::errc::invalid_argument), f(p); + BOOST_CHECK(c == e); + BOOST_CHECK(d == f); + } + // heterogeneous outcome comparison, so outcome<int> to outcome<double> etc + { + outcome<int> a(1); + outcome<double> b(1); + outcome<unsigned short> c(1); + BOOST_CHECK(a == b); + BOOST_CHECK(a == c); + BOOST_CHECK(b == a); + BOOST_CHECK(b == c); + BOOST_CHECK(c == a); + BOOST_CHECK(c == b); + // outcome<void> e(in_place_type<void>); + outcome<unsigned short> f(boost::system::errc::invalid_argument); + outcome<double> g(p); + // BOOST_CHECK(a != e); + BOOST_CHECK(a != f); + BOOST_CHECK(a != g); + // BOOST_CHECK(e != f); + BOOST_CHECK(f != g); + } + // upconverting outcome comparison, so outcome<int>==result<int> etc + { + outcome<int> a(1); + result<int> b(1); + BOOST_CHECK(a == b); + BOOST_CHECK(b == a); + // result<void> e(in_place_type<void>), f(boost::system::errc::invalid_argument); + // BOOST_CHECK(a != e); + // BOOST_CHECK(a != f); + } + // Should I do outcome<int>(5) == 5? Unsure if it's wise +#endif +} diff --git a/src/boost/libs/outcome/test/tests/constexpr.cpp b/src/boost/libs/outcome/test/tests/constexpr.cpp new file mode 100644 index 000000000..327b8f26a --- /dev/null +++ b/src/boost/libs/outcome/test/tests/constexpr.cpp @@ -0,0 +1,118 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (9 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#if __cplusplus >= 201700 || _HAS_CXX17 +// Match LiteralType, even on C++ 17 and later +template <class T> struct is_literal_type +{ + static constexpr bool value = // + std::is_void<T>::value // + || std::is_scalar<T>::value // + || std::is_reference<T>::value // + // leave out is_array for simplicity + || (std::is_class<T>::value && std::is_trivially_destructible<T>::value + // how does one detect if a type has at least one constexpr constructor without Reflection??? + ) // leave out union for simplicity + ; +}; +#else +template <class T> using is_literal_type = std::is_literal_type<T>; +#endif + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_constexpr, "Tests that outcome works as intended in a constexpr evaluation context") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + + static_assert(is_literal_type<result<int, void, void>>::value, "result<int, void, void> is not a literal type!"); + static_assert(is_literal_type<outcome<int, void, void>>::value, "outcome<int, void, void> is not a literal type!"); + + // Unfortunately result<T> can never be a literal type as error_code can never be literal + // + // It can however be trivially destructible as error_code is trivially destructible. That + // makes possible lots of compiler optimisations + static_assert(std::is_trivially_destructible<result<int>>::value, "result<int> is not trivially destructible!"); + static_assert(std::is_trivially_destructible<result<void>>::value, "result<void> is not trivially destructible!"); + + // outcome<T> default has no trivial operations, but if configured it can become so + static_assert(std::is_trivially_destructible<outcome<int, boost::system::error_code, void>>::value, + "outcome<int, boost::system::error_code, void> is not trivially destructible!"); + + { + // Test compatible results can be constructed from one another + constexpr result<int, long> g(in_place_type<int>, 5); + constexpr result<long, int> g2(g); + static_assert(g.has_value(), ""); + static_assert(!g.has_error(), ""); + static_assert(g.assume_value() == 5, ""); // value() with UDT E won't compile + static_assert(g2.has_value(), ""); + static_assert(!g2.has_error(), ""); + static_assert(g2.assume_value() == 5, ""); // value() with UDT E won't compile + constexpr result<void, int> g3(in_place_type<void>); + constexpr result<long, int> g4(g3); + constexpr result<int, void> g5(in_place_type<void>); + constexpr result<long, int> g6(g5); + (void) g4; + (void) g6; + + // Test void + constexpr result<void, int> h(in_place_type<void>); + static_assert(h.has_value(), ""); + constexpr result<int, void> h2(in_place_type<void>); + static_assert(!h2.has_value(), ""); + static_assert(h2.has_error(), ""); + + // Test const + constexpr result<const int, void> i(5); + constexpr result<const int, void> i2(i); + (void) i2; + } + { + // Test compatible outcomes can be constructed from one another + constexpr outcome<int, long, char *> g(in_place_type<int>, 5); + constexpr outcome<long, int, const char *> g2(g); + static_assert(g.has_value(), ""); + static_assert(!g.has_error(), ""); + static_assert(!g.has_exception(), ""); + static_assert(g.assume_value() == 5, ""); // value() with UDT E won't compile + static_assert(g2.has_value(), ""); + static_assert(!g2.has_error(), ""); + static_assert(!g2.has_exception(), ""); + static_assert(g2.assume_value() == 5, ""); // value() with UDT E won't compile + constexpr outcome<void, int, char *> g3(in_place_type<void>); + constexpr outcome<long, int, const char *> g4(g3); + constexpr outcome<int, void, char *> g5(in_place_type<void>); + constexpr outcome<long, int, const char *> g6(g5); + (void) g4; + (void) g6; + } +} diff --git a/src/boost/libs/outcome/test/tests/containers.cpp b/src/boost/libs/outcome/test/tests/containers.cpp new file mode 100644 index 000000000..b92af4b70 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/containers.cpp @@ -0,0 +1,58 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (7 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_containers, "Tests that outcome works as intended inside containers") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + outcome<std::vector<int>> a(std::vector<int>{5, 6, 7, 8}); + BOOST_CHECK(a.has_value()); + BOOST_CHECK(a.value().size() == 4U); + auto b(a); + BOOST_CHECK(a.has_value()); + BOOST_CHECK(a.value().size() == 4U); + BOOST_CHECK(b.has_value()); + BOOST_CHECK(b.value().size() == 4U); + + std::vector<outcome<std::vector<int>>> vect; + vect.push_back(std::vector<int>{5, 6, 7, 8}); + vect.push_back(std::vector<int>{1, 2, 3, 4}); + BOOST_REQUIRE(vect.size() == 2U); // NOLINT + BOOST_CHECK(vect[0].has_value()); + BOOST_CHECK(vect[1].has_value()); + BOOST_CHECK(vect[0].value().size() == 4U); + BOOST_CHECK(vect[1].value().size() == 4U); + BOOST_CHECK(vect[0].value().front() == 5); + BOOST_CHECK(vect[0].value().back() == 8); + BOOST_CHECK(vect[1].value().front() == 1); + BOOST_CHECK(vect[1].value().back() == 4); +} diff --git a/src/boost/libs/outcome/test/tests/core-outcome.cpp b/src/boost/libs/outcome/test/tests/core-outcome.cpp new file mode 100644 index 000000000..dfa15d355 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/core-outcome.cpp @@ -0,0 +1,258 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (18 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#include <iostream> + +#ifdef _MSC_VER +#pragma warning(disable : 4702) // unreachable code +#endif + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome, "Tests that the outcome works as intended") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + + static_assert(std::is_constructible<outcome<long>, int>::value, "Sanity check that monad can be constructed from a value_type"); + static_assert(!std::is_constructible<outcome<outcome<long>>, int>::value, "Sanity check that outer monad can be constructed from an inner monad's value_type"); + static_assert(!std::is_constructible<outcome<outcome<outcome<long>>>, int>::value, "Sanity check that outer monad can be constructed from an inner inner monad's value_type"); + static_assert(!std::is_constructible<outcome<outcome<outcome<outcome<long>>>>, int>::value, "Sanity check that outer monad can be constructed from an inner inner monad's value_type"); + + static_assert(std::is_constructible<outcome<int>, outcome<long>>::value, "Sanity check that compatible monads can be constructed from one another"); + static_assert(std::is_constructible<outcome<outcome<int>>, outcome<long>>::value, "Sanity check that outer monad can be constructed from a compatible monad"); + static_assert(!std::is_constructible<outcome<outcome<outcome<int>>>, outcome<long>>::value, "Sanity check that outer monad can be constructed from a compatible monad up to two nestings deep"); + static_assert(!std::is_constructible<outcome<outcome<outcome<outcome<int>>>>, outcome<long>>::value, "Sanity check that outer monad can be constructed from a compatible monad three or more nestings deep"); + static_assert(!std::is_constructible<outcome<std::string>, outcome<int>>::value, "Sanity check that incompatible monads cannot be constructed from one another"); + + static_assert(std::is_constructible<outcome<int>, outcome<void>>::value, "Sanity check that all monads can be constructed from a void monad"); + static_assert(std::is_constructible<outcome<outcome<int>>, outcome<void>>::value, "Sanity check that outer monad can be constructed from a compatible monad"); + static_assert(std::is_constructible<outcome<outcome<outcome<int>>>, outcome<void>>::value, "Sanity check that outer monad can be constructed from a compatible monad up to two nestings deep"); + static_assert(!std::is_constructible<outcome<void>, outcome<int>>::value, "Sanity check that incompatible monads cannot be constructed from one another"); + + static_assert(std::is_void<result<void>::value_type>::value, "Sanity check that result<void> has a void value_type"); + static_assert(std::is_void<result<void, void>::error_type>::value, "Sanity check that result<void, void> has a void error_type"); + // static_assert(std::is_void<outcome<void, void, void>::exception_type>::value, "Sanity check that outcome<void, void, void> has a void exception_type"); + + static_assert(std::is_same<outcome<int>::value_type, int>::value, "Sanity check that outcome<int> has a int value_type"); + static_assert(std::is_same<outcome<int>::error_type, boost::system::error_code>::value, "Sanity check that outcome<int> has a error_code error_type"); + static_assert(std::is_same<outcome<int>::exception_type, boost::exception_ptr>::value, "Sanity check that outcome<int> has a exception_ptr exception_type"); + + + { // errored int + outcome<int> m(boost::system::errc::bad_address); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(m.value(), boost::system::system_error); + BOOST_CHECK_NO_THROW(m.error()); + BOOST_CHECK_THROW(m.exception(), bad_outcome_access); + BOOST_CHECK_THROW(boost::rethrow_exception(m.failure()), boost::system::system_error); + } + { // errored void + outcome<void> m(boost::system::errc::bad_address); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(([&m]() -> void { return m.value(); }()), boost::system::system_error); + BOOST_CHECK_NO_THROW(m.error()); + BOOST_CHECK_THROW(m.exception(), bad_outcome_access); + BOOST_CHECK_THROW(boost::rethrow_exception(m.failure()), boost::system::system_error); + } + { // valued int + outcome<int> m(5); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == 5); + m.value() = 6; + BOOST_CHECK(m.value() == 6); + BOOST_CHECK_THROW(m.error(), bad_outcome_access); + BOOST_CHECK_THROW(m.exception(), bad_outcome_access); + BOOST_CHECK(!m.failure()); + } + { // moves do not clear state + outcome<std::string> m("niall"); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == "niall"); + m.value() = "NIALL"; + BOOST_CHECK(m.value() == "NIALL"); + auto temp(std::move(m).value()); + BOOST_CHECK(temp == "NIALL"); + BOOST_CHECK(m.value().empty()); // NOLINT + } + { // valued void + outcome<void> m(in_place_type<void>); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_NO_THROW(m.value()); // works, but type returned is unusable + BOOST_CHECK_THROW(m.error(), bad_outcome_access); + BOOST_CHECK_THROW(m.exception(), bad_outcome_access); + BOOST_CHECK(!m.failure()); + } + { // errored + boost::system::error_code ec(5, boost::system::system_category()); + outcome<int> m(ec); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(m.value(), boost::system::system_error); + BOOST_CHECK(m.error() == ec); + BOOST_CHECK_THROW(m.exception(), bad_outcome_access); +#ifndef BOOST_NO_EXCEPTIONS + BOOST_CHECK(m.failure()); + try + { + boost::rethrow_exception(m.failure()); + } + catch(const boost::system::system_error &ex) + { + BOOST_CHECK(ex.code() == ec); + BOOST_CHECK(ex.code().value() == 5); + } +#endif + } +#if !defined(__APPLE__) || defined(__cpp_exceptions) + { // excepted + boost::system::error_code ec(5, boost::system::system_category()); + auto e = boost::copy_exception(boost::system::system_error(ec)); // NOLINT + outcome<int> m(e); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(m.has_exception()); + BOOST_CHECK_THROW(m.value(), boost::system::system_error); + BOOST_CHECK_THROW(m.error(), bad_outcome_access); + BOOST_CHECK(m.exception() == e); +#ifndef BOOST_NO_EXCEPTIONS + BOOST_CHECK(m.failure()); + try + { + boost::rethrow_exception(m.failure()); + } + catch(const boost::system::system_error &ex) + { + BOOST_CHECK(ex.code() == ec); + BOOST_CHECK(ex.code().value() == 5); + } +#endif + } + { // custom error type + struct Foo + { + }; + auto e = boost::copy_exception(Foo()); + outcome<int> m(e); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(m.has_exception()); + BOOST_CHECK_THROW(m.value(), Foo); + BOOST_CHECK_THROW(m.error(), bad_outcome_access); + BOOST_CHECK(m.exception() == e); + } + { // outcome<void, void> should work + boost::system::error_code ec(5, boost::system::system_category()); + auto e = boost::copy_exception(boost::system::system_error(ec)); + outcome<void, void> m(e); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(m.has_exception()); + } +#endif + + + { + outcome<int> a(5); + outcome<int> b(make_error_code(boost::system::errc::invalid_argument)); + std::cout << sizeof(a) << std::endl; // 40 bytes + a.assume_value(); + b.assume_error(); +#ifndef BOOST_NO_EXCEPTIONS + try + { + b.value(); + std::cerr << "fail" << std::endl; + std::terminate(); + } + catch(const boost::system::system_error & /*unused*/) + { + } +#endif + static_assert(!std::is_default_constructible<decltype(a)>::value, ""); + static_assert(!std::is_nothrow_default_constructible<decltype(a)>::value, ""); + static_assert(std::is_copy_constructible<decltype(a)>::value, ""); + static_assert(!std::is_trivially_copy_constructible<decltype(a)>::value, ""); + static_assert(std::is_nothrow_copy_constructible<decltype(a)>::value, ""); + static_assert(std::is_copy_assignable<decltype(a)>::value, ""); + static_assert(!std::is_trivially_copy_assignable<decltype(a)>::value, ""); + static_assert(std::is_nothrow_copy_assignable<decltype(a)>::value, ""); + static_assert(!std::is_trivially_destructible<decltype(a)>::value, ""); + static_assert(std::is_nothrow_destructible<decltype(a)>::value, ""); + + // Test void compiles + outcome<void> c(in_place_type<void>); + outcome<void> c2(c); + (void) c2; + // Test int, void compiles + outcome<int, void> d(in_place_type<boost::exception_ptr>); + } + + { + // Can only be constructed via multiple args + struct udt3 + { + udt3() = delete; + udt3(udt3 &&) = delete; + udt3(const udt3 &) = delete; + udt3 &operator=(udt3 &&) = delete; + udt3 &operator=(const udt3 &) = delete; + explicit udt3(int /*unused*/, const char * /*unused*/, std::nullptr_t /*unused*/) {} + ~udt3() = default; + }; + // Test a udt which can only be constructed in place compiles + outcome<udt3> g(in_place_type<udt3>, 5, static_cast<const char *>("niall"), nullptr); + // Does converting inplace construction also work? + outcome<udt3> h(5, static_cast<const char *>("niall"), nullptr); + outcome<udt3> i(ENOMEM, boost::system::generic_category()); + BOOST_CHECK(h.has_value()); + BOOST_CHECK(i.has_error()); + } +} diff --git a/src/boost/libs/outcome/test/tests/core-result.cpp b/src/boost/libs/outcome/test/tests/core-result.cpp new file mode 100644 index 000000000..2ded9cb6a --- /dev/null +++ b/src/boost/libs/outcome/test/tests/core-result.cpp @@ -0,0 +1,370 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (30 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#ifdef TESTING_WG21_EXPERIMENTAL_RESULT +#include <boost/outcome/experimental/result.hpp> +#define BOOST_OUTCOME_AUTO_TEST_CASE(...) BOOST_AUTO_TEST_CASE(__VA_ARGS__) +#else +#include <boost/outcome/result.hpp> +#endif +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#include <iostream> + +#ifndef BOOST_NO_EXCEPTIONS +// Custom error type with payload +struct payload +{ + boost::system::error_code ec; + const char *str{nullptr}; + payload() = default; + payload(boost::system::errc::errc_t _ec, const char *_str) + : ec(make_error_code(_ec)) + , str(_str) + { + } +}; +struct payload_exception : std::runtime_error +{ + explicit payload_exception(const char *what) + : std::runtime_error(what) + { + } +}; +inline const boost::system::error_code &make_error_code(const payload &p) +{ + return p.ec; +} +inline void outcome_throw_as_system_error_with_payload(const payload &p) +{ + throw payload_exception(p.str); +} +#endif + +BOOST_OUTCOME_AUTO_TEST_CASE(works_result, "Tests that the result works as intended") +{ +#ifdef TESTING_WG21_EXPERIMENTAL_RESULT + using namespace std::experimental; + using std::in_place_type; +#else + using namespace BOOST_OUTCOME_V2_NAMESPACE; +#endif + + static_assert(std::is_constructible<result<long>, int>::value, "Sanity check that monad can be constructed from a value_type"); + static_assert(!std::is_constructible<result<result<long>>, int>::value, "Sanity check that outer monad can be constructed from an inner monad's value_type"); + static_assert(!std::is_constructible<result<result<result<long>>>, int>::value, "Sanity check that outer monad can be constructed from an inner inner monad's value_type"); + static_assert(!std::is_constructible<result<result<result<result<long>>>>, int>::value, "Sanity check that outer monad can be constructed from an inner inner monad's value_type"); + + static_assert(std::is_constructible<result<int>, result<long>>::value, "Sanity check that compatible monads can be constructed from one another"); + static_assert(std::is_constructible<result<result<int>>, result<long>>::value, "Sanity check that outer monad can be constructed from a compatible monad"); + static_assert(!std::is_constructible<result<result<result<int>>>, result<long>>::value, "Sanity check that outer monad can be constructed from a compatible monad up to two nestings deep"); + static_assert(!std::is_constructible<result<result<result<result<int>>>>, result<long>>::value, "Sanity check that outer monad can be constructed from a compatible monad three or more nestings deep"); + static_assert(!std::is_constructible<result<std::string>, result<int>>::value, "Sanity check that incompatible monads cannot be constructed from one another"); + +#ifndef TESTING_WG21_EXPERIMENTAL_RESULT + static_assert(std::is_constructible<result<int>, result<void>>::value, "Sanity check that all monads can be constructed from a void monad"); + static_assert(std::is_constructible<result<result<int>>, result<void>>::value, "Sanity check that outer monad can be constructed from a compatible monad"); + static_assert(std::is_constructible<result<result<result<int>>>, result<void>>::value, "Sanity check that outer monad can be constructed from a compatible monad up to two nestings deep"); + static_assert(!std::is_constructible<result<void>, result<int>>::value, "Sanity check that incompatible monads cannot be constructed from one another"); +#endif + static_assert(std::is_void<result<void>::value_type>::value, "Sanity check that result<void> has a void value_type"); +#ifndef TESTING_WG21_EXPERIMENTAL_RESULT + static_assert(std::is_void<result<void, void>::error_type>::value, "Sanity check that result<void, void> has a void error_type"); +#endif + + static_assert(std::is_same<result<int>::value_type, int>::value, "Sanity check that result<int> has a int value_type"); + static_assert(std::is_same<result<int>::error_type, boost::system::error_code>::value, "Sanity check that result<int> has a error_code error_type"); + + + { // errored int + result<int> m(boost::system::errc::bad_address); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(m.value(), boost::system::system_error); + BOOST_CHECK_NO_THROW(m.error()); + } + { // errored void + result<void> m(boost::system::errc::bad_address); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); +// BOOST_CHECK(!m.has_exception()); +#ifndef TESTING_WG21_EXPERIMENTAL_RESULT + BOOST_CHECK_THROW(([&m]() -> void { return m.value(); }()), boost::system::system_error); +#endif + BOOST_CHECK_NO_THROW(m.error()); + } + { // valued int + result<int> m(5); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == 5); + m.value() = 6; + BOOST_CHECK(m.value() == 6); + BOOST_CHECK_THROW(m.error(), bad_result_access); + } + { // valued bool + result<bool> m(false); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == false); + m.value() = true; + BOOST_CHECK(m.value() == true); + BOOST_CHECK_THROW(m.error(), bad_result_access); + } + { // moves do not clear state + result<std::string> m("niall"); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == "niall"); + m.value() = "NIALL"; + BOOST_CHECK(m.value() == "NIALL"); + auto temp(std::move(m).value()); + BOOST_CHECK(temp == "NIALL"); + BOOST_CHECK(m.value().empty()); // NOLINT + } + { // valued void + result<void> m(in_place_type<void>); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_NO_THROW(m.value()); // works, but type returned is unusable + BOOST_CHECK_THROW(m.error(), bad_result_access); + } + { // errored + boost::system::error_code ec(5, boost::system::system_category()); + result<int> m(ec); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(m.value(), boost::system::system_error); + BOOST_CHECK(m.error() == ec); + } +#if !defined(__APPLE__) || defined(__cpp_exceptions) + { // errored, custom + boost::system::error_code ec(5, boost::system::system_category()); + auto e = boost::copy_exception(boost::system::system_error(ec)); // NOLINT + result<int, boost::exception_ptr> m(e); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(m.value(), boost::system::system_error); + BOOST_CHECK(m.error() == e); + } +#endif +#ifndef TESTING_WG21_EXPERIMENTAL_RESULT + { // custom error type + struct Foo + { + }; + result<int, Foo> m(in_place_type<Foo>); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + // BOOST_CHECK(!m.has_exception()); + // BOOST_CHECK_NO_THROW(m.value()); + // BOOST_CHECK_NO_THROW(m.error()); + } + if(false) // NOLINT + { // void, void is permitted, but is not constructible + result<void, void> *m = nullptr; + m->value(); + m->error(); + } +#endif + + { + // Deliberately define non-trivial operations + struct udt + { + int _v{0}; + udt() = default; + udt(udt &&o) noexcept : _v(o._v) {} + udt(const udt &o) // NOLINT + : _v(o._v) + { + } + udt &operator=(udt &&o) noexcept + { + _v = o._v; + return *this; + } + udt &operator=(const udt &o) // NOLINT + { + _v = o._v; + return *this; + } + ~udt() { _v = 0; } + }; + // No default construction, no copy nor move + struct udt2 + { + udt2() = delete; + udt2(udt2 &&) = delete; + udt2(const udt2 &) = delete; + udt2 &operator=(udt2 &&) = delete; + udt2 &operator=(const udt2 &) = delete; + explicit udt2(int /*unused*/) {} + ~udt2() = default; + }; + // Can only be constructed via multiple args + struct udt3 + { + udt3() = delete; + udt3(udt3 &&) = delete; + udt3(const udt3 &) = delete; + udt3 &operator=(udt3 &&) = delete; + udt3 &operator=(const udt3 &) = delete; + explicit udt3(int /*unused*/, const char * /*unused*/, std::nullptr_t /*unused*/) {} + ~udt3() = default; + }; + + + result<int> a(5); + result<int> b(make_error_code(boost::system::errc::invalid_argument)); + std::cout << sizeof(a) << std::endl; // 32 bytes + if(false) // NOLINT + { + b.assume_value(); + a.assume_error(); + } +#ifndef BOOST_NO_EXCEPTIONS + try + { + b.value(); + std::cerr << "fail" << std::endl; + std::terminate(); + } + catch(const boost::system::system_error & /*unused*/) + { + } +#endif + static_assert(!std::is_default_constructible<decltype(a)>::value, ""); + static_assert(!std::is_nothrow_default_constructible<decltype(a)>::value, ""); + static_assert(std::is_copy_constructible<decltype(a)>::value, ""); +// Quality of implementation of std::optional is poor :( +#ifndef TESTING_WG21_EXPERIMENTAL_RESULT + static_assert(std::is_trivially_copy_constructible<decltype(a)>::value, ""); + static_assert(std::is_nothrow_copy_constructible<decltype(a)>::value, ""); + static_assert(std::is_copy_assignable<decltype(a)>::value, ""); + static_assert(std::is_trivially_copy_assignable<decltype(a)>::value, ""); + static_assert(std::is_nothrow_copy_assignable<decltype(a)>::value, ""); +#endif + static_assert(std::is_trivially_destructible<decltype(a)>::value, ""); + static_assert(std::is_nothrow_destructible<decltype(a)>::value, ""); + + // Test void compiles + result<void> c(in_place_type<void>); + result<void> c2(c); + (void) c2; + + // Test a standard udt compiles + result<udt> d(in_place_type<udt>); + result<udt> d2(d); + static_assert(!std::is_default_constructible<decltype(d)>::value, ""); + static_assert(!std::is_nothrow_default_constructible<decltype(d)>::value, ""); + static_assert(std::is_copy_constructible<decltype(d)>::value, ""); + static_assert(!std::is_trivially_copy_constructible<decltype(d)>::value, ""); + static_assert(!std::is_nothrow_copy_constructible<decltype(d)>::value, ""); + static_assert(std::is_copy_assignable<decltype(d)>::value, ""); + static_assert(!std::is_trivially_copy_assignable<decltype(d)>::value, ""); + static_assert(!std::is_nothrow_copy_assignable<decltype(d)>::value, ""); + static_assert(std::is_move_assignable<decltype(d)>::value, ""); + static_assert(!std::is_trivially_move_assignable<decltype(d)>::value, ""); + static_assert(std::is_nothrow_move_assignable<decltype(d)>::value, ""); + static_assert(!std::is_trivially_destructible<decltype(d)>::value, ""); + static_assert(std::is_nothrow_destructible<decltype(d)>::value, ""); + + // Test a highly pathological udt compiles + result<udt2> e(in_place_type<udt2>, 5); + // result<udt2> e2(e); + static_assert(!std::is_default_constructible<decltype(e)>::value, ""); + static_assert(!std::is_nothrow_default_constructible<decltype(e)>::value, ""); + static_assert(!std::is_copy_constructible<decltype(e)>::value, ""); + static_assert(!std::is_trivially_copy_constructible<decltype(e)>::value, ""); + static_assert(!std::is_nothrow_copy_constructible<decltype(e)>::value, ""); + static_assert(!std::is_copy_assignable<decltype(e)>::value, ""); + static_assert(!std::is_trivially_copy_assignable<decltype(e)>::value, ""); + static_assert(!std::is_nothrow_copy_assignable<decltype(e)>::value, ""); + static_assert(!std::is_move_assignable<decltype(e)>::value, ""); + static_assert(!std::is_trivially_move_assignable<decltype(e)>::value, ""); + static_assert(!std::is_nothrow_move_assignable<decltype(e)>::value, ""); + + // Test a udt which can only be constructed in place compiles + result<udt3> g(in_place_type<udt3>, 5, static_cast<const char *>("niall"), nullptr); + // Does converting inplace construction also work? + result<udt3> h(5, static_cast<const char *>("niall"), nullptr); + result<udt3> i(ENOMEM, boost::system::generic_category()); + BOOST_CHECK(h.has_value()); + BOOST_CHECK(i.has_error()); + } + + // Test direct use of error code enum works + { + constexpr result<int, boost::system::errc::errc_t> a(5), b(boost::system::errc::invalid_argument); + static_assert(a.value() == 5, "a is not 5"); + static_assert(b.error() == boost::system::errc::invalid_argument, "b is not errored"); + BOOST_CHECK_THROW(b.value(), boost::system::system_error); + } + +#ifndef TESTING_WG21_EXPERIMENTAL_RESULT +#ifndef BOOST_NO_EXCEPTIONS + // Test payload facility + { + const char *niall = "niall"; + result<int, payload> b{boost::system::errc::invalid_argument, niall}; + try + { + b.value(); + BOOST_CHECK(false); + } + catch(const payload_exception &e) + { + BOOST_CHECK(!strcmp(e.what(), niall)); + } + catch(...) + { + BOOST_CHECK(false); + } + } +#endif +#endif +} diff --git a/src/boost/libs/outcome/test/tests/coroutine-support.cpp b/src/boost/libs/outcome/test/tests/coroutine-support.cpp new file mode 100644 index 000000000..43c46b09b --- /dev/null +++ b/src/boost/libs/outcome/test/tests/coroutine-support.cpp @@ -0,0 +1,120 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (6 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#if defined(__cpp_coroutines) + +#include <boost/outcome/coroutine_support.hpp> +#include <boost/outcome/outcome.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +namespace coroutines +{ + template <class T> using eager = BOOST_OUTCOME_V2_NAMESPACE::awaitables::eager<T>; + template <class T> using lazy = BOOST_OUTCOME_V2_NAMESPACE::awaitables::lazy<T>; + template <class T, class E = boost::system::error_code> using result = BOOST_OUTCOME_V2_NAMESPACE::result<T, E>; + + inline eager<result<int>> eager_int(int x) { co_return x + 1; } + inline lazy<result<int>> lazy_int(int x) { co_return x + 1; } + inline eager<result<int>> eager_error() { co_return boost::system::errc::not_enough_memory; } + inline lazy<result<int>> lazy_error() { co_return boost::system::errc::not_enough_memory; } + inline eager<result<void>> eager_void() { co_return boost::system::errc::not_enough_memory; } + inline lazy<result<void>> lazy_void() { co_return boost::system::errc::not_enough_memory; } + + template <class U, class... Args> inline eager<result<std::string>> eager_coawait(U &&f, Args... args) + { + BOOST_OUTCOME_CO_TRY(co_await f(args...)); + co_return "hi"; + } + template <class U, class... Args> inline lazy<result<std::string>> lazy_coawait(U &&f, Args... args) + { + BOOST_OUTCOME_CO_TRY(co_await f(args...)); + co_return "hi"; + } + +#ifndef BOOST_NO_EXCEPTIONS + struct custom_exception_type + { + }; + inline lazy<result<int, boost::exception_ptr>> result_exception(boost::exception_ptr e) + { + boost::rethrow_exception(e); + co_return 5; + } + + inline lazy<BOOST_OUTCOME_V2_NAMESPACE::outcome<int>> outcome_exception(boost::exception_ptr e) + { + boost::rethrow_exception(e); + co_return 5; + } +#endif + + inline eager<int> eager_int2(int x) { co_return x + 1; } + inline lazy<int> lazy_int2(int x) { co_return x + 1; } + inline eager<void> eager_void2() { co_return; } + inline lazy<void> lazy_void2() { co_return; } +} // namespace coroutines + +BOOST_OUTCOME_AUTO_TEST_CASE(works_result_coroutine, "Tests that results are eager and lazy awaitable") +{ + using namespace coroutines; + auto eager_await = [](auto t) { return t.await_resume(); }; + auto lazy_await = [](auto t) { + t.await_suspend({}); + return t.await_resume(); + }; + + BOOST_CHECK(eager_await(eager_int(5)).value() == 6); + BOOST_CHECK(lazy_await(lazy_int(5)).value() == 6); + BOOST_CHECK(eager_await(eager_error()).error() == boost::system::errc::not_enough_memory); + BOOST_CHECK(lazy_await(lazy_error()).error() == boost::system::errc::not_enough_memory); + BOOST_CHECK(eager_await(eager_void()).error() == boost::system::errc::not_enough_memory); + BOOST_CHECK(lazy_await(lazy_void()).error() == boost::system::errc::not_enough_memory); + + BOOST_CHECK(eager_await(eager_coawait(eager_int, 5)).value() == "hi"); + BOOST_CHECK(lazy_await(lazy_coawait(lazy_int, 5)).value() == "hi"); + +#ifndef BOOST_NO_EXCEPTIONS + auto e = boost::copy_exception(custom_exception_type()); + BOOST_CHECK_THROW(lazy_await(result_exception(e)).value(), custom_exception_type); + BOOST_CHECK_THROW(lazy_await(outcome_exception(e)).value(), custom_exception_type); +#endif + + BOOST_CHECK(eager_await(eager_int2(5)) == 6); + BOOST_CHECK(lazy_await(lazy_int2(5)) == 6); + eager_await(eager_void2()); + lazy_await(lazy_void2()); +} +#else +int main(void) +{ + return 0; +} +#endif diff --git a/src/boost/libs/outcome/test/tests/default-construction.cpp b/src/boost/libs/outcome/test/tests/default-construction.cpp new file mode 100644 index 000000000..25726abb4 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/default-construction.cpp @@ -0,0 +1,57 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (4 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_default_construction, "Tests that outcome default constructs when it ought to") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + struct udt + { + int _v{78}; + udt() = default; + constexpr explicit udt(int v) noexcept : _v(v) {} + udt(udt &&o) = delete; + udt(const udt &) = delete; + udt &operator=(udt &&o) = delete; + udt &operator=(const udt &) = delete; + ~udt() = default; + constexpr int operator*() const noexcept { return _v; } + }; + // One path is via success_type<void> + outcome<udt> a(success()); + BOOST_CHECK(*a.value() == 78); + + // Other path is via explicit conversion from void + outcome<void> c = success(); + outcome<udt> d(c); + BOOST_CHECK(*d.value() == 78); +} diff --git a/src/boost/libs/outcome/test/tests/experimental-core-outcome-status.cpp b/src/boost/libs/outcome/test/tests/experimental-core-outcome-status.cpp new file mode 100644 index 000000000..b7aed1d8c --- /dev/null +++ b/src/boost/libs/outcome/test/tests/experimental-core-outcome-status.cpp @@ -0,0 +1,225 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (4 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/experimental/status_outcome.hpp> + +#define BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND std +template <class T, class S = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code, class P = BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::exception_ptr> using outcome = BOOST_OUTCOME_V2_NAMESPACE::experimental::status_outcome<T, S, P>; +using BOOST_OUTCOME_V2_NAMESPACE::in_place_type; + +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#include <iostream> + +#ifdef _MSC_VER +#pragma warning(disable : 4702) // unreachable code +#endif + +BOOST_OUTCOME_AUTO_TEST_CASE(works_status_code_outcome, "Tests that the outcome with status_code works as intended") +{ + using namespace BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE; + + { // errored int + outcome<int> m(generic_code{errc::bad_address}); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(m.value(), status_error<void>); + BOOST_CHECK_NO_THROW(m.error()); + BOOST_CHECK_THROW(BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::rethrow_exception(m.failure()), generic_error); + } + { // errored void + outcome<void> m(generic_code{errc::bad_address}); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(([&m]() -> void { return m.value(); }()), generic_error); + BOOST_CHECK_NO_THROW(m.error()); + BOOST_CHECK_THROW(BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::rethrow_exception(m.failure()), generic_error); + } + { // valued int + outcome<int> m(5); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == 5); + m.value() = 6; + BOOST_CHECK(m.value() == 6); + BOOST_CHECK(!m.failure()); + } + { // moves do not clear state + outcome<std::string> m("niall"); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == "niall"); + m.value() = "NIALL"; + BOOST_CHECK(m.value() == "NIALL"); + auto temp(std::move(m).value()); + BOOST_CHECK(temp == "NIALL"); + BOOST_CHECK(m.value().empty()); // NOLINT + } + { // valued void + outcome<void> m(in_place_type<void>); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_NO_THROW(m.value()); // works, but type returned is unusable + BOOST_CHECK(!m.failure()); + } + { // errored + error ec(errc::no_link); + outcome<int> m(ec.clone()); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(m.value(), generic_error); + BOOST_CHECK(m.error() == ec); +#ifndef BOOST_NO_EXCEPTIONS + BOOST_CHECK(m.failure()); + try + { + BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::rethrow_exception(m.failure()); + } + catch(const generic_error &ex) + { + BOOST_CHECK(ex.code() == ec); + BOOST_CHECK(ex.code().value() == errc::no_link); + } +#endif + } +#if !defined(__APPLE__) || defined(__cpp_exceptions) + { // excepted + BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::error_code ec(5, BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::system_category()); + auto e = BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::make_exception_ptr(BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::system_error(ec)); // NOLINT + outcome<int> m(e); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(m.has_exception()); + BOOST_CHECK_THROW(m.value(), BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::system_error); + BOOST_CHECK(m.exception() == e); +#ifndef BOOST_NO_EXCEPTIONS + BOOST_CHECK(m.failure()); + try + { + BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::rethrow_exception(m.failure()); + } + catch(const BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::system_error &ex) + { + BOOST_CHECK(ex.code() == ec); + BOOST_CHECK(ex.code().value() == 5); + } +#endif + } + { // custom error type + struct Foo + { + }; + auto e = BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::make_exception_ptr(Foo()); + outcome<int> m(e); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(m.has_exception()); + BOOST_CHECK_THROW(m.value(), Foo); + BOOST_CHECK(m.exception() == e); + } + { // outcome<void, void> should work + BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::error_code ec(5, BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::system_category()); + auto e = BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::make_exception_ptr(BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::system_error(ec)); + outcome<void, void> m(e); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(!m.has_error()); + BOOST_CHECK(m.has_exception()); + } +#endif + + + { + outcome<int> a(5); + outcome<int> b(generic_code{errc::invalid_argument}); + std::cout << sizeof(a) << std::endl; // 40 bytes + a.assume_value(); + b.assume_error(); +#ifndef BOOST_NO_EXCEPTIONS + try + { + b.value(); + std::cerr << "fail" << std::endl; + std::terminate(); + } + catch(const generic_error & /*unused*/) + { + } +#endif + static_assert(!std::is_default_constructible<decltype(a)>::value, ""); + static_assert(!std::is_nothrow_default_constructible<decltype(a)>::value, ""); + static_assert(!std::is_copy_constructible<decltype(a)>::value, ""); + static_assert(!std::is_trivially_copy_constructible<decltype(a)>::value, ""); + static_assert(!std::is_nothrow_copy_constructible<decltype(a)>::value, ""); + static_assert(!std::is_copy_assignable<decltype(a)>::value, ""); + static_assert(!std::is_trivially_copy_assignable<decltype(a)>::value, ""); + static_assert(!std::is_nothrow_copy_assignable<decltype(a)>::value, ""); + static_assert(!std::is_trivially_destructible<decltype(a)>::value, ""); + static_assert(std::is_nothrow_destructible<decltype(a)>::value, ""); + + // Test void compiles + outcome<void> c(in_place_type<void>); + // Test int, void compiles + outcome<int, void> d(in_place_type<BOOST_OUTCOME_PREVENT_CONVERSION_WORKAROUND::exception_ptr>); + } + + { + // Can only be constructed via multiple args + struct udt3 + { + udt3() = delete; + udt3(udt3 &&) = delete; + udt3(const udt3 &) = delete; + udt3 &operator=(udt3 &&) = delete; + udt3 &operator=(const udt3 &) = delete; + explicit udt3(int /*unused*/, const char * /*unused*/, std::nullptr_t /*unused*/) {} + ~udt3() = default; + }; + // Test a udt which can only be constructed in place compiles + outcome<udt3> g(in_place_type<udt3>, 5, static_cast<const char *>("niall"), nullptr); + // Does converting inplace construction also work? + outcome<udt3> h(5, static_cast<const char *>("niall"), nullptr); + BOOST_CHECK(h.has_value()); + } +} diff --git a/src/boost/libs/outcome/test/tests/experimental-core-result-status.cpp b/src/boost/libs/outcome/test/tests/experimental-core-result-status.cpp new file mode 100644 index 000000000..085c13dd2 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/experimental-core-result-status.cpp @@ -0,0 +1,357 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (8 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/experimental/status_result.hpp> + +template <class T, class S = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code, class NoValuePolicy = BOOST_OUTCOME_V2_NAMESPACE::experimental::policy::default_status_result_policy<T, S>> using result = BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<T, S, NoValuePolicy>; +using BOOST_OUTCOME_V2_NAMESPACE::in_place_type; + +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#include <exception> +#include <iostream> + +#ifndef BOOST_NO_EXCEPTIONS +// Custom error type with payload +struct payload +{ + BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc ec{BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc::success}; + const char *str{nullptr}; + payload() = default; + payload(BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc _ec, const char *_str) + : ec(_ec) + , str(_str) + { + } +}; +struct payload_exception : std::exception +{ + const char *_what{nullptr}; + explicit payload_exception(const char *what) + : _what(what) + { + } + virtual const char *what() const noexcept override final { return _what; } // NOLINT +}; + +class _payload_domain; +using status_code_payload = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<_payload_domain>; +class _payload_domain : public BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code_domain +{ + template <class> friend class status_code; + using _base = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code_domain; + +public: + using value_type = payload; + using string_ref = _base::string_ref; + +public: + constexpr _payload_domain() noexcept : _base(0x7b782c8f935e34ba) {} + + static inline constexpr const _payload_domain &get(); + + virtual _base::string_ref name() const noexcept override final { return string_ref("payload domain"); } // NOLINT +protected: + virtual bool _do_failure(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override final // NOLINT + { + assert(code.domain() == *this); // NOLINT + return static_cast<const status_code_payload &>(code).value().ec != BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc::success; // NOLINT + } + virtual bool _do_equivalent(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code1, const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code2) const noexcept override final // NOLINT + { + assert(code1.domain() == *this); // NOLINT + const auto &c1 = static_cast<const status_code_payload &>(code1); // NOLINT + if(code2.domain() == *this) + { + const auto &c2 = static_cast<const status_code_payload &>(code2); // NOLINT + return c1.value().ec == c2.value().ec; + } + return false; + } + virtual BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::generic_code _generic_code(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override final // NOLINT + { + assert(code.domain() == *this); // NOLINT + return static_cast<const status_code_payload &>(code).value().ec; // NOLINT + } + virtual _base::string_ref _do_message(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override final // NOLINT + { + assert(code.domain() == *this); // NOLINT + const auto &c = static_cast<const status_code_payload &>(code); // NOLINT + return string_ref(BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::detail::generic_code_message(c.value().ec)); + } + virtual void _do_throw_exception(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const override final // NOLINT + { + assert(code.domain() == *this); // NOLINT + const auto &c = static_cast<const status_code_payload &>(code); // NOLINT + throw payload_exception(c.value().str); + } +}; +constexpr _payload_domain payload_domain; +inline constexpr const _payload_domain &_payload_domain::get() +{ + return payload_domain; +} +inline status_code_payload make_status_code(payload c) noexcept +{ + return status_code_payload(BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::in_place, c); +} +#endif + +BOOST_OUTCOME_AUTO_TEST_CASE(works_status_code_result, "Tests that the result with status_code works as intended") +{ + using namespace BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE; + + { // errored int + result<int> m(generic_code{errc::bad_address}); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(m.value(), generic_error); + BOOST_CHECK_NO_THROW(m.error()); + } + { // errored void + result<void> m(generic_code{errc::bad_address}); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(([&m]() -> void { return m.value(); }()), generic_error); + BOOST_CHECK_NO_THROW(m.error()); + } + { // valued int + result<int> m(5); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == 5); + m.value() = 6; + BOOST_CHECK(m.value() == 6); + } + { // valued bool + result<bool> m(false); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == false); + m.value() = true; + BOOST_CHECK(m.value() == true); + } + { // moves do not clear state + result<std::string> m("niall"); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK(m.value() == "niall"); + m.value() = "NIALL"; + BOOST_CHECK(m.value() == "NIALL"); + auto temp(std::move(m).value()); + BOOST_CHECK(temp == "NIALL"); + BOOST_CHECK(m.value().empty()); // NOLINT + } + { // valued void + result<void> m(in_place_type<void>); + BOOST_CHECK(m); + BOOST_CHECK(m.has_value()); + BOOST_CHECK(!m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_NO_THROW(m.value()); // works, but type returned is unusable + } + { // errored + error ec(errc::no_link); + result<int> m(ec.clone()); + BOOST_CHECK(!m); + BOOST_CHECK(!m.has_value()); + BOOST_CHECK(m.has_error()); + // BOOST_CHECK(!m.has_exception()); + BOOST_CHECK_THROW(m.value(), generic_error); + BOOST_CHECK(m.error() == ec); + } + if(false) // NOLINT + { // void, void is permitted, but is not constructible + result<void, void> *m = nullptr; + m->value(); + m->error(); + } + + { + // Deliberately define non-trivial operations + struct udt + { + int _v{0}; + udt() = default; + udt(udt &&o) noexcept : _v(o._v) {} + udt(const udt &o) // NOLINT + : _v(o._v) + { + } + udt &operator=(udt &&o) noexcept + { + _v = o._v; + return *this; + } + udt &operator=(const udt &o) // NOLINT + { + _v = o._v; + return *this; + } + ~udt() { _v = 0; } + }; + // No default construction, no copy nor move + struct udt2 + { + udt2() = delete; + udt2(udt2 &&) = delete; + udt2(const udt2 &) = delete; + udt2 &operator=(udt2 &&) = delete; + udt2 &operator=(const udt2 &) = delete; + explicit udt2(int /*unused*/) {} + ~udt2() = default; + }; + // Can only be constructed via multiple args + struct udt3 + { + udt3() = delete; + udt3(udt3 &&) = delete; + udt3(const udt3 &) = delete; + udt3 &operator=(udt3 &&) = delete; + udt3 &operator=(const udt3 &) = delete; + explicit udt3(int /*unused*/, const char * /*unused*/, std::nullptr_t /*unused*/) {} + ~udt3() = default; + }; + + result<int> a(5); + result<int> b(generic_code{errc::invalid_argument}); + std::cout << sizeof(a) << std::endl; // 32 bytes + if(false) // NOLINT + { + b.assume_value(); + a.assume_error(); + } +#ifndef BOOST_NO_EXCEPTIONS + try + { + b.value(); + std::cerr << "fail" << std::endl; + std::terminate(); + } + catch(const generic_error &e) + { + BOOST_CHECK(!strcmp(e.what(), b.error().message().c_str())); + } +#endif + static_assert(!std::is_default_constructible<decltype(a)>::value, ""); + static_assert(!std::is_nothrow_default_constructible<decltype(a)>::value, ""); + static_assert(!std::is_copy_constructible<decltype(a)>::value, ""); +// Quality of implementation of std::optional is poor :( +#ifndef TESTING_WG21_EXPERIMENTAL_RESULT + static_assert(!std::is_trivially_copy_constructible<decltype(a)>::value, ""); + static_assert(!std::is_nothrow_copy_constructible<decltype(a)>::value, ""); + static_assert(!std::is_copy_assignable<decltype(a)>::value, ""); + static_assert(!std::is_trivially_copy_assignable<decltype(a)>::value, ""); + static_assert(!std::is_nothrow_copy_assignable<decltype(a)>::value, ""); +#endif + static_assert(!std::is_trivially_destructible<decltype(a)>::value, ""); + static_assert(std::is_nothrow_destructible<decltype(a)>::value, ""); + + // Test void compiles + result<void> c(in_place_type<void>); + + // Test a standard udt compiles + result<udt> d(in_place_type<udt>); + static_assert(!std::is_default_constructible<decltype(d)>::value, ""); + static_assert(!std::is_nothrow_default_constructible<decltype(d)>::value, ""); + static_assert(!std::is_copy_constructible<decltype(d)>::value, ""); + static_assert(!std::is_trivially_copy_constructible<decltype(d)>::value, ""); + static_assert(!std::is_nothrow_copy_constructible<decltype(d)>::value, ""); + static_assert(!std::is_copy_assignable<decltype(d)>::value, ""); + static_assert(!std::is_trivially_copy_assignable<decltype(d)>::value, ""); + static_assert(!std::is_nothrow_copy_assignable<decltype(d)>::value, ""); + static_assert(std::is_move_assignable<decltype(d)>::value, ""); + static_assert(!std::is_trivially_move_assignable<decltype(d)>::value, ""); + static_assert(std::is_nothrow_move_assignable<decltype(d)>::value, ""); + static_assert(!std::is_trivially_destructible<decltype(d)>::value, ""); + static_assert(std::is_nothrow_destructible<decltype(d)>::value, ""); + + // Test a highly pathological udt compiles + result<udt2> e(in_place_type<udt2>, 5); + // result<udt2> e2(e); + static_assert(!std::is_default_constructible<decltype(e)>::value, ""); + static_assert(!std::is_nothrow_default_constructible<decltype(e)>::value, ""); + static_assert(!std::is_copy_constructible<decltype(e)>::value, ""); + static_assert(!std::is_trivially_copy_constructible<decltype(e)>::value, ""); + static_assert(!std::is_nothrow_copy_constructible<decltype(e)>::value, ""); + static_assert(!std::is_copy_assignable<decltype(e)>::value, ""); + static_assert(!std::is_trivially_copy_assignable<decltype(e)>::value, ""); + static_assert(!std::is_nothrow_copy_assignable<decltype(e)>::value, ""); + static_assert(!std::is_move_assignable<decltype(e)>::value, ""); + static_assert(!std::is_trivially_move_assignable<decltype(e)>::value, ""); + static_assert(!std::is_nothrow_move_assignable<decltype(e)>::value, ""); + + // Test a udt which can only be constructed in place compiles + result<udt3> g(in_place_type<udt3>, 5, static_cast<const char *>("niall"), nullptr); + // Does converting inplace construction also work? + result<udt3> h(5, static_cast<const char *>("niall"), nullptr); + result<udt3> i(generic_code{errc::not_enough_memory}); + BOOST_CHECK(h.has_value()); + BOOST_CHECK(i.has_error()); + } + + // Test direct use of error code enum works + { + constexpr result<int, errc, BOOST_OUTCOME_V2_NAMESPACE::policy::all_narrow> a(5), b(errc::invalid_argument); + static_assert(a.value() == 5, "a is not 5"); + static_assert(b.error() == errc::invalid_argument, "b is not errored"); + } + +#ifndef BOOST_NO_EXCEPTIONS + // Test payload facility + { + const char *niall = "niall"; + result<int, status_code_payload> b{payload{errc::invalid_argument, niall}}; + try + { + b.value(); + BOOST_CHECK(false); + } + catch(const payload_exception &e) + { + BOOST_CHECK(!strcmp(e.what(), niall)); + } + catch(...) + { + BOOST_CHECK(false); + } + } +#endif +} diff --git a/src/boost/libs/outcome/test/tests/experimental-p0709a.cpp b/src/boost/libs/outcome/test/tests/experimental-p0709a.cpp new file mode 100644 index 000000000..8823568ae --- /dev/null +++ b/src/boost/libs/outcome/test/tests/experimental-p0709a.cpp @@ -0,0 +1,169 @@ +/* Unit testing for outcomes +(C) 2017-2020 Niall Douglas <http://www.nedproductions.biz/> (7 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/experimental/status_result.hpp> + +#include <climits> // for INT_MAX +#include <cstdio> + +// status_code<erased<intptr_t>> +using error = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error; +// Outcome's result must be told when it is dealing with an erased status code +template <class T, class E> using result = BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<T, E, BOOST_OUTCOME_V2_NAMESPACE::policy::all_narrow>; + +enum class arithmetic_errc +{ + success, + divide_by_zero, + integer_divide_overflows, + not_integer_division +}; + +class _arithmetic_errc_domain; +using arithmetic_errc_error = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<_arithmetic_errc_domain>; + +class _arithmetic_errc_domain : public BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code_domain +{ + using _base = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code_domain; + +public: + using value_type = arithmetic_errc; + + constexpr explicit _arithmetic_errc_domain(typename _base::unique_id_type id = 0x290f170194f0c6c7) noexcept : _base(id) {} + static inline constexpr const _arithmetic_errc_domain &get(); + + virtual _base::string_ref name() const noexcept override final // NOLINT + { + static string_ref v("arithmetic error domain"); + return v; // NOLINT + } + +protected: + virtual bool _do_failure(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override final // NOLINT + { + assert(code.domain() == *this); // NOLINT + const auto &c1 = static_cast<const arithmetic_errc_error &>(code); // NOLINT + return c1.value() != arithmetic_errc::success; + } + virtual bool _do_equivalent(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &, const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &) const noexcept override final { return false; } // NOLINT + virtual BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::generic_code _generic_code(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &) const noexcept override final { return {}; } // NOLINT + virtual _base::string_ref _do_message(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override final // NOLINT + { + assert(code.domain() == *this); // NOLINT + const auto &c1 = static_cast<const arithmetic_errc_error &>(code); // NOLINT + switch(c1.value()) + { + case arithmetic_errc::success: + return _base::string_ref("success"); + case arithmetic_errc::divide_by_zero: + return _base::string_ref("divide by zero"); + case arithmetic_errc::integer_divide_overflows: + return _base::string_ref("integer divide overflows"); + case arithmetic_errc::not_integer_division: + return _base::string_ref("not integer division"); + } + return _base::string_ref("unknown"); + } + BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &) const override final { abort(); } // NOLINT +}; + +constexpr _arithmetic_errc_domain arithmetic_errc_domain; +inline constexpr const _arithmetic_errc_domain &_arithmetic_errc_domain::get() +{ + return arithmetic_errc_domain; +} + + +// Tell status code about the available implicit conversion +inline arithmetic_errc_error make_status_code(arithmetic_errc e) +{ + return arithmetic_errc_error(BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::in_place, e); +} + +BOOST_OUTCOME_V2_NAMESPACE_BEGIN +namespace trait +{ + // Tell Outcome that arithmetic_errc is convertible into std::error + template <> struct is_error_type_enum<error, arithmetic_errc> + { + static constexpr bool value = true; + }; +} +BOOST_OUTCOME_V2_NAMESPACE_END +// And tell Outcome how to perform the implicit conversion +inline error make_error_code(arithmetic_errc e) +{ + return arithmetic_errc_error(BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::in_place, e); +} + + +result<int, error> safe_divide(int i, int j) +{ + if(j == 0) + { + return arithmetic_errc::divide_by_zero; + } + if(i == INT_MIN && j == -1) + { + return arithmetic_errc::integer_divide_overflows; + } + if(i % j != 0) + { + return arithmetic_errc::not_integer_division; + } + return i / j; +} + +int caller2(int i, int j) +{ + auto r = safe_divide(i, j); + if(r) + { + return r.value(); + } + if(r.error() == arithmetic_errc::divide_by_zero) + { + return 0; + } + if(r.error() == arithmetic_errc::not_integer_division) + { + return i / j; // ignore + } + if(r.error() == arithmetic_errc::integer_divide_overflows) + { + return INT_MIN; + } + return 0; +} + +int main() +{ + printf("%d\n", caller2(5, 6)); // NOLINT + return 0; +} diff --git a/src/boost/libs/outcome/test/tests/fileopen.cpp b/src/boost/libs/outcome/test/tests/fileopen.cpp new file mode 100644 index 000000000..f2634d4fd --- /dev/null +++ b/src/boost/libs/outcome/test/tests/fileopen.cpp @@ -0,0 +1,87 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (7 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#define _CRT_SECURE_NO_WARNINGS + +#include <boost/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#ifndef BOOST_NO_EXCEPTIONS + +#ifdef _MSC_VER +#define BOOST_OUTCOME_POSIX_OPEN ::_open +#include <io.h> +#else +#define BOOST_OUTCOME_POSIX_OPEN ::open +#include <fcntl.h> +#endif + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_fileopen, "Tests that the outcome semantically represents opening a file") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + + //! [file_open_example] + auto openfile = [](std::string path) noexcept->outcome<int> + { + int fd; + do + { + fd = BOOST_OUTCOME_POSIX_OPEN(path.c_str(), 0); // NOLINT + } while(-1 == fd && EINTR == errno); + try + { + if(-1 == fd) + { + int code = errno; + // If a temporary failure, this is an expected unexpected outcome + if(EBUSY == code || EISDIR == code || ELOOP == code || ENOENT == code || ENOTDIR == code || EPERM == code || EACCES == code) + { + return boost::system::error_code(code, boost::system::generic_category()); + } + // If a non-temporary failure, this is an unexpected outcome + return boost::copy_exception(boost::system::system_error(code, boost::system::generic_category(), strerror(code))); + } + return fd; + } + catch(...) + { + // Any exception thrown is truly unexpected + return boost::current_exception(); + } + }; + auto a = openfile("shouldneverexistnotever"); + BOOST_CHECK(!a); + BOOST_CHECK(!a.has_value()); + BOOST_CHECK(!a.has_exception()); + BOOST_CHECK(a.has_error()); + BOOST_CHECK(a.error() == boost::system::error_code(ENOENT, boost::system::generic_category())); + //! [file_open_example] +} +#endif diff --git a/src/boost/libs/outcome/test/tests/hooks.cpp b/src/boost/libs/outcome/test/tests/hooks.cpp new file mode 100644 index 000000000..857113cde --- /dev/null +++ b/src/boost/libs/outcome/test/tests/hooks.cpp @@ -0,0 +1,114 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (14 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#define _CRT_SECURE_NO_WARNINGS + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#include <iostream> + +namespace hook_test +{ + using BOOST_OUTCOME_V2_NAMESPACE::in_place_type; + // Use static storage to convey extended error info from result construction to outcome conversion + static char extended_error_info[256]; + + // Use the error_code type as the ADL bridge for the hooks by creating a type here + struct error_code : public boost::system::error_code + { + using boost::system::error_code::error_code; + error_code() = default; + error_code(boost::system::error_code ec) // NOLINT + : boost::system::error_code(ec) + { + } + }; + // Localise result to using the local error_code so this namespace gets looked up for the hooks + template <class R> using result = BOOST_OUTCOME_V2_NAMESPACE::result<R, error_code>; + // Specialise the result construction hook for our localised result + template <class U> constexpr inline void hook_result_construction(result<int> *res, U && /*unused*/) noexcept + { + // Write the value in the result into the static storage + snprintf(extended_error_info, sizeof(extended_error_info), "%d", res->assume_value()); // NOLINT + } + template <class U> constexpr inline void hook_result_construction(result<std::string> *res, U && /*unused*/) noexcept + { + // Write the value in the result into the static storage + snprintf(extended_error_info, sizeof(extended_error_info), "%s", res->assume_value().c_str()); // NOLINT + } +} // namespace hook_test + +BOOST_OUTCOME_AUTO_TEST_CASE(works_result_hooks, "Tests that you can hook result's construction") +{ + using namespace hook_test; + result<int> a(5); + BOOST_CHECK(!strcmp(extended_error_info, "5")); // NOLINT + result<std::string> b("niall"); + BOOST_CHECK(!strcmp(extended_error_info, "niall")); // NOLINT +} + +//! [extended_error_coding2] +namespace hook_test +{ + // Localise outcome to using the local error_code so this namespace gets looked up for the hooks + template <class R> using outcome = BOOST_OUTCOME_V2_NAMESPACE::outcome<R, error_code, std::string>; + + // Specialise the outcome copy and move conversion hook for our localised result + template <class T, class U> constexpr inline void hook_outcome_copy_construction(outcome<T> *res, const result<U> & /*unused*/) noexcept + { + // when copy constructing from a result<T>, place extended_error_coding::extended_error_info into the payload + std::cout << "hook_outcome_copy_construction fires" << std::endl; + BOOST_OUTCOME_V2_NAMESPACE::hooks::override_outcome_exception(res, extended_error_info); + } + template <class T, class U> constexpr inline void hook_outcome_move_construction(outcome<T> *res, result<U> && /*unused*/) noexcept + { + // when move constructing from a result<T>, place extended_error_coding::extended_error_info into the payload + std::cout << "hook_outcome_move_construction fires" << std::endl; + BOOST_OUTCOME_V2_NAMESPACE::hooks::override_outcome_exception(res, extended_error_info); + } +} // namespace hook_test + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_hooks, "Tests that you can hook outcome's conversion from a result") +{ + using namespace hook_test; + outcome<int> a(result<int>(5)); + BOOST_REQUIRE(a.has_exception()); // NOLINT + BOOST_CHECK(a.exception() == "5"); + outcome<std::string> b(result<std::string>("niall")); + BOOST_CHECK(b.exception() == "niall"); + + // Make sure hook does not fire for any other kind of outcome copy or move, only when converting from our custom result only + outcome<int> c(5); + outcome<long> d(c); // can't be the same type as source, else copy elision takes place and no ADL hook calling + BOOST_CHECK(!d.has_exception()); + outcome<int> e(BOOST_OUTCOME_V2_NAMESPACE::result<int>(5)); + BOOST_CHECK(!e.has_exception()); +} diff --git a/src/boost/libs/outcome/test/tests/issue0007.cpp b/src/boost/libs/outcome/test/tests/issue0007.cpp new file mode 100644 index 000000000..d890c333e --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0007.cpp @@ -0,0 +1,81 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0007_test, "BOOST_OUTCOME_TRYV(expr) in a function whose return outcome's type has no default constructor fails to compile") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + struct udt // NOLINT + { + explicit udt(int /*unused*/) {} + // udt() = delete; + udt(const udt &) = default; + udt(udt &&) = default; + }; + { + auto f = []() -> result<udt> { + auto g = [] { return result<int>(5); }; + /* This fails because BOOST_OUTCOME_TRYV() returns a result<void> + which if it were valued void, would implicitly convert into a + default constructed udt which is not possible, hence the compile error. + */ + BOOST_OUTCOME_TRYV(g()); + return udt(5); + }; + (void) f(); + } + { + auto f = []() -> outcome<udt> { + auto g = [] { return outcome<int>(5); }; + /* This fails because BOOST_OUTCOME_TRYV() returns a result<void> + which if it were valued void, would implicitly convert into a + default constructed udt which is not possible, hence the compile error. + */ + BOOST_OUTCOME_TRYV(g()); + return udt(5); + }; + (void) f(); + } + { + auto f = []() -> outcome<udt> { + auto g = [] { return result<int>(5); }; + /* This fails because BOOST_OUTCOME_TRYV() returns a result<void> + which if it were valued void, would implicitly convert into a + default constructed udt which is not possible, hence the compile error. + */ + BOOST_OUTCOME_TRYV(g()); + return udt(5); + }; + (void) f(); + } +} diff --git a/src/boost/libs/outcome/test/tests/issue0009.cpp b/src/boost/libs/outcome/test/tests/issue0009.cpp new file mode 100644 index 000000000..7a61cfc92 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0009.cpp @@ -0,0 +1,52 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0009_test, "Alternative TRY macros?") +{ +#ifdef BOOST_OUTCOME_TRYX + using namespace BOOST_OUTCOME_V2_NAMESPACE; + struct udt // NOLINT + { + explicit udt(int /*unused*/) {} + // udt() = delete; + udt(const udt &) = default; + udt(udt &&) = default; + }; + auto f = []() -> result<udt> { + auto g = [] { return result<int>(5); }; + return udt(BOOST_OUTCOME_TRYX(g())); + }; + (void) f(); +#endif +} diff --git a/src/boost/libs/outcome/test/tests/issue0010.cpp b/src/boost/libs/outcome/test/tests/issue0010.cpp new file mode 100644 index 000000000..84a897773 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0010.cpp @@ -0,0 +1,88 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (9 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0010_test, "Expected's operator->(), operator*() and .error() throw exceptions when they should not") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + const char *a = "hi", *b = "bye"; + struct udt1 // NOLINT + { + const char *_v{nullptr}; + udt1() = default; + constexpr explicit udt1(const char *v) noexcept : _v(v) {} + constexpr udt1(udt1 &&o) noexcept : _v(o._v) { o._v = nullptr; } + udt1(const udt1 &) = default; + constexpr udt1 &operator=(udt1 &&o) noexcept + { + _v = o._v; + o._v = nullptr; + return *this; + } + udt1 &operator=(const udt1 &) = delete; + constexpr const char *operator*() const noexcept { return _v; } + }; + struct udt2 // NOLINT + { + const char *_v{nullptr}; + udt2() = default; + constexpr explicit udt2(const char *v) noexcept : _v(v) {} + constexpr udt2(udt2 &&o) noexcept : _v(o._v) { o._v = nullptr; } + udt2(const udt2 &) = default; + constexpr udt2 &operator=(udt2 &&o) noexcept + { + _v = o._v; + o._v = nullptr; + return *this; + } + udt1 &operator=(const udt1 &) = delete; + constexpr const char *operator*() const noexcept { return _v; } + }; + result<udt1, udt2> p(udt1{a}); + result<udt1, udt2> n(udt2{b}); + // State check + BOOST_CHECK(p.has_value()); + BOOST_CHECK(!n.has_value()); + // These should behave as expected (!) + // BOOST_CHECK_NO_THROW(p.value()); + // BOOST_CHECK_NO_THROW(n.value()); + // And state is not destroyed + BOOST_CHECK(p.has_value() && *p.assume_value() == a); + BOOST_CHECK(!n.has_value() && *n.assume_error() == b); + // LEWG Expected provides rvalue ref semantics for operator*(), error() and error_or() + udt1 a1(std::move(p.assume_value())); + BOOST_CHECK(*a1 == a); + BOOST_CHECK(*p.assume_value() == nullptr); + udt2 e2(std::move(n).assume_error()); + BOOST_CHECK(*e2 == b); + BOOST_CHECK(*n.assume_error() == nullptr); // NOLINT +} diff --git a/src/boost/libs/outcome/test/tests/issue0012.cpp b/src/boost/libs/outcome/test/tests/issue0012.cpp new file mode 100644 index 000000000..ff5d3c83e --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0012.cpp @@ -0,0 +1,59 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0012_test, "outcome's copy assignment gets instantiated even when type T cannot be copied") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + const char *s = "hi"; + struct udt // NOLINT + { + const char *_v{nullptr}; + udt() = default; + constexpr explicit udt(const char *v) noexcept : _v(v) {} + constexpr udt(udt &&o) noexcept : _v(o._v) { o._v = nullptr; } + udt(const udt &) = delete; + constexpr udt &operator=(udt &&o) noexcept + { + _v = o._v; + o._v = nullptr; + return *this; + } + udt &operator=(const udt &) = delete; + constexpr const char *operator*() const noexcept { return _v; } + }; + static_assert(std::is_move_constructible<outcome<udt>>::value, "expected<udt> is not move constructible!"); + static_assert(!std::is_copy_constructible<outcome<udt>>::value, "expected<udt> is copy constructible!"); + outcome<udt> p(udt{s}), n(boost::system::error_code(ENOMEM, boost::system::generic_category())); + n = boost::system::error_code(EINVAL, boost::system::generic_category()); + BOOST_CHECK(n.error().value() == EINVAL); +} diff --git a/src/boost/libs/outcome/test/tests/issue0016.cpp b/src/boost/libs/outcome/test/tests/issue0016.cpp new file mode 100644 index 000000000..ddf5dd158 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0016.cpp @@ -0,0 +1,56 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0016_test, "Default constructor of T is sometimes compiled when T has no default constructor") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + struct udt + { + const char *_v{nullptr}; + udt() = delete; + constexpr explicit udt(const char *v) noexcept : _v(v) {} + constexpr udt(udt &&o) noexcept : _v(o._v) { o._v = nullptr; } + udt(const udt &) = delete; + constexpr udt &operator=(udt &&o) noexcept + { + _v = o._v; + o._v = nullptr; + return *this; + } + udt &operator=(const udt &) = delete; + ~udt() = default; + constexpr const char *operator*() const noexcept { return _v; } + }; + result<udt> n(boost::system::error_code(ENOMEM, boost::system::generic_category())); + (void) n; +} diff --git a/src/boost/libs/outcome/test/tests/issue0059.cpp b/src/boost/libs/outcome/test/tests/issue0059.cpp new file mode 100644 index 000000000..867ec6670 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0059.cpp @@ -0,0 +1,60 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (8 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/result.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0059_test, "result<NonMovable> supported?") +{ +#if defined(_MSC_VER) || __cplusplus >= 201700 + using namespace BOOST_OUTCOME_V2_NAMESPACE; + struct udt + { + const char *_v{nullptr}; + udt() = delete; + constexpr udt(const char *v) noexcept : _v(v) {} // NOLINT + udt(udt &&o) = delete; + udt(const udt &) = delete; + udt &operator=(udt &&o) = delete; + udt &operator=(const udt &) = delete; + ~udt() = default; + constexpr const char *operator*() const noexcept { return _v; } + }; + const char *niall = "niall"; + auto f = [niall]() -> result<void> { + auto g = [niall]() -> result<udt> { return {niall}; }; + BOOST_OUTCOME_TRY(v, g()); // this must never copy nor move + BOOST_CHECK(*v == niall); + return success(); + }; + (void) f(); +#endif +} diff --git a/src/boost/libs/outcome/test/tests/issue0061.cpp b/src/boost/libs/outcome/test/tests/issue0061.cpp new file mode 100644 index 000000000..aab9a3bff --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0061.cpp @@ -0,0 +1,128 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (6 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0061_result, "result<T1, E1> does not compare to incompatible result<T2, E2>") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + struct udt1 + { + const char *_v{nullptr}; + udt1() = default; + constexpr udt1(const char *v) noexcept : _v(v) {} // NOLINT + udt1(udt1 &&o) = delete; + udt1(const udt1 &) = delete; + udt1 &operator=(udt1 &&o) = delete; + udt1 &operator=(const udt1 &) = delete; + ~udt1() = default; + constexpr const char *operator*() const noexcept { return _v; } + }; + struct udt2 + { + const char *_v{nullptr}; + udt2() = default; + constexpr explicit udt2(const char *v) noexcept : _v(v) {} + udt2(udt2 &&o) = delete; + udt2(const udt2 &) = delete; + udt2 &operator=(udt2 &&o) = delete; + udt2 &operator=(const udt2 &) = delete; + ~udt2() = default; + constexpr const char *operator*() const noexcept { return _v; } + bool operator==(const udt1 &o) const noexcept { return _v == *o; } + bool operator!=(const udt1 &o) const noexcept { return _v != *o; } + }; + using result1 = result<int, udt1>; + using result2 = result<int, udt2>; + + result1 a(5); + result2 b(5); + BOOST_CHECK(b == a); // udt2 will compare to udt1 + BOOST_CHECK(!(b != a)); // udt2 will compare to udt1 + + result<void> c = success(); + result<void> d = success(); + BOOST_CHECK(c == d); + BOOST_CHECK(!(c != d)); + + BOOST_CHECK(a == success()); + BOOST_CHECK(success() == a); + BOOST_CHECK(b != failure("foo")); + BOOST_CHECK(failure("foo") != b); +} + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0061_outcome, "outcome<T1, E1, P1> does not compare to incompatible outcome<T2, E2, P2>") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + struct udt1 + { + const char *_v{nullptr}; + udt1() = default; + constexpr udt1(const char *v) noexcept : _v(v) {} // NOLINT + udt1(udt1 &&o) = delete; + udt1(const udt1 &) = delete; + udt1 &operator=(udt1 &&o) = delete; + udt1 &operator=(const udt1 &) = delete; + ~udt1() = default; + constexpr const char *operator*() const noexcept { return _v; } + }; + struct udt2 + { + const char *_v{nullptr}; + udt2() = default; + constexpr explicit udt2(const char *v) noexcept : _v(v) {} + udt2(udt2 &&o) = delete; + udt2(const udt2 &) = delete; + udt2 &operator=(udt2 &&o) = delete; + udt2 &operator=(const udt2 &) = delete; + ~udt2() = default; + constexpr const char *operator*() const noexcept { return _v; } + bool operator==(const udt1 &o) const noexcept { return _v == *o; } + bool operator!=(const udt1 &o) const noexcept { return _v != *o; } + }; + using outcome1 = outcome<int, udt1>; + using outcome2 = outcome<int, udt2>; + + outcome1 a(5), _a(6); + outcome2 b(5); + BOOST_CHECK(b == a); // udt2 will compare to udt1 + BOOST_CHECK(!(b != a)); // udt2 will compare to udt1 + + outcome<void> c = success(); + outcome<void> d = success(); + BOOST_CHECK(c == d); + BOOST_CHECK(!(c != d)); + + BOOST_CHECK(a == success()); + BOOST_CHECK(success() == a); + BOOST_CHECK(b != failure("foo")); + BOOST_CHECK(failure("foo") != b); +} diff --git a/src/boost/libs/outcome/test/tests/issue0064.cpp b/src/boost/libs/outcome/test/tests/issue0064.cpp new file mode 100644 index 000000000..6dbdcd91c --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0064.cpp @@ -0,0 +1,50 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (4 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/iostream_support.hpp> +#include <boost/outcome/outcome.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0064_outcome, "BOOST_OUTCOME_TRY on excepted outcome is propagating a null error rather than just an exception") +{ +#ifndef BOOST_NO_EXCEPTIONS + using namespace BOOST_OUTCOME_V2_NAMESPACE; + auto f = []() -> outcome<int> { + auto h = []() -> outcome<int> { return boost::copy_exception(std::runtime_error("hello")); }; + BOOST_OUTCOME_TRY((h())); + return 0; + }(); + std::cout << print(f) << std::endl; + BOOST_CHECK(!f.has_value()); + BOOST_CHECK(!f.has_error()); + BOOST_CHECK(f.has_exception()); +#endif +} diff --git a/src/boost/libs/outcome/test/tests/issue0065.cpp b/src/boost/libs/outcome/test/tests/issue0065.cpp new file mode 100644 index 000000000..c537a38a7 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0065.cpp @@ -0,0 +1,66 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (3 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0065_outcome, "BOOST_OUTCOME_TRY does not preserve the exception_ptr") +{ +#ifndef BOOST_NO_EXCEPTIONS + using namespace BOOST_OUTCOME_V2_NAMESPACE; + auto g = []() -> outcome<int> { + auto f = []() -> outcome<int> { + try + { + throw std::runtime_error{"XXX"}; + } + catch(...) + { + return boost::current_exception(); + } + }; + BOOST_OUTCOME_TRY(ans, (f())); + return ans; + }; + outcome<int> o = g(); + BOOST_CHECK(!o); + BOOST_CHECK(o.has_exception()); + try + { + o.value(); + BOOST_CHECK(false); + } + catch(const std::runtime_error &e) + { + BOOST_CHECK(!strcmp(e.what(), "XXX")); + } +#endif +} diff --git a/src/boost/libs/outcome/test/tests/issue0071.cpp b/src/boost/libs/outcome/test/tests/issue0071.cpp new file mode 100644 index 000000000..333fb2088 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0071.cpp @@ -0,0 +1,45 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (4 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/result.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0071_outcome, "Implicit construction is over eager") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + struct udt + { + int v; + explicit udt(int a) + : v(a){}; + }; + result<udt> m = udt{5}; + BOOST_CHECK(m.value().v == 5); +} diff --git a/src/boost/libs/outcome/test/tests/issue0095.cpp b/src/boost/libs/outcome/test/tests/issue0095.cpp new file mode 100644 index 000000000..c1ed1d460 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0095.cpp @@ -0,0 +1,58 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (6 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/result.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +namespace issue0095 +{ + namespace out = BOOST_OUTCOME_V2_NAMESPACE; + + struct E + { + }; + // struct F : E {}; + struct F + { + operator E() const { return E{}; } // NOLINT + }; + + out::result<int, F> f() { return F{}; } + out::result<int, E> e() + { + BOOST_OUTCOME_TRY(i, (f())); + return i; + } +} // namespace issue0095 +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0095_outcome, "operator conversions on E type cause TRY to fail") +{ + BOOST_CHECK(issue0095::e().has_error()); +} diff --git a/src/boost/libs/outcome/test/tests/issue0115.cpp b/src/boost/libs/outcome/test/tests/issue0115.cpp new file mode 100644 index 000000000..17d852274 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0115.cpp @@ -0,0 +1,57 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (1 commit) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0115_outcome, "Initialization from `failure_type` drops default-constructed values") +{ + namespace out = BOOST_OUTCOME_V2_NAMESPACE; + + out::outcome<int> o1 = boost::system::error_code{}; + BOOST_CHECK(o1.has_error()); + BOOST_CHECK(!o1.has_exception()); + + out::outcome<int> o2 = out::failure(boost::system::error_code{}); + BOOST_CHECK(o2.has_error()); + BOOST_CHECK(!o2.has_exception()); + + out::outcome<int> o3(boost::system::error_code{}, boost::exception_ptr{}); + BOOST_CHECK(o3.has_error()); + BOOST_CHECK(o3.has_exception()); + + out::outcome<int> o4 = out::failure(boost::system::error_code{}, boost::exception_ptr{}); + BOOST_CHECK(o4.has_error()); + BOOST_CHECK(o4.has_exception()); + + out::outcome<int> o5 = out::failure(boost::exception_ptr{}); + BOOST_CHECK(!o5.has_error()); + BOOST_CHECK(o5.has_exception()); +} diff --git a/src/boost/libs/outcome/test/tests/issue0116.cpp b/src/boost/libs/outcome/test/tests/issue0116.cpp new file mode 100644 index 000000000..168c3e5c4 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0116.cpp @@ -0,0 +1,45 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (2 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0116_outcome, "Bad implementation of outcome::operator==") +{ + namespace out = BOOST_OUTCOME_V2_NAMESPACE; + + out::outcome<int> o1 = 1; + BOOST_CHECK(!o1.has_error()); + + out::outcome<int> o2 = out::failure(boost::system::error_code{EINVAL, boost::system::generic_category()}); + BOOST_CHECK(o2.has_error()); + + BOOST_CHECK(o1 != o2); +} diff --git a/src/boost/libs/outcome/test/tests/issue0140.cpp b/src/boost/libs/outcome/test/tests/issue0140.cpp new file mode 100644 index 000000000..bb86f0619 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0140.cpp @@ -0,0 +1,96 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (2 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0140_result, "Construction of non copy constructible value_type fails to not compile") +{ + namespace out = BOOST_OUTCOME_V2_NAMESPACE; + + enum op + { + constructed, + moved, + copied + }; + struct NotCopyMoveConstructible + { + op v{op::constructed}; + NotCopyMoveConstructible() = default; + NotCopyMoveConstructible(const NotCopyMoveConstructible &o) = delete; + NotCopyMoveConstructible(NotCopyMoveConstructible &&) = delete; + NotCopyMoveConstructible &operator=(const NotCopyMoveConstructible &) = delete; + NotCopyMoveConstructible &operator=(NotCopyMoveConstructible &&) = delete; + ~NotCopyMoveConstructible() = default; + }; + struct NotMoveConstructible + { + op v{op::constructed}; + NotMoveConstructible() = default; + NotMoveConstructible(const NotMoveConstructible & /*unused*/) + : v(op::copied) + { + } + NotMoveConstructible(NotMoveConstructible &&) = delete; + NotMoveConstructible &operator=(const NotMoveConstructible &) = delete; + NotMoveConstructible &operator=(NotMoveConstructible &&) = delete; + ~NotMoveConstructible() = default; + }; + struct NotCopyConstructible + { + op v{op::constructed}; + NotCopyConstructible() = default; + NotCopyConstructible(NotCopyConstructible && /*unused*/) noexcept : v(op::moved) {} + NotCopyConstructible(const NotCopyConstructible & /*unused*/) = delete; + NotCopyConstructible &operator=(const NotCopyConstructible &) = delete; + NotCopyConstructible &operator=(NotCopyConstructible &&) = delete; + ~NotCopyConstructible() = default; + }; + + // Uncopyable and immovable items should be neither copyable nor moveable + static_assert(!std::is_copy_constructible<out::result<NotCopyMoveConstructible>>::value, "result<NotCopyMoveConstructible> is copy constructible!"); + static_assert(!std::is_move_constructible<out::result<NotCopyMoveConstructible>>::value, "result<NotCopyMoveConstructible> is move constructible!"); + static_assert(!std::is_convertible<const NotCopyMoveConstructible &, NotCopyMoveConstructible>::value, ""); + static_assert(!std::is_convertible<NotCopyMoveConstructible &&, NotCopyMoveConstructible>::value, ""); + static_assert(!std::is_constructible<out::result<NotCopyMoveConstructible>, const NotCopyMoveConstructible &>::value, "result<NotCopyMoveConstructible> is constructible from const NotCopyMoveConstructible&!"); + static_assert(!std::is_constructible<out::result<NotCopyMoveConstructible>, NotCopyMoveConstructible &&>::value, "result<NotCopyMoveConstructible> is constructible from NotCopyMoveConstructible&&!"); + + // Immovable items should fall back to copy + static_assert(!std::is_move_constructible<NotMoveConstructible>::value, "NotMoveConstructible is move constructible!"); + static_assert(std::is_move_constructible<out::result<NotMoveConstructible>>::value, "result<NotMoveConstructible> is not move constructible!"); + static_assert(std::is_constructible<out::result<NotMoveConstructible>, const NotMoveConstructible &>::value, "result<NotMoveConstructible> is not constructible from NotMoveConstructible&&!"); + + // Uncopyable items should never move (this was the bug report) + static_assert(!std::is_copy_constructible<out::result<NotCopyConstructible>>::value, "result<NotCopyConstructible> is copy constructible!"); + static_assert(!std::is_constructible<out::result<NotCopyConstructible>, const NotCopyConstructible &>::value, "result<NotCopyConstructible> is constructible from const NotCopyConstructible&!"); + + BOOST_CHECK(true); +} diff --git a/src/boost/libs/outcome/test/tests/issue0182.cpp b/src/boost/libs/outcome/test/tests/issue0182.cpp new file mode 100644 index 000000000..7bf06d424 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0182.cpp @@ -0,0 +1,42 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (1 commit) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0189_test, "result<void, int>.value() compiles without tripping fail_to_compile_observers") +{ + namespace outcome = BOOST_OUTCOME_V2_NAMESPACE; + static_assert(!outcome::trait::is_error_code_available<int>::value, "int is clearly not a source for make_error_code()"); + static_assert(!outcome::trait::is_exception_ptr_available<int>::value, "int is clearly not a source for make_exception_ptr()"); + //outcome::result<void, int> r(5); + //r.value(); + BOOST_CHECK(true); +} diff --git a/src/boost/libs/outcome/test/tests/issue0203.cpp b/src/boost/libs/outcome/test/tests/issue0203.cpp new file mode 100644 index 000000000..800fa8373 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0203.cpp @@ -0,0 +1,103 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (1 commit) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/std_result.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +namespace outcome = BOOST_OUTCOME_V2_NAMESPACE; + +enum class error +{ + test, + abcde +}; + +class error_category_impl : public std::error_category +{ +public: + const char *name() const noexcept override { return "test"; } + + std::string message(int code) const noexcept override + { + switch(static_cast<error>(code)) + { + case error::test: + return "test"; + case error::abcde: + return "abcde"; + } + return "unknown"; + } +}; +const std::error_category &error_category() noexcept +{ + static error_category_impl instance; + return instance; +} + +boost::system::error_code make_error_code(error error) noexcept +{ + return {static_cast<int>(error), error_category()}; +} + +namespace std +{ + template <> struct is_error_code_enum<error> : true_type + { + }; +} // namespace std + +template <typename T> using enum_result = outcome::basic_result<T, error, outcome::policy::default_policy<T, error, void>>; + +enum_result<int> test() +{ + return 5; +} + +outcome::std_result<int> abc() +{ + static_assert(std::is_error_code_enum<error>::value, "custom enum is not marked convertible to error code"); + static_assert(std::is_constructible<boost::system::error_code, error>::value, "error code is not explicitly constructible from custom enum"); + static_assert(std::is_convertible<error, boost::system::error_code>::value, "error code is not implicitly constructible from custom enum"); + boost::system::error_code ec = error::test; // custom enum is definitely convertible to error code + BOOST_OUTCOME_TRY(test()); // hence this should compile, as implicit conversions work here + (void) ec; + + // But explicit conversions are required between dissimilar basic_result, implicit conversions are disabled + static_assert(std::is_constructible<outcome::std_result<int>, enum_result<int>>::value, "basic_result with error code is not explicitly constructible from basic_result with custom enum"); + static_assert(!std::is_convertible<enum_result<int>, outcome::std_result<int>>::value, "basic_result with error code is implicitly constructible from basic_result with custom enum"); + return 5; +} + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0203_test, "enum convertible to error code works as designed") +{ + BOOST_CHECK(abc().value() == 5); +} diff --git a/src/boost/libs/outcome/test/tests/issue0210.cpp b/src/boost/libs/outcome/test/tests/issue0210.cpp new file mode 100644 index 000000000..0ac1b759a --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0210.cpp @@ -0,0 +1,78 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (1 commit) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +namespace issues210 +{ + namespace outcome = BOOST_OUTCOME_V2_NAMESPACE; + + struct error + { + boost::system::error_code code; + }; + + // say that my custom error code type is error code compatible + inline boost::system::error_code make_error_code(error error) noexcept { return error.code; } + + template <typename T> using custom_result = outcome::basic_result<T, error, outcome::policy::default_policy<T, error, void>>; + + // source of custom result type with error code compatible error type + inline custom_result<int> funcA(int x) { return x; } + + // Is the custom result type explicitly constructible to an ordinary result type? + inline outcome::result<int> funcB(int x) { return outcome::result<int>(funcA(x)); } + + // Does the custom result type TRY-convert to an ordinary result type? + inline outcome::result<int> func1(int x) + { + BOOST_OUTCOME_TRY(y, funcA(x)); + return funcB(y); + } + + // Is the custom result type explicitly constructible to an ordinary outcome type? + inline outcome::outcome<int> funcC(int x) { return outcome::outcome<int>(funcA(x)); } + + // Does the custom result type TRY-convert to an ordinary outcome type? + inline outcome::outcome<int> func2(int x) + { + BOOST_OUTCOME_TRY(y, funcA(x)); + return funcC(y); + } +} // namespace issues210 + + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0210_test, "result<int, E> with error code compatible custom E does not TRY into a result<int, boost::system::error_code> function") +{ + BOOST_CHECK(issues210::func1(5).value() == 5); + BOOST_CHECK(issues210::func2(5).value() == 5); +} diff --git a/src/boost/libs/outcome/test/tests/issue0220.cpp b/src/boost/libs/outcome/test/tests/issue0220.cpp new file mode 100644 index 000000000..0da6eaf16 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/issue0220.cpp @@ -0,0 +1,55 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (1 commit) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/experimental/status_result.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX +namespace issues220 +{ + namespace outcome_e = BOOST_OUTCOME_V2_NAMESPACE::experimental; + + template <class T, class E = outcome_e::error> using Result = outcome_e::status_result<T, E>; + + template <class T> using PosixResult = outcome_e::status_result<T, outcome_e::posix_code>; + + Result<int> convert(const PosixResult<int> &posix_result) { return Result<int>(posix_result); } +} // namespace issues220 +#endif + + +BOOST_OUTCOME_AUTO_TEST_CASE(issues_0220_test, "ubsan reports reference binding to null pointer") +{ +#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX + using namespace issues220; + BOOST_CHECK(convert(PosixResult<int>(0)).value() == 0); +#endif +} diff --git a/src/boost/libs/outcome/test/tests/noexcept-propagation.cpp b/src/boost/libs/outcome/test/tests/noexcept-propagation.cpp new file mode 100644 index 000000000..3754ff44d --- /dev/null +++ b/src/boost/libs/outcome/test/tests/noexcept-propagation.cpp @@ -0,0 +1,84 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (6 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#ifdef _MSC_VER +#pragma warning(disable : 4127) // conditional expression is constant +#endif + +#ifndef BOOST_NO_EXCEPTIONS +// std nothrow traits seem to return random values if exceptions are disabled on MSVC +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_noexcept, "Tests that the outcome correctly inherits noexcept from its type R") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + { + using type = outcome<int>; + BOOST_CHECK(std::is_nothrow_copy_constructible<type>::value); + BOOST_CHECK(std::is_nothrow_move_constructible<type>::value); + BOOST_CHECK(std::is_nothrow_copy_assignable<type>::value); + BOOST_CHECK(std::is_nothrow_move_assignable<type>::value); + BOOST_CHECK(std::is_nothrow_destructible<type>::value); + } + { + using type = outcome<std::string>; + BOOST_CHECK(std::is_nothrow_copy_constructible<type>::value == std::is_nothrow_copy_constructible<std::string>::value); + BOOST_CHECK(std::is_nothrow_move_constructible<type>::value == std::is_nothrow_move_constructible<std::string>::value); + BOOST_CHECK(std::is_nothrow_copy_assignable<type>::value == std::is_nothrow_copy_assignable<std::string>::value); + BOOST_CHECK(std::is_nothrow_move_assignable<type>::value == std::is_nothrow_move_assignable<std::string>::value); + BOOST_CHECK(std::is_nothrow_destructible<type>::value == std::is_nothrow_destructible<std::string>::value); + } + { + struct Except + { + int n; + Except() = delete; + Except(const Except & /*unused*/) noexcept(false) + : n(0) + { + } + Except(Except && /*unused*/) noexcept(false) + : n(0) + { + } + Except &operator=(const Except & /*unused*/) noexcept(false) { return *this; } + Except &operator=(Except && /*unused*/) noexcept(false) { return *this; } + ~Except() noexcept(false) { n = 0; } + }; + using type = outcome<Except>; + BOOST_CHECK(!std::is_nothrow_copy_constructible<type>::value); + BOOST_CHECK(!std::is_nothrow_move_constructible<type>::value); + BOOST_CHECK(!std::is_nothrow_copy_assignable<type>::value); + BOOST_CHECK(!std::is_nothrow_move_assignable<type>::value); + BOOST_CHECK(!std::is_nothrow_destructible<type>::value); + } +} +#endif diff --git a/src/boost/libs/outcome/test/tests/propagate.cpp b/src/boost/libs/outcome/test/tests/propagate.cpp new file mode 100644 index 000000000..0e3cbb545 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/propagate.cpp @@ -0,0 +1,90 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (7 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/outcome/try.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_propagate, "Tests that the outcome propagates errors between different editions of itself") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + { + auto t0 = [&](int a) { return result<long>(boost::system::error_code(a, boost::system::generic_category())); }; + auto t1 = [&](int a) { + result<double> f(t0(a)); // double is constructible from long + BOOST_CHECK(!f.has_value()); + BOOST_CHECK(f.has_error()); + return f; + }; + auto t2 = [&](int a) { + result<void> f(t1(a).error()); + BOOST_CHECK(!f.has_value()); + BOOST_CHECK(f.has_error()); + return f; + }; + auto t3 = [&](int a) { + outcome<std::string> f(t2(a)); + BOOST_CHECK(!f.has_value()); + BOOST_CHECK(f.has_error()); + return f; + }; + BOOST_CHECK(t3(5).error().value() == 5); + result<int> a2{result<void>(in_place_type<void>)}; + result<int> a3{result<void>(boost::system::error_code(5, boost::system::generic_category()))}; + BOOST_CHECK(a2.has_value()); + BOOST_CHECK(!a2.has_error()); + BOOST_CHECK(!a3.has_value()); + BOOST_CHECK(a3.has_error()); + } + { + auto t0 = [&](int a) { return result<long>(a); }; + auto t1 = [&](int a) -> result<std::string> { + BOOST_OUTCOME_TRY(f, (t0(a))); + return std::to_string(f); + }; + BOOST_CHECK(t1(5).value() == "5"); + } + { + auto t0 = [&](int a) { return result<long>(a); }; + auto t1 = [&](int a) -> outcome<std::string> { + BOOST_OUTCOME_TRY(f, (t0(a))); + return std::to_string(f); + }; + BOOST_CHECK(t1(5).value() == "5"); + } + { + auto t0 = [&](int a) -> result<long> { return result<long>(a); }; + auto t1 = [&](int a) -> outcome<void> { + BOOST_OUTCOME_TRY((t0(a))); + return outcome<void>(in_place_type<void>); + }; + (void) t1(5); + } +} diff --git a/src/boost/libs/outcome/test/tests/serialisation.cpp b/src/boost/libs/outcome/test/tests/serialisation.cpp new file mode 100644 index 000000000..55d978dd5 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/serialisation.cpp @@ -0,0 +1,49 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (7 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/iostream_support.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_serialisation, "Tests that the outcome serialises and deserialises as intended") +{ +#if !defined(__APPLE__) || defined(__cpp_exceptions) + using namespace BOOST_OUTCOME_V2_NAMESPACE; + outcome<std::string> a("niall"), b(boost::system::error_code(5, boost::system::generic_category())), c(boost::copy_exception(std::ios_base::failure("A test failure message"))); + std::cout << "a contains " << print(a) << " and b contains " << print(b) << " and c contains " << print(c) << std::endl; + + std::stringstream ss; + outcome<int, std::string, long> d(success(5)); + ss << d; + ss.seekg(0); + outcome<int, std::string, long> e(failure("")); + ss >> e; + BOOST_CHECK(d == e); +#endif +} diff --git a/src/boost/libs/outcome/test/tests/success-failure.cpp b/src/boost/libs/outcome/test/tests/success-failure.cpp new file mode 100644 index 000000000..af1c3e46d --- /dev/null +++ b/src/boost/libs/outcome/test/tests/success-failure.cpp @@ -0,0 +1,69 @@ +/* Unit testing for outcomes +(C) 2017-2020 Niall Douglas <http://www.nedproductions.biz/> (10 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/result.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +#include <iostream> + +BOOST_OUTCOME_AUTO_TEST_CASE(works_success_failure, "Tests that the success and failure type sugars work as intended") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; +#ifdef __cpp_deduction_guides + std::cout << "__cpp_deduction_guides = 1" << std::endl; +#endif + { + auto a = success(5); + auto b = success(); + auto c = success("hello"); + static_assert(std::is_same<decltype(a), success_type<int>>::value, ""); + static_assert(std::is_same<decltype(b), success_type<void>>::value, ""); + static_assert(std::is_same<decltype(c), success_type<const char *>>::value, ""); + static_assert(std::is_same<decltype(a)::value_type, int>::value, ""); + // static_assert(std::is_same<decltype(b.value), int>::value, ""); + static_assert(std::is_same<decltype(c)::value_type, const char *>::value, ""); + } +#if !defined(__APPLE__) || defined(__cpp_exceptions) + { + auto e = boost::copy_exception(std::exception()); + auto a = failure(5); + auto b = failure(5, e); + auto c = failure(5, 5); + static_assert(std::is_same<decltype(a), failure_type<int, void>>::value, ""); + static_assert(std::is_same<decltype(b), failure_type<int, boost::exception_ptr>>::value, ""); + static_assert(std::is_same<decltype(c), failure_type<int, int>>::value, ""); + static_assert(std::is_same<decltype(a)::error_type, int>::value, ""); + static_assert(std::is_same<decltype(b)::error_type, int>::value, ""); + static_assert(std::is_same<decltype(b)::exception_type, boost::exception_ptr>::value, ""); + static_assert(std::is_same<decltype(c)::error_type, int>::value, ""); + static_assert(std::is_same<decltype(c)::exception_type, int>::value, ""); + } +#endif +} diff --git a/src/boost/libs/outcome/test/tests/swap.cpp b/src/boost/libs/outcome/test/tests/swap.cpp new file mode 100644 index 000000000..0bcba3802 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/swap.cpp @@ -0,0 +1,432 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +/* Should be this: + +78 move constructor count = 2 +65 move assignment count = 3 +78 move assignment count = 1 +65 move constructor count = 2 +78 move assignment count = 0 +65 move assignment count = 1 + +78 move constructor count = 1 +65 move assignment count = 2 +78 move assignment count = 0 +65 move assignment count = 1 +78 move assignment count = 0 + +78 move constructor count = 2 +65 move assignment count = 3 +78 move assignment count = 1 +65 move constructor count = 2 +78 move assignment count = 0 +65 move assignment count = 1 + +78 move constructor count = 1 +65 move assignment count = 2 +78 move assignment count = 0 +65 move assignment count = 1 +78 move assignment count = 0 + +78 move constructor count = 2 +65 move assignment count = 3 +78 move assignment count = 1 +65 move constructor count = 2 +78 move assignment count = 0 +65 move assignment count = 1 + +78 move constructor count = 1 +65 move assignment count = 2 +78 move assignment count = 0 +65 move assignment count = 1 +78 move assignment count = 0 + +78 move constructor count = 2 +65 move assignment count = 3 +78 move assignment count = 1 +65 move constructor count = 2 +78 move assignment count = 0 +65 move assignment count = 1 + +78 move constructor count = 1 +65 move assignment count = 2 +78 move assignment count = 0 +65 move assignment count = 1 +78 move assignment count = 0 +*/ + +#ifndef BOOST_NO_EXCEPTIONS +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4297) // function assumed not to throw an exception but does +#endif +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wterminate" +#endif +template <bool mc, bool ma> struct Throwy +{ + int count{0}, inc{0}, id{0}; + Throwy() = default; + Throwy(int c, int d, int i = 1) noexcept + : count(c) + , inc(i) + , id(d) + { + } + Throwy(const Throwy &) = delete; + Throwy &operator=(const Throwy &) = delete; + Throwy(Throwy &&o) noexcept(!mc) + : count(o.count - o.inc) + , inc(o.inc) + , id(o.id) // NOLINT + { + if(mc) + { + std::cout << " " << id << " move constructor count = " << count << std::endl; + if(!count) + { + std::cout << " " << id << " move constructor throws!" << std::endl; + throw std::bad_alloc(); + } + } + o.count = 0; + o.inc = 0; + o.id = 0; + } + Throwy &operator=(Throwy &&o) noexcept(!ma) + { + count = o.count - o.inc; + if(ma) + { + std::cout << " " << o.id << " move assignment count = " << count << std::endl; + if(!count) + { + std::cout << " " << o.id << " move assignment throws!" << std::endl; + throw std::bad_alloc(); + } + } + inc = o.inc; + id = o.id; + o.count = 0; + o.inc = 0; + o.id = 0; + return *this; + } + ~Throwy() = default; +}; +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif +enum class ErrorCode +{ + dummy +}; +enum class ErrorCode2 +{ + dummy +}; +template <bool mc, bool ma> using resulty1 = BOOST_OUTCOME_V2_NAMESPACE::result<Throwy<mc, ma>, ErrorCode, BOOST_OUTCOME_V2_NAMESPACE::policy::all_narrow>; +template <bool mc, bool ma> using resulty2 = BOOST_OUTCOME_V2_NAMESPACE::result<ErrorCode, Throwy<mc, ma>, BOOST_OUTCOME_V2_NAMESPACE::policy::all_narrow>; +template <bool mc, bool ma> using outcomey1 = BOOST_OUTCOME_V2_NAMESPACE::outcome<ErrorCode, Throwy<mc, ma>, ErrorCode2, BOOST_OUTCOME_V2_NAMESPACE::policy::all_narrow>; +template <bool mc, bool ma> using outcomey2 = BOOST_OUTCOME_V2_NAMESPACE::outcome<ErrorCode, ErrorCode2, Throwy<mc, ma>, BOOST_OUTCOME_V2_NAMESPACE::policy::all_narrow>; +#endif + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_swap, "Tests that the outcome swaps as intended") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + { // Does swap actually swap? + outcome<std::string> a("niall"), b("douglas"); + BOOST_CHECK(a.value() == "niall"); + BOOST_CHECK(b.value() == "douglas"); + swap(a, b); + BOOST_CHECK(a.value() == "douglas"); + BOOST_CHECK(b.value() == "niall"); + a = boost::system::errc::not_enough_memory; + swap(a, b); + BOOST_CHECK(a.value() == "niall"); + BOOST_CHECK(b.error() == boost::system::errc::not_enough_memory); + BOOST_CHECK(!a.has_lost_consistency()); + BOOST_CHECK(!b.has_lost_consistency()); + } +#ifndef BOOST_NO_EXCEPTIONS + { // Is noexcept propagated? + using nothrow_t = Throwy<false, false>; + using nothrow = resulty1<false, false>; + static_assert(std::is_nothrow_move_constructible<nothrow_t>::value, "throwy not correct!"); + static_assert(std::is_nothrow_move_assignable<nothrow_t>::value, "throwy not correct!"); + static_assert(std::is_nothrow_move_constructible<nothrow>::value, "type not correct!"); + static_assert(std::is_nothrow_move_assignable<nothrow>::value, "type not correct!"); + + static_assert(detail::is_nothrow_swappable<nothrow_t>::value, "is_nothrow_swappable is not correct!"); + + static_assert(noexcept(nothrow(0, 0)), "type has a throwing value constructor!"); + nothrow a(1, 78), b(1, 65); + a.swap(b); + static_assert(noexcept(a.swap(b)), "type has a throwing swap!"); + } + { // Is noexcept propagated? + using nothrow_t = Throwy<false, false>; + using nothrow = resulty2<false, false>; + static_assert(std::is_nothrow_move_constructible<nothrow_t>::value, "throwy not correct!"); + static_assert(std::is_nothrow_move_assignable<nothrow_t>::value, "throwy not correct!"); + static_assert(std::is_nothrow_move_constructible<nothrow>::value, "type not correct!"); + static_assert(std::is_nothrow_move_assignable<nothrow>::value, "type not correct!"); + + static_assert(detail::is_nothrow_swappable<nothrow_t>::value, "is_nothrow_swappable is not correct!"); + + static_assert(noexcept(nothrow(0, 0)), "type has a throwing value constructor!"); + nothrow a(1, 78), b(1, 65); + a.swap(b); + static_assert(noexcept(a.swap(b)), "type has a throwing swap!"); + } + + { // Does swap implement the strong guarantee? + using throwy_t = Throwy<true, true>; + using throwy = resulty1<true, true>; + static_assert(!std::is_nothrow_move_constructible<throwy_t>::value, "throwy not correct!"); + static_assert(!std::is_nothrow_move_assignable<throwy_t>::value, "throwy not correct!"); + static_assert(!std::is_nothrow_move_constructible<throwy>::value, "type not correct!"); + static_assert(!std::is_nothrow_move_assignable<throwy>::value, "type not correct!"); + + static_assert(!detail::is_nothrow_swappable<throwy_t>::value, "is_nothrow_swappable is not correct!"); + + std::cout << "Result value first swap succeeds, second swap second move assignment throws:" << std::endl; + { + throwy a(3, 78), b(4, 65); + a.swap(b); + static_assert(!noexcept(a.swap(b)), "type has a non-throwing swap!"); + BOOST_CHECK(a.value().id == 65); + BOOST_CHECK(b.value().id == 78); + try + { + a.swap(b); // fails on first assignment + BOOST_REQUIRE(false); + } + catch(const std::bad_alloc & /*unused*/) + { + BOOST_CHECK(a.value().id == 65); // ensure it is perfectly restored + BOOST_CHECK(b.value().id == 78); + } + BOOST_CHECK(!a.has_lost_consistency()); + BOOST_CHECK(!b.has_lost_consistency()); + } + std::cout << "\nResult value second move assignment throws, on recover second move assignment throws:" << std::endl; + { + throwy a(2, 78), b(3, 65); // fails on second assignment, cannot restore + try + { + a.swap(b); + BOOST_REQUIRE(false); + } + catch(const std::bad_alloc & /*unused*/) + { + BOOST_CHECK(a.has_lost_consistency()); // both must be marked tainted + BOOST_CHECK(b.has_lost_consistency()); + } + } + } + std::cout << "\nResult error first swap succeeds, second swap first move assignment throws:" << std::endl; + { // Does swap implement the strong guarantee? + using throwy_t = Throwy<true, true>; + using throwy = resulty2<true, true>; + static_assert(!std::is_nothrow_move_constructible<throwy_t>::value, "throwy not correct!"); + static_assert(!std::is_nothrow_move_assignable<throwy_t>::value, "throwy not correct!"); + static_assert(!std::is_nothrow_move_constructible<throwy>::value, "type not correct!"); + static_assert(!std::is_nothrow_move_assignable<throwy>::value, "type not correct!"); + + static_assert(!detail::is_nothrow_swappable<throwy_t>::value, "is_nothrow_swappable is not correct!"); + + { + throwy a(3, 78), b(4, 65); + a.swap(b); + static_assert(!noexcept(a.swap(b)), "type has a non-throwing swap!"); + BOOST_CHECK(a.error().id == 65); + BOOST_CHECK(b.error().id == 78); + try + { + a.swap(b); // fails on first assignment + BOOST_REQUIRE(false); + } + catch(const std::bad_alloc & /*unused*/) + { + BOOST_CHECK(a.error().id == 65); // ensure it is perfectly restored + BOOST_CHECK(b.error().id == 78); + } + BOOST_CHECK(!a.has_lost_consistency()); + BOOST_CHECK(!b.has_lost_consistency()); + } + std::cout << "\nResult error second move assignment throws, on recover second move assignment throws:" << std::endl; + { + throwy a(2, 78), b(3, 65); // fails on second assignment, cannot restore + try + { + a.swap(b); + BOOST_REQUIRE(false); + } + catch(const std::bad_alloc & /*unused*/) + { + BOOST_CHECK(a.has_lost_consistency()); // both must be marked tainted + BOOST_CHECK(b.has_lost_consistency()); + } + } + } + + { // Is noexcept propagated? + using nothrow_t = Throwy<false, false>; + using nothrow = outcomey1<false, false>; + static_assert(std::is_nothrow_move_constructible<nothrow_t>::value, "throwy not correct!"); + static_assert(std::is_nothrow_move_assignable<nothrow_t>::value, "throwy not correct!"); + static_assert(std::is_nothrow_move_constructible<nothrow>::value, "type not correct!"); + static_assert(std::is_nothrow_move_assignable<nothrow>::value, "type not correct!"); + + static_assert(detail::is_nothrow_swappable<nothrow_t>::value, "is_nothrow_swappable is not correct!"); + + static_assert(noexcept(nothrow(0, 0)), "type has a throwing value constructor!"); + nothrow a(1, 78), b(1, 65); + a.swap(b); + static_assert(noexcept(a.swap(b)), "type has a throwing swap!"); + } + { // Is noexcept propagated? + using nothrow_t = Throwy<false, false>; + using nothrow = outcomey1<false, false>; + static_assert(std::is_nothrow_move_constructible<nothrow_t>::value, "throwy not correct!"); + static_assert(std::is_nothrow_move_assignable<nothrow_t>::value, "throwy not correct!"); + static_assert(std::is_nothrow_move_constructible<nothrow>::value, "type not correct!"); + static_assert(std::is_nothrow_move_assignable<nothrow>::value, "type not correct!"); + + static_assert(detail::is_nothrow_swappable<nothrow_t>::value, "is_nothrow_swappable is not correct!"); + + static_assert(noexcept(nothrow(0, 0)), "type has a throwing value constructor!"); + nothrow a(1, 78), b(1, 65); + a.swap(b); + static_assert(noexcept(a.swap(b)), "type has a throwing swap!"); + } + + std::cout << "\n\nOutcome value first swap succeeds, second swap first move assignment throws:" << std::endl; + { // Does swap implement the strong guarantee? + using throwy_t = Throwy<true, true>; + using throwy = outcomey1<true, true>; + static_assert(!std::is_nothrow_move_constructible<throwy_t>::value, "throwy not correct!"); + static_assert(!std::is_nothrow_move_assignable<throwy_t>::value, "throwy not correct!"); + static_assert(!std::is_nothrow_move_constructible<throwy>::value, "type not correct!"); + static_assert(!std::is_nothrow_move_assignable<throwy>::value, "type not correct!"); + + static_assert(!detail::is_nothrow_swappable<throwy_t>::value, "is_nothrow_swappable is not correct!"); + + { + throwy a(3, 78), b(4, 65); + a.swap(b); + static_assert(!noexcept(a.swap(b)), "type has a non-throwing swap!"); + BOOST_CHECK(a.error().id == 65); + BOOST_CHECK(b.error().id == 78); + try + { + a.swap(b); // fails on first assignment + BOOST_REQUIRE(false); + } + catch(const std::bad_alloc & /*unused*/) + { + BOOST_CHECK(a.error().id == 65); // ensure it is perfectly restored + BOOST_CHECK(b.error().id == 78); + } + BOOST_CHECK(!a.has_lost_consistency()); + BOOST_CHECK(!b.has_lost_consistency()); + } + std::cout << "\nOutcome value second move assignment throws, on recover second move assignment throws:" << std::endl; + { + throwy a(2, 78), b(3, 65); // fails on second assignment, cannot restore + try + { + a.swap(b); + BOOST_REQUIRE(false); + } + catch(const std::bad_alloc & /*unused*/) + { + BOOST_CHECK(a.has_lost_consistency()); // both must be marked tainted + BOOST_CHECK(b.has_lost_consistency()); + } + } + } + std::cout << "\nOutcome error first swap succeeds, second swap first move assignment throws:" << std::endl; + { // Does swap implement the strong guarantee? + using throwy_t = Throwy<true, true>; + using throwy = outcomey2<true, true>; + static_assert(!std::is_nothrow_move_constructible<throwy_t>::value, "throwy not correct!"); + static_assert(!std::is_nothrow_move_assignable<throwy_t>::value, "throwy not correct!"); + static_assert(!std::is_nothrow_move_constructible<throwy>::value, "type not correct!"); + static_assert(!std::is_nothrow_move_assignable<throwy>::value, "type not correct!"); + + static_assert(!detail::is_nothrow_swappable<throwy_t>::value, "is_nothrow_swappable is not correct!"); + + { + throwy a(3, 78), b(4, 65); + a.swap(b); + static_assert(!noexcept(a.swap(b)), "type has a non-throwing swap!"); + BOOST_CHECK(a.exception().id == 65); + BOOST_CHECK(b.exception().id == 78); + try + { + a.swap(b); // fails on first assignment + BOOST_REQUIRE(false); + } + catch(const std::bad_alloc & /*unused*/) + { + BOOST_CHECK(a.exception().id == 65); // ensure it is perfectly restored + BOOST_CHECK(b.exception().id == 78); + } + BOOST_CHECK(!a.has_lost_consistency()); + BOOST_CHECK(!b.has_lost_consistency()); + } + std::cout << "\nOutcome error second move assignment throws, on recover second move assignment throws:" << std::endl; + { + throwy a(2, 78), b(3, 65); // fails on second assignment, cannot restore + try + { + a.swap(b); + BOOST_REQUIRE(false); + } + catch(const std::bad_alloc & /*unused*/) + { + BOOST_CHECK(a.has_lost_consistency()); // both must be marked tainted + BOOST_CHECK(b.has_lost_consistency()); + } + } + std::cout << std::endl; + } +#endif +} diff --git a/src/boost/libs/outcome/test/tests/udts.cpp b/src/boost/libs/outcome/test/tests/udts.cpp new file mode 100644 index 000000000..740ca51d2 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/udts.cpp @@ -0,0 +1,154 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (7 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#ifdef _MSC_VER +#pragma warning(disable : 4702) // unreachable code +#endif + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_udts, "Tests that the outcome works as intended with user-defined types") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + // No default constructor, no copy/move, no assignment + { + struct udt + { + int a; + explicit udt(int _a) + : a(_a) + { + } + udt() = delete; + udt(const udt &) = delete; + udt(udt &&) = delete; + udt &operator=(const udt &) = delete; + udt &operator=(udt &&) = delete; + ~udt() = default; + }; + outcome<udt> foo(in_place_type<udt>, 5); + BOOST_CHECK(5 == foo.value().a); + } +#ifndef BOOST_NO_EXCEPTIONS + // Emplace construct, throws during move and copy + { + struct udt + { + std::string a; + explicit udt(std::string _a) + : a(std::move(_a)) + { + } + udt() = delete; + udt(const udt & /*unused*/) { throw std::logic_error("copy"); } + udt(udt && /*unused*/) noexcept(false) { throw std::logic_error("move"); } // NOLINT + udt &operator=(const udt & /*unused*/) { throw std::logic_error("copy"); } + udt &operator=(udt && /*unused*/) noexcept(false) { throw std::logic_error("move"); } // NOLINT + ~udt() { a.clear(); } + }; + static_assert(!std::is_default_constructible<udt>::value, "udt is default constructible"); + static_assert(std::is_copy_constructible<udt>::value, "udt is not copy constructible"); + static_assert(std::is_move_constructible<udt>::value, "udt is not move constructible"); + static_assert(!std::is_default_constructible<outcome<udt>>::value, "outcome<udt> is default constructible"); + static_assert(std::is_copy_constructible<outcome<udt>>::value, "outcome<udt> is not copy constructible"); + static_assert(std::is_move_constructible<outcome<udt>>::value, "outcome<udt> is not move constructible"); + // Emplace constructs + outcome<udt> foo(in_place_type<udt>, "niall"); + BOOST_CHECK("niall" == foo.value().a); + try + { + auto foo2(foo); // NOLINT + BOOST_CHECK(false); + } + catch(const std::logic_error &e) + { + BOOST_CHECK(!strcmp(e.what(), "copy")); + } + catch(...) + { + BOOST_CHECK(false); + } + BOOST_CHECK("niall" == foo.value().a); + try + { + auto foo2(std::move(foo)); + BOOST_CHECK(false); + } + catch(const std::logic_error &e) + { + BOOST_CHECK(!strcmp(e.what(), "move")); + } + catch(...) + { + BOOST_CHECK(false); + } + BOOST_CHECK("niall" == foo.value().a); // NOLINT + // Does throwing during copy assignment work? + { + outcome<udt> foo2(in_place_type<udt>, "douglas"); + try + { + foo2 = foo; + BOOST_CHECK(false); + } + catch(const std::logic_error &e) + { + BOOST_CHECK(!strcmp(e.what(), "copy")); + BOOST_CHECK(foo2.value().a == "douglas"); + } + catch(...) + { + BOOST_CHECK(false); + } + BOOST_CHECK("niall" == foo.value().a); + } + // Does throwing during move assignment work? + { + outcome<udt> foo2(in_place_type<udt>, "douglas"); + try + { + foo2 = std::move(foo); + BOOST_CHECK(false); + } + catch(const std::logic_error &e) + { + BOOST_CHECK(!strcmp(e.what(), "move")); + BOOST_CHECK(foo2.value().a == "douglas"); + } + catch(...) + { + BOOST_CHECK(false); + } + BOOST_CHECK("niall" == foo.value().a); // NOLINT + } + } +#endif +} diff --git a/src/boost/libs/outcome/test/tests/value-or-error.cpp b/src/boost/libs/outcome/test/tests/value-or-error.cpp new file mode 100644 index 000000000..558e229a7 --- /dev/null +++ b/src/boost/libs/outcome/test/tests/value-or-error.cpp @@ -0,0 +1,54 @@ +/* Unit testing for outcomes +(C) 2013-2020 Niall Douglas <http://www.nedproductions.biz/> (3 commits) + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include <boost/outcome/outcome.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/test/unit_test_monitor.hpp> + +BOOST_OUTCOME_AUTO_TEST_CASE(works_outcome_valueorerror, "Tests that outcome constructs from ValueOrError and ValueOrNone concept inputs") +{ + using namespace BOOST_OUTCOME_V2_NAMESPACE; + { + struct value_or_error + { + using value_type = int; + using error_type = void; + bool has_value() const { return true; } + int value() const { return 78; } + void error() const {} + } a; + static_assert(convert::ValueOrNone<value_or_error>, ""); + static_assert(convert::ValueOrError<value_or_error>, ""); + BOOST_CHECK((convert::value_or_error<result<long>, value_or_error>{}(a).value() == 78)); + + result<long> b(a); + BOOST_CHECK(b.has_value()); + BOOST_CHECK(b.value() == 78); + } +} |