1 //===- llvm/unittest/ADT/OptionalTest.cpp - Optional unit tests -----------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/Optional.h"
10 #include "llvm/ADT/SmallString.h"
11 #include "llvm/Support/raw_ostream.h"
12 #include "gtest/gtest-spi.h"
13 #include "gtest/gtest.h"
20 static_assert(is_trivially_copyable
<Optional
<int>>::value
,
21 "trivially copyable");
23 static_assert(is_trivially_copyable
<Optional
<std::array
<int, 3>>>::value
,
24 "trivially copyable");
28 struct NonDefaultConstructible
{
29 static unsigned CopyConstructions
;
30 static unsigned Destructions
;
31 static unsigned CopyAssignments
;
32 explicit NonDefaultConstructible(int) {
34 NonDefaultConstructible(const NonDefaultConstructible
&) {
37 NonDefaultConstructible
&operator=(const NonDefaultConstructible
&) {
41 ~NonDefaultConstructible() {
44 static void ResetCounts() {
45 CopyConstructions
= 0;
51 unsigned NonDefaultConstructible::CopyConstructions
= 0;
52 unsigned NonDefaultConstructible::Destructions
= 0;
53 unsigned NonDefaultConstructible::CopyAssignments
= 0;
56 !is_trivially_copyable
<Optional
<NonDefaultConstructible
>>::value
,
57 "not trivially copyable");
60 class OptionalTest
: public testing::Test
{
63 TEST_F(OptionalTest
, NonDefaultConstructibleTest
) {
64 Optional
<NonDefaultConstructible
> O
;
68 TEST_F(OptionalTest
, ResetTest
) {
69 NonDefaultConstructible::ResetCounts();
70 Optional
<NonDefaultConstructible
> O(NonDefaultConstructible(3));
71 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions
);
72 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
73 EXPECT_EQ(1u, NonDefaultConstructible::Destructions
);
74 NonDefaultConstructible::ResetCounts();
76 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
77 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
78 EXPECT_EQ(1u, NonDefaultConstructible::Destructions
);
81 TEST_F(OptionalTest
, InitializationLeakTest
) {
82 NonDefaultConstructible::ResetCounts();
83 Optional
<NonDefaultConstructible
>(NonDefaultConstructible(3));
84 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions
);
85 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
86 EXPECT_EQ(2u, NonDefaultConstructible::Destructions
);
89 TEST_F(OptionalTest
, CopyConstructionTest
) {
90 NonDefaultConstructible::ResetCounts();
92 Optional
<NonDefaultConstructible
> A(NonDefaultConstructible(3));
93 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions
);
94 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
95 EXPECT_EQ(1u, NonDefaultConstructible::Destructions
);
96 NonDefaultConstructible::ResetCounts();
97 Optional
<NonDefaultConstructible
> B(A
);
98 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions
);
99 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
100 EXPECT_EQ(0u, NonDefaultConstructible::Destructions
);
101 NonDefaultConstructible::ResetCounts();
103 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
104 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
105 EXPECT_EQ(2u, NonDefaultConstructible::Destructions
);
108 TEST_F(OptionalTest
, ConstructingCopyAssignmentTest
) {
109 NonDefaultConstructible::ResetCounts();
111 Optional
<NonDefaultConstructible
> A(NonDefaultConstructible(3));
112 Optional
<NonDefaultConstructible
> B
;
113 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions
);
114 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
115 EXPECT_EQ(1u, NonDefaultConstructible::Destructions
);
116 NonDefaultConstructible::ResetCounts();
118 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions
);
119 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
120 EXPECT_EQ(0u, NonDefaultConstructible::Destructions
);
121 NonDefaultConstructible::ResetCounts();
123 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
124 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
125 EXPECT_EQ(2u, NonDefaultConstructible::Destructions
);
128 TEST_F(OptionalTest
, CopyingCopyAssignmentTest
) {
129 NonDefaultConstructible::ResetCounts();
131 Optional
<NonDefaultConstructible
> A(NonDefaultConstructible(3));
132 Optional
<NonDefaultConstructible
> B(NonDefaultConstructible(4));
133 EXPECT_EQ(2u, NonDefaultConstructible::CopyConstructions
);
134 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
135 EXPECT_EQ(2u, NonDefaultConstructible::Destructions
);
136 NonDefaultConstructible::ResetCounts();
138 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
139 EXPECT_EQ(1u, NonDefaultConstructible::CopyAssignments
);
140 EXPECT_EQ(0u, NonDefaultConstructible::Destructions
);
141 NonDefaultConstructible::ResetCounts();
143 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
144 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
145 EXPECT_EQ(2u, NonDefaultConstructible::Destructions
);
148 TEST_F(OptionalTest
, DeletingCopyAssignmentTest
) {
149 NonDefaultConstructible::ResetCounts();
151 Optional
<NonDefaultConstructible
> A
;
152 Optional
<NonDefaultConstructible
> B(NonDefaultConstructible(3));
153 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions
);
154 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
155 EXPECT_EQ(1u, NonDefaultConstructible::Destructions
);
156 NonDefaultConstructible::ResetCounts();
158 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
159 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
160 EXPECT_EQ(1u, NonDefaultConstructible::Destructions
);
161 NonDefaultConstructible::ResetCounts();
163 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
164 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
165 EXPECT_EQ(0u, NonDefaultConstructible::Destructions
);
168 TEST_F(OptionalTest
, NullCopyConstructionTest
) {
169 NonDefaultConstructible::ResetCounts();
171 Optional
<NonDefaultConstructible
> A
;
172 Optional
<NonDefaultConstructible
> B
;
173 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
174 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
175 EXPECT_EQ(0u, NonDefaultConstructible::Destructions
);
176 NonDefaultConstructible::ResetCounts();
178 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
179 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
180 EXPECT_EQ(0u, NonDefaultConstructible::Destructions
);
181 NonDefaultConstructible::ResetCounts();
183 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions
);
184 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments
);
185 EXPECT_EQ(0u, NonDefaultConstructible::Destructions
);
188 TEST_F(OptionalTest
, GetValueOr
) {
190 EXPECT_EQ(42, A
.getValueOr(42));
193 EXPECT_EQ(5, A
.getValueOr(42));
196 struct MultiArgConstructor
{
198 MultiArgConstructor(int x
, int y
) : x(x
), y(y
) {}
199 explicit MultiArgConstructor(int x
, bool positive
)
200 : x(x
), y(positive
? x
: -x
) {}
202 MultiArgConstructor(const MultiArgConstructor
&) = delete;
203 MultiArgConstructor(MultiArgConstructor
&&) = delete;
204 MultiArgConstructor
&operator=(const MultiArgConstructor
&) = delete;
205 MultiArgConstructor
&operator=(MultiArgConstructor
&&) = delete;
207 static unsigned Destructions
;
208 ~MultiArgConstructor() {
211 static void ResetCounts() {
215 unsigned MultiArgConstructor::Destructions
= 0;
218 !is_trivially_copyable
<Optional
<MultiArgConstructor
>>::value
,
219 "not trivially copyable");
221 TEST_F(OptionalTest
, Emplace
) {
222 MultiArgConstructor::ResetCounts();
223 Optional
<MultiArgConstructor
> A
;
226 EXPECT_TRUE(A
.hasValue());
229 EXPECT_EQ(0u, MultiArgConstructor::Destructions
);
232 EXPECT_TRUE(A
.hasValue());
235 EXPECT_EQ(1u, MultiArgConstructor::Destructions
);
239 static unsigned MoveConstructions
;
240 static unsigned Destructions
;
241 static unsigned MoveAssignments
;
243 explicit MoveOnly(int val
) : val(val
) {
245 MoveOnly(MoveOnly
&& other
) {
249 MoveOnly
&operator=(MoveOnly
&& other
) {
257 static void ResetCounts() {
258 MoveConstructions
= 0;
264 unsigned MoveOnly::MoveConstructions
= 0;
265 unsigned MoveOnly::Destructions
= 0;
266 unsigned MoveOnly::MoveAssignments
= 0;
268 static_assert(!is_trivially_copyable
<Optional
<MoveOnly
>>::value
,
269 "not trivially copyable");
271 TEST_F(OptionalTest
, MoveOnlyNull
) {
272 MoveOnly::ResetCounts();
273 Optional
<MoveOnly
> O
;
274 EXPECT_EQ(0u, MoveOnly::MoveConstructions
);
275 EXPECT_EQ(0u, MoveOnly::MoveAssignments
);
276 EXPECT_EQ(0u, MoveOnly::Destructions
);
279 TEST_F(OptionalTest
, MoveOnlyConstruction
) {
280 MoveOnly::ResetCounts();
281 Optional
<MoveOnly
> O(MoveOnly(3));
282 EXPECT_TRUE((bool)O
);
283 EXPECT_EQ(3, O
->val
);
284 EXPECT_EQ(1u, MoveOnly::MoveConstructions
);
285 EXPECT_EQ(0u, MoveOnly::MoveAssignments
);
286 EXPECT_EQ(1u, MoveOnly::Destructions
);
289 TEST_F(OptionalTest
, MoveOnlyMoveConstruction
) {
290 Optional
<MoveOnly
> A(MoveOnly(3));
291 MoveOnly::ResetCounts();
292 Optional
<MoveOnly
> B(std::move(A
));
293 EXPECT_TRUE((bool)A
);
294 EXPECT_TRUE((bool)B
);
295 EXPECT_EQ(3, B
->val
);
296 EXPECT_EQ(1u, MoveOnly::MoveConstructions
);
297 EXPECT_EQ(0u, MoveOnly::MoveAssignments
);
298 EXPECT_EQ(0u, MoveOnly::Destructions
);
301 TEST_F(OptionalTest
, MoveOnlyAssignment
) {
302 MoveOnly::ResetCounts();
303 Optional
<MoveOnly
> O
;
305 EXPECT_TRUE((bool)O
);
306 EXPECT_EQ(3, O
->val
);
307 EXPECT_EQ(1u, MoveOnly::MoveConstructions
);
308 EXPECT_EQ(0u, MoveOnly::MoveAssignments
);
309 EXPECT_EQ(1u, MoveOnly::Destructions
);
312 TEST_F(OptionalTest
, MoveOnlyInitializingAssignment
) {
313 Optional
<MoveOnly
> A(MoveOnly(3));
314 Optional
<MoveOnly
> B
;
315 MoveOnly::ResetCounts();
317 EXPECT_TRUE((bool)A
);
318 EXPECT_TRUE((bool)B
);
319 EXPECT_EQ(3, B
->val
);
320 EXPECT_EQ(1u, MoveOnly::MoveConstructions
);
321 EXPECT_EQ(0u, MoveOnly::MoveAssignments
);
322 EXPECT_EQ(0u, MoveOnly::Destructions
);
325 TEST_F(OptionalTest
, MoveOnlyNullingAssignment
) {
326 Optional
<MoveOnly
> A
;
327 Optional
<MoveOnly
> B(MoveOnly(3));
328 MoveOnly::ResetCounts();
330 EXPECT_FALSE((bool)A
);
331 EXPECT_FALSE((bool)B
);
332 EXPECT_EQ(0u, MoveOnly::MoveConstructions
);
333 EXPECT_EQ(0u, MoveOnly::MoveAssignments
);
334 EXPECT_EQ(1u, MoveOnly::Destructions
);
337 TEST_F(OptionalTest
, MoveOnlyAssigningAssignment
) {
338 Optional
<MoveOnly
> A(MoveOnly(3));
339 Optional
<MoveOnly
> B(MoveOnly(4));
340 MoveOnly::ResetCounts();
342 EXPECT_TRUE((bool)A
);
343 EXPECT_TRUE((bool)B
);
344 EXPECT_EQ(3, B
->val
);
345 EXPECT_EQ(0u, MoveOnly::MoveConstructions
);
346 EXPECT_EQ(1u, MoveOnly::MoveAssignments
);
347 EXPECT_EQ(0u, MoveOnly::Destructions
);
351 static unsigned Constructions
;
352 static unsigned Destructions
;
354 explicit Immovable(int val
) : val(val
) {
360 static void ResetCounts() {
365 // This should disable all move/copy operations.
366 Immovable(Immovable
&& other
) = delete;
369 unsigned Immovable::Constructions
= 0;
370 unsigned Immovable::Destructions
= 0;
372 static_assert(!is_trivially_copyable
<Optional
<Immovable
>>::value
,
373 "not trivially copyable");
375 TEST_F(OptionalTest
, ImmovableEmplace
) {
376 Optional
<Immovable
> A
;
377 Immovable::ResetCounts();
379 EXPECT_TRUE((bool)A
);
380 EXPECT_EQ(4, A
->val
);
381 EXPECT_EQ(1u, Immovable::Constructions
);
382 EXPECT_EQ(0u, Immovable::Destructions
);
385 #if LLVM_HAS_RVALUE_REFERENCE_THIS
387 TEST_F(OptionalTest
, MoveGetValueOr
) {
388 Optional
<MoveOnly
> A
;
390 MoveOnly::ResetCounts();
391 EXPECT_EQ(42, std::move(A
).getValueOr(MoveOnly(42)).val
);
392 EXPECT_EQ(1u, MoveOnly::MoveConstructions
);
393 EXPECT_EQ(0u, MoveOnly::MoveAssignments
);
394 EXPECT_EQ(2u, MoveOnly::Destructions
);
397 MoveOnly::ResetCounts();
398 EXPECT_EQ(5, std::move(A
).getValueOr(MoveOnly(42)).val
);
399 EXPECT_EQ(1u, MoveOnly::MoveConstructions
);
400 EXPECT_EQ(0u, MoveOnly::MoveAssignments
);
401 EXPECT_EQ(2u, MoveOnly::Destructions
);
404 #endif // LLVM_HAS_RVALUE_REFERENCE_THIS
407 template <typename T
, typename U
> static bool apply(const T
&X
, const U
&Y
) {
413 template <typename T
, typename U
> static bool apply(const T
&X
, const U
&Y
) {
419 template <typename T
, typename U
> static bool apply(const T
&X
, const U
&Y
) {
425 template <typename T
, typename U
> static bool apply(const T
&X
, const U
&Y
) {
431 template <typename T
, typename U
> static bool apply(const T
&X
, const U
&Y
) {
436 struct GreaterEqual
{
437 template <typename T
, typename U
> static bool apply(const T
&X
, const U
&Y
) {
442 template <typename OperatorT
, typename T
>
443 void CheckRelation(const Optional
<T
> &Lhs
, const Optional
<T
> &Rhs
,
445 EXPECT_EQ(Expected
, OperatorT::apply(Lhs
, Rhs
));
448 EXPECT_EQ(Expected
, OperatorT::apply(*Lhs
, Rhs
));
450 EXPECT_EQ(Expected
, OperatorT::apply(None
, Rhs
));
453 EXPECT_EQ(Expected
, OperatorT::apply(Lhs
, *Rhs
));
455 EXPECT_EQ(Expected
, OperatorT::apply(Lhs
, None
));
458 struct EqualityMock
{};
459 const Optional
<EqualityMock
> NoneEq
, EqualityLhs((EqualityMock())),
460 EqualityRhs((EqualityMock()));
463 bool operator==(const EqualityMock
&Lhs
, const EqualityMock
&Rhs
) {
464 EXPECT_EQ(&*EqualityLhs
, &Lhs
);
465 EXPECT_EQ(&*EqualityRhs
, &Rhs
);
469 TEST_F(OptionalTest
, OperatorEqual
) {
470 CheckRelation
<EqualTo
>(NoneEq
, NoneEq
, true);
471 CheckRelation
<EqualTo
>(NoneEq
, EqualityRhs
, false);
472 CheckRelation
<EqualTo
>(EqualityLhs
, NoneEq
, false);
475 CheckRelation
<EqualTo
>(EqualityLhs
, EqualityRhs
, IsEqual
);
477 CheckRelation
<EqualTo
>(EqualityLhs
, EqualityRhs
, IsEqual
);
480 TEST_F(OptionalTest
, OperatorNotEqual
) {
481 CheckRelation
<NotEqualTo
>(NoneEq
, NoneEq
, false);
482 CheckRelation
<NotEqualTo
>(NoneEq
, EqualityRhs
, true);
483 CheckRelation
<NotEqualTo
>(EqualityLhs
, NoneEq
, true);
486 CheckRelation
<NotEqualTo
>(EqualityLhs
, EqualityRhs
, !IsEqual
);
488 CheckRelation
<NotEqualTo
>(EqualityLhs
, EqualityRhs
, !IsEqual
);
491 struct InequalityMock
{};
492 const Optional
<InequalityMock
> NoneIneq
, InequalityLhs((InequalityMock())),
493 InequalityRhs((InequalityMock()));
496 bool operator<(const InequalityMock
&Lhs
, const InequalityMock
&Rhs
) {
497 EXPECT_EQ(&*InequalityLhs
, &Lhs
);
498 EXPECT_EQ(&*InequalityRhs
, &Rhs
);
502 TEST_F(OptionalTest
, OperatorLess
) {
503 CheckRelation
<Less
>(NoneIneq
, NoneIneq
, false);
504 CheckRelation
<Less
>(NoneIneq
, InequalityRhs
, true);
505 CheckRelation
<Less
>(InequalityLhs
, NoneIneq
, false);
508 CheckRelation
<Less
>(InequalityLhs
, InequalityRhs
, IsLess
);
510 CheckRelation
<Less
>(InequalityLhs
, InequalityRhs
, IsLess
);
513 TEST_F(OptionalTest
, OperatorGreater
) {
514 CheckRelation
<Greater
>(NoneIneq
, NoneIneq
, false);
515 CheckRelation
<Greater
>(NoneIneq
, InequalityRhs
, false);
516 CheckRelation
<Greater
>(InequalityLhs
, NoneIneq
, true);
519 CheckRelation
<Greater
>(InequalityRhs
, InequalityLhs
, IsLess
);
521 CheckRelation
<Greater
>(InequalityRhs
, InequalityLhs
, IsLess
);
524 TEST_F(OptionalTest
, OperatorLessEqual
) {
525 CheckRelation
<LessEqual
>(NoneIneq
, NoneIneq
, true);
526 CheckRelation
<LessEqual
>(NoneIneq
, InequalityRhs
, true);
527 CheckRelation
<LessEqual
>(InequalityLhs
, NoneIneq
, false);
530 CheckRelation
<LessEqual
>(InequalityRhs
, InequalityLhs
, !IsLess
);
532 CheckRelation
<LessEqual
>(InequalityRhs
, InequalityLhs
, !IsLess
);
535 TEST_F(OptionalTest
, OperatorGreaterEqual
) {
536 CheckRelation
<GreaterEqual
>(NoneIneq
, NoneIneq
, true);
537 CheckRelation
<GreaterEqual
>(NoneIneq
, InequalityRhs
, false);
538 CheckRelation
<GreaterEqual
>(InequalityLhs
, NoneIneq
, true);
541 CheckRelation
<GreaterEqual
>(InequalityLhs
, InequalityRhs
, !IsLess
);
543 CheckRelation
<GreaterEqual
>(InequalityLhs
, InequalityRhs
, !IsLess
);
546 struct ComparableAndStreamable
{
547 friend bool operator==(ComparableAndStreamable
,
548 ComparableAndStreamable
) LLVM_ATTRIBUTE_USED
{
552 friend raw_ostream
&operator<<(raw_ostream
&OS
, ComparableAndStreamable
) {
553 return OS
<< "ComparableAndStreamable";
556 static Optional
<ComparableAndStreamable
> get() {
557 return ComparableAndStreamable();
561 TEST_F(OptionalTest
, StreamOperator
) {
562 auto to_string
= [](Optional
<ComparableAndStreamable
> O
) {
564 raw_svector_ostream
OS(S
);
568 EXPECT_EQ("ComparableAndStreamable",
569 to_string(ComparableAndStreamable::get()));
570 EXPECT_EQ("None", to_string(None
));
574 friend bool operator==(Comparable
, Comparable
) LLVM_ATTRIBUTE_USED
{
577 static Optional
<Comparable
> get() { return Comparable(); }
580 TEST_F(OptionalTest
, UseInUnitTests
) {
581 // Test that we invoke the streaming operators when pretty-printing values in
583 EXPECT_NONFATAL_FAILURE(EXPECT_EQ(llvm::None
, ComparableAndStreamable::get()),
584 "Expected: llvm::None\n"
586 "To be equal to: ComparableAndStreamable::get()\n"
587 " Which is: ComparableAndStreamable");
589 // Test that it is still possible to compare objects which do not have a
590 // custom streaming operator.
591 EXPECT_NONFATAL_FAILURE(EXPECT_EQ(llvm::None
, Comparable::get()), "object");
594 } // end anonymous namespace