#include #include #define TOKENPASTE(x, y) x##y #define TOKENPASTE2(x, y) TOKENPASTE(x, y) #undef STATIC_REQUIRE #define STATIC_REQUIRE(e) \ constexpr bool TOKENPASTE2(rqure, __LINE__) = e; \ (void)TOKENPASTE2(rqure, __LINE__); \ EXPECT_TRUE(e); TEST(Expected, MapExtensions) { auto mul2 = [](int a) { return a * 2; }; auto ret_void = [](int a) { (void)a; }; { m5::stl::expected e = 21; auto ret = e.map(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { const m5::stl::expected e = 21; auto ret = e.map(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { m5::stl::expected e = 21; auto ret = std::move(e).map(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { const m5::stl::expected e = 21; auto ret = std::move(e).map(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.map(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.map(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).map(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).map(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { m5::stl::expected e = 21; auto ret = e.map(ret_void); EXPECT_TRUE(ret); STATIC_REQUIRE((std::is_same>::value)); } { const m5::stl::expected e = 21; auto ret = e.map(ret_void); EXPECT_TRUE(ret); STATIC_REQUIRE((std::is_same>::value)); } { m5::stl::expected e = 21; auto ret = std::move(e).map(ret_void); EXPECT_TRUE(ret); STATIC_REQUIRE((std::is_same>::value)); } { const m5::stl::expected e = 21; auto ret = std::move(e).map(ret_void); EXPECT_TRUE(ret); STATIC_REQUIRE((std::is_same>::value)); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.map(ret_void); EXPECT_TRUE(!ret); STATIC_REQUIRE((std::is_same>::value)); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.map(ret_void); EXPECT_TRUE(!ret); STATIC_REQUIRE((std::is_same>::value)); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).map(ret_void); EXPECT_TRUE(!ret); STATIC_REQUIRE((std::is_same>::value)); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).map(ret_void); EXPECT_TRUE(!ret); STATIC_REQUIRE((std::is_same>::value)); } // mapping functions which return references { m5::stl::expected e(42); auto ret = e.map([](int& i) -> int& { return i; }); EXPECT_TRUE(ret); EXPECT_TRUE(ret == 42); } } TEST(Expected, MapErrorExtensions) { auto mul2 = [](int a) { return a * 2; }; auto ret_void = [](int a) { (void)a; }; { m5::stl::expected e = 21; auto ret = e.map_error(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { const m5::stl::expected e = 21; auto ret = e.map_error(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { m5::stl::expected e = 21; auto ret = std::move(e).map_error(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { const m5::stl::expected e = 21; auto ret = std::move(e).map_error(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.map_error(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 42); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.map_error(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 42); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).map_error(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 42); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).map_error(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 42); } { m5::stl::expected e = 21; auto ret = e.map_error(ret_void); EXPECT_TRUE(ret); } { const m5::stl::expected e = 21; auto ret = e.map_error(ret_void); EXPECT_TRUE(ret); } { m5::stl::expected e = 21; auto ret = std::move(e).map_error(ret_void); EXPECT_TRUE(ret); } { const m5::stl::expected e = 21; auto ret = std::move(e).map_error(ret_void); EXPECT_TRUE(ret); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.map_error(ret_void); EXPECT_TRUE(!ret); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.map_error(ret_void); EXPECT_TRUE(!ret); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).map_error(ret_void); EXPECT_TRUE(!ret); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).map_error(ret_void); EXPECT_TRUE(!ret); } } TEST(Expected, AndThenExtensions) { auto succeed = [](int a) { (void)a; return m5::stl::expected(21 * 2); }; auto fail = [](int a) { (void)a; return m5::stl::expected(m5::stl::unexpect, 17); }; { m5::stl::expected e = 21; auto ret = e.and_then(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { const m5::stl::expected e = 21; auto ret = e.and_then(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { m5::stl::expected e = 21; auto ret = std::move(e).and_then(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { const m5::stl::expected e = 21; auto ret = std::move(e).and_then(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { m5::stl::expected e = 21; auto ret = e.and_then(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 17); } { const m5::stl::expected e = 21; auto ret = e.and_then(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 17); } { m5::stl::expected e = 21; auto ret = std::move(e).and_then(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 17); } { const m5::stl::expected e = 21; auto ret = std::move(e).and_then(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 17); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.and_then(succeed); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.and_then(succeed); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).and_then(succeed); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).and_then(succeed); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.and_then(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.and_then(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).and_then(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).and_then(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } } TEST(Expected, or_else) { using eptr = std::unique_ptr; auto succeed = [](int a) { (void)a; return m5::stl::expected(21 * 2); }; auto succeedptr = [](eptr e) { (void)e; return m5::stl::expected(21 * 2); }; auto fail = [](int a) { (void)a; return m5::stl::expected(m5::stl::unexpect, 17); }; auto failptr = [](eptr e) { *e = 17; return m5::stl::expected(m5::stl::unexpect, std::move(e)); }; auto failvoid = [](int) {}; auto failvoidptr = [](const eptr&) { /* don't consume */ }; auto consumeptr = [](eptr) {}; auto make_u_int = [](int n) { return std::unique_ptr(new int(n)); }; { m5::stl::expected e = 21; auto ret = e.or_else(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { const m5::stl::expected e = 21; auto ret = e.or_else(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { m5::stl::expected e = 21; auto ret = std::move(e).or_else(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { m5::stl::expected e = 21; auto ret = std::move(e).or_else(succeedptr); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { const m5::stl::expected e = 21; auto ret = std::move(e).or_else(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { m5::stl::expected e = 21; auto ret = e.or_else(fail); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { const m5::stl::expected e = 21; auto ret = e.or_else(fail); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { m5::stl::expected e = 21; auto ret = std::move(e).or_else(fail); EXPECT_TRUE(ret); EXPECT_TRUE(ret == 21); } { m5::stl::expected e = 21; auto ret = std::move(e).or_else(failptr); EXPECT_TRUE(ret); EXPECT_TRUE(ret == 21); } { const m5::stl::expected e = 21; auto ret = std::move(e).or_else(fail); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.or_else(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.or_else(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).or_else(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { m5::stl::expected e(m5::stl::unexpect, make_u_int(21)); auto ret = std::move(e).or_else(succeedptr); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).or_else(succeed); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.or_else(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 17); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.or_else(failvoid); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.or_else(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 17); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.or_else(failvoid); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).or_else(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 17); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).or_else(failvoid); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { m5::stl::expected e(m5::stl::unexpect, make_u_int(21)); auto ret = std::move(e).or_else(failvoidptr); EXPECT_TRUE(!ret); EXPECT_TRUE(*ret.error() == 21); } { m5::stl::expected e(m5::stl::unexpect, make_u_int(21)); auto ret = std::move(e).or_else(consumeptr); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == nullptr); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).or_else(fail); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 17); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).or_else(failvoid); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } } TEST(Expected, TransformExtensions) { auto mul2 = [](int a) { return a * 2; }; auto ret_void = [](int a) { (void)a; }; { m5::stl::expected e = 21; auto ret = e.transform(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { const m5::stl::expected e = 21; auto ret = e.transform(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { m5::stl::expected e = 21; auto ret = std::move(e).transform(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { const m5::stl::expected e = 21; auto ret = std::move(e).transform(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 42); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.transform(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.transform(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).transform(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).transform(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 21); } { m5::stl::expected e = 21; auto ret = e.transform(ret_void); EXPECT_TRUE(ret); STATIC_REQUIRE((std::is_same>::value)); } { const m5::stl::expected e = 21; auto ret = e.transform(ret_void); EXPECT_TRUE(ret); STATIC_REQUIRE((std::is_same>::value)); } { m5::stl::expected e = 21; auto ret = std::move(e).transform(ret_void); EXPECT_TRUE(ret); STATIC_REQUIRE((std::is_same>::value)); } { const m5::stl::expected e = 21; auto ret = std::move(e).transform(ret_void); EXPECT_TRUE(ret); STATIC_REQUIRE((std::is_same>::value)); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.transform(ret_void); EXPECT_TRUE(!ret); STATIC_REQUIRE((std::is_same>::value)); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.transform(ret_void); EXPECT_TRUE(!ret); STATIC_REQUIRE((std::is_same>::value)); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).transform(ret_void); EXPECT_TRUE(!ret); STATIC_REQUIRE((std::is_same>::value)); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).transform(ret_void); EXPECT_TRUE(!ret); STATIC_REQUIRE((std::is_same>::value)); } // mapping functions which return references { m5::stl::expected e(42); auto ret = e.transform([](int& i) -> int& { return i; }); EXPECT_TRUE(ret); EXPECT_TRUE(ret == 42); } } TEST(Expected, TransformErrorExtensions) { auto mul2 = [](int a) { return a * 2; }; auto ret_void = [](int a) { (void)a; }; { m5::stl::expected e = 21; auto ret = e.transform_error(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { const m5::stl::expected e = 21; auto ret = e.transform_error(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { m5::stl::expected e = 21; auto ret = std::move(e).transform_error(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { const m5::stl::expected e = 21; auto ret = std::move(e).transform_error(mul2); EXPECT_TRUE(ret); EXPECT_TRUE(*ret == 21); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.transform_error(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 42); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.transform_error(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 42); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).transform_error(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 42); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).transform_error(mul2); EXPECT_TRUE(!ret); EXPECT_TRUE(ret.error() == 42); } { m5::stl::expected e = 21; auto ret = e.transform_error(ret_void); EXPECT_TRUE(ret); } { const m5::stl::expected e = 21; auto ret = e.transform_error(ret_void); EXPECT_TRUE(ret); } { m5::stl::expected e = 21; auto ret = std::move(e).transform_error(ret_void); EXPECT_TRUE(ret); } { const m5::stl::expected e = 21; auto ret = std::move(e).transform_error(ret_void); EXPECT_TRUE(ret); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.transform_error(ret_void); EXPECT_TRUE(!ret); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = e.transform_error(ret_void); EXPECT_TRUE(!ret); } { m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).transform_error(ret_void); EXPECT_TRUE(!ret); } { const m5::stl::expected e(m5::stl::unexpect, 21); auto ret = std::move(e).transform_error(ret_void); EXPECT_TRUE(!ret); } } struct S { int x; }; struct F { int x; }; TEST(Expected, issue14) { auto res = m5::stl::expected{m5::stl::unexpect, F{}}; res.map_error([](F f) { (void)f; }); } TEST(Expected, issue32) { int i = 0; m5::stl::expected a; a.map([&i] { i = 42; }); EXPECT_TRUE(i == 42); auto x = a.map([] { return 42; }); EXPECT_TRUE(*x == 42); }