| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// \brief Unit tests for LIBC_NAMESPACE::cpp::expected and unexpected. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "src/__support/CPP/expected.h" |
| #include "src/__support/CPP/type_traits.h" |
| #include "test/UnitTest/Test.h" |
| |
| using LIBC_NAMESPACE::cpp::expected; |
| using LIBC_NAMESPACE::cpp::unexpected; |
| |
| TEST(LlvmLibcExpectedTest, Unexpected) { |
| unexpected<int> u1(42); |
| ASSERT_EQ(u1.error(), 42); |
| } |
| |
| TEST(LlvmLibcExpectedTest, ValueConstruction) { |
| expected<int, double> e(123); |
| ASSERT_TRUE(e.has_value()); |
| ASSERT_TRUE(static_cast<bool>(e)); |
| ASSERT_EQ(e.value(), 123); |
| ASSERT_EQ(*e, 123); |
| } |
| |
| TEST(LlvmLibcExpectedTest, ErrorConstruction) { |
| expected<int, int> e(unexpected(404)); |
| ASSERT_FALSE(e.has_value()); |
| ASSERT_FALSE(static_cast<bool>(e)); |
| ASSERT_EQ(e.error(), 404); |
| } |
| |
| TEST(LlvmLibcExpectedTest, Mutation) { |
| expected<int, int> e(10); |
| ASSERT_EQ(e.value(), 10); |
| e.value() = 20; |
| ASSERT_EQ(e.value(), 20); |
| *e = 30; |
| ASSERT_EQ(*e, 30); |
| |
| expected<int, int> u(unexpected<int>(1)); |
| ASSERT_EQ(u.error(), 1); |
| u.error() = 2; |
| ASSERT_EQ(u.error(), 2); |
| } |
| |
| TEST(LlvmLibcExpectedTest, ConstAccess) { |
| const expected<int, int> CE(100); |
| ASSERT_TRUE(CE.has_value()); |
| ASSERT_TRUE(static_cast<bool>(CE)); |
| ASSERT_EQ(CE.value(), 100); |
| ASSERT_EQ(*CE, 100); |
| |
| const expected<int, int> CU(unexpected(500)); |
| ASSERT_FALSE(CU.has_value()); |
| ASSERT_FALSE(static_cast<bool>(CU)); |
| ASSERT_EQ(CU.error(), 500); |
| } |
| |
| struct Foo { |
| int x; |
| int get_x() const { return x; } |
| void set_x(int new_x) { x = new_x; } |
| }; |
| |
| TEST(LlvmLibcExpectedTest, ArrowOperator) { |
| expected<Foo, int> e(Foo{42}); |
| ASSERT_TRUE(e.has_value()); |
| ASSERT_EQ(e->x, 42); |
| ASSERT_EQ(e->get_x(), 42); |
| e->set_x(99); |
| ASSERT_EQ(e->x, 99); |
| |
| const expected<Foo, int> CE(Foo{123}); |
| ASSERT_EQ(CE->x, 123); |
| ASSERT_EQ(CE->get_x(), 123); |
| } |
| |
| TEST(LlvmLibcExpectedTest, VoidValueConstruction) { |
| expected<void, int> e; |
| ASSERT_TRUE(e.has_value()); |
| ASSERT_TRUE(static_cast<bool>(e)); |
| e.value(); |
| *e; |
| } |
| |
| TEST(LlvmLibcExpectedTest, VoidErrorConstruction) { |
| expected<void, int> e(unexpected(404)); |
| ASSERT_FALSE(e.has_value()); |
| ASSERT_FALSE(static_cast<bool>(e)); |
| ASSERT_EQ(e.error(), 404); |
| } |
| |
| TEST(LlvmLibcExpectedTest, VoidMutation) { |
| expected<void, int> u(unexpected<int>(1)); |
| ASSERT_EQ(u.error(), 1); |
| u.error() = 2; |
| ASSERT_EQ(u.error(), 2); |
| } |
| |
| TEST(LlvmLibcExpectedTest, VoidConstAccess) { |
| const expected<void, int> CE; |
| ASSERT_TRUE(CE.has_value()); |
| ASSERT_TRUE(static_cast<bool>(CE)); |
| CE.value(); |
| *CE; |
| |
| const expected<void, int> CU(unexpected(500)); |
| ASSERT_FALSE(CU.has_value()); |
| ASSERT_FALSE(static_cast<bool>(CU)); |
| ASSERT_EQ(CU.error(), 500); |
| } |
| |
| constexpr bool test_constexpr_value() { |
| expected<int, int> e(42); |
| if (!e.has_value() || !static_cast<bool>(e)) |
| return false; |
| if (e.value() != 42 || *e != 42) |
| return false; |
| return true; |
| } |
| |
| static_assert(test_constexpr_value(), "expected constexpr value check failed"); |
| |
| constexpr bool test_constexpr_void_value() { |
| expected<void, int> e; |
| if (!e.has_value() || !static_cast<bool>(e)) |
| return false; |
| e.value(); |
| *e; |
| return true; |
| } |
| |
| static_assert(test_constexpr_void_value(), |
| "expected<void> constexpr value check failed"); |
| |
| constexpr bool test_constexpr_error() { |
| expected<int, int> e(unexpected<int>(99)); |
| if (e.has_value() || static_cast<bool>(e)) |
| return false; |
| if (e.error() != 99) |
| return false; |
| return true; |
| } |
| |
| static_assert(test_constexpr_error(), "expected constexpr error check failed"); |
| |
| constexpr bool test_constexpr_void_error() { |
| expected<void, int> e(unexpected<int>(99)); |
| if (e.has_value() || static_cast<bool>(e)) |
| return false; |
| if (e.error() != 99) |
| return false; |
| return true; |
| } |
| |
| static_assert(test_constexpr_void_error(), |
| "expected<void> constexpr error check failed"); |
| |
| static_assert(!LIBC_NAMESPACE::cpp::is_convertible_v<expected<int, long>, bool>, |
| "only explicit conversions allowed"); |
| static_assert( |
| !LIBC_NAMESPACE::cpp::is_convertible_v<expected<void, long>, bool>, |
| "only explicit conversions allowed"); |