Home | History | Annotate | Download | only in ADT
      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