| //===-- Unittests for Optional --------------------------------------------===// | |
| // | |
| // 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "src/__support/CPP/optional.h" | |
| #include "test/UnitTest/Test.h" | |
| using LIBC_NAMESPACE::cpp::nullopt; | |
| using LIBC_NAMESPACE::cpp::optional; | |
| // This class has three properties for testing: | |
| // 1) No default constructor. | |
| // 2) A non-trivial destructor with an observable side-effect. | |
| // 3) Functions that can be called explicitly. | |
| class Contrived { | |
| int *_a; | |
| public: | |
| Contrived(int *a) : _a(a) {} | |
| ~Contrived() { (*_a)++; } | |
| int get_a() { return *_a; } | |
| void inc_a() { (*_a)++; } | |
| }; | |
| TEST(LlvmLibcOptionalTest, Tests) { | |
| optional<int> Trivial1(12); | |
| ASSERT_TRUE(Trivial1.has_value()); | |
| ASSERT_EQ(Trivial1.value(), 12); | |
| ASSERT_EQ(*Trivial1, 12); | |
| Trivial1.reset(); | |
| ASSERT_FALSE(Trivial1.has_value()); | |
| optional<int> Trivial2(12); | |
| ASSERT_TRUE(Trivial2.has_value()); | |
| Trivial2 = nullopt; | |
| ASSERT_FALSE(Trivial2.has_value()); | |
| // For this test case, the destructor increments the pointed-to value. | |
| int holding = 1; | |
| { | |
| optional<Contrived> Complicated(&holding); | |
| // Destructor was run once as part of copying the object. | |
| ASSERT_EQ(holding, 2); | |
| // Destructor was run a second time as part of destruction. | |
| Complicated.reset(); | |
| ASSERT_EQ(holding, 3); | |
| // Destructor was not run a third time as the object is already destroyed. | |
| Complicated.reset(); | |
| ASSERT_EQ(holding, 3); | |
| } | |
| // Make sure the destructor isn't called when the optional is destroyed. | |
| ASSERT_EQ(holding, 3); | |
| // Test that assigning an optional to another works when set | |
| optional<int> Trivial3(12); | |
| optional<int> Trivial4 = Trivial3; | |
| ASSERT_TRUE(Trivial4.has_value()); | |
| ASSERT_EQ(Trivial4.value(), 12); | |
| // Test that assigning an option to another works when unset | |
| optional<int> Trivial5; | |
| ASSERT_FALSE(Trivial5.has_value()); | |
| optional<int> Trivial6 = Trivial5; | |
| ASSERT_FALSE(Trivial6.has_value()); | |
| // Test operator-> | |
| int arrow_num = 5; | |
| optional<Contrived> arrow_test(&arrow_num); | |
| ASSERT_TRUE(arrow_test.has_value()); | |
| ASSERT_EQ(arrow_test->get_a(), arrow_num); | |
| arrow_num = 10; | |
| ASSERT_EQ(arrow_test->get_a(), arrow_num); | |
| arrow_test->inc_a(); | |
| ASSERT_EQ(arrow_test->get_a(), arrow_num); | |
| ASSERT_EQ(arrow_num, 11); | |
| arrow_test.reset(); | |
| } |