1 //===- llvm/unittest/ADT/OptionalTest.cpp - Optional unit tests -----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ADT/Optional.h" 11 #include "gtest/gtest.h" 12 13 using namespace llvm; 14 15 namespace { 16 17 struct NonDefaultConstructible { 18 static unsigned CopyConstructions; 19 static unsigned Destructions; 20 static unsigned CopyAssignments; 21 explicit NonDefaultConstructible(int) { 22 } 23 NonDefaultConstructible(const NonDefaultConstructible&) { 24 ++CopyConstructions; 25 } 26 NonDefaultConstructible &operator=(const NonDefaultConstructible&) { 27 ++CopyAssignments; 28 return *this; 29 } 30 ~NonDefaultConstructible() { 31 ++Destructions; 32 } 33 static void ResetCounts() { 34 CopyConstructions = 0; 35 Destructions = 0; 36 CopyAssignments = 0; 37 } 38 }; 39 40 unsigned NonDefaultConstructible::CopyConstructions = 0; 41 unsigned NonDefaultConstructible::Destructions = 0; 42 unsigned NonDefaultConstructible::CopyAssignments = 0; 43 44 // Test fixture 45 class OptionalTest : public testing::Test { 46 }; 47 48 TEST_F(OptionalTest, NonDefaultConstructibleTest) { 49 Optional<NonDefaultConstructible> O; 50 EXPECT_FALSE(O); 51 } 52 53 TEST_F(OptionalTest, ResetTest) { 54 NonDefaultConstructible::ResetCounts(); 55 Optional<NonDefaultConstructible> O(NonDefaultConstructible(3)); 56 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 57 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 58 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 59 NonDefaultConstructible::ResetCounts(); 60 O.reset(); 61 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 62 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 63 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 64 } 65 66 TEST_F(OptionalTest, InitializationLeakTest) { 67 NonDefaultConstructible::ResetCounts(); 68 Optional<NonDefaultConstructible>(NonDefaultConstructible(3)); 69 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 70 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 71 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 72 } 73 74 TEST_F(OptionalTest, CopyConstructionTest) { 75 NonDefaultConstructible::ResetCounts(); 76 { 77 Optional<NonDefaultConstructible> A(NonDefaultConstructible(3)); 78 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 79 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 80 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 81 NonDefaultConstructible::ResetCounts(); 82 Optional<NonDefaultConstructible> B(A); 83 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 84 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 85 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 86 NonDefaultConstructible::ResetCounts(); 87 } 88 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 89 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 90 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 91 } 92 93 TEST_F(OptionalTest, ConstructingCopyAssignmentTest) { 94 NonDefaultConstructible::ResetCounts(); 95 { 96 Optional<NonDefaultConstructible> A(NonDefaultConstructible(3)); 97 Optional<NonDefaultConstructible> B; 98 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 99 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 100 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 101 NonDefaultConstructible::ResetCounts(); 102 B = A; 103 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 104 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 105 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 106 NonDefaultConstructible::ResetCounts(); 107 } 108 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 109 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 110 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 111 } 112 113 TEST_F(OptionalTest, CopyingCopyAssignmentTest) { 114 NonDefaultConstructible::ResetCounts(); 115 { 116 Optional<NonDefaultConstructible> A(NonDefaultConstructible(3)); 117 Optional<NonDefaultConstructible> B(NonDefaultConstructible(4)); 118 EXPECT_EQ(2u, NonDefaultConstructible::CopyConstructions); 119 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 120 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 121 NonDefaultConstructible::ResetCounts(); 122 B = A; 123 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 124 EXPECT_EQ(1u, NonDefaultConstructible::CopyAssignments); 125 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 126 NonDefaultConstructible::ResetCounts(); 127 } 128 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 129 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 130 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 131 } 132 133 TEST_F(OptionalTest, DeletingCopyAssignmentTest) { 134 NonDefaultConstructible::ResetCounts(); 135 { 136 Optional<NonDefaultConstructible> A; 137 Optional<NonDefaultConstructible> B(NonDefaultConstructible(3)); 138 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 139 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 140 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 141 NonDefaultConstructible::ResetCounts(); 142 B = A; 143 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 144 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 145 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 146 NonDefaultConstructible::ResetCounts(); 147 } 148 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 149 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 150 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 151 } 152 153 TEST_F(OptionalTest, NullCopyConstructionTest) { 154 NonDefaultConstructible::ResetCounts(); 155 { 156 Optional<NonDefaultConstructible> A; 157 Optional<NonDefaultConstructible> B; 158 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 159 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 160 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 161 NonDefaultConstructible::ResetCounts(); 162 B = A; 163 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 164 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 165 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 166 NonDefaultConstructible::ResetCounts(); 167 } 168 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 169 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 170 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 171 } 172 173 TEST_F(OptionalTest, GetValueOr) { 174 Optional<int> A; 175 EXPECT_EQ(42, A.getValueOr(42)); 176 177 A = 5; 178 EXPECT_EQ(5, A.getValueOr(42)); 179 } 180 181 struct MultiArgConstructor { 182 int x, y; 183 MultiArgConstructor(int x, int y) : x(x), y(y) {} 184 explicit MultiArgConstructor(int x, bool positive) 185 : x(x), y(positive ? x : -x) {} 186 187 MultiArgConstructor(const MultiArgConstructor &) = delete; 188 MultiArgConstructor(MultiArgConstructor &&) = delete; 189 MultiArgConstructor &operator=(const MultiArgConstructor &) = delete; 190 MultiArgConstructor &operator=(MultiArgConstructor &&) = delete; 191 192 static unsigned Destructions; 193 ~MultiArgConstructor() { 194 ++Destructions; 195 } 196 static void ResetCounts() { 197 Destructions = 0; 198 } 199 }; 200 unsigned MultiArgConstructor::Destructions = 0; 201 202 TEST_F(OptionalTest, Emplace) { 203 MultiArgConstructor::ResetCounts(); 204 Optional<MultiArgConstructor> A; 205 206 A.emplace(1, 2); 207 EXPECT_TRUE(A.hasValue()); 208 EXPECT_EQ(1, A->x); 209 EXPECT_EQ(2, A->y); 210 EXPECT_EQ(0u, MultiArgConstructor::Destructions); 211 212 A.emplace(5, false); 213 EXPECT_TRUE(A.hasValue()); 214 EXPECT_EQ(5, A->x); 215 EXPECT_EQ(-5, A->y); 216 EXPECT_EQ(1u, MultiArgConstructor::Destructions); 217 } 218 219 struct MoveOnly { 220 static unsigned MoveConstructions; 221 static unsigned Destructions; 222 static unsigned MoveAssignments; 223 int val; 224 explicit MoveOnly(int val) : val(val) { 225 } 226 MoveOnly(MoveOnly&& other) { 227 val = other.val; 228 ++MoveConstructions; 229 } 230 MoveOnly &operator=(MoveOnly&& other) { 231 val = other.val; 232 ++MoveAssignments; 233 return *this; 234 } 235 ~MoveOnly() { 236 ++Destructions; 237 } 238 static void ResetCounts() { 239 MoveConstructions = 0; 240 Destructions = 0; 241 MoveAssignments = 0; 242 } 243 }; 244 245 unsigned MoveOnly::MoveConstructions = 0; 246 unsigned MoveOnly::Destructions = 0; 247 unsigned MoveOnly::MoveAssignments = 0; 248 249 TEST_F(OptionalTest, MoveOnlyNull) { 250 MoveOnly::ResetCounts(); 251 Optional<MoveOnly> O; 252 EXPECT_EQ(0u, MoveOnly::MoveConstructions); 253 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 254 EXPECT_EQ(0u, MoveOnly::Destructions); 255 } 256 257 TEST_F(OptionalTest, MoveOnlyConstruction) { 258 MoveOnly::ResetCounts(); 259 Optional<MoveOnly> O(MoveOnly(3)); 260 EXPECT_TRUE((bool)O); 261 EXPECT_EQ(3, O->val); 262 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 263 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 264 EXPECT_EQ(1u, MoveOnly::Destructions); 265 } 266 267 TEST_F(OptionalTest, MoveOnlyMoveConstruction) { 268 Optional<MoveOnly> A(MoveOnly(3)); 269 MoveOnly::ResetCounts(); 270 Optional<MoveOnly> B(std::move(A)); 271 EXPECT_TRUE((bool)A); 272 EXPECT_TRUE((bool)B); 273 EXPECT_EQ(3, B->val); 274 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 275 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 276 EXPECT_EQ(0u, MoveOnly::Destructions); 277 } 278 279 TEST_F(OptionalTest, MoveOnlyAssignment) { 280 MoveOnly::ResetCounts(); 281 Optional<MoveOnly> O; 282 O = MoveOnly(3); 283 EXPECT_TRUE((bool)O); 284 EXPECT_EQ(3, O->val); 285 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 286 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 287 EXPECT_EQ(1u, MoveOnly::Destructions); 288 } 289 290 TEST_F(OptionalTest, MoveOnlyInitializingAssignment) { 291 Optional<MoveOnly> A(MoveOnly(3)); 292 Optional<MoveOnly> B; 293 MoveOnly::ResetCounts(); 294 B = std::move(A); 295 EXPECT_TRUE((bool)A); 296 EXPECT_TRUE((bool)B); 297 EXPECT_EQ(3, B->val); 298 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 299 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 300 EXPECT_EQ(0u, MoveOnly::Destructions); 301 } 302 303 TEST_F(OptionalTest, MoveOnlyNullingAssignment) { 304 Optional<MoveOnly> A; 305 Optional<MoveOnly> B(MoveOnly(3)); 306 MoveOnly::ResetCounts(); 307 B = std::move(A); 308 EXPECT_FALSE((bool)A); 309 EXPECT_FALSE((bool)B); 310 EXPECT_EQ(0u, MoveOnly::MoveConstructions); 311 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 312 EXPECT_EQ(1u, MoveOnly::Destructions); 313 } 314 315 TEST_F(OptionalTest, MoveOnlyAssigningAssignment) { 316 Optional<MoveOnly> A(MoveOnly(3)); 317 Optional<MoveOnly> B(MoveOnly(4)); 318 MoveOnly::ResetCounts(); 319 B = std::move(A); 320 EXPECT_TRUE((bool)A); 321 EXPECT_TRUE((bool)B); 322 EXPECT_EQ(3, B->val); 323 EXPECT_EQ(0u, MoveOnly::MoveConstructions); 324 EXPECT_EQ(1u, MoveOnly::MoveAssignments); 325 EXPECT_EQ(0u, MoveOnly::Destructions); 326 } 327 328 struct Immovable { 329 static unsigned Constructions; 330 static unsigned Destructions; 331 int val; 332 explicit Immovable(int val) : val(val) { 333 ++Constructions; 334 } 335 ~Immovable() { 336 ++Destructions; 337 } 338 static void ResetCounts() { 339 Constructions = 0; 340 Destructions = 0; 341 } 342 private: 343 // This should disable all move/copy operations. 344 Immovable(Immovable&& other) = delete; 345 }; 346 347 unsigned Immovable::Constructions = 0; 348 unsigned Immovable::Destructions = 0; 349 350 TEST_F(OptionalTest, ImmovableEmplace) { 351 Optional<Immovable> A; 352 Immovable::ResetCounts(); 353 A.emplace(4); 354 EXPECT_TRUE((bool)A); 355 EXPECT_EQ(4, A->val); 356 EXPECT_EQ(1u, Immovable::Constructions); 357 EXPECT_EQ(0u, Immovable::Destructions); 358 } 359 360 #if LLVM_HAS_RVALUE_REFERENCE_THIS 361 362 TEST_F(OptionalTest, MoveGetValueOr) { 363 Optional<MoveOnly> A; 364 365 MoveOnly::ResetCounts(); 366 EXPECT_EQ(42, std::move(A).getValueOr(MoveOnly(42)).val); 367 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 368 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 369 EXPECT_EQ(2u, MoveOnly::Destructions); 370 371 A = MoveOnly(5); 372 MoveOnly::ResetCounts(); 373 EXPECT_EQ(5, std::move(A).getValueOr(MoveOnly(42)).val); 374 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 375 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 376 EXPECT_EQ(2u, MoveOnly::Destructions); 377 } 378 379 #endif // LLVM_HAS_RVALUE_REFERENCE_THIS 380 381 struct EqualTo { 382 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 383 return X == Y; 384 } 385 }; 386 387 struct NotEqualTo { 388 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 389 return X != Y; 390 } 391 }; 392 393 struct Less { 394 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 395 return X < Y; 396 } 397 }; 398 399 struct Greater { 400 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 401 return X > Y; 402 } 403 }; 404 405 struct LessEqual { 406 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 407 return X <= Y; 408 } 409 }; 410 411 struct GreaterEqual { 412 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 413 return X >= Y; 414 } 415 }; 416 417 template <typename OperatorT, typename T> 418 void CheckRelation(const Optional<T> &Lhs, const Optional<T> &Rhs, 419 bool Expected) { 420 EXPECT_EQ(Expected, OperatorT::apply(Lhs, Rhs)); 421 422 if (Lhs) 423 EXPECT_EQ(Expected, OperatorT::apply(*Lhs, Rhs)); 424 else 425 EXPECT_EQ(Expected, OperatorT::apply(None, Rhs)); 426 427 if (Rhs) 428 EXPECT_EQ(Expected, OperatorT::apply(Lhs, *Rhs)); 429 else 430 EXPECT_EQ(Expected, OperatorT::apply(Lhs, None)); 431 } 432 433 struct EqualityMock {}; 434 const Optional<EqualityMock> NoneEq, EqualityLhs((EqualityMock())), 435 EqualityRhs((EqualityMock())); 436 bool IsEqual; 437 438 bool operator==(const EqualityMock &Lhs, const EqualityMock &Rhs) { 439 EXPECT_EQ(&*EqualityLhs, &Lhs); 440 EXPECT_EQ(&*EqualityRhs, &Rhs); 441 return IsEqual; 442 } 443 444 TEST_F(OptionalTest, OperatorEqual) { 445 CheckRelation<EqualTo>(NoneEq, NoneEq, true); 446 CheckRelation<EqualTo>(NoneEq, EqualityRhs, false); 447 CheckRelation<EqualTo>(EqualityLhs, NoneEq, false); 448 449 IsEqual = false; 450 CheckRelation<EqualTo>(EqualityLhs, EqualityRhs, IsEqual); 451 IsEqual = true; 452 CheckRelation<EqualTo>(EqualityLhs, EqualityRhs, IsEqual); 453 } 454 455 TEST_F(OptionalTest, OperatorNotEqual) { 456 CheckRelation<NotEqualTo>(NoneEq, NoneEq, false); 457 CheckRelation<NotEqualTo>(NoneEq, EqualityRhs, true); 458 CheckRelation<NotEqualTo>(EqualityLhs, NoneEq, true); 459 460 IsEqual = false; 461 CheckRelation<NotEqualTo>(EqualityLhs, EqualityRhs, !IsEqual); 462 IsEqual = true; 463 CheckRelation<NotEqualTo>(EqualityLhs, EqualityRhs, !IsEqual); 464 } 465 466 struct InequalityMock {}; 467 const Optional<InequalityMock> NoneIneq, InequalityLhs((InequalityMock())), 468 InequalityRhs((InequalityMock())); 469 bool IsLess; 470 471 bool operator<(const InequalityMock &Lhs, const InequalityMock &Rhs) { 472 EXPECT_EQ(&*InequalityLhs, &Lhs); 473 EXPECT_EQ(&*InequalityRhs, &Rhs); 474 return IsLess; 475 } 476 477 TEST_F(OptionalTest, OperatorLess) { 478 CheckRelation<Less>(NoneIneq, NoneIneq, false); 479 CheckRelation<Less>(NoneIneq, InequalityRhs, true); 480 CheckRelation<Less>(InequalityLhs, NoneIneq, false); 481 482 IsLess = false; 483 CheckRelation<Less>(InequalityLhs, InequalityRhs, IsLess); 484 IsLess = true; 485 CheckRelation<Less>(InequalityLhs, InequalityRhs, IsLess); 486 } 487 488 TEST_F(OptionalTest, OperatorGreater) { 489 CheckRelation<Greater>(NoneIneq, NoneIneq, false); 490 CheckRelation<Greater>(NoneIneq, InequalityRhs, false); 491 CheckRelation<Greater>(InequalityLhs, NoneIneq, true); 492 493 IsLess = false; 494 CheckRelation<Greater>(InequalityRhs, InequalityLhs, IsLess); 495 IsLess = true; 496 CheckRelation<Greater>(InequalityRhs, InequalityLhs, IsLess); 497 } 498 499 TEST_F(OptionalTest, OperatorLessEqual) { 500 CheckRelation<LessEqual>(NoneIneq, NoneIneq, true); 501 CheckRelation<LessEqual>(NoneIneq, InequalityRhs, true); 502 CheckRelation<LessEqual>(InequalityLhs, NoneIneq, false); 503 504 IsLess = false; 505 CheckRelation<LessEqual>(InequalityRhs, InequalityLhs, !IsLess); 506 IsLess = true; 507 CheckRelation<LessEqual>(InequalityRhs, InequalityLhs, !IsLess); 508 } 509 510 TEST_F(OptionalTest, OperatorGreaterEqual) { 511 CheckRelation<GreaterEqual>(NoneIneq, NoneIneq, true); 512 CheckRelation<GreaterEqual>(NoneIneq, InequalityRhs, false); 513 CheckRelation<GreaterEqual>(InequalityLhs, NoneIneq, true); 514 515 IsLess = false; 516 CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess); 517 IsLess = true; 518 CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess); 519 } 520 521 #if __has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION) 522 static_assert(std::is_trivially_copyable<Optional<int>>::value, 523 "Should be trivially copyable"); 524 static_assert( 525 !std::is_trivially_copyable<Optional<NonDefaultConstructible>>::value, 526 "Shouldn't be trivially copyable"); 527 #endif 528 529 } // end anonymous namespace 530 531