blob: f54da1448e9ef1eb49872af78cc90e8f9c72c59b [file]
//===----------------------------------------------------------------------===//
//
// 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");