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"
12using namespace llvm;
13
14namespace {
15
16struct 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
39unsigned NonDefaultConstructible::CopyConstructions = 0;
40unsigned NonDefaultConstructible::Destructions = 0;
41unsigned NonDefaultConstructible::CopyAssignments = 0;
42
43// Test fixture
44class OptionalTest : public testing::Test {
45};
46
47TEST_F(OptionalTest, NonDefaultConstructibleTest) {
48  Optional<NonDefaultConstructible> O;
49  EXPECT_FALSE(O);
50}
51
52TEST_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
65TEST_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
73TEST_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
92TEST_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
112TEST_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
132TEST_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
152TEST_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
172TEST_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
180struct 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};
199unsigned MultiArgConstructor::Destructions = 0;
200
201TEST_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
218struct 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
244unsigned MoveOnly::MoveConstructions = 0;
245unsigned MoveOnly::Destructions = 0;
246unsigned MoveOnly::MoveAssignments = 0;
247
248TEST_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
256TEST_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
266TEST_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
278TEST_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
289TEST_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
302TEST_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
314TEST_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
327struct 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  }
341private:
342  // This should disable all move/copy operations.
343  Immovable(Immovable&& other) = delete;
344};
345
346unsigned Immovable::Constructions = 0;
347unsigned Immovable::Destructions = 0;
348
349TEST_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
361TEST_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
380TEST_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