New upstream version 8.1.0
This commit is contained in:
324
thirdparty/source/nu/tests/error_or.cpp
vendored
Normal file
324
thirdparty/source/nu/tests/error_or.cpp
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
#include <nu/error_or.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
// LCOV_EXCL_START
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(error_or, example)
|
||||
{
|
||||
#include "error_or_example.cpp"
|
||||
}
|
||||
|
||||
using namespace nu;
|
||||
|
||||
struct ctor_throws {
|
||||
ctor_throws(ctor_throws&&);
|
||||
ctor_throws& operator=(ctor_throws&&) noexcept;
|
||||
};
|
||||
|
||||
struct dtor_throws {
|
||||
~dtor_throws() noexcept(false);
|
||||
};
|
||||
|
||||
struct swap_throws {
|
||||
};
|
||||
|
||||
[[gnu::unused]]
|
||||
void swap(swap_throws&, swap_throws) {}
|
||||
|
||||
struct called_mask {
|
||||
bool dtor;
|
||||
bool swap;
|
||||
};
|
||||
|
||||
struct track_calls {
|
||||
called_mask* called;
|
||||
int v;
|
||||
|
||||
track_calls(called_mask& c, int v): called(&c), v(v) {}
|
||||
|
||||
~track_calls() {
|
||||
called->dtor = true;
|
||||
}
|
||||
|
||||
friend void swap(track_calls& a, track_calls& b) noexcept {
|
||||
std::swap(a, b);
|
||||
a.called->swap = true;
|
||||
b.called->swap = true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
TEST(error_or, noexceptness)
|
||||
{
|
||||
using std::declval;
|
||||
|
||||
EXPECT_TRUE(std::is_nothrow_default_constructible<error_or<int>>::value);
|
||||
|
||||
EXPECT_TRUE(std::is_nothrow_destructible<error_or<int>>::value);
|
||||
EXPECT_FALSE(std::is_nothrow_destructible<error_or<dtor_throws>>::value);
|
||||
|
||||
EXPECT_TRUE((std::is_nothrow_constructible<error_or<int>, std::error_code>::value));
|
||||
|
||||
EXPECT_TRUE((std::is_nothrow_constructible<error_or<int>, int>::value));
|
||||
EXPECT_FALSE((std::is_nothrow_constructible<error_or<ctor_throws>, ctor_throws>::value));
|
||||
|
||||
EXPECT_TRUE((std::is_nothrow_move_constructible<error_or<int>>::value));
|
||||
EXPECT_FALSE((std::is_nothrow_move_constructible<error_or<ctor_throws>>::value));
|
||||
|
||||
EXPECT_TRUE(noexcept(swap(declval<error_or<int>&>(), declval<error_or<int>&>())));
|
||||
EXPECT_FALSE(noexcept(swap(declval<error_or<swap_throws>&>(), declval<error_or<swap_throws>&>())));
|
||||
|
||||
EXPECT_TRUE((std::is_nothrow_move_assignable<error_or<int>>::value));
|
||||
EXPECT_FALSE((std::is_nothrow_move_assignable<error_or<ctor_throws>>::value));
|
||||
}
|
||||
|
||||
TEST(error_or, validity)
|
||||
{
|
||||
{
|
||||
error_or<int> d;
|
||||
|
||||
EXPECT_FALSE(d);
|
||||
EXPECT_TRUE(!d);
|
||||
}
|
||||
{
|
||||
error_or<int> e(make_error_code(std::errc::invalid_argument));
|
||||
|
||||
EXPECT_FALSE(e);
|
||||
EXPECT_TRUE(!e);
|
||||
}
|
||||
{
|
||||
error_or<int> v(0);
|
||||
|
||||
EXPECT_TRUE(v);
|
||||
EXPECT_FALSE(!v);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(error_or, dtor)
|
||||
{
|
||||
{
|
||||
called_mask called{};
|
||||
|
||||
{
|
||||
error_or<track_calls> e;
|
||||
}
|
||||
EXPECT_FALSE(called.dtor);
|
||||
}
|
||||
|
||||
{
|
||||
called_mask called{};
|
||||
|
||||
{
|
||||
error_or<track_calls> e(make_error_code(std::errc::invalid_argument));
|
||||
}
|
||||
EXPECT_FALSE(called.dtor);
|
||||
}
|
||||
|
||||
{
|
||||
called_mask called{};
|
||||
|
||||
{
|
||||
error_or<track_calls> e{track_calls{called, 0}};
|
||||
}
|
||||
EXPECT_TRUE(called.dtor);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(error_or, swap)
|
||||
{
|
||||
{
|
||||
error_or<track_calls> d1(make_error_code(std::errc::no_message_available));
|
||||
error_or<track_calls> d2(make_error_code(std::errc::argument_out_of_domain));
|
||||
|
||||
swap(d1, d2);
|
||||
|
||||
EXPECT_EQ(d1.error(), std::errc::argument_out_of_domain);
|
||||
EXPECT_EQ(d2.error(), std::errc::no_message_available);
|
||||
}
|
||||
{
|
||||
called_mask called = {};
|
||||
|
||||
error_or<track_calls> d1(make_error_code(std::errc::io_error));
|
||||
error_or<track_calls> d2(track_calls{called, 1});
|
||||
|
||||
swap(d1, d2);
|
||||
|
||||
EXPECT_EQ(d1.value().v, 1);
|
||||
EXPECT_EQ(d2.error(), std::errc::io_error);
|
||||
}
|
||||
{
|
||||
called_mask called1 = {};
|
||||
called_mask called2 = {};
|
||||
|
||||
error_or<track_calls> d1(track_calls{called1, 1});
|
||||
error_or<track_calls> d2(track_calls{called2, 2});
|
||||
|
||||
swap(d1, d2);
|
||||
|
||||
EXPECT_EQ(d1.value().v, 2);
|
||||
EXPECT_EQ(d2.value().v, 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(error_or, move_construct)
|
||||
{
|
||||
{
|
||||
error_or<track_calls> d1;
|
||||
error_or<track_calls> d2(std::move(d1));
|
||||
|
||||
EXPECT_FALSE(d1);
|
||||
EXPECT_FALSE(d2);
|
||||
}
|
||||
{
|
||||
called_mask called = {};
|
||||
|
||||
error_or<track_calls> d2(track_calls{called, 1});
|
||||
error_or<track_calls> d1(std::move(d2));
|
||||
|
||||
EXPECT_EQ(d1.value().v, 1);
|
||||
EXPECT_FALSE(d2);
|
||||
EXPECT_FALSE(called.swap);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(error_or, move_assign)
|
||||
{
|
||||
{
|
||||
error_or<track_calls> d1;
|
||||
error_or<track_calls> d2;
|
||||
|
||||
d2 = std::move(d1);
|
||||
|
||||
EXPECT_FALSE(d1);
|
||||
EXPECT_FALSE(d2);
|
||||
}
|
||||
{
|
||||
called_mask called = {};
|
||||
|
||||
error_or<track_calls> d2(track_calls{called, 1});
|
||||
error_or<track_calls> d1;
|
||||
|
||||
d1 = std::move(d2);
|
||||
|
||||
EXPECT_EQ(d1.value().v, 1);
|
||||
EXPECT_FALSE(d2);
|
||||
EXPECT_FALSE(called.swap);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(error_or, value__error)
|
||||
{
|
||||
called_mask c;
|
||||
|
||||
error_or<track_calls> err(make_error_code(std::errc::operation_not_supported));
|
||||
error_or<track_calls> value(track_calls{c, 1});
|
||||
|
||||
ASSERT_THROW(err.value(), bad_error_or_access);
|
||||
ASSERT_THROW(value.error(), bad_error_or_access);
|
||||
ASSERT_THROW(static_cast<const error_or<track_calls>&&>(err).value(), bad_error_or_access);
|
||||
ASSERT_THROW(const_cast<const error_or<track_calls>&>(err).value(), bad_error_or_access);
|
||||
ASSERT_THROW(err.release_value(), bad_error_or_access);
|
||||
|
||||
ASSERT_THROW(value.error(), bad_error_or_access);
|
||||
|
||||
ASSERT_EQ(value.value().v, 1);
|
||||
ASSERT_EQ(const_cast<const error_or<track_calls>&>(value).value().v, 1);
|
||||
ASSERT_EQ(static_cast<const error_or<track_calls>&&>(error_or<track_calls>(value.value())).value().v, 1);
|
||||
ASSERT_EQ(error_or<track_calls>(value.value()).value().v, 1);
|
||||
ASSERT_EQ(error_or<track_calls>(value.value()).release_value().v, 1);
|
||||
}
|
||||
|
||||
TEST(error_or, apply)
|
||||
{
|
||||
called_mask c;
|
||||
|
||||
error_or<track_calls> e(make_error_code(std::errc::io_error));
|
||||
error_or<track_calls> v(track_calls{c, 1});
|
||||
|
||||
auto conv = [] (track_calls x) { return track_calls{*x.called, x.v + 1}; };
|
||||
auto convM = [] (track_calls&& x) { return track_calls{*x.called, x.v + 1}; };
|
||||
auto convI = [] (track_calls) { return 0; };
|
||||
auto convE = [] (std::error_code) { return 1.; };
|
||||
auto convC = [] (track_calls) -> error_or<char> { return 17; };
|
||||
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<
|
||||
decltype(static_cast<const decltype(e)&>(e) / convI),
|
||||
error_or<int>>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<
|
||||
decltype(static_cast<decltype(e)&>(e) / convI),
|
||||
error_or<int>>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<
|
||||
decltype(static_cast<decltype(e)&&>(e) / convI),
|
||||
error_or<int>>::value));
|
||||
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<
|
||||
decltype(static_cast<const decltype(e)&>(e).reduce(convI, convE)),
|
||||
double>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<
|
||||
decltype(static_cast<decltype(e)&>(e).reduce(convI, convE)),
|
||||
double>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<
|
||||
decltype(static_cast<decltype(e)&&>(e).reduce(convI, convE)),
|
||||
double>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<
|
||||
decltype(static_cast<const decltype(e)&>(e) % convC),
|
||||
error_or<char>>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<
|
||||
decltype(static_cast<decltype(e)&>(e) % convC),
|
||||
error_or<char>>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<
|
||||
decltype(static_cast<decltype(e)&&>(e) % convC),
|
||||
error_or<char>>::value));
|
||||
|
||||
{
|
||||
EXPECT_EQ((static_cast<const decltype(e)&>(e) / conv).error(), std::errc::io_error);
|
||||
EXPECT_EQ((static_cast<const decltype(e)&>(e) % convC).error(), std::errc::io_error);
|
||||
|
||||
EXPECT_EQ((static_cast<const decltype(e)&>(e).reduce(convI, convE)), 1);
|
||||
|
||||
EXPECT_EQ((static_cast<const decltype(v)&>(v) / conv).value().v, 2);
|
||||
EXPECT_EQ((static_cast<const decltype(v)&>(v) % convC).value(), 17);
|
||||
|
||||
EXPECT_EQ((static_cast<const decltype(v)&>(v).reduce(convI, convE)), 0);
|
||||
}
|
||||
|
||||
{
|
||||
EXPECT_EQ((static_cast<decltype(e)&>(e) / conv).error(), std::errc::io_error);
|
||||
EXPECT_EQ((static_cast<decltype(e)&>(e) % convC).error(), std::errc::io_error);
|
||||
|
||||
EXPECT_EQ((static_cast<decltype(e)&>(e).reduce(convI, convE)), 1);
|
||||
|
||||
EXPECT_EQ((static_cast<decltype(v)&>(v) / conv).value().v, 2);
|
||||
EXPECT_EQ((static_cast<decltype(v)&>(v) % convC).value(), 17);
|
||||
|
||||
EXPECT_EQ((static_cast<decltype(v)&>(v).reduce(convI, convE)), 0);
|
||||
}
|
||||
|
||||
{
|
||||
EXPECT_EQ((decltype(e)(e.error()) / convM).error(), std::errc::io_error);
|
||||
EXPECT_EQ((decltype(e)(e.error()) % convC).error(), std::errc::io_error);
|
||||
|
||||
EXPECT_EQ((decltype(e)(e.error()).reduce(convI, convE)), 1);
|
||||
|
||||
EXPECT_EQ((decltype(v)(v.value()) / convM).value().v, 2);
|
||||
EXPECT_EQ((decltype(v)(v.value()) % convC).value(), 17);
|
||||
|
||||
EXPECT_EQ((decltype(v)(v.value()).reduce(convI, convE)), 0);
|
||||
}
|
||||
}
|
||||
38
thirdparty/source/nu/tests/error_or_example.cpp
vendored
Normal file
38
thirdparty/source/nu/tests/error_or_example.cpp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
using nu::error_or;
|
||||
using nu::make_error_or;
|
||||
|
||||
// default-constructed objects contain Err(), which by default is std::error_code
|
||||
error_or<int> e;
|
||||
error_or<int> i(1);
|
||||
|
||||
// et will still contain Err()
|
||||
error_or<int> et = e / [] (int i) { return i+1; };
|
||||
ASSERT_EQ(et.error(), std::error_code());
|
||||
|
||||
// it will contain 2
|
||||
error_or<int> it = i / [] (int i) { return i+1; };
|
||||
ASSERT_EQ(it.value(), 2);
|
||||
|
||||
// er will be set to -1
|
||||
int er = e.reduce(
|
||||
[] (int i) { return i; },
|
||||
[] (std::error_code) { return -1; });
|
||||
ASSERT_EQ(er, -1);
|
||||
|
||||
// ir will be set to 1
|
||||
int ir = i.reduce(
|
||||
[] (int i) { return i; },
|
||||
[] (std::error_code) { return -1; });
|
||||
ASSERT_EQ(ir, 1);
|
||||
|
||||
// % can be used to chain operations that may themselves fail
|
||||
error_or<double> d =
|
||||
make_error_or<int>(1)
|
||||
/ [] (int i) { return i - 1; }
|
||||
% [] (int i) -> error_or<double> {
|
||||
if (i != 0)
|
||||
return i * 3.14;
|
||||
else
|
||||
return {std::make_error_code(std::errc::invalid_argument)};
|
||||
};
|
||||
ASSERT_FALSE(d);
|
||||
Reference in New Issue
Block a user