1#include <c10/util/intrusive_ptr.h>
2
3#include <gtest/gtest.h>
4#include <map>
5#include <memory>
6#include <set>
7#include <unordered_map>
8#include <unordered_set>
9
10using c10::intrusive_ptr;
11using c10::intrusive_ptr_target;
12using c10::make_intrusive;
13using c10::weak_intrusive_ptr;
14
15#ifndef _MSC_VER
16#pragma GCC diagnostic ignored "-Wpragmas"
17#pragma GCC diagnostic ignored "-Wunknown-warning-option"
18#pragma GCC diagnostic ignored "-Wself-move"
19#endif
20
21#ifdef __clang__
22#pragma clang diagnostic ignored "-Wself-assign-overloaded"
23#endif
24
25namespace {
26class SomeClass0Parameters : public intrusive_ptr_target {};
27class SomeClass1Parameter : public intrusive_ptr_target {
28 public:
29 SomeClass1Parameter(int param_) : param(param_) {}
30 int param;
31};
32class SomeClass2Parameters : public intrusive_ptr_target {
33 public:
34 SomeClass2Parameters(int param1_, int param2_)
35 : param1(param1_), param2(param2_) {}
36 int param1;
37 int param2;
38};
39using SomeClass = SomeClass0Parameters;
40struct SomeBaseClass : public intrusive_ptr_target {
41 SomeBaseClass(int v_) : v(v_) {}
42 int v;
43};
44struct SomeChildClass : SomeBaseClass {
45 SomeChildClass(int v) : SomeBaseClass(v) {}
46};
47
48class DestructableMock : public intrusive_ptr_target {
49 public:
50 DestructableMock(bool* resourcesReleased, bool* wasDestructed)
51 : resourcesReleased_(resourcesReleased), wasDestructed_(wasDestructed) {}
52
53 ~DestructableMock() override {
54 *resourcesReleased_ = true;
55 *wasDestructed_ = true;
56 }
57
58 void release_resources() override {
59 *resourcesReleased_ = true;
60 }
61
62 private:
63 bool* resourcesReleased_;
64 bool* wasDestructed_;
65};
66
67class ChildDestructableMock final : public DestructableMock {
68 public:
69 ChildDestructableMock(bool* resourcesReleased, bool* wasDestructed)
70 : DestructableMock(resourcesReleased, wasDestructed) {}
71};
72class NullType1 final {
73 static SomeClass singleton_;
74
75 public:
76 static constexpr SomeClass* singleton() {
77 return &singleton_;
78 }
79};
80SomeClass NullType1::singleton_;
81class NullType2 final {
82 static SomeClass singleton_;
83
84 public:
85 static constexpr SomeClass* singleton() {
86 return &singleton_;
87 }
88};
89SomeClass NullType2::singleton_;
90static_assert(NullType1::singleton() != NullType2::singleton(), "");
91} // namespace
92
93static_assert(
94 std::is_same<SomeClass, intrusive_ptr<SomeClass>::element_type>::value,
95 "intrusive_ptr<T>::element_type is wrong");
96
97TEST(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
104TEST(MakeIntrusiveTest, ClassWith1Parameter) {
105 intrusive_ptr<SomeClass1Parameter> var =
106 make_intrusive<SomeClass1Parameter>(5);
107 EXPECT_EQ(5, var->param);
108}
109
110TEST(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
117TEST(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
123TEST(MakeIntrusiveTest, CanAssignToBaseClassPtr) {
124 intrusive_ptr<SomeBaseClass> var = make_intrusive<SomeChildClass>(3);
125 EXPECT_EQ(3, var->v);
126}
127
128TEST(IntrusivePtrTargetTest, whenAllocatedOnStack_thenDoesntCrash) {
129 SomeClass myClass;
130}
131
132TEST(IntrusivePtrTest, givenValidPtr_whenCallingGet_thenReturnsObject) {
133 intrusive_ptr<SomeClass1Parameter> obj =
134 make_intrusive<SomeClass1Parameter>(5);
135 EXPECT_EQ(5, obj.get()->param);
136}
137
138TEST(IntrusivePtrTest, givenValidPtr_whenCallingConstGet_thenReturnsObject) {
139 const intrusive_ptr<SomeClass1Parameter> obj =
140 make_intrusive<SomeClass1Parameter>(5);
141 EXPECT_EQ(5, obj.get()->param);
142}
143
144TEST(IntrusivePtrTest, givenInvalidPtr_whenCallingGet_thenReturnsNullptr) {
145 intrusive_ptr<SomeClass1Parameter> obj;
146 EXPECT_EQ(nullptr, obj.get());
147}
148
149TEST(IntrusivePtrTest, givenNullptr_whenCallingGet_thenReturnsNullptr) {
150 intrusive_ptr<SomeClass1Parameter> obj(nullptr);
151 EXPECT_EQ(nullptr, obj.get());
152}
153
154TEST(IntrusivePtrTest, givenValidPtr_whenDereferencing_thenReturnsObject) {
155 intrusive_ptr<SomeClass1Parameter> obj =
156 make_intrusive<SomeClass1Parameter>(5);
157 EXPECT_EQ(5, (*obj).param);
158}
159
160TEST(IntrusivePtrTest, givenValidPtr_whenConstDereferencing_thenReturnsObject) {
161 const intrusive_ptr<SomeClass1Parameter> obj =
162 make_intrusive<SomeClass1Parameter>(5);
163 EXPECT_EQ(5, (*obj).param);
164}
165
166TEST(IntrusivePtrTest, givenValidPtr_whenArrowDereferencing_thenReturnsObject) {
167 intrusive_ptr<SomeClass1Parameter> obj =
168 make_intrusive<SomeClass1Parameter>(3);
169 EXPECT_EQ(3, obj->param);
170}
171
172TEST(
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
180TEST(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
188TEST(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
196TEST(
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
206TEST(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
213TEST(
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
222TEST(
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
231TEST(
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
241TEST(
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
251TEST(
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
262TEST(
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
272TEST(
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
281TEST(
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
292TEST(
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
302TEST(
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
316TEST(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
324TEST(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
331TEST(
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
341TEST(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
348TEST(
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
357TEST(
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
366TEST(
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
375TEST(
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
384TEST(
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
393TEST(
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
404TEST(
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
414TEST(
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
427TEST(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
434TEST(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
441TEST(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
447TEST(
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
455TEST(
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
465TEST(
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
474TEST(
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
482TEST(
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
490TEST(
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
503TEST(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
512TEST(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
519TEST(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
526TEST(
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
535TEST(
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
545TEST(
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
553TEST(
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
561TEST(
562 IntrusivePtrTest,
563 givenPtr_whenCopyConstructingToBaseClassFromInvalidPtr_thenNewInstanceInvalid) {
564 intrusive_ptr<SomeChildClass> obj1;
565 intrusive_ptr<SomeBaseClass> obj2 = obj1;
566 EXPECT_FALSE(obj2.defined());
567}
568
569TEST(
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
581TEST(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
591TEST(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
601TEST(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
611TEST(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
621TEST(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
631TEST(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
641TEST(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
649TEST(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
657TEST(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
663TEST(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
669TEST(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
675TEST(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
687TEST(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
699TEST(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
707TEST(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
715TEST(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
722TEST(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
729TEST(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
736TEST(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
743TEST(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
751TEST(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
759TEST(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
768TEST(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
777TEST(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
785TEST(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
795TEST(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
802TEST(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
809TEST(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
816TEST(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
823TEST(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
830TEST(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
843TEST(
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
859TEST(
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
875TEST(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
891TEST(
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
909TEST(
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
932TEST(
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
955TEST(
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
978TEST(
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
996TEST(
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
1014TEST(
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
1035TEST(
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
1055TEST(
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
1072TEST(
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
1089TEST(
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
1112TEST(
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
1135TEST(
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
1157TEST(
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
1179TEST(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
1195TEST(
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
1213TEST(
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
1236TEST(
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
1259TEST(
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
1282TEST(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
1294TEST(
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
1312TEST(
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
1330TEST(
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
1349TEST(
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
1364TEST(IntrusivePtrTest, AllowsMoveConstructingToConst) {
1365 intrusive_ptr<SomeClass> a = make_intrusive<SomeClass>();
1366 intrusive_ptr<const SomeClass> b = std::move(a);
1367}
1368
1369TEST(IntrusivePtrTest, AllowsCopyConstructingToConst) {
1370 intrusive_ptr<SomeClass> a = make_intrusive<SomeClass>();
1371 intrusive_ptr<const SomeClass> b = a;
1372}
1373
1374TEST(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
1380TEST(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
1386TEST(IntrusivePtrTest, givenNewPtr_thenHasUseCount1) {
1387 intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1388 EXPECT_EQ(1, obj.use_count());
1389}
1390
1391TEST(IntrusivePtrTest, givenNewPtr_thenIsUnique) {
1392 intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1393 EXPECT_TRUE(obj.unique());
1394}
1395
1396TEST(IntrusivePtrTest, givenEmptyPtr_thenHasUseCount0) {
1397 intrusive_ptr<SomeClass> obj;
1398 EXPECT_EQ(0, obj.use_count());
1399}
1400
1401TEST(IntrusivePtrTest, givenEmptyPtr_thenIsNotUnique) {
1402 intrusive_ptr<SomeClass> obj;
1403 EXPECT_FALSE(obj.unique());
1404}
1405
1406TEST(IntrusivePtrTest, givenResetPtr_thenHasUseCount0) {
1407 intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1408 obj.reset();
1409 EXPECT_EQ(0, obj.use_count());
1410}
1411
1412TEST(IntrusivePtrTest, givenResetPtr_thenIsNotUnique) {
1413 intrusive_ptr<SomeClass> obj = make_intrusive<SomeClass>();
1414 obj.reset();
1415 EXPECT_FALSE(obj.unique());
1416}
1417
1418TEST(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
1424TEST(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
1430TEST(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
1437TEST(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
1444TEST(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
1451TEST(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
1458TEST(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
1466TEST(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
1474TEST(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
1481TEST(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
1488TEST(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
1495TEST(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
1502TEST(
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
1514TEST(
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
1526TEST(
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
1537TEST(
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
1548TEST(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
1556TEST(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
1564TEST(
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
1576TEST(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
1586TEST(
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
1598TEST(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
1608TEST(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
1615TEST(
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/*
1640TEST(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
1652TEST(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
1662TEST(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
1683namespace {
1684template <class T>
1685struct IntrusiveAndWeak final {
1686 IntrusiveAndWeak(intrusive_ptr<T> ptr_) : ptr(std::move(ptr_)), weak(ptr) {}
1687
1688 intrusive_ptr<T> ptr;
1689 weak_intrusive_ptr<T> weak;
1690};
1691template <class T, class... Args>
1692IntrusiveAndWeak<T> make_weak_intrusive(Args&&... args) {
1693 return IntrusiveAndWeak<T>(make_intrusive<T>(std::forward<Args>(args)...));
1694}
1695template <class T, class... Args>
1696weak_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}
1700template <
1701 class T,
1702 class NullType = c10::detail::intrusive_target_default_null_type<T>>
1703weak_intrusive_ptr<T, NullType> make_invalid_weak() {
1704 return weak_intrusive_ptr<T, NullType>(intrusive_ptr<T, NullType>());
1705}
1706
1707struct WeakReferenceToSelf : public intrusive_ptr_target {
1708 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
1717static_assert(
1718 std::is_same<SomeClass, weak_intrusive_ptr<SomeClass>::element_type>::value,
1719 "weak_intrusive_ptr<T>::element_type is wrong");
1720
1721TEST(
1722 WeakIntrusivePtrTest,
1723 givenPtr_whenCreatingAndDestructing_thenDoesntCrash) {
1724 IntrusiveAndWeak<SomeClass> var = make_weak_intrusive<SomeClass>();
1725}
1726
1727TEST(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
1733TEST(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
1742TEST(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
1748TEST(
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
1758TEST(
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
1767TEST(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}
1774TEST(
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
1784TEST(
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
1793TEST(
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
1801TEST(
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
1811TEST(
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
1820TEST(
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
1830TEST(
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
1840TEST(
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
1850TEST(
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
1860TEST(
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
1870TEST(
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
1880TEST(
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
1892TEST(
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
1902TEST(
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
1913TEST(
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
1925TEST(
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
1935TEST(
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
1946TEST(
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
1958TEST(
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
1968TEST(
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
1982TEST(
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
1992TEST(
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
2001TEST(
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
2010TEST(
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
2018TEST(
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
2028TEST(
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
2037TEST(
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
2047TEST(
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
2057TEST(
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
2067TEST(
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
2077TEST(
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
2087TEST(
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
2097TEST(
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
2108TEST(
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
2120TEST(
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
2130TEST(
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
2141TEST(
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
2153TEST(
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
2163TEST(
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
2176TEST(
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
2185TEST(
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
2193TEST(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
2199TEST(
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
2207TEST(
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
2215TEST(
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
2226TEST(
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
2235TEST(
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
2244TEST(
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
2252TEST(
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
2260TEST(
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
2272TEST(
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
2282TEST(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
2288TEST(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
2294TEST(
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
2303TEST(
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
2312TEST(
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
2323TEST(
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
2332TEST(
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
2341TEST(
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
2349TEST(
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
2357TEST(
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
2368TEST(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
2378TEST(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
2388TEST(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
2398TEST(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
2408TEST(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
2418TEST(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
2428TEST(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
2436TEST(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
2444TEST(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
2454TEST(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
2464TEST(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
2474TEST(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
2484TEST(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
2492TEST(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
2500TEST(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
2508TEST(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
2516TEST(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
2524TEST(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
2538TEST(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
2552TEST(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
2559TEST(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
2567TEST(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
2575TEST(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
2582TEST(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
2589TEST(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
2596TEST(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
2603TEST(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
2610TEST(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
2618TEST(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
2626TEST(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
2634TEST(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
2642TEST(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
2650TEST(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
2659TEST(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
2668TEST(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
2677TEST(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
2685TEST(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
2695TEST(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
2702TEST(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
2709TEST(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
2716TEST(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
2723TEST(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
2730TEST(WeakIntrusivePtrTest, AllowsMoveConstructingToConst) {
2731 IntrusiveAndWeak<SomeClass> a = make_weak_intrusive<SomeClass>();
2732 weak_intrusive_ptr<const SomeClass> b = std::move(a.weak);
2733}
2734
2735TEST(WeakIntrusivePtrTest, AllowsCopyConstructingToConst) {
2736 IntrusiveAndWeak<SomeClass> a = make_weak_intrusive<SomeClass>();
2737 weak_intrusive_ptr<const SomeClass> b = a.weak;
2738}
2739
2740TEST(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
2746TEST(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
2752TEST(WeakIntrusivePtrTest, givenNewPtr_thenHasUseCount1) {
2753 IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2754 EXPECT_EQ(1, obj.weak.use_count());
2755}
2756
2757TEST(WeakIntrusivePtrTest, givenNewPtr_thenIsNotExpired) {
2758 IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2759 EXPECT_FALSE(obj.weak.expired());
2760}
2761
2762TEST(WeakIntrusivePtrTest, givenInvalidPtr_thenHasUseCount0) {
2763 weak_intrusive_ptr<SomeClass> obj = make_invalid_weak<SomeClass>();
2764 EXPECT_EQ(0, obj.use_count());
2765}
2766
2767TEST(WeakIntrusivePtrTest, givenInvalidPtr_thenIsExpired) {
2768 weak_intrusive_ptr<SomeClass> obj = make_invalid_weak<SomeClass>();
2769 EXPECT_TRUE(obj.expired());
2770}
2771
2772TEST(WeakIntrusivePtrTest, givenWeakOnlyPtr_thenHasUseCount0) {
2773 weak_intrusive_ptr<SomeClass> obj = make_weak_only<SomeClass>();
2774 EXPECT_EQ(0, obj.use_count());
2775}
2776
2777TEST(WeakIntrusivePtrTest, givenWeakOnlyPtr_thenIsExpired) {
2778 weak_intrusive_ptr<SomeClass> obj = make_weak_only<SomeClass>();
2779 EXPECT_TRUE(obj.expired());
2780}
2781
2782TEST(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
2788TEST(WeakIntrusivePtrTest, givenPtr_whenCallingWeakReset_thenIsExpired) {
2789 IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2790 obj.weak.reset();
2791 EXPECT_TRUE(obj.weak.expired());
2792}
2793
2794TEST(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
2800TEST(WeakIntrusivePtrTest, givenPtr_whenCallingStrongReset_thenIsExpired) {
2801 IntrusiveAndWeak<SomeClass> obj = make_weak_intrusive<SomeClass>();
2802 obj.ptr.reset();
2803 EXPECT_TRUE(obj.weak.expired());
2804}
2805
2806TEST(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
2812TEST(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
2818TEST(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
2824TEST(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
2830TEST(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
2837TEST(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
2844TEST(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
2851TEST(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
2858TEST(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
2864TEST(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
2870TEST(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
2876TEST(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
2882TEST(
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
2899TEST(
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
2916TEST(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
2929TEST(
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
2945TEST(
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
2961TEST(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
2977TEST(
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
2995TEST(
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
3018TEST(
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
3041TEST(
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
3064TEST(
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
3082TEST(
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
3100TEST(
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
3121TEST(
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
3141TEST(
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
3158TEST(
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
3175TEST(
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
3198TEST(
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
3221TEST(
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
3243TEST(
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
3265TEST(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
3281TEST(
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
3299TEST(
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
3322TEST(
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
3345TEST(
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
3368TEST(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
3380TEST(
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
3398TEST(
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
3416TEST(
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
3435TEST(
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
3450TEST(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
3457TEST(
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
3466TEST(
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
3499TEST(
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
3526TEST(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
3539TEST(
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