xref: /llvm-project/libc/test/src/__support/CPP/optional_test.cpp (revision f90f036efbe6879ecf1c9ff8cf0fb956b5ceb877)
1 //===-- Unittests for Optional --------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "src/__support/CPP/optional.h"
10 #include "test/UnitTest/Test.h"
11 
12 using LIBC_NAMESPACE::cpp::nullopt;
13 using LIBC_NAMESPACE::cpp::optional;
14 
15 // This class has three properties for testing:
16 // 1) No default constructor.
17 // 2) A non-trivial destructor with an observable side-effect.
18 // 3) Functions that can be called explicitly.
19 class Contrived {
20   int *_a;
21 
22 public:
Contrived(int * a)23   Contrived(int *a) : _a(a) {}
~Contrived()24   ~Contrived() { (*_a)++; }
25 
get_a()26   int get_a() { return *_a; }
inc_a()27   void inc_a() { (*_a)++; }
28 };
29 
TEST(LlvmLibcOptionalTest,Tests)30 TEST(LlvmLibcOptionalTest, Tests) {
31   optional<int> Trivial1(12);
32   ASSERT_TRUE(Trivial1.has_value());
33   ASSERT_EQ(Trivial1.value(), 12);
34   ASSERT_EQ(*Trivial1, 12);
35   Trivial1.reset();
36   ASSERT_FALSE(Trivial1.has_value());
37 
38   optional<int> Trivial2(12);
39   ASSERT_TRUE(Trivial2.has_value());
40   Trivial2 = nullopt;
41   ASSERT_FALSE(Trivial2.has_value());
42 
43   // For this test case, the destructor increments the pointed-to value.
44   int holding = 1;
45   {
46     optional<Contrived> Complicated(&holding);
47     // Destructor was run once as part of copying the object.
48     ASSERT_EQ(holding, 2);
49     // Destructor was run a second time as part of destruction.
50     Complicated.reset();
51     ASSERT_EQ(holding, 3);
52     // Destructor was not run a third time as the object is already destroyed.
53     Complicated.reset();
54     ASSERT_EQ(holding, 3);
55   }
56   // Make sure the destructor isn't called when the optional is destroyed.
57   ASSERT_EQ(holding, 3);
58 
59   // Test that assigning an optional to another works when set
60   optional<int> Trivial3(12);
61   optional<int> Trivial4 = Trivial3;
62   ASSERT_TRUE(Trivial4.has_value());
63   ASSERT_EQ(Trivial4.value(), 12);
64 
65   // Test that assigning an option to another works when unset
66   optional<int> Trivial5;
67   ASSERT_FALSE(Trivial5.has_value());
68   optional<int> Trivial6 = Trivial5;
69   ASSERT_FALSE(Trivial6.has_value());
70 
71   // Test operator->
72   int arrow_num = 5;
73   optional<Contrived> arrow_test(&arrow_num);
74   ASSERT_TRUE(arrow_test.has_value());
75   ASSERT_EQ(arrow_test->get_a(), arrow_num);
76   arrow_num = 10;
77   ASSERT_EQ(arrow_test->get_a(), arrow_num);
78   arrow_test->inc_a();
79   ASSERT_EQ(arrow_test->get_a(), arrow_num);
80   ASSERT_EQ(arrow_num, 11);
81   arrow_test.reset();
82 }
83