Caffe2 - C++ API
A deep learning, cross platform ML framework
intrusive_ptr_test.cpp
1 #include <c10/util/intrusive_ptr.h>
2 
3 #include <gtest/gtest.h>
4 #include <map>
5 #include <set>
6 #include <unordered_map>
7 #include <unordered_set>
8 
11 using c10::make_intrusive;
13 
14 #ifndef _MSC_VER
15 #pragma GCC diagnostic ignored "-Wpragmas"
16 #pragma GCC diagnostic ignored "-Wunknown-warning-option"
17 #pragma GCC diagnostic ignored "-Wself-move"
18 #endif
19 
20 namespace {
21 class SomeClass0Parameters : public intrusive_ptr_target {};
22 class SomeClass1Parameter : public intrusive_ptr_target {
23  public:
24  SomeClass1Parameter(int param_) : param(param_) {}
25  int param;
26 };
27 class SomeClass2Parameters : public intrusive_ptr_target {
28  public:
29  SomeClass2Parameters(int param1_, int param2_)
30  : param1(param1_), param2(param2_) {}
31  int param1;
32  int param2;
33 };
34 using SomeClass = SomeClass0Parameters;
35 struct SomeBaseClass : public intrusive_ptr_target {
36  SomeBaseClass(int v_) : v(v_) {}
37  int v;
38 };
39 struct SomeChildClass : SomeBaseClass {
40  SomeChildClass(int v) : SomeBaseClass(v) {}
41 };
42 
43 class DestructableMock : public intrusive_ptr_target {
44  public:
45  DestructableMock(bool* resourcesReleased, bool* wasDestructed)
46  : resourcesReleased_(resourcesReleased), wasDestructed_(wasDestructed) {}
47 
48  ~DestructableMock() override {
49  *wasDestructed_ = true;
50  }
51 
52  void release_resources() override {
53  *resourcesReleased_ = true;
54  }
55 
56  private:
57  bool* resourcesReleased_;
58  bool* wasDestructed_;
59 };
60 
61 class ChildDestructableMock final : public DestructableMock {
62  public:
63  ChildDestructableMock(bool* resourcesReleased, bool* wasDestructed)
64  : DestructableMock(resourcesReleased, wasDestructed) {}
65 };
66 class NullType1 final {
67  static SomeClass singleton_;
68 public:
69  static constexpr SomeClass* singleton() {
70  return &singleton_;
71  }
72 };
73 SomeClass NullType1::singleton_;
74 class NullType2 final {
75  static SomeClass singleton_;
76 public:
77  static constexpr SomeClass* singleton() {
78  return &singleton_;
79  }
80 };
81 SomeClass NullType2::singleton_;
82 static_assert(NullType1::singleton() != NullType2::singleton(), "");
83 } // namespace
84 
85 static_assert(
86  std::is_same<SomeClass, intrusive_ptr<SomeClass>::element_type>::value,
87  "intrusive_ptr<T>::element_type is wrong");
88 
89 TEST(MakeIntrusiveTest, ClassWith0Parameters) {
91  make_intrusive<SomeClass0Parameters>();
92  // Check that the type is correct
93  EXPECT_EQ(var.get(), dynamic_cast<SomeClass0Parameters*>(var.get()));
94 }
95 
96 TEST(MakeIntrusiveTest, ClassWith1Parameter) {
98  make_intrusive<SomeClass1Parameter>(5);
99  EXPECT_EQ(5, var->param);
100 }
101 
102 TEST(MakeIntrusiveTest, ClassWith2Parameters) {
104  make_intrusive<SomeClass2Parameters>(7, 2);
105  EXPECT_EQ(7, var->param1);
106  EXPECT_EQ(2, var->param2);
107 }
108 
109 TEST(MakeIntrusiveTest, TypeIsAutoDeductible) {
110  auto var2 = make_intrusive<SomeClass0Parameters>();
111  auto var3 = make_intrusive<SomeClass1Parameter>(2);
112  auto var4 = make_intrusive<SomeClass2Parameters>(2, 3);
113 }
114 
115 TEST(MakeIntrusiveTest, CanAssignToBaseClassPtr) {
116  intrusive_ptr<SomeBaseClass> var = make_intrusive<SomeChildClass>(3);
117  EXPECT_EQ(3, var->v);
118 }
119 
120 TEST(IntrusivePtrTargetTest, whenAllocatedOnStack_thenDoesntCrash) {
121  SomeClass myClass;
122 }
123 
124 TEST(IntrusivePtrTest, givenValidPtr_whenCallingGet_thenReturnsObject) {
126  make_intrusive<SomeClass1Parameter>(5);
127  EXPECT_EQ(5, obj.get()->param);
128 }
129 
130 TEST(IntrusivePtrTest, givenValidPtr_whenCallingConstGet_thenReturnsObject) {
132  make_intrusive<SomeClass1Parameter>(5);
133  EXPECT_EQ(5, obj.get()->param);
134 }
135 
136 TEST(IntrusivePtrTest, givenInvalidPtr_whenCallingGet_thenReturnsNullptr) {
138  EXPECT_EQ(nullptr, obj.get());
139 }
140 
141 TEST(IntrusivePtrTest, givenValidPtr_whenDereferencing_thenReturnsObject) {
143  make_intrusive<SomeClass1Parameter>(5);
144  EXPECT_EQ(5, (*obj).param);
145 }
146 
147 TEST(IntrusivePtrTest, givenValidPtr_whenConstDereferencing_thenReturnsObject) {
149  make_intrusive<SomeClass1Parameter>(5);
150  EXPECT_EQ(5, (*obj).param);
151 }
152 
153 TEST(IntrusivePtrTest, givenValidPtr_whenArrowDereferencing_thenReturnsObject) {
155  make_intrusive<SomeClass1Parameter>(3);
156  EXPECT_EQ(3, obj->param);
157 }
158 
159 TEST(
160  IntrusivePtrTest,
161  givenValidPtr_whenConstArrowDereferencing_thenReturnsObject) {
163  make_intrusive<SomeClass1Parameter>(3);
164  EXPECT_EQ(3, obj->param);
165 }
166 
167 TEST(IntrusivePtrTest, givenValidPtr_whenMoveAssigning_thenPointsToSameObject) {
168  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
169  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
170  SomeClass* obj1ptr = obj1.get();
171  obj2 = std::move(obj1);
172  EXPECT_EQ(obj1ptr, obj2.get());
173 }
174 
175 TEST(IntrusivePtrTest, givenValidPtr_whenMoveAssigning_thenOldInstanceInvalid) {
176  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
177  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
178  obj2 = std::move(obj1);
179  EXPECT_FALSE(obj1.defined());
180 }
181 
182 TEST(
183  IntrusivePtrTest,
184  givenValidPtr_whenMoveAssigningToSelf_thenPointsToSameObject) {
185  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
186  SomeClass* obj1ptr = obj1.get();
187  obj1 = std::move(obj1);
188  EXPECT_EQ(obj1ptr, obj1.get());
189 }
190 
191 TEST(IntrusivePtrTest, givenValidPtr_whenMoveAssigningToSelf_thenStaysValid) {
192  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
193  obj1 = std::move(obj1);
194  EXPECT_TRUE(obj1.defined());
195 }
196 
197 TEST(
198  IntrusivePtrTest,
199  givenInvalidPtr_whenMoveAssigningToSelf_thenStaysInvalid) {
201  obj1 = std::move(obj1);
202  EXPECT_FALSE(obj1.defined());
203 }
204 
205 TEST(
206  IntrusivePtrTest,
207  givenInvalidPtr_whenMoveAssigning_thenNewInstanceIsValid) {
208  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
210  SomeClass* obj1ptr = obj1.get();
211  obj2 = std::move(obj1);
212  EXPECT_TRUE(obj2.defined());
213 }
214 
215 TEST(
216  IntrusivePtrTest,
217  givenInvalidPtr_whenMoveAssigning_thenPointsToSameObject) {
218  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
220  SomeClass* obj1ptr = obj1.get();
221  obj2 = std::move(obj1);
222  EXPECT_EQ(obj1ptr, obj2.get());
223 }
224 
225 TEST(
226  IntrusivePtrTest,
227  givenValidPtr_whenMoveAssigningFromInvalidPtr_thenNewInstanceIsInvalid) {
229  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
230  EXPECT_TRUE(obj2.defined());
231  obj2 = std::move(obj1);
232  EXPECT_FALSE(obj2.defined());
233 }
234 
235 TEST(
236  IntrusivePtrTest,
237  givenValidPtr_whenMoveAssigningToBaseClass_thenPointsToSameObject) {
238  intrusive_ptr<SomeChildClass> obj1 = make_intrusive<SomeChildClass>(1);
239  intrusive_ptr<SomeBaseClass> obj2 = make_intrusive<SomeBaseClass>(2);
240  SomeBaseClass* obj1ptr = obj1.get();
241  obj2 = std::move(obj1);
242  EXPECT_EQ(obj1ptr, obj2.get());
243  EXPECT_EQ(1, obj2->v);
244 }
245 
246 TEST(
247  IntrusivePtrTest,
248  givenValidPtr_whenMoveAssigningToBaseClass_thenOldInstanceInvalid) {
249  intrusive_ptr<SomeChildClass> obj1 = make_intrusive<SomeChildClass>(1);
250  intrusive_ptr<SomeBaseClass> obj2 = make_intrusive<SomeBaseClass>(2);
251  obj2 = std::move(obj1);
252  EXPECT_FALSE(obj1.defined());
253 }
254 
255 TEST(
256  IntrusivePtrTest,
257  givenInvalidPtr_whenMoveAssigningToBaseClass_thenNewInstanceIsValid) {
258  intrusive_ptr<SomeChildClass> obj1 = make_intrusive<SomeChildClass>(5);
260  SomeBaseClass* obj1ptr = obj1.get();
261  obj2 = std::move(obj1);
262  EXPECT_TRUE(obj2.defined());
263 }
264 
265 TEST(
266  IntrusivePtrTest,
267  givenInvalidPtr_whenMoveAssigningToBaseClass_thenPointsToSameObject) {
268  intrusive_ptr<SomeChildClass> obj1 = make_intrusive<SomeChildClass>(5);
270  SomeBaseClass* obj1ptr = obj1.get();
271  obj2 = std::move(obj1);
272  EXPECT_EQ(obj1ptr, obj2.get());
273  EXPECT_EQ(5, obj2->v);
274 }
275 
276 TEST(
277  IntrusivePtrTest,
278  givenInvalidPtr_whenMoveAssigningInvalidPtrToBaseClass_thenNewInstanceIsValid) {
280  intrusive_ptr<SomeBaseClass> obj2 = make_intrusive<SomeBaseClass>(2);
281  EXPECT_TRUE(obj2.defined());
282  obj2 = std::move(obj1);
283  EXPECT_FALSE(obj2.defined());
284 }
285 
286 TEST(
287  IntrusivePtrTest,
288  givenNullPtr_whenMoveAssigningToDifferentNullptr_thenHasNewNullptr) {
291  obj2 = std::move(obj1);
292  EXPECT_NE(NullType1::singleton(), NullType2::singleton());
293  EXPECT_EQ(NullType1::singleton(), obj1.get());
294  EXPECT_EQ(NullType2::singleton(), obj2.get());
295  EXPECT_FALSE(obj1.defined());
296  EXPECT_FALSE(obj2.defined());
297 }
298 
299 TEST(IntrusivePtrTest, givenValidPtr_whenCopyAssigning_thenPointsToSameObject) {
300  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
301  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
302  SomeClass* obj1ptr = obj1.get();
303  obj2 = obj1;
304  EXPECT_EQ(obj1ptr, obj2.get());
305 }
306 
307 TEST(IntrusivePtrTest, givenValidPtr_whenCopyAssigning_thenOldInstanceValid) {
308  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
309  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
310  obj2 = obj1;
311  EXPECT_TRUE(obj1.defined());
312 }
313 
314 TEST(
315  IntrusivePtrTest,
316  givenValidPtr_whenCopyAssigningToSelf_thenPointsToSameObject) {
317  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
318  SomeClass* obj1ptr = obj1.get();
319  obj1 = obj1;
320  EXPECT_EQ(obj1ptr, obj1.get());
321 }
322 
323 TEST(IntrusivePtrTest, givenValidPtr_whenCopyAssigningToSelf_thenStaysValid) {
324  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
325  obj1 = obj1;
326  EXPECT_TRUE(obj1.defined());
327 }
328 
329 TEST(
330  IntrusivePtrTest,
331  givenInvalidPtr_whenCopyAssigningToSelf_thenStaysInvalid) {
333  obj1 = obj1;
334  EXPECT_FALSE(obj1.defined());
335 }
336 
337 TEST(
338  IntrusivePtrTest,
339  givenInvalidPtr_whenCopyAssigning_thenNewInstanceIsValid) {
340  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
342  SomeClass* obj1ptr = obj1.get();
343  obj2 = obj1;
344  EXPECT_TRUE(obj2.defined());
345 }
346 
347 TEST(
348  IntrusivePtrTest,
349  givenValidPtr_whenCopyAssigningToBaseClass_thenPointsToSameObject) {
350  intrusive_ptr<SomeChildClass> child = make_intrusive<SomeChildClass>(3);
351  intrusive_ptr<SomeBaseClass> base = make_intrusive<SomeBaseClass>(10);
352  base = child;
353  EXPECT_EQ(3, base->v);
354 }
355 
356 TEST(
357  IntrusivePtrTest,
358  givenValidPtr_whenCopyAssigningToBaseClass_thenOldInstanceInvalid) {
359  intrusive_ptr<SomeChildClass> obj1 = make_intrusive<SomeChildClass>(3);
360  intrusive_ptr<SomeBaseClass> obj2 = make_intrusive<SomeBaseClass>(10);
361  obj2 = obj1;
362  EXPECT_TRUE(obj1.defined());
363 }
364 
365 TEST(
366  IntrusivePtrTest,
367  givenInvalidPtr_whenCopyAssigningToBaseClass_thenNewInstanceIsValid) {
368  intrusive_ptr<SomeChildClass> obj1 = make_intrusive<SomeChildClass>(5);
370  SomeBaseClass* obj1ptr = obj1.get();
371  obj2 = obj1;
372  EXPECT_TRUE(obj2.defined());
373 }
374 
375 TEST(
376  IntrusivePtrTest,
377  givenInvalidPtr_whenCopyAssigningToBaseClass_thenPointsToSameObject) {
378  intrusive_ptr<SomeChildClass> obj1 = make_intrusive<SomeChildClass>(5);
380  SomeBaseClass* obj1ptr = obj1.get();
381  obj2 = obj1;
382  EXPECT_EQ(obj1ptr, obj2.get());
383  EXPECT_EQ(5, obj2->v);
384 }
385 
386 TEST(
387  IntrusivePtrTest,
388  givenPtr_whenCopyAssigningInvalidPtrToBaseClass_thenNewInstanceIsInvalid) {
390  intrusive_ptr<SomeBaseClass> obj2 = make_intrusive<SomeBaseClass>(2);
391  EXPECT_TRUE(obj2.defined());
392  obj2 = obj1;
393  EXPECT_FALSE(obj2.defined());
394 }
395 
396 TEST(
397  IntrusivePtrTest,
398  givenNullPtr_whenCopyAssigningToDifferentNullptr_thenHasNewNullptr) {
401  obj2 = obj1;
402  EXPECT_NE(NullType1::singleton(), NullType2::singleton());
403  EXPECT_EQ(NullType1::singleton(), obj1.get());
404  EXPECT_EQ(NullType2::singleton(), obj2.get());
405  EXPECT_FALSE(obj1.defined());
406  EXPECT_FALSE(obj2.defined());
407 }
408 
409 TEST(IntrusivePtrTest, givenPtr_whenMoveConstructing_thenPointsToSameObject) {
410  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
411  SomeClass* obj1ptr = obj1.get();
412  intrusive_ptr<SomeClass> obj2 = std::move(obj1);
413  EXPECT_EQ(obj1ptr, obj2.get());
414 }
415 
416 TEST(IntrusivePtrTest, givenPtr_whenMoveConstructing_thenOldInstanceInvalid) {
417  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
418  intrusive_ptr<SomeClass> obj2 = std::move(obj1);
419  EXPECT_FALSE(obj1.defined());
420 }
421 
422 TEST(IntrusivePtrTest, givenPtr_whenMoveConstructing_thenNewInstanceValid) {
423  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
424  intrusive_ptr<SomeClass> obj2 = std::move(obj1);
425  EXPECT_TRUE(obj2.defined());
426 }
427 
428 TEST(
429  IntrusivePtrTest,
430  givenPtr_whenMoveConstructingFromInvalidPtr_thenNewInstanceInvalid) {
432  intrusive_ptr<SomeClass> obj2 = std::move(obj1);
433  EXPECT_FALSE(obj2.defined());
434 }
435 
436 TEST(
437  IntrusivePtrTest,
438  givenPtr_whenMoveConstructingToBaseClass_thenPointsToSameObject) {
439  intrusive_ptr<SomeChildClass> child = make_intrusive<SomeChildClass>(3);
440  SomeBaseClass* objptr = child.get();
441  intrusive_ptr<SomeBaseClass> base = std::move(child);
442  EXPECT_EQ(3, base->v);
443  EXPECT_EQ(objptr, base.get());
444 }
445 
446 TEST(
447  IntrusivePtrTest,
448  givenPtr_whenMoveConstructingToBaseClass_thenOldInstanceInvalid) {
449  intrusive_ptr<SomeChildClass> child = make_intrusive<SomeChildClass>(3);
450  intrusive_ptr<SomeBaseClass> base = std::move(child);
451  EXPECT_FALSE(child.defined());
452 }
453 
454 TEST(
455  IntrusivePtrTest,
456  givenPtr_whenMoveConstructingToBaseClass_thenNewInstanceValid) {
457  intrusive_ptr<SomeChildClass> obj1 = make_intrusive<SomeChildClass>(2);
458  intrusive_ptr<SomeBaseClass> obj2 = std::move(obj1);
459  EXPECT_TRUE(obj2.defined());
460 }
461 
462 TEST(
463  IntrusivePtrTest,
464  givenPtr_whenMoveConstructingToBaseClassFromInvalidPtr_thenNewInstanceInvalid) {
466  intrusive_ptr<SomeBaseClass> obj2 = std::move(obj1);
467  EXPECT_FALSE(obj2.defined());
468 }
469 
470 TEST(
471  IntrusivePtrTest,
472  givenNullPtr_whenMoveConstructingToDifferentNullptr_thenHasNewNullptr) {
474  intrusive_ptr<SomeClass, NullType2> obj2 = std::move(obj1);
475  EXPECT_NE(NullType1::singleton(), NullType2::singleton());
476  EXPECT_EQ(NullType1::singleton(), obj1.get());
477  EXPECT_EQ(NullType2::singleton(), obj2.get());
478  EXPECT_FALSE(obj1.defined());
479  EXPECT_FALSE(obj2.defined());
480 }
481 
482 TEST(IntrusivePtrTest, givenPtr_whenCopyConstructing_thenPointsToSameObject) {
483  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
484  SomeClass* obj1ptr = obj1.get();
485  intrusive_ptr<SomeClass> obj2 = obj1;
486  EXPECT_EQ(obj1ptr, obj2.get());
487  EXPECT_TRUE(obj1.defined());
488 }
489 
490 TEST(IntrusivePtrTest, givenPtr_whenCopyConstructing_thenOldInstanceValid) {
491  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
492  intrusive_ptr<SomeClass> obj2 = obj1;
493  EXPECT_TRUE(obj1.defined());
494 }
495 
496 TEST(IntrusivePtrTest, givenPtr_whenCopyConstructing_thenNewInstanceValid) {
497  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
498  intrusive_ptr<SomeClass> obj2 = obj1;
499  EXPECT_TRUE(obj2.defined());
500 }
501 
502 TEST(
503  IntrusivePtrTest,
504  givenPtr_whenCopyConstructingFromInvalidPtr_thenNewInstanceInvalid) {
506  intrusive_ptr<SomeClass> obj2 = obj1;
507  EXPECT_FALSE(obj2.defined());
508 }
509 
510 TEST(
511  IntrusivePtrTest,
512  givenPtr_whenCopyConstructingToBaseClass_thenPointsToSameObject) {
513  intrusive_ptr<SomeChildClass> child = make_intrusive<SomeChildClass>(3);
514  SomeBaseClass* objptr = child.get();
515  intrusive_ptr<SomeBaseClass> base = child;
516  EXPECT_EQ(3, base->v);
517  EXPECT_EQ(objptr, base.get());
518 }
519 
520 TEST(
521  IntrusivePtrTest,
522  givenPtr_whenCopyConstructingToBaseClass_thenOldInstanceInvalid) {
523  intrusive_ptr<SomeChildClass> child = make_intrusive<SomeChildClass>(3);
524  intrusive_ptr<SomeBaseClass> base = child;
525  EXPECT_TRUE(child.defined());
526 }
527 
528 TEST(
529  IntrusivePtrTest,
530  givenPtr_whenCopyConstructingToBaseClass_thenNewInstanceInvalid) {
531  intrusive_ptr<SomeChildClass> child = make_intrusive<SomeChildClass>(3);
532  intrusive_ptr<SomeBaseClass> base = child;
533  EXPECT_TRUE(base.defined());
534 }
535 
536 TEST(
537  IntrusivePtrTest,
538  givenPtr_whenCopyConstructingToBaseClassFromInvalidPtr_thenNewInstanceInvalid) {
540  intrusive_ptr<SomeBaseClass> obj2 = obj1;
541  EXPECT_FALSE(obj2.defined());
542 }
543 
544 TEST(
545  IntrusivePtrTest,
546  givenNullPtr_whenCopyConstructingToDifferentNullptr_thenHasNewNullptr) {
549  EXPECT_NE(NullType1::singleton(), NullType2::singleton());
550  EXPECT_EQ(NullType1::singleton(), obj1.get());
551  EXPECT_EQ(NullType2::singleton(), obj2.get());
552  EXPECT_FALSE(obj1.defined());
553  EXPECT_FALSE(obj2.defined());
554 }
555 
556 TEST(IntrusivePtrTest, SwapFunction) {
557  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
558  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
559  SomeClass* obj1ptr = obj1.get();
560  SomeClass* obj2ptr = obj2.get();
561  swap(obj1, obj2);
562  EXPECT_EQ(obj2ptr, obj1.get());
563  EXPECT_EQ(obj1ptr, obj2.get());
564 }
565 
566 TEST(IntrusivePtrTest, SwapMethod) {
567  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
568  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
569  SomeClass* obj1ptr = obj1.get();
570  SomeClass* obj2ptr = obj2.get();
571  obj1.swap(obj2);
572  EXPECT_EQ(obj2ptr, obj1.get());
573  EXPECT_EQ(obj1ptr, obj2.get());
574 }
575 
576 TEST(IntrusivePtrTest, SwapFunctionFromInvalid) {
578  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
579  SomeClass* obj2ptr = obj2.get();
580  swap(obj1, obj2);
581  EXPECT_EQ(obj2ptr, obj1.get());
582  EXPECT_TRUE(obj1.defined());
583  EXPECT_FALSE(obj2.defined());
584 }
585 
586 TEST(IntrusivePtrTest, SwapMethodFromInvalid) {
588  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
589  SomeClass* obj2ptr = obj2.get();
590  obj1.swap(obj2);
591  EXPECT_EQ(obj2ptr, obj1.get());
592  EXPECT_TRUE(obj1.defined());
593  EXPECT_FALSE(obj2.defined());
594 }
595 
596 TEST(IntrusivePtrTest, SwapFunctionWithInvalid) {
597  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
599  SomeClass* obj1ptr = obj1.get();
600  swap(obj1, obj2);
601  EXPECT_FALSE(obj1.defined());
602  EXPECT_TRUE(obj2.defined());
603  EXPECT_EQ(obj1ptr, obj2.get());
604 }
605 
606 TEST(IntrusivePtrTest, SwapMethodWithInvalid) {
607  intrusive_ptr<SomeClass> obj1 = make_intrusive<SomeClass>();
609  SomeClass* obj1ptr = obj1.get();
610  obj1.swap(obj2);
611  EXPECT_FALSE(obj1.defined());
612  EXPECT_TRUE(obj2.defined());
613  EXPECT_EQ(obj1ptr, obj2.get());
614 }
615 
616 TEST(IntrusivePtrTest, SwapFunctionInvalidWithInvalid) {
619  swap(obj1, obj2);
620  EXPECT_FALSE(obj1.defined());
621  EXPECT_FALSE(obj2.defined());
622 }
623 
624 TEST(IntrusivePtrTest, SwapMethodInvalidWithInvalid) {
627  obj1.swap(obj2);
628  EXPECT_FALSE(obj1.defined());
629  EXPECT_FALSE(obj2.defined());
630 }
631 
632 TEST(IntrusivePtrTest, CanBePutInContainer) {
633  std::vector<intrusive_ptr<SomeClass1Parameter>> vec;
634  vec.push_back(make_intrusive<SomeClass1Parameter>(5));
635  EXPECT_EQ(5, vec[0]->param);
636 }
637 
638 TEST(IntrusivePtrTest, CanBePutInSet) {
639  std::set<intrusive_ptr<SomeClass1Parameter>> set;
640  set.insert(make_intrusive<SomeClass1Parameter>(5));
641  EXPECT_EQ(5, (*set.begin())->param);
642 }
643 
644 TEST(IntrusivePtrTest, CanBePutInUnorderedSet) {
645  std::unordered_set<intrusive_ptr<SomeClass1Parameter>> set;
646  set.insert(make_intrusive<SomeClass1Parameter>(5));
647  EXPECT_EQ(5, (*set.begin())->param);
648 }
649 
650 TEST(IntrusivePtrTest, CanBePutInMap) {
651  std::map<
653  intrusive_ptr<SomeClass1Parameter>>
654  map;
655  map.insert(std::make_pair(
656  make_intrusive<SomeClass1Parameter>(5),
657  make_intrusive<SomeClass1Parameter>(3)));
658  EXPECT_EQ(5, map.begin()->first->param);
659  EXPECT_EQ(3, map.begin()->second->param);
660 }
661 
662 TEST(IntrusivePtrTest, CanBePutInUnorderedMap) {
663  std::unordered_map<
664  intrusive_ptr<SomeClass1Parameter>,
665  intrusive_ptr<SomeClass1Parameter>>
666  map;
667  map.insert(std::make_pair(
668  make_intrusive<SomeClass1Parameter>(3),
669  make_intrusive<SomeClass1Parameter>(5)));
670  EXPECT_EQ(3, map.begin()->first->param);
671  EXPECT_EQ(5, map.begin()->second->param);
672 }
673 
674 TEST(IntrusivePtrTest, Equality_AfterCopyConstructor) {
675  intrusive_ptr<SomeClass> var1 = make_intrusive<SomeClass>();
676  intrusive_ptr<SomeClass> var2 = var1;
677  EXPECT_TRUE(var1 == var2);
678  EXPECT_FALSE(var1 != var2);
679 }
680 
681 TEST(IntrusivePtrTest, Equality_AfterCopyAssignment) {
682  intrusive_ptr<SomeClass> var1 = make_intrusive<SomeClass>();
683  intrusive_ptr<SomeClass> var2 = make_intrusive<SomeClass>();
684  var2 = var1;
685  EXPECT_TRUE(var1 == var2);
686  EXPECT_FALSE(var1 != var2);
687 }
688 
689 TEST(IntrusivePtrTest, Equality_Nullptr) {
692  EXPECT_TRUE(var1 == var2);
693  EXPECT_FALSE(var1 != var2);
694 }
695 
696 TEST(IntrusivePtrTest, Nonequality) {
697  intrusive_ptr<SomeClass> var1 = make_intrusive<SomeClass>();
698  intrusive_ptr<SomeClass> var2 = make_intrusive<SomeClass>();
699  EXPECT_TRUE(var1 != var2);
700  EXPECT_FALSE(var1 == var2);
701 }
702 
703 TEST(IntrusivePtrTest, Nonequality_NullptrLeft) {
705  intrusive_ptr<SomeClass> var2 = make_intrusive<SomeClass>();
706  EXPECT_TRUE(var1 != var2);
707  EXPECT_FALSE(var1 == var2);
708 }
709 
710 TEST(IntrusivePtrTest, Nonequality_NullptrRight) {
711  intrusive_ptr<SomeClass> var1 = make_intrusive<SomeClass>();
713  EXPECT_TRUE(var1 != var2);
714  EXPECT_FALSE(var1 == var2);
715 }
716 
717 TEST(IntrusivePtrTest, HashIsDifferent) {
718  intrusive_ptr<SomeClass> var1 = make_intrusive<SomeClass>();
719  intrusive_ptr<SomeClass> var2 = make_intrusive<SomeClass>();
720  EXPECT_NE(
721  std::hash<intrusive_ptr<SomeClass>>()(var1),
722  std::hash<intrusive_ptr<SomeClass>>()(var2));
723 }
724 
725 TEST(IntrusivePtrTest, HashIsDifferent_ValidAndInvalid) {
727  intrusive_ptr<SomeClass> var2 = make_intrusive<SomeClass>();
728  EXPECT_NE(
729  std::hash<intrusive_ptr<SomeClass>>()(var1),
730  std::hash<intrusive_ptr<SomeClass>>()(var2));
731 }
732 
733 TEST(IntrusivePtrTest, HashIsSame_AfterCopyConstructor) {
734  intrusive_ptr<SomeClass> var1 = make_intrusive<SomeClass>();
735  intrusive_ptr<SomeClass> var2 = var1;
736  EXPECT_EQ(
737  std::hash<intrusive_ptr<SomeClass>>()(var1),
738  std::hash<intrusive_ptr<SomeClass>>()(var2));
739 }
740 
741 TEST(IntrusivePtrTest, HashIsSame_AfterCopyAssignment) {
742  intrusive_ptr<SomeClass> var1 = make_intrusive<SomeClass>();
743  intrusive_ptr<SomeClass> var2 = make_intrusive<SomeClass>();
744  var2 = var1;
745  EXPECT_EQ(
746  std::hash<intrusive_ptr<SomeClass>>()(var1),
747  std::hash<intrusive_ptr<SomeClass>>()(var2));
748 }
749 
750 TEST(IntrusivePtrTest, HashIsSame_BothNullptr) {
753  EXPECT_EQ(
754  std::hash<intrusive_ptr<SomeClass>>()(var1),
755  std::hash<intrusive_ptr<SomeClass>>()(var2));
756 }
757 
758 TEST(IntrusivePtrTest, OneIsLess) {
759  intrusive_ptr<SomeClass> var1 = make_intrusive<SomeClass>();
760  intrusive_ptr<SomeClass> var2 = make_intrusive<SomeClass>();
761  EXPECT_TRUE(
762  std::less<intrusive_ptr<SomeClass>>()(var1, var2) !=
763  std::less<intrusive_ptr<SomeClass>>()(var2, var1));
764 }
765 
766 TEST(IntrusivePtrTest, NullptrIsLess1) {
768  intrusive_ptr<SomeClass> var2 = make_intrusive<SomeClass>();
769  EXPECT_TRUE(std::less<intrusive_ptr<SomeClass>>()(var1, var2));
770 }
771 
772 TEST(IntrusivePtrTest, NullptrIsLess2) {
773  intrusive_ptr<SomeClass> var1 = make_intrusive<SomeClass>();
775  EXPECT_FALSE(std::less<intrusive_ptr<SomeClass>>()(var1, var2));
776 }
777 
778 TEST(IntrusivePtrTest, NullptrIsNotLessThanNullptr) {
781  EXPECT_FALSE(std::less<intrusive_ptr<SomeClass>>()(var1, var2));
782 }
783 
784 TEST(IntrusivePtrTest, givenPtr_whenCallingReset_thenIsInvalid) {
785  auto obj = make_intrusive<SomeClass>();
786  EXPECT_TRUE(obj.defined());
787  obj.reset();
788  EXPECT_FALSE(obj.defined());
789 }
790 
791 TEST(IntrusivePtrTest, givenPtr_whenCallingReset_thenHoldsNullptr) {
792  auto obj = make_intrusive<SomeClass>();
793  EXPECT_NE(nullptr, obj.get());
794  obj.reset();
795  EXPECT_EQ(nullptr, obj.get());
796 }
797 
798 TEST(IntrusivePtrTest, givenPtr_whenDestructed_thenDestructsObject) {
799  bool resourcesReleased = false;
800  bool wasDestructed = false;
801  {
802  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
803  EXPECT_FALSE(resourcesReleased);
804  EXPECT_FALSE(wasDestructed);
805  }
806  EXPECT_TRUE(resourcesReleased);
807  EXPECT_TRUE(wasDestructed);
808 }
809 
810 TEST(
811  IntrusivePtrTest,
812  givenPtr_whenMoveConstructed_thenDestructsObjectAfterSecondDestructed) {
813  bool resourcesReleased = false;
814  bool wasDestructed = false;
815  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
816  {
817  auto obj2 = std::move(obj);
818  EXPECT_FALSE(resourcesReleased);
819  EXPECT_FALSE(wasDestructed);
820  }
821  EXPECT_TRUE(resourcesReleased);
822  EXPECT_TRUE(wasDestructed);
823 }
824 
825 TEST(
826  IntrusivePtrTest,
827  givenPtr_whenMoveConstructedToBaseClass_thenDestructsObjectAfterSecondDestructed) {
828  bool resourcesReleased = false;
829  bool wasDestructed = false;
830  auto obj = make_intrusive<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
831  {
832  intrusive_ptr<DestructableMock> obj2 = std::move(obj);
833  EXPECT_FALSE(resourcesReleased);
834  EXPECT_FALSE(wasDestructed);
835  }
836  EXPECT_TRUE(resourcesReleased);
837  EXPECT_TRUE(wasDestructed);
838 }
839 
840 TEST(IntrusivePtrTest, givenPtr_whenMoveAssigned_thenDestructsOldObject) {
841  bool dummy = false;
842  bool resourcesReleased = false;
843  bool wasDestructed = false;
844  auto obj = make_intrusive<DestructableMock>(&dummy, &dummy);
845  {
846  auto obj2 = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
847  EXPECT_FALSE(resourcesReleased);
848  EXPECT_FALSE(wasDestructed);
849  obj2 = std::move(obj);
850  EXPECT_TRUE(resourcesReleased);
851  EXPECT_TRUE(wasDestructed);
852  }
853 }
854 
855 TEST(
856  IntrusivePtrTest,
857  givenPtr_whenMoveAssignedToBaseClass_thenDestructsOldObject) {
858  bool dummy = false;
859  bool resourcesReleased = false;
860  bool wasDestructed = false;
861  auto obj = make_intrusive<ChildDestructableMock>(&dummy, &dummy);
862  {
863  auto obj2 = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
864  EXPECT_FALSE(resourcesReleased);
865  EXPECT_FALSE(wasDestructed);
866  obj2 = std::move(obj);
867  EXPECT_TRUE(resourcesReleased);
868  EXPECT_TRUE(wasDestructed);
869  }
870 }
871 
872 TEST(
873  IntrusivePtrTest,
874  givenPtrWithCopy_whenMoveAssigned_thenDestructsOldObjectAfterCopyIsDestructed) {
875  bool dummy = false;
876  bool resourcesReleased = false;
877  bool wasDestructed = false;
878  auto obj = make_intrusive<DestructableMock>(&dummy, &dummy);
879  {
880  auto obj2 = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
881  {
882  auto copy = obj2;
883  EXPECT_FALSE(resourcesReleased);
884  EXPECT_FALSE(wasDestructed);
885  obj2 = std::move(obj);
886  EXPECT_FALSE(resourcesReleased);
887  EXPECT_FALSE(wasDestructed);
888  }
889  EXPECT_TRUE(resourcesReleased);
890  EXPECT_TRUE(wasDestructed);
891  }
892 }
893 
894 TEST(
895  IntrusivePtrTest,
896  givenPtrWithBaseClassCopy_whenMoveAssigned_thenDestructsOldObjectAfterCopyIsDestructed) {
897  bool dummy = false;
898  bool resourcesReleased = false;
899  bool wasDestructed = false;
900  auto obj = make_intrusive<ChildDestructableMock>(&dummy, &dummy);
901  {
902  auto obj2 =
903  make_intrusive<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
904  {
906  EXPECT_FALSE(resourcesReleased);
907  EXPECT_FALSE(wasDestructed);
908  obj2 = std::move(obj);
909  EXPECT_FALSE(resourcesReleased);
910  EXPECT_FALSE(wasDestructed);
911  }
912  EXPECT_TRUE(resourcesReleased);
913  EXPECT_TRUE(wasDestructed);
914  }
915 }
916 
917 TEST(
918  IntrusivePtrTest,
919  givenPtrWithCopy_whenMoveAssignedToBaseClass_thenDestructsOldObjectAfterCopyIsDestructed) {
920  bool dummy = false;
921  bool resourcesReleased = false;
922  bool wasDestructed = false;
923  auto obj = make_intrusive<ChildDestructableMock>(&dummy, &dummy);
924  {
925  auto obj2 = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
926  {
928  EXPECT_FALSE(resourcesReleased);
929  EXPECT_FALSE(wasDestructed);
930  obj2 = std::move(obj);
931  EXPECT_FALSE(resourcesReleased);
932  EXPECT_FALSE(wasDestructed);
933  }
934  EXPECT_TRUE(resourcesReleased);
935  EXPECT_TRUE(wasDestructed);
936  }
937 }
938 
939 TEST(
940  IntrusivePtrTest,
941  givenPtr_whenMoveAssigned_thenDestructsObjectAfterSecondDestructed) {
942  bool dummy = false;
943  bool resourcesReleased = false;
944  bool wasDestructed = false;
945  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
946  {
947  auto obj2 = make_intrusive<DestructableMock>(&dummy, &dummy);
948  obj2 = std::move(obj);
949  EXPECT_FALSE(resourcesReleased);
950  EXPECT_FALSE(wasDestructed);
951  }
952  EXPECT_TRUE(resourcesReleased);
953  EXPECT_TRUE(wasDestructed);
954 }
955 
956 TEST(
957  IntrusivePtrTest,
958  givenPtr_whenMoveAssignedToBaseClass_thenDestructsObjectAfterSecondDestructed) {
959  bool dummy = false;
960  bool resourcesReleased = false;
961  bool wasDestructed = false;
962  auto obj = make_intrusive<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
963  {
964  auto obj2 = make_intrusive<DestructableMock>(&dummy, &dummy);
965  obj2 = std::move(obj);
966  EXPECT_FALSE(resourcesReleased);
967  EXPECT_FALSE(wasDestructed);
968  }
969  EXPECT_TRUE(resourcesReleased);
970  EXPECT_TRUE(wasDestructed);
971 }
972 
973 TEST(
974  IntrusivePtrTest,
975  givenPtr_whenCopyConstructedAndDestructed_thenDestructsObjectAfterLastDestruction) {
976  bool resourcesReleased = false;
977  bool wasDestructed = false;
978  {
979  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
980  {
982  EXPECT_FALSE(resourcesReleased);
983  EXPECT_FALSE(wasDestructed);
984  }
985  EXPECT_FALSE(resourcesReleased);
986  EXPECT_FALSE(wasDestructed);
987  }
988  EXPECT_TRUE(resourcesReleased);
989  EXPECT_TRUE(wasDestructed);
990 }
991 
992 TEST(
993  IntrusivePtrTest,
994  givenPtr_whenCopyConstructedToBaseClassAndDestructed_thenDestructsObjectAfterLastDestruction) {
995  bool resourcesReleased = false;
996  bool wasDestructed = false;
997  {
998  auto obj = make_intrusive<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
999  {
1001  EXPECT_FALSE(resourcesReleased);
1002  EXPECT_FALSE(wasDestructed);
1003  }
1004  EXPECT_FALSE(resourcesReleased);
1005  EXPECT_FALSE(wasDestructed);
1006  }
1007  EXPECT_TRUE(resourcesReleased);
1008  EXPECT_TRUE(wasDestructed);
1009 }
1010 
1011 TEST(
1012  IntrusivePtrTest,
1013  givenPtr_whenCopyConstructedAndOriginalDestructed_thenDestructsObjectAfterLastDestruction) {
1014  bool resourcesReleased = false;
1015  bool wasDestructed = false;
1016  {
1017  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1019  obj.reset();
1020  EXPECT_FALSE(resourcesReleased);
1021  EXPECT_FALSE(wasDestructed);
1022  }
1023  EXPECT_TRUE(resourcesReleased);
1024  EXPECT_TRUE(wasDestructed);
1025 }
1026 
1027 TEST(
1028  IntrusivePtrTest,
1029  givenPtr_whenCopyConstructedToBaseClassAndOriginalDestructed_thenDestructsObjectAfterLastDestruction) {
1030  bool resourcesReleased = false;
1031  bool wasDestructed = false;
1032  {
1033  auto obj = make_intrusive<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
1035  obj.reset();
1036  EXPECT_FALSE(resourcesReleased);
1037  EXPECT_FALSE(wasDestructed);
1038  }
1039  EXPECT_TRUE(resourcesReleased);
1040  EXPECT_TRUE(wasDestructed);
1041 }
1042 
1043 TEST(
1044  IntrusivePtrTest,
1045  givenPtr_whenCopyAssignedAndDestructed_thenDestructsObjectAfterLastDestruction) {
1046  bool resourcesReleased = false;
1047  bool wasDestructed = false;
1048  bool dummy = false;
1049  {
1050  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1051  {
1053  make_intrusive<DestructableMock>(&dummy, &dummy);
1054  copy = obj;
1055  EXPECT_FALSE(resourcesReleased);
1056  EXPECT_FALSE(wasDestructed);
1057  }
1058  EXPECT_FALSE(resourcesReleased);
1059  EXPECT_FALSE(wasDestructed);
1060  }
1061  EXPECT_TRUE(resourcesReleased);
1062  EXPECT_TRUE(wasDestructed);
1063 }
1064 
1065 TEST(
1066  IntrusivePtrTest,
1067  givenPtr_whenCopyAssignedToBaseClassAndDestructed_thenDestructsObjectAfterLastDestruction) {
1068  bool resourcesReleased = false;
1069  bool wasDestructed = false;
1070  bool dummy = false;
1071  {
1072  auto obj = make_intrusive<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
1073  {
1075  make_intrusive<DestructableMock>(&dummy, &dummy);
1076  copy = obj;
1077  EXPECT_FALSE(resourcesReleased);
1078  EXPECT_FALSE(wasDestructed);
1079  }
1080  EXPECT_FALSE(resourcesReleased);
1081  EXPECT_FALSE(wasDestructed);
1082  }
1083  EXPECT_TRUE(resourcesReleased);
1084  EXPECT_TRUE(wasDestructed);
1085 }
1086 
1087 TEST(
1088  IntrusivePtrTest,
1089  givenPtr_whenCopyAssignedAndOriginalDestructed_thenDestructsObjectAfterLastDestruction) {
1090  bool resourcesReleased = false;
1091  bool wasDestructed = false;
1092  bool dummy = false;
1093  {
1094  auto copy = make_intrusive<DestructableMock>(&dummy, &dummy);
1095  {
1096  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1097  copy = obj;
1098  EXPECT_FALSE(resourcesReleased);
1099  EXPECT_FALSE(wasDestructed);
1100  }
1101  EXPECT_FALSE(resourcesReleased);
1102  EXPECT_FALSE(wasDestructed);
1103  }
1104  EXPECT_TRUE(resourcesReleased);
1105  EXPECT_TRUE(wasDestructed);
1106 }
1107 
1108 TEST(
1109  IntrusivePtrTest,
1110  givenPtr_whenCopyAssignedToBaseClassAndOriginalDestructed_thenDestructsObjectAfterLastDestruction) {
1111  bool wasDestructed = false;
1112  bool resourcesReleased = false;
1113  bool dummy = false;
1114  {
1115  auto copy = make_intrusive<DestructableMock>(&dummy, &dummy);
1116  {
1117  auto obj =
1118  make_intrusive<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
1119  copy = obj;
1120  EXPECT_FALSE(resourcesReleased);
1121  EXPECT_FALSE(wasDestructed);
1122  }
1123  EXPECT_FALSE(resourcesReleased);
1124  EXPECT_FALSE(wasDestructed);
1125  }
1126  EXPECT_TRUE(resourcesReleased);
1127  EXPECT_TRUE(wasDestructed);
1128 }
1129 
1130 TEST(IntrusivePtrTest, givenPtr_whenCopyAssigned_thenDestructsOldObject) {
1131  bool dummy = false;
1132  bool resourcesReleased = false;
1133  bool wasDestructed = false;
1134  auto obj = make_intrusive<DestructableMock>(&dummy, &dummy);
1135  {
1136  auto obj2 = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1137  EXPECT_FALSE(resourcesReleased);
1138  EXPECT_FALSE(wasDestructed);
1139  obj2 = obj;
1140  EXPECT_TRUE(resourcesReleased);
1141  EXPECT_TRUE(wasDestructed);
1142  }
1143 }
1144 
1145 TEST(
1146  IntrusivePtrTest,
1147  givenPtr_whenCopyAssignedToBaseClass_thenDestructsOldObject) {
1148  bool dummy = false;
1149  bool resourcesReleased = false;
1150  bool wasDestructed = false;
1151  auto obj = make_intrusive<ChildDestructableMock>(&dummy, &dummy);
1152  {
1153  auto obj2 = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1154  EXPECT_FALSE(resourcesReleased);
1155  EXPECT_FALSE(wasDestructed);
1156  obj2 = obj;
1157  EXPECT_TRUE(resourcesReleased);
1158  EXPECT_TRUE(wasDestructed);
1159  }
1160 }
1161 
1162 TEST(
1163  IntrusivePtrTest,
1164  givenPtrWithCopy_whenCopyAssigned_thenDestructsOldObjectAfterCopyIsDestructed) {
1165  bool dummy = false;
1166  bool resourcesReleased = false;
1167  bool wasDestructed = false;
1168  auto obj = make_intrusive<DestructableMock>(&dummy, &dummy);
1169  {
1170  auto obj2 = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1171  {
1172  auto copy = obj2;
1173  EXPECT_FALSE(resourcesReleased);
1174  EXPECT_FALSE(wasDestructed);
1175  obj2 = obj;
1176  EXPECT_FALSE(resourcesReleased);
1177  EXPECT_FALSE(wasDestructed);
1178  }
1179  EXPECT_TRUE(resourcesReleased);
1180  EXPECT_TRUE(wasDestructed);
1181  }
1182 }
1183 
1184 TEST(
1185  IntrusivePtrTest,
1186  givenPtrWithBaseClassCopy_whenCopyAssigned_thenDestructsOldObjectAfterCopyIsDestructed) {
1187  bool dummy = false;
1188  bool resourcesReleased = false;
1189  bool wasDestructed = false;
1190  auto obj = make_intrusive<ChildDestructableMock>(&dummy, &dummy);
1191  {
1192  auto obj2 =
1193  make_intrusive<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
1194  {
1195  intrusive_ptr<DestructableMock> copy = obj2;
1196  EXPECT_FALSE(resourcesReleased);
1197  EXPECT_FALSE(wasDestructed);
1198  obj2 = obj;
1199  EXPECT_FALSE(resourcesReleased);
1200  EXPECT_FALSE(wasDestructed);
1201  }
1202  EXPECT_TRUE(resourcesReleased);
1203  EXPECT_TRUE(wasDestructed);
1204  }
1205 }
1206 
1207 TEST(
1208  IntrusivePtrTest,
1209  givenPtrWithCopy_whenCopyAssignedToBaseClass_thenDestructsOldObjectAfterCopyIsDestructed) {
1210  bool dummy = false;
1211  bool resourcesReleased = false;
1212  bool wasDestructed = false;
1213  auto obj = make_intrusive<ChildDestructableMock>(&dummy, &dummy);
1214  {
1215  auto obj2 = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1216  {
1217  intrusive_ptr<DestructableMock> copy = obj2;
1218  EXPECT_FALSE(resourcesReleased);
1219  EXPECT_FALSE(wasDestructed);
1220  obj2 = obj;
1221  EXPECT_FALSE(resourcesReleased);
1222  EXPECT_FALSE(wasDestructed);
1223  }
1224  EXPECT_TRUE(resourcesReleased);
1225  EXPECT_TRUE(wasDestructed);
1226  }
1227 }
1228 
1229 TEST(IntrusivePtrTest, givenPtr_whenCallingReset_thenDestructs) {
1230  bool resourcesReleased = false;
1231  bool wasDestructed = false;
1232  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1233  EXPECT_FALSE(resourcesReleased);
1234  EXPECT_FALSE(wasDestructed);
1235  obj.reset();
1236  EXPECT_TRUE(resourcesReleased);
1237  EXPECT_TRUE(wasDestructed);
1238 }
1239 
1240 TEST(
1241  IntrusivePtrTest,
1242  givenPtrWithCopy_whenCallingReset_thenDestructsAfterCopyDestructed) {
1243  bool resourcesReleased = false;
1244  bool wasDestructed = false;
1245  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1246  {
1247  auto copy = obj;
1248  obj.reset();
1249  EXPECT_FALSE(resourcesReleased);
1250  EXPECT_FALSE(wasDestructed);
1251  copy.reset();
1252  EXPECT_TRUE(resourcesReleased);
1253  EXPECT_TRUE(wasDestructed);
1254  }
1255 }
1256 
1257 TEST(
1258  IntrusivePtrTest,
1259  givenPtrWithCopy_whenCallingResetOnCopy_thenDestructsAfterOriginalDestructed) {
1260  bool resourcesReleased = false;
1261  bool wasDestructed = false;
1262  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1263  {
1264  auto copy = obj;
1265  copy.reset();
1266  EXPECT_FALSE(resourcesReleased);
1267  EXPECT_FALSE(wasDestructed);
1268  obj.reset();
1269  EXPECT_TRUE(resourcesReleased);
1270  EXPECT_TRUE(wasDestructed);
1271  }
1272 }
1273 
1274 TEST(
1275  IntrusivePtrTest,
1276  givenPtrWithMoved_whenCallingReset_thenDestructsAfterMovedDestructed) {
1277  bool resourcesReleased = false;
1278  bool wasDestructed = false;
1279  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1280  {
1281  auto moved = std::move(obj);
1282  obj.reset();
1283  EXPECT_FALSE(resourcesReleased);
1284  EXPECT_FALSE(wasDestructed);
1285  moved.reset();
1286  EXPECT_TRUE(resourcesReleased);
1287  EXPECT_TRUE(wasDestructed);
1288  }
1289 }
1290 
1291 TEST(
1292  IntrusivePtrTest,
1293  givenPtrWithMoved_whenCallingResetOnMoved_thenDestructsImmediately) {
1294  bool resourcesReleased = false;
1295  bool wasDestructed = false;
1296  auto obj = make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1297  {
1298  auto moved = std::move(obj);
1299  moved.reset();
1300  EXPECT_TRUE(resourcesReleased);
1301  EXPECT_TRUE(wasDestructed);
1302  }
1303 }
1304 
1305 TEST(IntrusivePtrTest, AllowsMoveConstructingToConst) {
1306  intrusive_ptr<SomeClass> a = make_intrusive<SomeClass>();
1307  intrusive_ptr<const SomeClass> b = std::move(a);
1308 }
1309 
1310 TEST(IntrusivePtrTest, AllowsCopyConstructingToConst) {
1311  intrusive_ptr<SomeClass> a = make_intrusive<SomeClass>();
1313 }
1314 
1315 TEST(IntrusivePtrTest, AllowsMoveAssigningToConst) {
1316  intrusive_ptr<SomeClass> a = make_intrusive<SomeClass>();
1317  intrusive_ptr<const SomeClass> b = make_intrusive<SomeClass>();
1318  b = std::move(a);
1319 }
1320 
1321 TEST(IntrusivePtrTest, AllowsCopyAssigningToConst) {
1322  intrusive_ptr<SomeClass> a = make_intrusive<SomeClass>();
1323  intrusive_ptr<const SomeClass> b = make_intrusive<const SomeClass>();
1324  b = a;
1325 }
1326 
1327 TEST(IntrusivePtrTest, givenNewPtr_thenHasUseCount1) {
1328  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1329  EXPECT_EQ(1, obj.use_count());
1330 }
1331 
1332 TEST(IntrusivePtrTest, givenNewPtr_thenIsUnique) {
1333  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1334  EXPECT_TRUE(obj.unique());
1335 }
1336 
1337 TEST(IntrusivePtrTest, givenEmptyPtr_thenHasUseCount0) {
1339  EXPECT_EQ(0, obj.use_count());
1340 }
1341 
1342 TEST(IntrusivePtrTest, givenEmptyPtr_thenIsNotUnique) {
1344  EXPECT_FALSE(obj.unique());
1345 }
1346 
1347 TEST(IntrusivePtrTest, givenResetPtr_thenHasUseCount0) {
1348  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1349  obj.reset();
1350  EXPECT_EQ(0, obj.use_count());
1351 }
1352 
1353 TEST(IntrusivePtrTest, givenResetPtr_thenIsNotUnique) {
1354  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1355  obj.reset();
1356  EXPECT_FALSE(obj.unique());
1357 }
1358 
1359 TEST(IntrusivePtrTest, givenMoveConstructedPtr_thenHasUseCount1) {
1360  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1361  intrusive_ptr<SomeClass> obj2 = std::move(obj);
1362  EXPECT_EQ(1, obj2.use_count());
1363 }
1364 
1365 TEST(IntrusivePtrTest, givenMoveConstructedPtr_thenIsUnique) {
1366  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1367  intrusive_ptr<SomeClass> obj2 = std::move(obj);
1368  EXPECT_TRUE(obj2.unique());
1369 }
1370 
1371 TEST(IntrusivePtrTest, givenMoveConstructedPtr_thenOldHasUseCount0) {
1372  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1373  intrusive_ptr<SomeClass> obj2 = std::move(obj);
1374  EXPECT_EQ(0, obj.use_count());
1375 }
1376 
1377 TEST(IntrusivePtrTest, givenMoveConstructedPtr_thenOldIsNotUnique) {
1378  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1379  intrusive_ptr<SomeClass> obj2 = std::move(obj);
1380  EXPECT_FALSE(obj.unique());
1381 }
1382 
1383 TEST(IntrusivePtrTest, givenMoveAssignedPtr_thenHasUseCount1) {
1384  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1385  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1386  obj2 = std::move(obj);
1387  EXPECT_EQ(1, obj2.use_count());
1388 }
1389 
1390 TEST(IntrusivePtrTest, givenMoveAssignedPtr_thenIsUnique) {
1391  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1392  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1393  obj2 = std::move(obj);
1394  EXPECT_TRUE(obj2.unique());
1395 }
1396 
1397 TEST(IntrusivePtrTest, givenMoveAssignedPtr_thenOldHasUseCount0) {
1398  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1399  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1400  obj2 = std::move(obj);
1401  EXPECT_EQ(0, obj.use_count());
1402 }
1403 
1404 TEST(IntrusivePtrTest, givenMoveAssignedPtr_thenOldIsNotUnique) {
1405  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1406  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1407  obj2 = std::move(obj);
1408  EXPECT_FALSE(obj.unique());
1409 }
1410 
1411 TEST(IntrusivePtrTest, givenCopyConstructedPtr_thenHasUseCount2) {
1412  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1413  intrusive_ptr<SomeClass> obj2 = obj;
1414  EXPECT_EQ(2, obj2.use_count());
1415 }
1416 
1417 TEST(IntrusivePtrTest, givenCopyConstructedPtr_thenIsNotUnique) {
1418  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1419  intrusive_ptr<SomeClass> obj2 = obj;
1420  EXPECT_FALSE(obj2.unique());
1421 }
1422 
1423 TEST(IntrusivePtrTest, givenCopyConstructedPtr_thenOldHasUseCount2) {
1424  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1425  intrusive_ptr<SomeClass> obj2 = obj;
1426  EXPECT_EQ(2, obj.use_count());
1427 }
1428 
1429 TEST(IntrusivePtrTest, givenCopyConstructedPtr_thenOldIsNotUnique) {
1430  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1431  intrusive_ptr<SomeClass> obj2 = obj;
1432  EXPECT_FALSE(obj.unique());
1433 }
1434 
1435 TEST(
1436  IntrusivePtrTest,
1437  givenCopyConstructedPtr_whenDestructingCopy_thenHasUseCount1) {
1438  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1439  {
1440  intrusive_ptr<SomeClass> obj2 = obj;
1441  EXPECT_EQ(2, obj.use_count());
1442  }
1443  EXPECT_EQ(1, obj.use_count());
1444 }
1445 
1446 TEST(
1447  IntrusivePtrTest,
1448  givenCopyConstructedPtr_whenDestructingCopy_thenIsUnique) {
1449  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1450  {
1451  intrusive_ptr<SomeClass> obj2 = obj;
1452  EXPECT_FALSE(obj.unique());
1453  }
1454  EXPECT_TRUE(obj.unique());
1455 }
1456 
1457 TEST(
1458  IntrusivePtrTest,
1459  givenCopyConstructedPtr_whenReassigningCopy_thenHasUseCount1) {
1460  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1461  intrusive_ptr<SomeClass> obj2 = obj;
1462  EXPECT_EQ(2, obj.use_count());
1463  obj2 = make_intrusive<SomeClass>();
1464  EXPECT_EQ(1, obj.use_count());
1465  EXPECT_EQ(1, obj2.use_count());
1466 }
1467 
1468 TEST(
1469  IntrusivePtrTest,
1470  givenCopyConstructedPtr_whenReassigningCopy_thenIsUnique) {
1471  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1472  intrusive_ptr<SomeClass> obj2 = obj;
1473  EXPECT_FALSE(obj.unique());
1474  obj2 = make_intrusive<SomeClass>();
1475  EXPECT_TRUE(obj.unique());
1476  EXPECT_TRUE(obj2.unique());
1477 }
1478 
1479 TEST(IntrusivePtrTest, givenCopyAssignedPtr_thenHasUseCount2) {
1480  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1481  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1482  obj2 = obj;
1483  EXPECT_EQ(2, obj.use_count());
1484  EXPECT_EQ(2, obj2.use_count());
1485 }
1486 
1487 TEST(IntrusivePtrTest, givenCopyAssignedPtr_thenIsNotUnique) {
1488  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1489  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1490  obj2 = obj;
1491  EXPECT_FALSE(obj.unique());
1492  EXPECT_FALSE(obj2.unique());
1493 }
1494 
1495 TEST(
1496  IntrusivePtrTest,
1497  givenCopyAssignedPtr_whenDestructingCopy_thenHasUseCount1) {
1498  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1499  {
1500  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1501  obj2 = obj;
1502  EXPECT_EQ(2, obj.use_count());
1503  }
1504  EXPECT_EQ(1, obj.use_count());
1505 }
1506 
1507 TEST(IntrusivePtrTest, givenCopyAssignedPtr_whenDestructingCopy_thenIsUnique) {
1508  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1509  {
1510  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1511  obj2 = obj;
1512  EXPECT_FALSE(obj.unique());
1513  }
1514  EXPECT_TRUE(obj.unique());
1515 }
1516 
1517 TEST(
1518  IntrusivePtrTest,
1519  givenCopyAssignedPtr_whenReassigningCopy_thenHasUseCount1) {
1520  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1521  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1522  obj2 = obj;
1523  EXPECT_EQ(2, obj.use_count());
1524  obj2 = make_intrusive<SomeClass>();
1525  EXPECT_EQ(1, obj.use_count());
1526  EXPECT_EQ(1, obj2.use_count());
1527 }
1528 
1529 TEST(IntrusivePtrTest, givenCopyAssignedPtr_whenReassigningCopy_thenIsUnique) {
1530  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1531  intrusive_ptr<SomeClass> obj2 = make_intrusive<SomeClass>();
1532  obj2 = obj;
1533  EXPECT_FALSE(obj.unique());
1534  obj2 = make_intrusive<SomeClass>();
1535  EXPECT_TRUE(obj.unique());
1536  EXPECT_TRUE(obj2.unique());
1537 }
1538 
1539 TEST(IntrusivePtrTest, givenPtr_whenReleasedAndReclaimed_thenDoesntCrash) {
1540  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1541  SomeClass* ptr = obj.release();
1542  EXPECT_FALSE(obj.defined());
1544 }
1545 
1546 TEST(
1547  IntrusivePtrTest,
1548  givenPtr_whenReleasedAndReclaimed_thenIsDestructedAtEnd) {
1549  bool resourcesReleased = false;
1550  bool wasDestructed = false;
1551  {
1553  {
1555  make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1556  DestructableMock* ptr = inner.release();
1557  EXPECT_FALSE(resourcesReleased);
1558  EXPECT_FALSE(wasDestructed);
1560  }
1561  // inner is destructed
1562  EXPECT_FALSE(resourcesReleased);
1563  EXPECT_FALSE(wasDestructed);
1564  }
1565  // outer is destructed
1566  EXPECT_TRUE(resourcesReleased);
1567  EXPECT_TRUE(wasDestructed);
1568 }
1569 
1570 TEST(IntrusivePtrTest, givenStackObject_whenReclaimed_thenCrashes) {
1571  // This would cause very weird bugs on destruction.
1572  // Better to crash early on creation.
1573  SomeClass obj;
1575  EXPECT_ANY_THROW(ptr = intrusive_ptr<SomeClass>::reclaim(&obj));
1576 }
1577 
1578 TEST(IntrusivePtrTest, givenPtr_whenNonOwningReclaimed_thenDoesntCrash) {
1579  intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1580  SomeClass* raw_ptr = obj.get();
1581  EXPECT_TRUE(obj.defined());
1582  intrusive_ptr<SomeClass> reclaimed =
1584  EXPECT_TRUE(reclaimed.defined());
1585  EXPECT_EQ(reclaimed.get(), obj.get());
1586 }
1587 
1588 TEST(
1589  IntrusivePtrTest,
1590  givenPtr_whenNonOwningReclaimed_thenIsDestructedAtEnd) {
1591  bool resourcesReleased = false;
1592  bool wasDestructed = false;
1593  {
1595  {
1597  make_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
1598  DestructableMock* raw_ptr = inner.get();
1600  raw_ptr);
1601  }
1602  // inner is destructed
1603  EXPECT_FALSE(resourcesReleased);
1604  EXPECT_FALSE(wasDestructed);
1605  }
1606  // outer is destructed
1607  EXPECT_TRUE(resourcesReleased);
1608  EXPECT_TRUE(wasDestructed);
1609 }
1610 
1611 namespace {
1612 template <class T>
1613 struct IntrusiveAndWeak final {
1614  IntrusiveAndWeak(intrusive_ptr<T> ptr_) : ptr(std::move(ptr_)), weak(ptr) {}
1615 
1616  intrusive_ptr<T> ptr;
1617  weak_intrusive_ptr<T> weak;
1618 };
1619 template <class T, class... Args>
1620 IntrusiveAndWeak<T> make_weak_intrusive(Args&&... args) {
1621  return IntrusiveAndWeak<T>(make_intrusive<T>(std::forward<Args>(args)...));
1622 }
1623 template <class T, class... Args>
1624 weak_intrusive_ptr<T> make_weak_only(Args&&... args) {
1625  auto intrusive = make_intrusive<T>(std::forward<Args>(args)...);
1626  return weak_intrusive_ptr<T>(intrusive);
1627 }
1628 template <class T, class NullType = c10::detail::intrusive_target_default_null_type<T>>
1629 weak_intrusive_ptr<T, NullType> make_invalid_weak() {
1631 }
1632 } // namespace
1633 
1634 static_assert(
1635  std::is_same<SomeClass, weak_intrusive_ptr<SomeClass>::element_type>::value,
1636  "weak_intrusive_ptr<T>::element_type is wrong");
1637 
1638 TEST(
1639  WeakIntrusivePtrTest,
1640  givenPtr_whenCreatingAndDestructing_thenDoesntCrash) {
1641  IntrusiveAndWeak<SomeClass> var = make_weak_intrusive<SomeClass>();
1642 }
1643 
1644 TEST(WeakIntrusivePtrTest, givenPtr_whenLocking_thenReturnsCorrectObject) {
1645  IntrusiveAndWeak<SomeClass> var = make_weak_intrusive<SomeClass>();
1646  intrusive_ptr<SomeClass> locked = var.weak.lock();
1647  EXPECT_EQ(var.ptr.get(), locked.get());
1648 }
1649 
1650 TEST(
1651  WeakIntrusivePtrTest,
1652  givenValidPtr_whenMoveAssigning_thenPointsToSameObject) {
1653  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1654  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
1655  SomeClass* obj1ptr = obj1.weak.lock().get();
1656  obj2.weak = std::move(obj1.weak);
1657  EXPECT_EQ(obj1ptr, obj2.weak.lock().get());
1658 }
1659 
1660 TEST(
1661  WeakIntrusivePtrTest,
1662  givenValidPtr_whenMoveAssigning_thenOldInstanceInvalid) {
1663  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1664  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
1665  obj2.weak = std::move(obj1.weak);
1666  EXPECT_TRUE(obj1.weak.expired());
1667 }
1668 
1669 TEST(
1670  WeakIntrusivePtrTest,
1671  givenInvalidPtr_whenMoveAssigning_thenNewInstanceIsValid) {
1672  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1673  weak_intrusive_ptr<SomeClass> obj2 = make_invalid_weak<SomeClass>();
1674  SomeClass* obj1ptr = obj1.weak.lock().get();
1675  obj2 = std::move(obj1.weak);
1676  EXPECT_FALSE(obj2.expired());
1677 }
1678 
1679 TEST(
1680  WeakIntrusivePtrTest,
1681  givenValidPtr_whenMoveAssigningToSelf_thenPointsToSameObject) {
1682  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1683  SomeClass* obj1ptr = obj1.weak.lock().get();
1684  obj1.weak = std::move(obj1.weak);
1685  EXPECT_EQ(obj1ptr, obj1.weak.lock().get());
1686 }
1687 
1688 TEST(
1689  WeakIntrusivePtrTest,
1690  givenValidPtr_whenMoveAssigningToSelf_thenStaysValid) {
1691  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1692  obj1.weak = std::move(obj1.weak);
1693  EXPECT_FALSE(obj1.weak.expired());
1694 }
1695 
1696 TEST(
1697  WeakIntrusivePtrTest,
1698  givenInvalidPtr_whenMoveAssigning_thenPointsToSameObject) {
1699  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1700  weak_intrusive_ptr<SomeClass> obj2 = make_invalid_weak<SomeClass>();
1701  SomeClass* obj1ptr = obj1.weak.lock().get();
1702  obj2 = std::move(obj1.weak);
1703  EXPECT_EQ(obj1ptr, obj2.lock().get());
1704 }
1705 
1706 TEST(
1707  WeakIntrusivePtrTest,
1708  givenInvalidPtr_whenMoveAssigningToSelf_thenStaysInvalid) {
1709  weak_intrusive_ptr<SomeClass> obj1 = make_invalid_weak<SomeClass>();
1710  obj1 = std::move(obj1);
1711  EXPECT_TRUE(obj1.expired());
1712 }
1713 
1714 TEST(
1715  WeakIntrusivePtrTest,
1716  givenWeakOnlyPtr_whenMoveAssigning_thenNewInstanceIsValid) {
1717  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1718  weak_intrusive_ptr<SomeClass> obj2 = make_weak_only<SomeClass>();
1719  SomeClass* obj1ptr = obj1.weak.lock().get();
1720  obj2 = std::move(obj1.weak);
1721  EXPECT_FALSE(obj2.expired());
1722 }
1723 
1724 TEST(
1725  WeakIntrusivePtrTest,
1726  givenWeakOnlyPtr_whenMoveAssigning_thenPointsToSameObject) {
1727  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1728  weak_intrusive_ptr<SomeClass> obj2 = make_weak_only<SomeClass>();
1729  SomeClass* obj1ptr = obj1.weak.lock().get();
1730  obj2 = std::move(obj1.weak);
1731  EXPECT_EQ(obj1ptr, obj2.lock().get());
1732 }
1733 
1734 TEST(
1735  WeakIntrusivePtrTest,
1736  givenWeakOnlyPtr_whenMoveAssigningToSelf_thenStaysInvalid) {
1737  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
1738  SomeClass* obj1ptr = obj1.lock().get();
1739  obj1 = std::move(obj1);
1740  EXPECT_TRUE(obj1.expired());
1741 }
1742 
1743 TEST(
1744  WeakIntrusivePtrTest,
1745  givenWeakOnlyPtr_whenMoveAssigningToSelf_thenPointsToSameObject) {
1746  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
1747  SomeClass* obj1ptr = obj1.lock().get();
1748  obj1 = std::move(obj1);
1749  EXPECT_EQ(obj1ptr, obj1.lock().get());
1750 }
1751 
1752 TEST(
1753  WeakIntrusivePtrTest,
1754  givenValidPtr_whenMoveAssigningFromInvalidPtr_thenNewInstanceIsInvalid) {
1755  weak_intrusive_ptr<SomeClass> obj1 = make_invalid_weak<SomeClass>();
1756  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
1757  EXPECT_FALSE(obj2.weak.expired());
1758  obj2.weak = std::move(obj1);
1759  EXPECT_TRUE(obj2.weak.expired());
1760 }
1761 
1762 TEST(
1763  WeakIntrusivePtrTest,
1764  givenValidPtr_whenMoveAssigningFromWeakOnlyPtr_thenNewInstanceIsInvalid) {
1765  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
1766  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
1767  EXPECT_FALSE(obj2.weak.expired());
1768  obj2.weak = std::move(obj1);
1769  EXPECT_TRUE(obj2.weak.expired());
1770 }
1771 
1772 TEST(
1773  WeakIntrusivePtrTest,
1774  givenValidPtr_whenMoveAssigningToBaseClass_thenPointsToSameObject) {
1775  IntrusiveAndWeak<SomeChildClass> obj1 =
1776  make_weak_intrusive<SomeChildClass>(1);
1777  IntrusiveAndWeak<SomeBaseClass> obj2 = make_weak_intrusive<SomeBaseClass>(2);
1778  SomeBaseClass* obj1ptr = obj1.weak.lock().get();
1779  obj2.weak = std::move(obj1.weak);
1780  EXPECT_EQ(obj1ptr, obj2.weak.lock().get());
1781  EXPECT_EQ(1, obj2.weak.lock()->v);
1782 }
1783 
1784 TEST(
1785  WeakIntrusivePtrTest,
1786  givenValidPtr_whenMoveAssigningToBaseClass_thenOldInstanceInvalid) {
1787  IntrusiveAndWeak<SomeChildClass> obj1 =
1788  make_weak_intrusive<SomeChildClass>(1);
1789  IntrusiveAndWeak<SomeBaseClass> obj2 = make_weak_intrusive<SomeBaseClass>(2);
1790  obj2.weak = std::move(obj1.weak);
1791  EXPECT_TRUE(obj1.weak.expired());
1792 }
1793 
1794 TEST(
1795  WeakIntrusivePtrTest,
1796  givenInvalidPtr_whenMoveAssigningToBaseClass_thenNewInstanceIsValid) {
1797  IntrusiveAndWeak<SomeChildClass> obj1 =
1798  make_weak_intrusive<SomeChildClass>(5);
1799  weak_intrusive_ptr<SomeBaseClass> obj2 = make_invalid_weak<SomeBaseClass>();
1800  SomeBaseClass* obj1ptr = obj1.weak.lock().get();
1801  obj2 = std::move(obj1.weak);
1802  EXPECT_FALSE(obj2.expired());
1803 }
1804 
1805 TEST(
1806  WeakIntrusivePtrTest,
1807  givenInvalidPtr_whenMoveAssigningToBaseClass_thenPointsToSameObject) {
1808  IntrusiveAndWeak<SomeChildClass> obj1 =
1809  make_weak_intrusive<SomeChildClass>(5);
1810  weak_intrusive_ptr<SomeBaseClass> obj2 = make_invalid_weak<SomeBaseClass>();
1811  SomeBaseClass* obj1ptr = obj1.weak.lock().get();
1812  obj2 = std::move(obj1.weak);
1813  EXPECT_EQ(obj1ptr, obj2.lock().get());
1814  EXPECT_EQ(5, obj2.lock()->v);
1815 }
1816 
1817 TEST(
1818  WeakIntrusivePtrTest,
1819  givenInvalidPtr_whenMoveAssigningInvalidPtrToBaseClass_thenNewInstanceIsValid) {
1820  weak_intrusive_ptr<SomeChildClass> obj1 = make_invalid_weak<SomeChildClass>();
1821  IntrusiveAndWeak<SomeBaseClass> obj2 = make_weak_intrusive<SomeBaseClass>(2);
1822  EXPECT_FALSE(obj2.weak.expired());
1823  obj2.weak = std::move(obj1);
1824  EXPECT_TRUE(obj2.weak.expired());
1825 }
1826 
1827 TEST(
1828  WeakIntrusivePtrTest,
1829  givenWeakOnlyPtr_whenMoveAssigningToBaseClass_thenNewInstanceIsValid) {
1830  IntrusiveAndWeak<SomeChildClass> obj1 =
1831  make_weak_intrusive<SomeChildClass>(5);
1832  weak_intrusive_ptr<SomeBaseClass> obj2 = make_weak_only<SomeBaseClass>(2);
1833  SomeBaseClass* obj1ptr = obj1.weak.lock().get();
1834  obj2 = std::move(obj1.weak);
1835  EXPECT_FALSE(obj2.expired());
1836 }
1837 
1838 TEST(
1839  WeakIntrusivePtrTest,
1840  givenWeakOnlyPtr_whenMoveAssigningToBaseClass_thenPointsToSameObject) {
1841  IntrusiveAndWeak<SomeChildClass> obj1 =
1842  make_weak_intrusive<SomeChildClass>(5);
1843  weak_intrusive_ptr<SomeBaseClass> obj2 = make_weak_only<SomeBaseClass>(2);
1844  SomeBaseClass* obj1ptr = obj1.weak.lock().get();
1845  obj2 = std::move(obj1.weak);
1846  EXPECT_EQ(obj1ptr, obj2.lock().get());
1847  EXPECT_EQ(5, obj2.lock()->v);
1848 }
1849 
1850 TEST(
1851  WeakIntrusivePtrTest,
1852  givenWeakOnlyPtr_whenMoveAssigningInvalidPtrToBaseClass_thenNewInstanceIsValid) {
1853  weak_intrusive_ptr<SomeChildClass> obj1 = make_weak_only<SomeChildClass>(5);
1854  IntrusiveAndWeak<SomeBaseClass> obj2 = make_weak_intrusive<SomeBaseClass>(2);
1855  EXPECT_FALSE(obj2.weak.expired());
1856  obj2.weak = std::move(obj1);
1857  EXPECT_TRUE(obj2.weak.expired());
1858 }
1859 
1860 TEST(
1861  WeakIntrusivePtrTest,
1862  givenNullPtr_whenMoveAssigningToDifferentNullptr_thenHasNewNullptr) {
1863  weak_intrusive_ptr<SomeClass, NullType1> obj1 = make_invalid_weak<SomeClass, NullType1>();
1864  weak_intrusive_ptr<SomeClass, NullType2> obj2 = make_invalid_weak<SomeClass, NullType2>();
1865  obj2 = std::move(obj1);
1866  EXPECT_NE(NullType1::singleton(), NullType2::singleton());
1867  EXPECT_TRUE(obj1.expired());
1868  EXPECT_TRUE(obj2.expired());
1869 }
1870 
1871 TEST(
1872  WeakIntrusivePtrTest,
1873  givenValidPtr_whenCopyAssigning_thenPointsToSameObject) {
1874  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1875  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
1876  SomeClass* obj1ptr = obj1.weak.lock().get();
1877  obj2.weak = obj1.weak;
1878  EXPECT_EQ(obj1ptr, obj2.weak.lock().get());
1879 }
1880 
1881 TEST(
1882  WeakIntrusivePtrTest,
1883  givenValidPtr_whenCopyAssigning_thenOldInstanceValid) {
1884  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1885  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
1886  obj2.weak = obj1.weak;
1887  EXPECT_FALSE(obj1.weak.expired());
1888 }
1889 
1890 TEST(
1891  WeakIntrusivePtrTest,
1892  givenValidPtr_whenCopyAssigningToSelf_thenPointsToSameObject) {
1893  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1894  SomeClass* obj1ptr = obj1.weak.lock().get();
1895  obj1.weak = obj1.weak;
1896  EXPECT_EQ(obj1ptr, obj1.weak.lock().get());
1897 }
1898 
1899 TEST(
1900  WeakIntrusivePtrTest,
1901  givenValidPtr_whenCopyAssigningToSelf_thenStaysValid) {
1902  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1903  obj1.weak = obj1.weak;
1904  EXPECT_FALSE(obj1.weak.expired());
1905 }
1906 
1907 TEST(
1908  WeakIntrusivePtrTest,
1909  givenInvalidPtr_whenCopyAssigning_thenNewInstanceIsValid) {
1910  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1911  weak_intrusive_ptr<SomeClass> obj2 = make_invalid_weak<SomeClass>();
1912  SomeClass* obj1ptr = obj1.weak.lock().get();
1913  obj2 = obj1.weak;
1914  EXPECT_FALSE(obj2.expired());
1915 }
1916 
1917 TEST(
1918  WeakIntrusivePtrTest,
1919  givenInvalidPtr_whenCopyAssigningToSelf_thenStaysInvalid) {
1920  weak_intrusive_ptr<SomeClass> obj1 = make_invalid_weak<SomeClass>();
1921  obj1 = obj1;
1922  EXPECT_TRUE(obj1.expired());
1923 }
1924 
1925 TEST(
1926  WeakIntrusivePtrTest,
1927  givenWeakOnlyPtr_whenCopyAssigning_thenNewInstanceIsValid) {
1928  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1929  weak_intrusive_ptr<SomeClass> obj2 = make_weak_only<SomeClass>();
1930  SomeClass* obj1ptr = obj1.weak.lock().get();
1931  obj2 = obj1.weak;
1932  EXPECT_FALSE(obj2.expired());
1933 }
1934 
1935 TEST(
1936  WeakIntrusivePtrTest,
1937  givenWeakOnlyPtr_whenCopyAssigning_thenPointsToSameObject) {
1938  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
1939  weak_intrusive_ptr<SomeClass> obj2 = make_weak_only<SomeClass>();
1940  SomeClass* obj1ptr = obj1.weak.lock().get();
1941  obj2 = obj1.weak;
1942  EXPECT_EQ(obj1ptr, obj2.lock().get());
1943 }
1944 
1945 TEST(
1946  WeakIntrusivePtrTest,
1947  givenWeakOnlyPtr_whenCopyAssigningToSelf_thenStaysInvalid) {
1948  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
1949  SomeClass* obj1ptr = obj1.lock().get();
1950  obj1 = obj1;
1951  EXPECT_TRUE(obj1.expired());
1952 }
1953 
1954 TEST(
1955  WeakIntrusivePtrTest,
1956  givenWeakOnlyPtr_whenCopyAssigningToSelf_thenPointsToSameObject) {
1957  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
1958  SomeClass* obj1ptr = obj1.lock().get();
1959  obj1 = obj1;
1960  EXPECT_EQ(obj1ptr, obj1.lock().get());
1961 }
1962 
1963 TEST(
1964  WeakIntrusivePtrTest,
1965  givenValidPtr_whenCopyAssigningToBaseClass_thenPointsToSameObject) {
1966  IntrusiveAndWeak<SomeChildClass> child =
1967  make_weak_intrusive<SomeChildClass>(3);
1968  IntrusiveAndWeak<SomeBaseClass> base = make_weak_intrusive<SomeBaseClass>(10);
1969  base.weak = child.weak;
1970  EXPECT_EQ(3, base.weak.lock()->v);
1971 }
1972 
1973 TEST(
1974  WeakIntrusivePtrTest,
1975  givenValidPtr_whenCopyAssigningToBaseClass_thenOldInstanceInvalid) {
1976  IntrusiveAndWeak<SomeChildClass> obj1 =
1977  make_weak_intrusive<SomeChildClass>(3);
1978  IntrusiveAndWeak<SomeBaseClass> obj2 = make_weak_intrusive<SomeBaseClass>(10);
1979  obj2.weak = obj1.weak;
1980  EXPECT_FALSE(obj1.weak.expired());
1981 }
1982 
1983 TEST(
1984  WeakIntrusivePtrTest,
1985  givenInvalidPtr_whenCopyAssigningToBaseClass_thenNewInstanceIsValid) {
1986  IntrusiveAndWeak<SomeChildClass> obj1 =
1987  make_weak_intrusive<SomeChildClass>(5);
1988  weak_intrusive_ptr<SomeBaseClass> obj2 = make_invalid_weak<SomeBaseClass>();
1989  SomeBaseClass* obj1ptr = obj1.weak.lock().get();
1990  obj2 = obj1.weak;
1991  EXPECT_FALSE(obj2.expired());
1992 }
1993 
1994 TEST(
1995  WeakIntrusivePtrTest,
1996  givenInvalidPtr_whenCopyAssigningToBaseClass_thenPointsToSameObject) {
1997  IntrusiveAndWeak<SomeChildClass> obj1 =
1998  make_weak_intrusive<SomeChildClass>(5);
1999  weak_intrusive_ptr<SomeBaseClass> obj2 = make_invalid_weak<SomeBaseClass>();
2000  SomeBaseClass* obj1ptr = obj1.weak.lock().get();
2001  obj2 = obj1.weak;
2002  EXPECT_EQ(obj1ptr, obj2.lock().get());
2003  EXPECT_EQ(5, obj2.lock()->v);
2004 }
2005 
2006 TEST(
2007  WeakIntrusivePtrTest,
2008  givenPtr_whenCopyAssigningInvalidPtrToBaseClass_thenNewInstanceIsInvalid) {
2009  weak_intrusive_ptr<SomeChildClass> obj1 = make_invalid_weak<SomeChildClass>();
2010  IntrusiveAndWeak<SomeBaseClass> obj2 = make_weak_intrusive<SomeBaseClass>(2);
2011  EXPECT_FALSE(obj2.weak.expired());
2012  obj2.weak = obj1;
2013  EXPECT_TRUE(obj2.weak.expired());
2014 }
2015 
2016 TEST(
2017  WeakIntrusivePtrTest,
2018  givenWeakOnlyPtr_whenCopyAssigningToBaseClass_thenNewInstanceIsValid) {
2019  IntrusiveAndWeak<SomeChildClass> obj1 =
2020  make_weak_intrusive<SomeChildClass>(5);
2021  weak_intrusive_ptr<SomeBaseClass> obj2 = make_weak_only<SomeBaseClass>(2);
2022  SomeBaseClass* obj1ptr = obj1.weak.lock().get();
2023  obj2 = obj1.weak;
2024  EXPECT_FALSE(obj2.expired());
2025 }
2026 
2027 TEST(
2028  WeakIntrusivePtrTest,
2029  givenWeakOnlyPtr_whenCopyAssigningToBaseClass_thenPointsToSameObject) {
2030  IntrusiveAndWeak<SomeChildClass> obj1 =
2031  make_weak_intrusive<SomeChildClass>(5);
2032  weak_intrusive_ptr<SomeBaseClass> obj2 = make_weak_only<SomeBaseClass>(2);
2033  SomeBaseClass* obj1ptr = obj1.weak.lock().get();
2034  obj2 = obj1.weak;
2035  EXPECT_EQ(obj1ptr, obj2.lock().get());
2036  EXPECT_EQ(5, obj2.lock()->v);
2037 }
2038 
2039 TEST(
2040  WeakIntrusivePtrTest,
2041  givenPtr_whenCopyAssigningWeakOnlyPtrToBaseClass_thenNewInstanceIsValid) {
2042  weak_intrusive_ptr<SomeChildClass> obj1 = make_weak_only<SomeChildClass>(2);
2043  IntrusiveAndWeak<SomeBaseClass> obj2 = make_weak_intrusive<SomeBaseClass>(2);
2044  EXPECT_FALSE(obj2.weak.expired());
2045  obj2.weak = obj1;
2046  EXPECT_TRUE(obj2.weak.expired());
2047 }
2048 
2049 TEST(
2050  WeakIntrusivePtrTest,
2051  givenNullPtr_whenCopyAssigningToDifferentNullptr_thenHasNewNullptr) {
2052  weak_intrusive_ptr<SomeClass, NullType1> obj1 = make_invalid_weak<SomeClass, NullType1>();
2053  weak_intrusive_ptr<SomeClass, NullType2> obj2 = make_invalid_weak<SomeClass, NullType2>();
2054  obj2 = obj1;
2055  EXPECT_NE(NullType1::singleton(), NullType2::singleton());
2056  EXPECT_TRUE(obj1.expired());
2057  EXPECT_TRUE(obj2.expired());
2058 }
2059 
2060 TEST(
2061  WeakIntrusivePtrTest,
2062  givenPtr_whenMoveConstructing_thenPointsToSameObject) {
2063  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2064  SomeClass* obj1ptr = obj1.weak.lock().get();
2065  weak_intrusive_ptr<SomeClass> obj2 = std::move(obj1.weak);
2066  EXPECT_EQ(obj1ptr, obj2.lock().get());
2067 }
2068 
2069 TEST(
2070  WeakIntrusivePtrTest,
2071  givenPtr_whenMoveConstructing_thenOldInstanceInvalid) {
2072  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2073  weak_intrusive_ptr<SomeClass> obj2 = std::move(obj1.weak);
2074  EXPECT_TRUE(obj1.weak.expired());
2075 }
2076 
2077 TEST(WeakIntrusivePtrTest, givenPtr_whenMoveConstructing_thenNewInstanceValid) {
2078  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2079  weak_intrusive_ptr<SomeClass> obj2 = std::move(obj1.weak);
2080  EXPECT_FALSE(obj2.expired());
2081 }
2082 
2083 TEST(
2084  WeakIntrusivePtrTest,
2085  givenPtr_whenMoveConstructingFromInvalidPtr_thenNewInstanceInvalid) {
2086  weak_intrusive_ptr<SomeClass> obj1 = make_invalid_weak<SomeClass>();
2087  weak_intrusive_ptr<SomeClass> obj2 = std::move(obj1);
2088  EXPECT_TRUE(obj2.expired());
2089 }
2090 
2091 TEST(
2092  WeakIntrusivePtrTest,
2093  givenPtr_whenMoveConstructingFromWeakOnlyPtr_thenNewInstanceInvalid) {
2094  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
2095  weak_intrusive_ptr<SomeClass> obj2 = std::move(obj1);
2096  EXPECT_TRUE(obj2.expired());
2097 }
2098 
2099 TEST(
2100  WeakIntrusivePtrTest,
2101  givenPtr_whenMoveConstructingToBaseClass_thenPointsToSameObject) {
2102  IntrusiveAndWeak<SomeChildClass> child =
2103  make_weak_intrusive<SomeChildClass>(3);
2104  SomeBaseClass* objptr = child.weak.lock().get();
2105  weak_intrusive_ptr<SomeBaseClass> base = std::move(child.weak);
2106  EXPECT_EQ(3, base.lock()->v);
2107  EXPECT_EQ(objptr, base.lock().get());
2108 }
2109 
2110 TEST(
2111  WeakIntrusivePtrTest,
2112  givenPtr_whenMoveConstructingToBaseClass_thenOldInstanceInvalid) {
2113  IntrusiveAndWeak<SomeChildClass> child =
2114  make_weak_intrusive<SomeChildClass>(3);
2115  weak_intrusive_ptr<SomeBaseClass> base = std::move(child.weak);
2116  EXPECT_TRUE(child.weak.expired());
2117 }
2118 
2119 TEST(
2120  WeakIntrusivePtrTest,
2121  givenPtr_whenMoveConstructingToBaseClass_thenNewInstanceValid) {
2122  IntrusiveAndWeak<SomeChildClass> obj1 =
2123  make_weak_intrusive<SomeChildClass>(2);
2124  weak_intrusive_ptr<SomeBaseClass> obj2 = std::move(obj1.weak);
2125  EXPECT_FALSE(obj2.expired());
2126 }
2127 
2128 TEST(
2129  WeakIntrusivePtrTest,
2130  givenPtr_whenMoveConstructingToBaseClassFromInvalidPtr_thenNewInstanceInvalid) {
2131  weak_intrusive_ptr<SomeChildClass> obj1 = make_invalid_weak<SomeChildClass>();
2132  weak_intrusive_ptr<SomeBaseClass> obj2 = std::move(obj1);
2133  EXPECT_TRUE(obj2.expired());
2134 }
2135 
2136 TEST(
2137  WeakIntrusivePtrTest,
2138  givenPtr_whenMoveConstructingToBaseClassFromWeakOnlyPtr_thenNewInstanceInvalid) {
2139  weak_intrusive_ptr<SomeChildClass> obj1 = make_weak_only<SomeChildClass>(2);
2140  weak_intrusive_ptr<SomeBaseClass> obj2 = std::move(obj1);
2141  EXPECT_TRUE(obj2.expired());
2142 }
2143 
2144 TEST(
2145  WeakIntrusivePtrTest,
2146  givenNullPtr_whenMoveConstructingToDifferentNullptr_thenHasNewNullptr) {
2147  weak_intrusive_ptr<SomeClass, NullType1> obj1 = make_invalid_weak<SomeClass, NullType1>();
2148  weak_intrusive_ptr<SomeClass, NullType2> obj2 = std::move(obj1);
2149  EXPECT_NE(NullType1::singleton(), NullType2::singleton());
2150  EXPECT_TRUE(obj1.expired());
2151  EXPECT_TRUE(obj2.expired());
2152 }
2153 
2154 TEST(
2155  WeakIntrusivePtrTest,
2156  givenPtr_whenCopyConstructing_thenPointsToSameObject) {
2157  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2158  SomeClass* obj1ptr = obj1.weak.lock().get();
2159  weak_intrusive_ptr<SomeClass> obj2 = obj1.weak;
2160  EXPECT_EQ(obj1ptr, obj2.lock().get());
2161  EXPECT_FALSE(obj1.weak.expired());
2162 }
2163 
2164 TEST(WeakIntrusivePtrTest, givenPtr_whenCopyConstructing_thenOldInstanceValid) {
2165  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2166  weak_intrusive_ptr<SomeClass> obj2 = obj1.weak;
2167  EXPECT_FALSE(obj1.weak.expired());
2168 }
2169 
2170 TEST(WeakIntrusivePtrTest, givenPtr_whenCopyConstructing_thenNewInstanceValid) {
2171  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2172  weak_intrusive_ptr<SomeClass> obj2 = obj1.weak;
2173  EXPECT_FALSE(obj2.expired());
2174 }
2175 
2176 TEST(
2177  WeakIntrusivePtrTest,
2178  givenPtr_whenCopyConstructingFromInvalidPtr_thenNewInstanceInvalid) {
2179  weak_intrusive_ptr<SomeClass> obj1 = make_invalid_weak<SomeClass>();
2180  weak_intrusive_ptr<SomeClass> obj2 = obj1;
2181  EXPECT_TRUE(obj2.expired());
2182 }
2183 
2184 TEST(
2185  WeakIntrusivePtrTest,
2186  givenPtr_whenCopyConstructingFromWeakOnlyPtr_thenNewInstanceInvalid) {
2187  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
2188  weak_intrusive_ptr<SomeClass> obj2 = obj1;
2189  EXPECT_TRUE(obj2.expired());
2190 }
2191 
2192 TEST(
2193  WeakIntrusivePtrTest,
2194  givenPtr_whenCopyConstructingToBaseClass_thenPointsToSameObject) {
2195  IntrusiveAndWeak<SomeChildClass> child =
2196  make_weak_intrusive<SomeChildClass>(3);
2197  SomeBaseClass* objptr = child.weak.lock().get();
2198  weak_intrusive_ptr<SomeBaseClass> base = child.weak;
2199  EXPECT_EQ(3, base.lock()->v);
2200  EXPECT_EQ(objptr, base.lock().get());
2201 }
2202 
2203 TEST(
2204  WeakIntrusivePtrTest,
2205  givenPtr_whenCopyConstructingToBaseClass_thenOldInstanceInvalid) {
2206  IntrusiveAndWeak<SomeChildClass> child =
2207  make_weak_intrusive<SomeChildClass>(3);
2208  weak_intrusive_ptr<SomeBaseClass> base = child.weak;
2209  EXPECT_FALSE(child.weak.expired());
2210 }
2211 
2212 TEST(
2213  WeakIntrusivePtrTest,
2214  givenPtr_whenCopyConstructingToBaseClass_thenNewInstanceInvalid) {
2215  IntrusiveAndWeak<SomeChildClass> child =
2216  make_weak_intrusive<SomeChildClass>(3);
2217  weak_intrusive_ptr<SomeBaseClass> base = child.weak;
2218  EXPECT_FALSE(base.expired());
2219 }
2220 
2221 TEST(
2222  WeakIntrusivePtrTest,
2223  givenPtr_whenCopyConstructingToBaseClassFromInvalidPtr_thenNewInstanceInvalid) {
2224  weak_intrusive_ptr<SomeChildClass> obj1 = make_invalid_weak<SomeChildClass>();
2226  EXPECT_TRUE(obj2.expired());
2227 }
2228 
2229 TEST(
2230  WeakIntrusivePtrTest,
2231  givenPtr_whenCopyConstructingToBaseClassFromWeakOnlyPtr_thenNewInstanceInvalid) {
2232  weak_intrusive_ptr<SomeChildClass> obj1 = make_weak_only<SomeChildClass>(2);
2234  EXPECT_TRUE(obj2.expired());
2235 }
2236 
2237 TEST(
2238  WeakIntrusivePtrTest,
2239  givenNullPtr_whenCopyConstructingToDifferentNullptr_thenHasNewNullptr) {
2240  weak_intrusive_ptr<SomeClass, NullType1> obj1 = make_invalid_weak<SomeClass, NullType1>();
2242  EXPECT_NE(NullType1::singleton(), NullType2::singleton());
2243  EXPECT_TRUE(obj1.expired());
2244  EXPECT_TRUE(obj2.expired());
2245 }
2246 
2247 TEST(WeakIntrusivePtrTest, SwapFunction) {
2248  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2249  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2250  SomeClass* obj1ptr = obj1.weak.lock().get();
2251  SomeClass* obj2ptr = obj2.weak.lock().get();
2252  swap(obj1.weak, obj2.weak);
2253  EXPECT_EQ(obj2ptr, obj1.weak.lock().get());
2254  EXPECT_EQ(obj1ptr, obj2.weak.lock().get());
2255 }
2256 
2257 TEST(WeakIntrusivePtrTest, SwapMethod) {
2258  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2259  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2260  SomeClass* obj1ptr = obj1.weak.lock().get();
2261  SomeClass* obj2ptr = obj2.weak.lock().get();
2262  obj1.weak.swap(obj2.weak);
2263  EXPECT_EQ(obj2ptr, obj1.weak.lock().get());
2264  EXPECT_EQ(obj1ptr, obj2.weak.lock().get());
2265 }
2266 
2267 TEST(WeakIntrusivePtrTest, SwapFunctionFromInvalid) {
2268  weak_intrusive_ptr<SomeClass> obj1 = make_invalid_weak<SomeClass>();
2269  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2270  SomeClass* obj2ptr = obj2.weak.lock().get();
2271  swap(obj1, obj2.weak);
2272  EXPECT_EQ(obj2ptr, obj1.lock().get());
2273  EXPECT_FALSE(obj1.expired());
2274  EXPECT_TRUE(obj2.weak.expired());
2275 }
2276 
2277 TEST(WeakIntrusivePtrTest, SwapMethodFromInvalid) {
2278  weak_intrusive_ptr<SomeClass> obj1 = make_invalid_weak<SomeClass>();
2279  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2280  SomeClass* obj2ptr = obj2.weak.lock().get();
2281  obj1.swap(obj2.weak);
2282  EXPECT_EQ(obj2ptr, obj1.lock().get());
2283  EXPECT_FALSE(obj1.expired());
2284  EXPECT_TRUE(obj2.weak.expired());
2285 }
2286 
2287 TEST(WeakIntrusivePtrTest, SwapFunctionWithInvalid) {
2288  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2289  weak_intrusive_ptr<SomeClass> obj2 = make_invalid_weak<SomeClass>();
2290  SomeClass* obj1ptr = obj1.weak.lock().get();
2291  swap(obj1.weak, obj2);
2292  EXPECT_TRUE(obj1.weak.expired());
2293  EXPECT_FALSE(obj2.expired());
2294  EXPECT_EQ(obj1ptr, obj2.lock().get());
2295 }
2296 
2297 TEST(WeakIntrusivePtrTest, SwapMethodWithInvalid) {
2298  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2299  weak_intrusive_ptr<SomeClass> obj2 = make_invalid_weak<SomeClass>();
2300  SomeClass* obj1ptr = obj1.weak.lock().get();
2301  obj1.weak.swap(obj2);
2302  EXPECT_TRUE(obj1.weak.expired());
2303  EXPECT_FALSE(obj2.expired());
2304  EXPECT_EQ(obj1ptr, obj2.lock().get());
2305 }
2306 
2307 TEST(WeakIntrusivePtrTest, SwapFunctionInvalidWithInvalid) {
2308  weak_intrusive_ptr<SomeClass> obj1 = make_invalid_weak<SomeClass>();
2309  weak_intrusive_ptr<SomeClass> obj2 = make_invalid_weak<SomeClass>();
2310  swap(obj1, obj2);
2311  EXPECT_TRUE(obj1.expired());
2312  EXPECT_TRUE(obj2.expired());
2313 }
2314 
2315 TEST(WeakIntrusivePtrTest, SwapMethodInvalidWithInvalid) {
2316  weak_intrusive_ptr<SomeClass> obj1 = make_invalid_weak<SomeClass>();
2317  weak_intrusive_ptr<SomeClass> obj2 = make_invalid_weak<SomeClass>();
2318  obj1.swap(obj2);
2319  EXPECT_TRUE(obj1.expired());
2320  EXPECT_TRUE(obj2.expired());
2321 }
2322 
2323 TEST(WeakIntrusivePtrTest, SwapFunctionFromWeakOnlyPtr) {
2324  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
2325  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2326  SomeClass* obj2ptr = obj2.weak.lock().get();
2327  swap(obj1, obj2.weak);
2328  EXPECT_EQ(obj2ptr, obj1.lock().get());
2329  EXPECT_FALSE(obj1.expired());
2330  EXPECT_TRUE(obj2.weak.expired());
2331 }
2332 
2333 TEST(WeakIntrusivePtrTest, SwapMethodFromWeakOnlyPtr) {
2334  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
2335  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2336  SomeClass* obj2ptr = obj2.weak.lock().get();
2337  obj1.swap(obj2.weak);
2338  EXPECT_EQ(obj2ptr, obj1.lock().get());
2339  EXPECT_FALSE(obj1.expired());
2340  EXPECT_TRUE(obj2.weak.expired());
2341 }
2342 
2343 TEST(WeakIntrusivePtrTest, SwapFunctionWithWeakOnlyPtr) {
2344  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2345  weak_intrusive_ptr<SomeClass> obj2 = make_weak_only<SomeClass>();
2346  SomeClass* obj1ptr = obj1.weak.lock().get();
2347  swap(obj1.weak, obj2);
2348  EXPECT_TRUE(obj1.weak.expired());
2349  EXPECT_FALSE(obj2.expired());
2350  EXPECT_EQ(obj1ptr, obj2.lock().get());
2351 }
2352 
2353 TEST(WeakIntrusivePtrTest, SwapMethodWithWeakOnlyPtr) {
2354  IntrusiveAndWeak<SomeClass> obj1 = make_weak_intrusive<SomeClass>();
2355  weak_intrusive_ptr<SomeClass> obj2 = make_weak_only<SomeClass>();
2356  SomeClass* obj1ptr = obj1.weak.lock().get();
2357  obj1.weak.swap(obj2);
2358  EXPECT_TRUE(obj1.weak.expired());
2359  EXPECT_FALSE(obj2.expired());
2360  EXPECT_EQ(obj1ptr, obj2.lock().get());
2361 }
2362 
2363 TEST(WeakIntrusivePtrTest, SwapFunctionWeakOnlyPtrWithWeakOnlyPtr) {
2364  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
2365  weak_intrusive_ptr<SomeClass> obj2 = make_weak_only<SomeClass>();
2366  swap(obj1, obj2);
2367  EXPECT_TRUE(obj1.expired());
2368  EXPECT_TRUE(obj2.expired());
2369 }
2370 
2371 TEST(WeakIntrusivePtrTest, SwapMethodWeakOnlyPtrWithWeakOnlyPtr) {
2372  weak_intrusive_ptr<SomeClass> obj1 = make_weak_only<SomeClass>();
2373  weak_intrusive_ptr<SomeClass> obj2 = make_weak_only<SomeClass>();
2374  obj1.swap(obj2);
2375  EXPECT_TRUE(obj1.expired());
2376  EXPECT_TRUE(obj2.expired());
2377 }
2378 
2379 TEST(WeakIntrusivePtrTest, CanBePutInContainer) {
2380  std::vector<weak_intrusive_ptr<SomeClass1Parameter>> vec;
2381  IntrusiveAndWeak<SomeClass1Parameter> obj =
2382  make_weak_intrusive<SomeClass1Parameter>(5);
2383  vec.push_back(obj.weak);
2384  EXPECT_EQ(5, vec[0].lock()->param);
2385 }
2386 
2387 TEST(WeakIntrusivePtrTest, CanBePutInSet) {
2388  std::set<weak_intrusive_ptr<SomeClass1Parameter>> set;
2389  IntrusiveAndWeak<SomeClass1Parameter> obj =
2390  make_weak_intrusive<SomeClass1Parameter>(5);
2391  set.insert(obj.weak);
2392  EXPECT_EQ(5, set.begin()->lock()->param);
2393 }
2394 
2395 TEST(WeakIntrusivePtrTest, CanBePutInUnorderedSet) {
2396  std::unordered_set<weak_intrusive_ptr<SomeClass1Parameter>> set;
2397  IntrusiveAndWeak<SomeClass1Parameter> obj =
2398  make_weak_intrusive<SomeClass1Parameter>(5);
2399  set.insert(obj.weak);
2400  EXPECT_EQ(5, set.begin()->lock()->param);
2401 }
2402 
2403 TEST(WeakIntrusivePtrTest, CanBePutInMap) {
2404  std::map<
2406  weak_intrusive_ptr<SomeClass1Parameter>>
2407  map;
2408  IntrusiveAndWeak<SomeClass1Parameter> obj1 =
2409  make_weak_intrusive<SomeClass1Parameter>(5);
2410  IntrusiveAndWeak<SomeClass1Parameter> obj2 =
2411  make_weak_intrusive<SomeClass1Parameter>(3);
2412  map.insert(std::make_pair(obj1.weak, obj2.weak));
2413  EXPECT_EQ(5, map.begin()->first.lock()->param);
2414  EXPECT_EQ(3, map.begin()->second.lock()->param);
2415 }
2416 
2417 TEST(WeakIntrusivePtrTest, CanBePutInUnorderedMap) {
2418  std::unordered_map<
2419  weak_intrusive_ptr<SomeClass1Parameter>,
2420  weak_intrusive_ptr<SomeClass1Parameter>>
2421  map;
2422  IntrusiveAndWeak<SomeClass1Parameter> obj1 =
2423  make_weak_intrusive<SomeClass1Parameter>(5);
2424  IntrusiveAndWeak<SomeClass1Parameter> obj2 =
2425  make_weak_intrusive<SomeClass1Parameter>(3);
2426  map.insert(std::make_pair(obj1.weak, obj2.weak));
2427  EXPECT_EQ(5, map.begin()->first.lock()->param);
2428  EXPECT_EQ(3, map.begin()->second.lock()->param);
2429 }
2430 
2431 TEST(WeakIntrusivePtrTest, Equality_AfterCopyConstructor) {
2432  IntrusiveAndWeak<SomeClass> var1 = make_weak_intrusive<SomeClass>();
2433  weak_intrusive_ptr<SomeClass> var2 = var1.weak;
2434  EXPECT_TRUE(var1.weak == var2);
2435  EXPECT_FALSE(var1.weak != var2);
2436 }
2437 
2438 TEST(WeakIntrusivePtrTest, Equality_AfterCopyAssignment) {
2439  IntrusiveAndWeak<SomeClass> var1 = make_weak_intrusive<SomeClass>();
2440  IntrusiveAndWeak<SomeClass> var2 = make_weak_intrusive<SomeClass>();
2441  var2.weak = var1.weak;
2442  EXPECT_TRUE(var1.weak == var2.weak);
2443  EXPECT_FALSE(var1.weak != var2.weak);
2444 }
2445 
2446 TEST(WeakIntrusivePtrTest, Equality_AfterCopyAssignment_WeakOnly) {
2447  weak_intrusive_ptr<SomeClass> var1 = make_weak_only<SomeClass>();
2448  weak_intrusive_ptr<SomeClass> var2 = var1;
2449  EXPECT_TRUE(var1 == var2);
2450  EXPECT_FALSE(var1 != var2);
2451 }
2452 
2453 TEST(WeakIntrusivePtrTest, Equality_Invalid) {
2454  weak_intrusive_ptr<SomeClass> var1 = make_invalid_weak<SomeClass>();
2455  weak_intrusive_ptr<SomeClass> var2 = make_invalid_weak<SomeClass>();
2456  EXPECT_TRUE(var1 == var2);
2457  EXPECT_FALSE(var1 != var2);
2458 }
2459 
2460 TEST(WeakIntrusivePtrTest, Nonequality) {
2461  IntrusiveAndWeak<SomeClass> var1 = make_intrusive<SomeClass>();
2462  IntrusiveAndWeak<SomeClass> var2 = make_intrusive<SomeClass>();
2463  EXPECT_TRUE(var1.weak != var2.weak);
2464  EXPECT_FALSE(var1.weak == var2.weak);
2465 }
2466 
2467 TEST(WeakIntrusivePtrTest, Nonequality_InvalidLeft) {
2468  weak_intrusive_ptr<SomeClass> var1 = make_invalid_weak<SomeClass>();
2469  IntrusiveAndWeak<SomeClass> var2 = make_intrusive<SomeClass>();
2470  EXPECT_TRUE(var1 != var2.weak);
2471  EXPECT_FALSE(var1 == var2.weak);
2472 }
2473 
2474 TEST(WeakIntrusivePtrTest, Nonequality_InvalidRight) {
2475  IntrusiveAndWeak<SomeClass> var1 = make_intrusive<SomeClass>();
2476  weak_intrusive_ptr<SomeClass> var2 = make_invalid_weak<SomeClass>();
2477  EXPECT_TRUE(var1.weak != var2);
2478  EXPECT_FALSE(var1.weak == var2);
2479 }
2480 
2481 TEST(WeakIntrusivePtrTest, Nonequality_WeakOnly) {
2482  weak_intrusive_ptr<SomeClass> var1 = make_weak_only<SomeClass>();
2483  weak_intrusive_ptr<SomeClass> var2 = make_weak_only<SomeClass>();
2484  EXPECT_TRUE(var1 != var2);
2485  EXPECT_FALSE(var1 == var2);
2486 }
2487 
2488 TEST(WeakIntrusivePtrTest, HashIsDifferent) {
2489  IntrusiveAndWeak<SomeClass> var1 = make_weak_intrusive<SomeClass>();
2490  IntrusiveAndWeak<SomeClass> var2 = make_weak_intrusive<SomeClass>();
2491  EXPECT_NE(
2492  std::hash<weak_intrusive_ptr<SomeClass>>()(var1.weak),
2493  std::hash<weak_intrusive_ptr<SomeClass>>()(var2.weak));
2494 }
2495 
2496 TEST(WeakIntrusivePtrTest, HashIsDifferent_ValidAndInvalid) {
2497  weak_intrusive_ptr<SomeClass> var1 = make_invalid_weak<SomeClass>();
2498  IntrusiveAndWeak<SomeClass> var2 = make_weak_intrusive<SomeClass>();
2499  EXPECT_NE(
2500  std::hash<weak_intrusive_ptr<SomeClass>>()(var1),
2501  std::hash<weak_intrusive_ptr<SomeClass>>()(var2.weak));
2502 }
2503 
2504 TEST(WeakIntrusivePtrTest, HashIsDifferent_ValidAndWeakOnly) {
2505  weak_intrusive_ptr<SomeClass> var1 = make_weak_only<SomeClass>();
2506  IntrusiveAndWeak<SomeClass> var2 = make_weak_intrusive<SomeClass>();
2507  EXPECT_NE(
2508  std::hash<weak_intrusive_ptr<SomeClass>>()(var1),
2509  std::hash<weak_intrusive_ptr<SomeClass>>()(var2.weak));
2510 }
2511 
2512 TEST(WeakIntrusivePtrTest, HashIsDifferent_WeakOnlyAndWeakOnly) {
2513  weak_intrusive_ptr<SomeClass> var1 = make_weak_only<SomeClass>();
2514  weak_intrusive_ptr<SomeClass> var2 = make_weak_only<SomeClass>();
2515  EXPECT_NE(
2516  std::hash<weak_intrusive_ptr<SomeClass>>()(var1),
2517  std::hash<weak_intrusive_ptr<SomeClass>>()(var2));
2518 }
2519 
2520 TEST(WeakIntrusivePtrTest, HashIsSame_AfterCopyConstructor) {
2521  IntrusiveAndWeak<SomeClass> var1 = make_weak_intrusive<SomeClass>();
2522  weak_intrusive_ptr<SomeClass> var2 = var1.weak;
2523  EXPECT_EQ(
2524  std::hash<weak_intrusive_ptr<SomeClass>>()(var1.weak),
2525  std::hash<weak_intrusive_ptr<SomeClass>>()(var2));
2526 }
2527 
2528 TEST(WeakIntrusivePtrTest, HashIsSame_AfterCopyConstructor_WeakOnly) {
2529  weak_intrusive_ptr<SomeClass> var1 = make_weak_only<SomeClass>();
2530  weak_intrusive_ptr<SomeClass> var2 = var1;
2531  EXPECT_EQ(
2532  std::hash<weak_intrusive_ptr<SomeClass>>()(var1),
2533  std::hash<weak_intrusive_ptr<SomeClass>>()(var2));
2534 }
2535 
2536 TEST(WeakIntrusivePtrTest, HashIsSame_AfterCopyAssignment) {
2537  IntrusiveAndWeak<SomeClass> var1 = make_weak_intrusive<SomeClass>();
2538  IntrusiveAndWeak<SomeClass> var2 = make_weak_intrusive<SomeClass>();
2539  var2.weak = var1.weak;
2540  EXPECT_EQ(
2541  std::hash<weak_intrusive_ptr<SomeClass>>()(var1.weak),
2542  std::hash<weak_intrusive_ptr<SomeClass>>()(var2.weak));
2543 }
2544 
2545 TEST(WeakIntrusivePtrTest, HashIsSame_AfterCopyAssignment_WeakOnly) {
2546  weak_intrusive_ptr<SomeClass> var1 = make_weak_only<SomeClass>();
2547  weak_intrusive_ptr<SomeClass> var2 = make_invalid_weak<SomeClass>();
2548  var2 = var1;
2549  EXPECT_EQ(
2550  std::hash<weak_intrusive_ptr<SomeClass>>()(var1),
2551  std::hash<weak_intrusive_ptr<SomeClass>>()(var2));
2552 }
2553 
2554 TEST(WeakIntrusivePtrTest, HashIsSame_BothInvalid) {
2555  weak_intrusive_ptr<SomeClass> var1 = make_invalid_weak<SomeClass>();
2556  weak_intrusive_ptr<SomeClass> var2 = make_invalid_weak<SomeClass>();
2557  EXPECT_EQ(
2558  std::hash<weak_intrusive_ptr<SomeClass>>()(var1),
2559  std::hash<weak_intrusive_ptr<SomeClass>>()(var2));
2560 }
2561 
2562 TEST(WeakIntrusivePtrTest, OneIsLess) {
2563  IntrusiveAndWeak<SomeClass> var1 = make_weak_intrusive<SomeClass>();
2564  IntrusiveAndWeak<SomeClass> var2 = make_weak_intrusive<SomeClass>();
2565  EXPECT_TRUE(
2566  std::less<weak_intrusive_ptr<SomeClass>>()(var1.weak, var2.weak) !=
2567  std::less<weak_intrusive_ptr<SomeClass>>()(var2.weak, var1.weak));
2568 }
2569 
2570 TEST(WeakIntrusivePtrTest, InvalidIsLess1) {
2571  weak_intrusive_ptr<SomeClass> var1 = make_invalid_weak<SomeClass>();
2572  IntrusiveAndWeak<SomeClass> var2 = make_weak_intrusive<SomeClass>();
2573  EXPECT_TRUE(std::less<weak_intrusive_ptr<SomeClass>>()(var1, var2.weak));
2574 }
2575 
2576 TEST(WeakIntrusivePtrTest, InvalidIsLess2) {
2577  IntrusiveAndWeak<SomeClass> var1 = make_weak_intrusive<SomeClass>();
2578  weak_intrusive_ptr<SomeClass> var2 = make_invalid_weak<SomeClass>();
2579  EXPECT_FALSE(std::less<weak_intrusive_ptr<SomeClass>>()(var1.weak, var2));
2580 }
2581 
2582 TEST(WeakIntrusivePtrTest, InvalidIsNotLessThanInvalid) {
2583  weak_intrusive_ptr<SomeClass> var1 = make_invalid_weak<SomeClass>();
2584  weak_intrusive_ptr<SomeClass> var2 = make_invalid_weak<SomeClass>();
2585  EXPECT_FALSE(std::less<weak_intrusive_ptr<SomeClass>>()(var1, var2));
2586 }
2587 
2588 TEST(WeakIntrusivePtrTest, givenPtr_whenCallingResetOnWeakPtr_thenIsInvalid) {
2589  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2590  EXPECT_FALSE(obj.weak.expired());
2591  obj.weak.reset();
2592  EXPECT_TRUE(obj.weak.expired());
2593 }
2594 
2595 TEST(WeakIntrusivePtrTest, givenPtr_whenCallingResetOnStrongPtr_thenIsInvalid) {
2596  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2597  EXPECT_FALSE(obj.weak.expired());
2598  obj.ptr.reset();
2599  EXPECT_TRUE(obj.weak.expired());
2600 }
2601 
2602 TEST(WeakIntrusivePtrTest, AllowsMoveConstructingToConst) {
2603  IntrusiveAndWeak<SomeClass> a = make_weak_intrusive<SomeClass>();
2604  weak_intrusive_ptr<const SomeClass> b = std::move(a.weak);
2605 }
2606 
2607 TEST(WeakIntrusivePtrTest, AllowsCopyConstructingToConst) {
2608  IntrusiveAndWeak<SomeClass> a = make_weak_intrusive<SomeClass>();
2610 }
2611 
2612 TEST(WeakIntrusivePtrTest, AllowsMoveAssigningToConst) {
2613  IntrusiveAndWeak<SomeClass> a = make_weak_intrusive<SomeClass>();
2614  IntrusiveAndWeak<const SomeClass> b = make_weak_intrusive<const SomeClass>();
2615  b.weak = std::move(a.weak);
2616 }
2617 
2618 TEST(WeakIntrusivePtrTest, AllowsCopyAssigningToConst) {
2619  IntrusiveAndWeak<SomeClass> a = make_weak_intrusive<SomeClass>();
2620  IntrusiveAndWeak<const SomeClass> b = make_weak_intrusive<const SomeClass>();
2621  b.weak = a.weak;
2622 }
2623 
2624 TEST(WeakIntrusivePtrTest, givenNewPtr_thenHasUseCount1) {
2625  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2626  EXPECT_EQ(1, obj.weak.use_count());
2627 }
2628 
2629 TEST(WeakIntrusivePtrTest, givenNewPtr_thenIsNotExpired) {
2630  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2631  EXPECT_FALSE(obj.weak.expired());
2632 }
2633 
2634 TEST(WeakIntrusivePtrTest, givenInvalidPtr_thenHasUseCount0) {
2635  weak_intrusive_ptr<SomeClass> obj = make_invalid_weak<SomeClass>();
2636  EXPECT_EQ(0, obj.use_count());
2637 }
2638 
2639 TEST(WeakIntrusivePtrTest, givenInvalidPtr_thenIsExpired) {
2640  weak_intrusive_ptr<SomeClass> obj = make_invalid_weak<SomeClass>();
2641  EXPECT_TRUE(obj.expired());
2642 }
2643 
2644 TEST(WeakIntrusivePtrTest, givenWeakOnlyPtr_thenHasUseCount0) {
2645  weak_intrusive_ptr<SomeClass> obj = make_weak_only<SomeClass>();
2646  EXPECT_EQ(0, obj.use_count());
2647 }
2648 
2649 TEST(WeakIntrusivePtrTest, givenWeakOnlyPtr_thenIsExpired) {
2650  weak_intrusive_ptr<SomeClass> obj = make_weak_only<SomeClass>();
2651  EXPECT_TRUE(obj.expired());
2652 }
2653 
2654 TEST(WeakIntrusivePtrTest, givenPtr_whenCallingWeakReset_thenHasUseCount0) {
2655  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2656  obj.weak.reset();
2657  EXPECT_EQ(0, obj.weak.use_count());
2658 }
2659 
2660 TEST(WeakIntrusivePtrTest, givenPtr_whenCallingWeakReset_thenIsExpired) {
2661  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2662  obj.weak.reset();
2663  EXPECT_TRUE(obj.weak.expired());
2664 }
2665 
2666 TEST(WeakIntrusivePtrTest, givenPtr_whenCallingStrongReset_thenHasUseCount0) {
2667  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2668  obj.ptr.reset();
2669  EXPECT_EQ(0, obj.weak.use_count());
2670 }
2671 
2672 TEST(WeakIntrusivePtrTest, givenPtr_whenCallingStrongReset_thenIsExpired) {
2673  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2674  obj.ptr.reset();
2675  EXPECT_TRUE(obj.weak.expired());
2676 }
2677 
2678 TEST(WeakIntrusivePtrTest, givenMoveConstructedPtr_thenHasUseCount1) {
2679  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2680  weak_intrusive_ptr<SomeClass> obj2 = std::move(obj.weak);
2681  EXPECT_EQ(1, obj2.use_count());
2682 }
2683 
2684 TEST(WeakIntrusivePtrTest, givenMoveConstructedPtr_thenIsNotExpired) {
2685  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2686  weak_intrusive_ptr<SomeClass> obj2 = std::move(obj.weak);
2687  EXPECT_FALSE(obj2.expired());
2688 }
2689 
2690 TEST(WeakIntrusivePtrTest, givenMoveConstructedPtr_thenOldHasUseCount0) {
2691  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2692  weak_intrusive_ptr<SomeClass> obj2 = std::move(obj.weak);
2693  EXPECT_EQ(0, obj.weak.use_count());
2694 }
2695 
2696 TEST(WeakIntrusivePtrTest, givenMoveConstructedPtr_thenOldIsExpired) {
2697  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2698  weak_intrusive_ptr<SomeClass> obj2 = std::move(obj.weak);
2699  EXPECT_TRUE(obj.weak.expired());
2700 }
2701 
2702 TEST(WeakIntrusivePtrTest, givenMoveAssignedPtr_thenHasUseCount1) {
2703  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2704  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2705  obj2.weak = std::move(obj.weak);
2706  EXPECT_EQ(1, obj2.weak.use_count());
2707 }
2708 
2709 TEST(WeakIntrusivePtrTest, givenMoveAssignedPtr_thenIsNotExpired) {
2710  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2711  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2712  obj2.weak = std::move(obj.weak);
2713  EXPECT_FALSE(obj2.weak.expired());
2714 }
2715 
2716 TEST(WeakIntrusivePtrTest, givenMoveAssignedPtr_thenOldHasUseCount0) {
2717  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2718  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2719  obj2.weak = std::move(obj.weak);
2720  EXPECT_EQ(0, obj.weak.use_count());
2721 }
2722 
2723 TEST(WeakIntrusivePtrTest, givenMoveAssignedPtr_thenOldIsExpired) {
2724  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2725  IntrusiveAndWeak<SomeClass> obj2 = make_weak_intrusive<SomeClass>();
2726  obj2.weak = std::move(obj.weak);
2727  EXPECT_TRUE(obj.weak.expired());
2728 }
2729 
2730 TEST(WeakIntrusivePtrTest, givenCopyConstructedPtr_thenHasUseCount1) {
2731  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2732  weak_intrusive_ptr<SomeClass> obj2 = obj.weak;
2733  EXPECT_EQ(1, obj2.use_count());
2734 }
2735 
2736 TEST(WeakIntrusivePtrTest, givenCopyConstructedPtr_thenIsNotExpired) {
2737  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2738  weak_intrusive_ptr<SomeClass> obj2 = obj.weak;
2739  EXPECT_FALSE(obj2.expired());
2740 }
2741 
2742 TEST(WeakIntrusivePtrTest, givenCopyConstructedPtr_thenOldHasUseCount1) {
2743  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2744  weak_intrusive_ptr<SomeClass> obj2 = obj.weak;
2745  EXPECT_EQ(1, obj.weak.use_count());
2746 }
2747 
2748 TEST(WeakIntrusivePtrTest, givenCopyConstructedPtr_thenOldIsNotExpired) {
2749  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2750  weak_intrusive_ptr<SomeClass> obj2 = obj.weak;
2751  EXPECT_FALSE(obj.weak.expired());
2752 }
2753 
2754 TEST(
2755  WeakIntrusivePtrTest,
2756  givenPtr_whenLastStrongPointerResets_thenReleasesResources) {
2757  bool resourcesReleased = false;
2758  bool wasDestructed = false;
2759  auto obj = make_weak_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
2760  EXPECT_FALSE(resourcesReleased);
2761  EXPECT_FALSE(wasDestructed);
2762  obj.ptr.reset();
2763  EXPECT_TRUE(resourcesReleased);
2764  EXPECT_FALSE(wasDestructed);
2765  obj.weak.reset();
2766  EXPECT_TRUE(resourcesReleased);
2767  EXPECT_TRUE(wasDestructed);
2768 }
2769 
2770 TEST(
2771  WeakIntrusivePtrTest,
2772  givenPtr_whenDestructedButStillHasStrongPointers_thenDoesntReleaseResources) {
2773  bool resourcesReleased = false;
2774  bool wasDestructed = false;
2775  auto obj = make_weak_intrusive<DestructableMock>(&resourcesReleased, &wasDestructed);
2776  EXPECT_FALSE(resourcesReleased);
2777  EXPECT_FALSE(wasDestructed);
2778  obj.weak.reset();
2779  EXPECT_FALSE(resourcesReleased);
2780  EXPECT_FALSE(wasDestructed);
2781  obj.ptr.reset();
2782  EXPECT_TRUE(resourcesReleased);
2783  EXPECT_TRUE(wasDestructed);
2784 }
2785 
2786 TEST(WeakIntrusivePtrTest, givenPtr_whenDestructed_thenDestructsObject) {
2787  bool resourcesReleased = false;
2788  bool wasDestructed = false;
2789  {
2790  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
2791  EXPECT_TRUE(resourcesReleased);
2792  EXPECT_FALSE(wasDestructed);
2793  }
2794  EXPECT_TRUE(resourcesReleased);
2795  EXPECT_TRUE(wasDestructed);
2796 }
2797 
2798 TEST(
2799  WeakIntrusivePtrTest,
2800  givenPtr_whenMoveConstructed_thenDestructsObjectAfterSecondDestructed) {
2801  bool resourcesReleased = false;
2802  bool wasDestructed = false;
2803  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
2804  {
2805  auto obj2 = std::move(obj);
2806  EXPECT_TRUE(resourcesReleased);
2807  EXPECT_FALSE(wasDestructed);
2808  }
2809  EXPECT_TRUE(resourcesReleased);
2810  EXPECT_TRUE(wasDestructed);
2811 }
2812 
2813 TEST(
2814  WeakIntrusivePtrTest,
2815  givenPtr_whenMoveConstructedToBaseClass_thenDestructsObjectAfterSecondDestructed) {
2816  bool resourcesReleased = false;
2817  bool wasDestructed = false;
2818  auto obj = make_weak_only<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
2819  {
2820  weak_intrusive_ptr<DestructableMock> obj2 = std::move(obj);
2821  EXPECT_TRUE(resourcesReleased);
2822  EXPECT_FALSE(wasDestructed);
2823  }
2824  EXPECT_TRUE(resourcesReleased);
2825  EXPECT_TRUE(wasDestructed);
2826 }
2827 
2828 TEST(WeakIntrusivePtrTest, givenPtr_whenMoveAssigned_thenDestructsOldObject) {
2829  bool dummy = false;
2830  bool resourcesReleased = false;
2831  bool wasDestructed = false;
2832  auto obj = make_weak_only<DestructableMock>(&dummy, &dummy);
2833  {
2834  auto obj2 = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
2835  EXPECT_TRUE(resourcesReleased);
2836  EXPECT_FALSE(wasDestructed);
2837  obj2 = std::move(obj);
2838  EXPECT_TRUE(resourcesReleased);
2839  EXPECT_TRUE(wasDestructed);
2840  }
2841 }
2842 
2843 TEST(
2844  WeakIntrusivePtrTest,
2845  givenPtr_whenMoveAssignedToBaseClass_thenDestructsOldObject) {
2846  bool dummy = false;
2847  bool resourcesReleased = false;
2848  bool wasDestructed = false;
2849  auto obj = make_weak_only<ChildDestructableMock>(&dummy, &dummy);
2850  {
2851  auto obj2 = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
2852  EXPECT_TRUE(resourcesReleased);
2853  EXPECT_FALSE(wasDestructed);
2854  obj2 = std::move(obj);
2855  EXPECT_TRUE(resourcesReleased);
2856  EXPECT_TRUE(wasDestructed);
2857  }
2858 }
2859 
2860 TEST(
2861  WeakIntrusivePtrTest,
2862  givenPtrWithCopy_whenMoveAssigned_thenDestructsOldObjectAfterCopyIsDestructed) {
2863  bool dummy = false;
2864  bool resourcesReleased = false;
2865  bool wasDestructed = false;
2866  auto obj = make_weak_only<DestructableMock>(&dummy, &dummy);
2867  {
2868  auto obj2 = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
2869  {
2870  auto copy = obj2;
2871  EXPECT_TRUE(resourcesReleased);
2872  EXPECT_FALSE(wasDestructed);
2873  obj2 = std::move(obj);
2874  EXPECT_TRUE(resourcesReleased);
2875  EXPECT_FALSE(wasDestructed);
2876  }
2877  EXPECT_TRUE(resourcesReleased);
2878  EXPECT_TRUE(wasDestructed);
2879  }
2880 }
2881 
2882 TEST(
2883  WeakIntrusivePtrTest,
2884  givenPtrWithBaseClassCopy_whenMoveAssigned_thenDestructsOldObjectAfterCopyIsDestructed) {
2885  bool dummy = false;
2886  bool resourcesReleased = false;
2887  bool wasDestructed = false;
2888  auto obj = make_weak_only<ChildDestructableMock>(&dummy, &dummy);
2889  {
2890  auto obj2 =
2891  make_weak_only<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
2892  {
2894  EXPECT_TRUE(resourcesReleased);
2895  EXPECT_FALSE(wasDestructed);
2896  obj2 = std::move(obj);
2897  EXPECT_TRUE(resourcesReleased);
2898  EXPECT_FALSE(wasDestructed);
2899  }
2900  EXPECT_TRUE(resourcesReleased);
2901  EXPECT_TRUE(wasDestructed);
2902  }
2903 }
2904 
2905 TEST(
2906  WeakIntrusivePtrTest,
2907  givenPtrWithCopy_whenMoveAssignedToBaseClass_thenDestructsOldObjectAfterCopyIsDestructed) {
2908  bool dummy = false;
2909  bool resourcesReleased = false;
2910  bool wasDestructed = false;
2911  auto obj = make_weak_only<ChildDestructableMock>(&dummy, &dummy);
2912  {
2913  auto obj2 = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
2914  {
2916  EXPECT_TRUE(resourcesReleased);
2917  EXPECT_FALSE(wasDestructed);
2918  obj2 = std::move(obj);
2919  EXPECT_TRUE(resourcesReleased);
2920  EXPECT_FALSE(wasDestructed);
2921  }
2922  EXPECT_TRUE(resourcesReleased);
2923  EXPECT_TRUE(wasDestructed);
2924  }
2925 }
2926 
2927 TEST(
2928  WeakIntrusivePtrTest,
2929  givenPtr_whenMoveAssigned_thenDestructsObjectAfterSecondDestructed) {
2930  bool dummy = false;
2931  bool resourcesReleased = false;
2932  bool wasDestructed = false;
2933  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
2934  {
2935  auto obj2 = make_weak_only<DestructableMock>(&dummy, &dummy);
2936  obj2 = std::move(obj);
2937  EXPECT_TRUE(resourcesReleased);
2938  EXPECT_FALSE(wasDestructed);
2939  }
2940  EXPECT_TRUE(resourcesReleased);
2941  EXPECT_TRUE(wasDestructed);
2942 }
2943 
2944 TEST(
2945  WeakIntrusivePtrTest,
2946  givenPtr_whenMoveAssignedToBaseClass_thenDestructsObjectAfterSecondDestructed) {
2947  bool dummy = false;
2948  bool resourcesReleased = false;
2949  bool wasDestructed = false;
2950  auto obj = make_weak_only<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
2951  {
2952  auto obj2 = make_weak_only<DestructableMock>(&dummy, &dummy);
2953  obj2 = std::move(obj);
2954  EXPECT_TRUE(resourcesReleased);
2955  EXPECT_FALSE(wasDestructed);
2956  }
2957  EXPECT_TRUE(resourcesReleased);
2958  EXPECT_TRUE(wasDestructed);
2959 }
2960 
2961 TEST(
2962  WeakIntrusivePtrTest,
2963  givenPtr_whenCopyConstructedAndDestructed_thenDestructsObjectAfterLastDestruction) {
2964  bool resourcesReleased = false;
2965  bool wasDestructed = false;
2966  {
2967  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
2968  {
2970  EXPECT_TRUE(resourcesReleased);
2971  EXPECT_FALSE(wasDestructed);
2972  }
2973  EXPECT_TRUE(resourcesReleased);
2974  EXPECT_FALSE(wasDestructed);
2975  }
2976  EXPECT_TRUE(resourcesReleased);
2977  EXPECT_TRUE(wasDestructed);
2978 }
2979 
2980 TEST(
2981  WeakIntrusivePtrTest,
2982  givenPtr_whenCopyConstructedToBaseClassAndDestructed_thenDestructsObjectAfterLastDestruction) {
2983  bool resourcesReleased = false;
2984  bool wasDestructed = false;
2985  {
2986  auto obj = make_weak_only<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
2987  {
2989  EXPECT_TRUE(resourcesReleased);
2990  EXPECT_FALSE(wasDestructed);
2991  }
2992  EXPECT_TRUE(resourcesReleased);
2993  EXPECT_FALSE(wasDestructed);
2994  }
2995  EXPECT_TRUE(resourcesReleased);
2996  EXPECT_TRUE(wasDestructed);
2997 }
2998 
2999 TEST(
3000  WeakIntrusivePtrTest,
3001  givenPtr_whenCopyConstructedAndOriginalDestructed_thenDestructsObjectAfterLastDestruction) {
3002  bool resourcesReleased = false;
3003  bool wasDestructed = false;
3004  {
3005  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3007  obj.reset();
3008  EXPECT_TRUE(resourcesReleased);
3009  EXPECT_FALSE(wasDestructed);
3010  }
3011  EXPECT_TRUE(resourcesReleased);
3012  EXPECT_TRUE(wasDestructed);
3013 }
3014 
3015 TEST(
3016  WeakIntrusivePtrTest,
3017  givenPtr_whenCopyConstructedToBaseClassAndOriginalDestructed_thenDestructsObjectAfterLastDestruction) {
3018  bool resourcesReleased = false;
3019  bool wasDestructed = false;
3020  {
3021  auto obj = make_weak_only<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
3023  obj.reset();
3024  EXPECT_TRUE(resourcesReleased);
3025  EXPECT_FALSE(wasDestructed);
3026  }
3027  EXPECT_TRUE(resourcesReleased);
3028  EXPECT_TRUE(wasDestructed);
3029 }
3030 
3031 TEST(
3032  WeakIntrusivePtrTest,
3033  givenPtr_whenCopyAssignedAndDestructed_thenDestructsObjectAfterLastDestruction) {
3034  bool resourcesReleased = false;
3035  bool wasDestructed = false;
3036  bool dummy = false;
3037  {
3038  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3039  {
3041  make_weak_only<DestructableMock>(&dummy, &dummy);
3042  copy = obj;
3043  EXPECT_TRUE(resourcesReleased);
3044  EXPECT_FALSE(wasDestructed);
3045  }
3046  EXPECT_TRUE(resourcesReleased);
3047  EXPECT_FALSE(wasDestructed);
3048  }
3049  EXPECT_TRUE(resourcesReleased);
3050  EXPECT_TRUE(wasDestructed);
3051 }
3052 
3053 TEST(
3054  WeakIntrusivePtrTest,
3055  givenPtr_whenCopyAssignedToBaseClassAndDestructed_thenDestructsObjectAfterLastDestruction) {
3056  bool resourcesReleased = false;
3057  bool wasDestructed = false;
3058  bool dummy = false;
3059  {
3060  auto obj = make_weak_only<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
3061  {
3063  make_weak_only<DestructableMock>(&dummy, &dummy);
3064  copy = obj;
3065  EXPECT_TRUE(resourcesReleased);
3066  EXPECT_FALSE(wasDestructed);
3067  }
3068  EXPECT_TRUE(resourcesReleased);
3069  EXPECT_FALSE(wasDestructed);
3070  }
3071  EXPECT_TRUE(resourcesReleased);
3072  EXPECT_TRUE(wasDestructed);
3073 }
3074 
3075 TEST(
3076  WeakIntrusivePtrTest,
3077  givenPtr_whenCopyAssignedAndOriginalDestructed_thenDestructsObjectAfterLastDestruction) {
3078  bool resourcesReleased = false;
3079  bool wasDestructed = false;
3080  bool dummy = false;
3081  {
3082  auto copy = make_weak_only<DestructableMock>(&dummy, &dummy);
3083  {
3084  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3085  copy = obj;
3086  EXPECT_TRUE(resourcesReleased);
3087  EXPECT_FALSE(wasDestructed);
3088  }
3089  EXPECT_TRUE(resourcesReleased);
3090  EXPECT_FALSE(wasDestructed);
3091  }
3092  EXPECT_TRUE(resourcesReleased);
3093  EXPECT_TRUE(wasDestructed);
3094 }
3095 
3096 TEST(
3097  WeakIntrusivePtrTest,
3098  givenPtr_whenCopyAssignedToBaseClassAndOriginalDestructed_thenDestructsObjectAfterLastDestruction) {
3099  bool wasDestructed = false;
3100  bool resourcesReleased = false;
3101  bool dummy = false;
3102  {
3103  auto copy = make_weak_only<DestructableMock>(&dummy, &dummy);
3104  {
3105  auto obj =
3106  make_weak_only<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
3107  copy = obj;
3108  EXPECT_TRUE(resourcesReleased);
3109  EXPECT_FALSE(wasDestructed);
3110  }
3111  EXPECT_TRUE(resourcesReleased);
3112  EXPECT_FALSE(wasDestructed);
3113  }
3114  EXPECT_TRUE(resourcesReleased);
3115  EXPECT_TRUE(wasDestructed);
3116 }
3117 
3118 TEST(WeakIntrusivePtrTest, givenPtr_whenCopyAssigned_thenDestructsOldObject) {
3119  bool dummy = false;
3120  bool resourcesReleased = false;
3121  bool wasDestructed = false;
3122  auto obj = make_weak_only<DestructableMock>(&dummy, &dummy);
3123  {
3124  auto obj2 = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3125  EXPECT_TRUE(resourcesReleased);
3126  EXPECT_FALSE(wasDestructed);
3127  obj2 = obj;
3128  EXPECT_TRUE(resourcesReleased);
3129  EXPECT_TRUE(wasDestructed);
3130  }
3131 }
3132 
3133 TEST(
3134  WeakIntrusivePtrTest,
3135  givenPtr_whenCopyAssignedToBaseClass_thenDestructsOldObject) {
3136  bool dummy = false;
3137  bool resourcesReleased = false;
3138  bool wasDestructed = false;
3139  auto obj = make_weak_only<ChildDestructableMock>(&dummy, &dummy);
3140  {
3141  auto obj2 = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3142  EXPECT_TRUE(resourcesReleased);
3143  EXPECT_FALSE(wasDestructed);
3144  obj2 = obj;
3145  EXPECT_TRUE(resourcesReleased);
3146  EXPECT_TRUE(wasDestructed);
3147  }
3148 }
3149 
3150 TEST(
3151  WeakIntrusivePtrTest,
3152  givenPtrWithCopy_whenCopyAssigned_thenDestructsOldObjectAfterCopyIsDestructed) {
3153  bool dummy = false;
3154  bool resourcesReleased = false;
3155  bool wasDestructed = false;
3156  auto obj = make_weak_only<DestructableMock>(&dummy, &dummy);
3157  {
3158  auto obj2 = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3159  {
3160  auto copy = obj2;
3161  EXPECT_TRUE(resourcesReleased);
3162  EXPECT_FALSE(wasDestructed);
3163  obj2 = obj;
3164  EXPECT_TRUE(resourcesReleased);
3165  EXPECT_FALSE(wasDestructed);
3166  }
3167  EXPECT_TRUE(resourcesReleased);
3168  EXPECT_TRUE(wasDestructed);
3169  }
3170 }
3171 
3172 TEST(
3173  WeakIntrusivePtrTest,
3174  givenPtrWithBaseClassCopy_whenCopyAssigned_thenDestructsOldObjectAfterCopyIsDestructed) {
3175  bool dummy = false;
3176  bool resourcesReleased = false;
3177  bool wasDestructed = false;
3178  auto obj = make_weak_only<ChildDestructableMock>(&dummy, &dummy);
3179  {
3180  auto obj2 =
3181  make_weak_only<ChildDestructableMock>(&resourcesReleased, &wasDestructed);
3182  {
3184  EXPECT_TRUE(resourcesReleased);
3185  EXPECT_FALSE(wasDestructed);
3186  obj2 = obj;
3187  EXPECT_TRUE(resourcesReleased);
3188  EXPECT_FALSE(wasDestructed);
3189  }
3190  EXPECT_TRUE(resourcesReleased);
3191  EXPECT_TRUE(wasDestructed);
3192  }
3193 }
3194 
3195 TEST(
3196  WeakIntrusivePtrTest,
3197  givenPtrWithCopy_whenCopyAssignedToBaseClass_thenDestructsOldObjectAfterCopyIsDestructed) {
3198  bool dummy = false;
3199  bool resourcesReleased = false;
3200  bool wasDestructed = false;
3201  auto obj = make_weak_only<ChildDestructableMock>(&dummy, &dummy);
3202  {
3203  auto obj2 = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3204  {
3206  EXPECT_TRUE(resourcesReleased);
3207  EXPECT_FALSE(wasDestructed);
3208  obj2 = obj;
3209  EXPECT_TRUE(resourcesReleased);
3210  EXPECT_FALSE(wasDestructed);
3211  }
3212  EXPECT_TRUE(resourcesReleased);
3213  EXPECT_TRUE(wasDestructed);
3214  }
3215 }
3216 
3217 TEST(WeakIntrusivePtrTest, givenPtr_whenCallingReset_thenDestructs) {
3218  bool resourcesReleased = false;
3219  bool wasDestructed = false;
3220  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3221  EXPECT_TRUE(resourcesReleased);
3222  EXPECT_FALSE(wasDestructed);
3223  obj.reset();
3224  EXPECT_TRUE(resourcesReleased);
3225  EXPECT_TRUE(wasDestructed);
3226 }
3227 
3228 TEST(
3229  WeakIntrusivePtrTest,
3230  givenPtrWithCopy_whenCallingReset_thenDestructsAfterCopyDestructed) {
3231  bool resourcesReleased = false;
3232  bool wasDestructed = false;
3233  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3234  {
3235  auto copy = obj;
3236  obj.reset();
3237  EXPECT_TRUE(resourcesReleased);
3238  EXPECT_FALSE(wasDestructed);
3239  copy.reset();
3240  EXPECT_TRUE(resourcesReleased);
3241  EXPECT_TRUE(wasDestructed);
3242  }
3243 }
3244 
3245 TEST(
3246  WeakIntrusivePtrTest,
3247  givenPtrWithCopy_whenCallingResetOnCopy_thenDestructsAfterOriginalDestructed) {
3248  bool resourcesReleased = false;
3249  bool wasDestructed = false;
3250  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3251  {
3252  auto copy = obj;
3253  copy.reset();
3254  EXPECT_TRUE(resourcesReleased);
3255  EXPECT_FALSE(wasDestructed);
3256  obj.reset();
3257  EXPECT_TRUE(resourcesReleased);
3258  EXPECT_TRUE(wasDestructed);
3259  }
3260 }
3261 
3262 TEST(
3263  WeakIntrusivePtrTest,
3264  givenPtrWithMoved_whenCallingReset_thenDestructsAfterMovedDestructed) {
3265  bool resourcesReleased = false;
3266  bool wasDestructed = false;
3267  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3268  {
3269  auto moved = std::move(obj);
3270  obj.reset();
3271  EXPECT_TRUE(resourcesReleased);
3272  EXPECT_FALSE(wasDestructed);
3273  moved.reset();
3274  EXPECT_TRUE(resourcesReleased);
3275  EXPECT_TRUE(wasDestructed);
3276  }
3277 }
3278 
3279 TEST(
3280  WeakIntrusivePtrTest,
3281  givenPtrWithMoved_whenCallingResetOnMoved_thenDestructsImmediately) {
3282  bool resourcesReleased = false;
3283  bool wasDestructed = false;
3284  auto obj = make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3285  {
3286  auto moved = std::move(obj);
3287  moved.reset();
3288  EXPECT_TRUE(resourcesReleased);
3289  EXPECT_TRUE(wasDestructed);
3290  }
3291 }
3292 
3293 TEST(WeakIntrusivePtrTest, givenPtr_whenReleasedAndReclaimed_thenDoesntCrash) {
3294  IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
3295  SomeClass* ptr = obj.weak.release();
3296  weak_intrusive_ptr<SomeClass> reclaimed =
3298 }
3299 
3300 TEST(
3301  WeakIntrusivePtrTest,
3302  givenWeakOnlyPtr_whenReleasedAndReclaimed_thenDoesntCrash) {
3303  weak_intrusive_ptr<SomeClass> obj = make_weak_only<SomeClass>();
3304  SomeClass* ptr = obj.release();
3305  weak_intrusive_ptr<SomeClass> reclaimed =
3307 }
3308 
3309 TEST(
3310  WeakIntrusivePtrTest,
3311  givenPtr_whenReleasedAndReclaimed_thenIsDestructedAtEnd) {
3312  bool resourcesReleased = false;
3313  bool wasDestructed = false;
3314  bool dummy = false;
3315  {
3316  IntrusiveAndWeak<DestructableMock> outer =
3317  make_weak_intrusive<DestructableMock>(&dummy, &dummy);
3318  {
3319  IntrusiveAndWeak<DestructableMock> inner =
3320  make_weak_intrusive<DestructableMock>(
3321  &resourcesReleased, &wasDestructed);
3322  EXPECT_FALSE(resourcesReleased);
3323  EXPECT_FALSE(wasDestructed);
3324  DestructableMock* ptr = inner.weak.release();
3325  EXPECT_FALSE(resourcesReleased);
3326  EXPECT_FALSE(wasDestructed);
3327  outer.ptr = inner.ptr;
3329  }
3330  // inner is destructed
3331  EXPECT_FALSE(resourcesReleased);
3332  EXPECT_FALSE(wasDestructed);
3333  outer.weak.reset();
3334  EXPECT_FALSE(resourcesReleased);
3335  EXPECT_FALSE(wasDestructed);
3336  }
3337  // outer is destructed
3338  EXPECT_TRUE(resourcesReleased);
3339  EXPECT_TRUE(wasDestructed);
3340 }
3341 
3342 TEST(
3343  WeakIntrusivePtrTest,
3344  givenWeakOnlyPtr_whenReleasedAndReclaimed_thenIsDestructedAtEnd) {
3345  bool resourcesReleased = false;
3346  bool wasDestructed = false;
3347  {
3349  make_invalid_weak<DestructableMock>();
3350  {
3352  make_weak_only<DestructableMock>(&resourcesReleased, &wasDestructed);
3353  EXPECT_TRUE(resourcesReleased);
3354  EXPECT_FALSE(wasDestructed);
3355  DestructableMock* ptr = inner.release();
3356  EXPECT_TRUE(resourcesReleased);
3357  EXPECT_FALSE(wasDestructed);
3359  }
3360  // inner is destructed
3361  EXPECT_TRUE(resourcesReleased);
3362  EXPECT_FALSE(wasDestructed);
3363  }
3364  // outer is destructed
3365  EXPECT_TRUE(resourcesReleased);
3366  EXPECT_TRUE(wasDestructed);
3367 }
3368 
3369 TEST(WeakIntrusivePtrTest, givenStackObject_whenReclaimed_thenCrashes) {
3370  // This would cause very weird bugs on destruction.
3371  // Better to crash early on creation.
3372  SomeClass obj;
3373  weak_intrusive_ptr<SomeClass> ptr = make_invalid_weak<SomeClass>();
3374  EXPECT_ANY_THROW(ptr = weak_intrusive_ptr<SomeClass>::reclaim(&obj));
3375 }
intrusive_ptr<T> is an alternative to shared_ptr<T> that has better performance because it does the r...
Definition: intrusive_ptr.h:35
TTarget * release() noexcept
Returns an owning (!) pointer to the underlying object and makes the intrusive_ptr instance invalid...
TTarget * release() noexcept
Returns an owning (but still only weakly referenced) pointer to the underlying object and makes the w...