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 "gtest/gtest.h" 11 #include "llvm/ADT/Optional.h" 12 using namespace llvm; 13 14 namespace { 15 16 struct NonDefaultConstructible { 17 static unsigned CopyConstructions; 18 static unsigned Destructions; 19 static unsigned CopyAssignments; 20 explicit NonDefaultConstructible(int) { 21 } 22 NonDefaultConstructible(const NonDefaultConstructible&) { 23 ++CopyConstructions; 24 } 25 NonDefaultConstructible &operator=(const NonDefaultConstructible&) { 26 ++CopyAssignments; 27 return *this; 28 } 29 ~NonDefaultConstructible() { 30 ++Destructions; 31 } 32 static void ResetCounts() { 33 CopyConstructions = 0; 34 Destructions = 0; 35 CopyAssignments = 0; 36 } 37 }; 38 39 unsigned NonDefaultConstructible::CopyConstructions = 0; 40 unsigned NonDefaultConstructible::Destructions = 0; 41 unsigned NonDefaultConstructible::CopyAssignments = 0; 42 43 // Test fixture 44 class OptionalTest : public testing::Test { 45 }; 46 47 TEST_F(OptionalTest, NonDefaultConstructibleTest) { 48 Optional<NonDefaultConstructible> O; 49 EXPECT_FALSE(O); 50 } 51 52 TEST_F(OptionalTest, ResetTest) { 53 NonDefaultConstructible::ResetCounts(); 54 Optional<NonDefaultConstructible> O(NonDefaultConstructible(3)); 55 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 56 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 57 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 58 NonDefaultConstructible::ResetCounts(); 59 O.reset(); 60 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 61 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 62 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 63 } 64 65 TEST_F(OptionalTest, InitializationLeakTest) { 66 NonDefaultConstructible::ResetCounts(); 67 Optional<NonDefaultConstructible>(NonDefaultConstructible(3)); 68 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 69 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 70 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 71 } 72 73 TEST_F(OptionalTest, CopyConstructionTest) { 74 NonDefaultConstructible::ResetCounts(); 75 { 76 Optional<NonDefaultConstructible> A(NonDefaultConstructible(3)); 77 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 78 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 79 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 80 NonDefaultConstructible::ResetCounts(); 81 Optional<NonDefaultConstructible> B(A); 82 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 83 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 84 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 85 NonDefaultConstructible::ResetCounts(); 86 } 87 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 88 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 89 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 90 } 91 92 TEST_F(OptionalTest, ConstructingCopyAssignmentTest) { 93 NonDefaultConstructible::ResetCounts(); 94 { 95 Optional<NonDefaultConstructible> A(NonDefaultConstructible(3)); 96 Optional<NonDefaultConstructible> B; 97 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 98 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 99 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 100 NonDefaultConstructible::ResetCounts(); 101 B = A; 102 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 103 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 104 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 105 NonDefaultConstructible::ResetCounts(); 106 } 107 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 108 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 109 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 110 } 111 112 TEST_F(OptionalTest, CopyingCopyAssignmentTest) { 113 NonDefaultConstructible::ResetCounts(); 114 { 115 Optional<NonDefaultConstructible> A(NonDefaultConstructible(3)); 116 Optional<NonDefaultConstructible> B(NonDefaultConstructible(4)); 117 EXPECT_EQ(2u, NonDefaultConstructible::CopyConstructions); 118 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 119 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 120 NonDefaultConstructible::ResetCounts(); 121 B = A; 122 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 123 EXPECT_EQ(1u, NonDefaultConstructible::CopyAssignments); 124 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 125 NonDefaultConstructible::ResetCounts(); 126 } 127 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 128 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 129 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 130 } 131 132 TEST_F(OptionalTest, DeletingCopyAssignmentTest) { 133 NonDefaultConstructible::ResetCounts(); 134 { 135 Optional<NonDefaultConstructible> A; 136 Optional<NonDefaultConstructible> B(NonDefaultConstructible(3)); 137 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 138 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 139 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 140 NonDefaultConstructible::ResetCounts(); 141 B = A; 142 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 143 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 144 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 145 NonDefaultConstructible::ResetCounts(); 146 } 147 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 148 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 149 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 150 } 151 152 TEST_F(OptionalTest, NullCopyConstructionTest) { 153 NonDefaultConstructible::ResetCounts(); 154 { 155 Optional<NonDefaultConstructible> A; 156 Optional<NonDefaultConstructible> B; 157 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 158 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 159 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 160 NonDefaultConstructible::ResetCounts(); 161 B = A; 162 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 163 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 164 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 165 NonDefaultConstructible::ResetCounts(); 166 } 167 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 168 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 169 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 170 } 171 172 TEST_F(OptionalTest, GetValueOr) { 173 Optional<int> A; 174 EXPECT_EQ(42, A.getValueOr(42)); 175 176 A = 5; 177 EXPECT_EQ(5, A.getValueOr(42)); 178 } 179 180 struct MultiArgConstructor { 181 int x, y; 182 MultiArgConstructor(int x, int y) : x(x), y(y) {} 183 explicit MultiArgConstructor(int x, bool positive) 184 : x(x), y(positive ? x : -x) {} 185 186 MultiArgConstructor(const MultiArgConstructor &) = delete; 187 MultiArgConstructor(MultiArgConstructor &&) = delete; 188 MultiArgConstructor &operator=(const MultiArgConstructor &) = delete; 189 MultiArgConstructor &operator=(MultiArgConstructor &&) = delete; 190 191 static unsigned Destructions; 192 ~MultiArgConstructor() { 193 ++Destructions; 194 } 195 static void ResetCounts() { 196 Destructions = 0; 197 } 198 }; 199 unsigned MultiArgConstructor::Destructions = 0; 200 201 TEST_F(OptionalTest, Emplace) { 202 MultiArgConstructor::ResetCounts(); 203 Optional<MultiArgConstructor> A; 204 205 A.emplace(1, 2); 206 EXPECT_TRUE(A.hasValue()); 207 EXPECT_EQ(1, A->x); 208 EXPECT_EQ(2, A->y); 209 EXPECT_EQ(0u, MultiArgConstructor::Destructions); 210 211 A.emplace(5, false); 212 EXPECT_TRUE(A.hasValue()); 213 EXPECT_EQ(5, A->x); 214 EXPECT_EQ(-5, A->y); 215 EXPECT_EQ(1u, MultiArgConstructor::Destructions); 216 } 217 218 struct MoveOnly { 219 static unsigned MoveConstructions; 220 static unsigned Destructions; 221 static unsigned MoveAssignments; 222 int val; 223 explicit MoveOnly(int val) : val(val) { 224 } 225 MoveOnly(MoveOnly&& other) { 226 val = other.val; 227 ++MoveConstructions; 228 } 229 MoveOnly &operator=(MoveOnly&& other) { 230 val = other.val; 231 ++MoveAssignments; 232 return *this; 233 } 234 ~MoveOnly() { 235 ++Destructions; 236 } 237 static void ResetCounts() { 238 MoveConstructions = 0; 239 Destructions = 0; 240 MoveAssignments = 0; 241 } 242 }; 243 244 unsigned MoveOnly::MoveConstructions = 0; 245 unsigned MoveOnly::Destructions = 0; 246 unsigned MoveOnly::MoveAssignments = 0; 247 248 TEST_F(OptionalTest, MoveOnlyNull) { 249 MoveOnly::ResetCounts(); 250 Optional<MoveOnly> O; 251 EXPECT_EQ(0u, MoveOnly::MoveConstructions); 252 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 253 EXPECT_EQ(0u, MoveOnly::Destructions); 254 } 255 256 TEST_F(OptionalTest, MoveOnlyConstruction) { 257 MoveOnly::ResetCounts(); 258 Optional<MoveOnly> O(MoveOnly(3)); 259 EXPECT_TRUE((bool)O); 260 EXPECT_EQ(3, O->val); 261 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 262 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 263 EXPECT_EQ(1u, MoveOnly::Destructions); 264 } 265 266 TEST_F(OptionalTest, MoveOnlyMoveConstruction) { 267 Optional<MoveOnly> A(MoveOnly(3)); 268 MoveOnly::ResetCounts(); 269 Optional<MoveOnly> B(std::move(A)); 270 EXPECT_FALSE((bool)A); 271 EXPECT_TRUE((bool)B); 272 EXPECT_EQ(3, B->val); 273 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 274 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 275 EXPECT_EQ(1u, MoveOnly::Destructions); 276 } 277 278 TEST_F(OptionalTest, MoveOnlyAssignment) { 279 MoveOnly::ResetCounts(); 280 Optional<MoveOnly> O; 281 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); 287 } 288 289 TEST_F(OptionalTest, MoveOnlyInitializingAssignment) { 290 Optional<MoveOnly> A(MoveOnly(3)); 291 Optional<MoveOnly> B; 292 MoveOnly::ResetCounts(); 293 B = std::move(A); 294 EXPECT_FALSE((bool)A); 295 EXPECT_TRUE((bool)B); 296 EXPECT_EQ(3, B->val); 297 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 298 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 299 EXPECT_EQ(1u, MoveOnly::Destructions); 300 } 301 302 TEST_F(OptionalTest, MoveOnlyNullingAssignment) { 303 Optional<MoveOnly> A; 304 Optional<MoveOnly> B(MoveOnly(3)); 305 MoveOnly::ResetCounts(); 306 B = std::move(A); 307 EXPECT_FALSE((bool)A); 308 EXPECT_FALSE((bool)B); 309 EXPECT_EQ(0u, MoveOnly::MoveConstructions); 310 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 311 EXPECT_EQ(1u, MoveOnly::Destructions); 312 } 313 314 TEST_F(OptionalTest, MoveOnlyAssigningAssignment) { 315 Optional<MoveOnly> A(MoveOnly(3)); 316 Optional<MoveOnly> B(MoveOnly(4)); 317 MoveOnly::ResetCounts(); 318 B = std::move(A); 319 EXPECT_FALSE((bool)A); 320 EXPECT_TRUE((bool)B); 321 EXPECT_EQ(3, B->val); 322 EXPECT_EQ(0u, MoveOnly::MoveConstructions); 323 EXPECT_EQ(1u, MoveOnly::MoveAssignments); 324 EXPECT_EQ(1u, MoveOnly::Destructions); 325 } 326 327 struct Immovable { 328 static unsigned Constructions; 329 static unsigned Destructions; 330 int val; 331 explicit Immovable(int val) : val(val) { 332 ++Constructions; 333 } 334 ~Immovable() { 335 ++Destructions; 336 } 337 static void ResetCounts() { 338 Constructions = 0; 339 Destructions = 0; 340 } 341 private: 342 // This should disable all move/copy operations. 343 Immovable(Immovable&& other) = delete; 344 }; 345 346 unsigned Immovable::Constructions = 0; 347 unsigned Immovable::Destructions = 0; 348 349 TEST_F(OptionalTest, ImmovableEmplace) { 350 Optional<Immovable> A; 351 Immovable::ResetCounts(); 352 A.emplace(4); 353 EXPECT_TRUE((bool)A); 354 EXPECT_EQ(4, A->val); 355 EXPECT_EQ(1u, Immovable::Constructions); 356 EXPECT_EQ(0u, Immovable::Destructions); 357 } 358 359 #if LLVM_HAS_RVALUE_REFERENCE_THIS 360 361 TEST_F(OptionalTest, MoveGetValueOr) { 362 Optional<MoveOnly> A; 363 364 MoveOnly::ResetCounts(); 365 EXPECT_EQ(42, std::move(A).getValueOr(MoveOnly(42)).val); 366 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 367 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 368 EXPECT_EQ(2u, MoveOnly::Destructions); 369 370 A = MoveOnly(5); 371 MoveOnly::ResetCounts(); 372 EXPECT_EQ(5, std::move(A).getValueOr(MoveOnly(42)).val); 373 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 374 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 375 EXPECT_EQ(2u, MoveOnly::Destructions); 376 } 377 378 #endif // LLVM_HAS_RVALUE_REFERENCE_THIS 379 380 TEST_F(OptionalTest, NoneComparison) { 381 Optional<int> o; 382 EXPECT_EQ(o, None); 383 EXPECT_EQ(None, o); 384 EXPECT_FALSE(o != None); 385 EXPECT_FALSE(None != o); 386 o = 3; 387 EXPECT_FALSE(o == None); 388 EXPECT_FALSE(None == o); 389 EXPECT_TRUE(o != None); 390 EXPECT_TRUE(None != o); 391 } 392 393 } // end anonymous namespace 394 395