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