xref: /aosp_15_r20/external/cronet/base/memory/ref_counted_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/memory/ref_counted.h"
6 
7 #include <type_traits>
8 #include <utility>
9 
10 #include "base/memory/raw_ptr.h"
11 #include "base/test/gtest_util.h"
12 #include "build/build_config.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace base {
16 namespace subtle {
17 namespace {
18 
19 class SelfAssign : public base::RefCounted<SelfAssign> {
20  protected:
21   virtual ~SelfAssign() = default;
22 
23  private:
24   friend class base::RefCounted<SelfAssign>;
25 };
26 
27 class Derived : public SelfAssign {
28  protected:
29   ~Derived() override = default;
30 
31  private:
32   friend class base::RefCounted<Derived>;
33 };
34 
35 class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> {
36  public:
CheckDerivedMemberAccess()37   CheckDerivedMemberAccess() {
38     // This shouldn't compile if we don't have access to the member variable.
39     SelfAssign** pptr = &ptr_;
40     EXPECT_EQ(*pptr, ptr_);
41   }
42 };
43 
44 class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> {
45  public:
ScopedRefPtrToSelf()46   ScopedRefPtrToSelf() : self_ptr_(this) {}
47 
was_destroyed()48   static bool was_destroyed() { return was_destroyed_; }
49 
reset_was_destroyed()50   static void reset_was_destroyed() { was_destroyed_ = false; }
51 
52   scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
53 
54  private:
55   friend class base::RefCounted<ScopedRefPtrToSelf>;
~ScopedRefPtrToSelf()56   ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
57 
58   static bool was_destroyed_;
59 };
60 
61 bool ScopedRefPtrToSelf::was_destroyed_ = false;
62 
63 class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
64  public:
ScopedRefPtrCountBase()65   ScopedRefPtrCountBase() { ++constructor_count_; }
66 
constructor_count()67   static int constructor_count() { return constructor_count_; }
68 
destructor_count()69   static int destructor_count() { return destructor_count_; }
70 
reset_count()71   static void reset_count() {
72     constructor_count_ = 0;
73     destructor_count_ = 0;
74   }
75 
76  protected:
~ScopedRefPtrCountBase()77   virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
78 
79  private:
80   friend class base::RefCounted<ScopedRefPtrCountBase>;
81 
82   static int constructor_count_;
83   static int destructor_count_;
84 };
85 
86 int ScopedRefPtrCountBase::constructor_count_ = 0;
87 int ScopedRefPtrCountBase::destructor_count_ = 0;
88 
89 class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
90  public:
ScopedRefPtrCountDerived()91   ScopedRefPtrCountDerived() { ++constructor_count_; }
92 
constructor_count()93   static int constructor_count() { return constructor_count_; }
94 
destructor_count()95   static int destructor_count() { return destructor_count_; }
96 
reset_count()97   static void reset_count() {
98     constructor_count_ = 0;
99     destructor_count_ = 0;
100   }
101 
102  protected:
~ScopedRefPtrCountDerived()103   ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
104 
105  private:
106   friend class base::RefCounted<ScopedRefPtrCountDerived>;
107 
108   static int constructor_count_;
109   static int destructor_count_;
110 };
111 
112 int ScopedRefPtrCountDerived::constructor_count_ = 0;
113 int ScopedRefPtrCountDerived::destructor_count_ = 0;
114 
115 class Other : public base::RefCounted<Other> {
116  private:
117   friend class base::RefCounted<Other>;
118 
119   ~Other() = default;
120 };
121 
122 class HasPrivateDestructorWithDeleter;
123 
124 struct Deleter {
125   static void Destruct(const HasPrivateDestructorWithDeleter* x);
126 };
127 
128 class HasPrivateDestructorWithDeleter
129     : public base::RefCounted<HasPrivateDestructorWithDeleter, Deleter> {
130  public:
131   HasPrivateDestructorWithDeleter() = default;
132 
133  private:
134   friend struct Deleter;
135   ~HasPrivateDestructorWithDeleter() = default;
136 };
137 
Destruct(const HasPrivateDestructorWithDeleter * x)138 void Deleter::Destruct(const HasPrivateDestructorWithDeleter* x) {
139   delete x;
140 }
141 
Overloaded(scoped_refptr<Other> other)142 scoped_refptr<Other> Overloaded(scoped_refptr<Other> other) {
143   return other;
144 }
145 
Overloaded(scoped_refptr<SelfAssign> self_assign)146 scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) {
147   return self_assign;
148 }
149 
150 class InitialRefCountIsOne : public base::RefCounted<InitialRefCountIsOne> {
151  public:
152   REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
153 
154   InitialRefCountIsOne() = default;
155 
156  private:
157   friend class base::RefCounted<InitialRefCountIsOne>;
158   ~InitialRefCountIsOne() = default;
159 };
160 
161 // Checks that the scoped_refptr is null before the reference counted object is
162 // destroyed.
163 class CheckRefptrNull : public base::RefCounted<CheckRefptrNull> {
164  public:
165   // Set the last scoped_refptr that will have a reference to this object.
set_scoped_refptr(scoped_refptr<CheckRefptrNull> * ptr)166   void set_scoped_refptr(scoped_refptr<CheckRefptrNull>* ptr) { ptr_ = ptr; }
167 
168  protected:
~CheckRefptrNull()169   virtual ~CheckRefptrNull() {
170     EXPECT_NE(ptr_, nullptr);
171     EXPECT_EQ(ptr_->get(), nullptr);
172   }
173 
174  private:
175   friend class base::RefCounted<CheckRefptrNull>;
176 
177   raw_ptr<scoped_refptr<CheckRefptrNull>> ptr_ = nullptr;
178 };
179 
180 }  // namespace
181 
TEST(RefCountedUnitTest,TestSelfAssignment)182 TEST(RefCountedUnitTest, TestSelfAssignment) {
183   SelfAssign* p = new SelfAssign;
184   scoped_refptr<SelfAssign> var(p);
185   var = *&var;  // The *& defeats Clang's -Wself-assign warning.
186   EXPECT_EQ(var.get(), p);
187   var = std::move(var);
188   EXPECT_EQ(var.get(), p);
189   var.swap(var);
190   EXPECT_EQ(var.get(), p);
191   swap(var, var);
192   EXPECT_EQ(var.get(), p);
193 }
194 
TEST(RefCountedUnitTest,ScopedRefPtrMemberAccess)195 TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
196   CheckDerivedMemberAccess check;
197 }
198 
TEST(RefCountedUnitTest,ScopedRefPtrToSelfPointerAssignment)199 TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
200   ScopedRefPtrToSelf::reset_was_destroyed();
201 
202   ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
203   EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
204   check->self_ptr_ = nullptr;
205   EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
206 }
207 
TEST(RefCountedUnitTest,ScopedRefPtrToSelfMoveAssignment)208 TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
209   ScopedRefPtrToSelf::reset_was_destroyed();
210 
211   ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
212   EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
213   // Releasing |check->self_ptr_| will delete |check|.
214   // The move assignment operator must assign |check->self_ptr_| first then
215   // release |check->self_ptr_|.
216   check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
217   EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
218 }
219 
TEST(RefCountedUnitTest,BooleanTesting)220 TEST(RefCountedUnitTest, BooleanTesting) {
221   scoped_refptr<SelfAssign> ptr_to_an_instance = new SelfAssign;
222   EXPECT_TRUE(ptr_to_an_instance);
223   EXPECT_FALSE(!ptr_to_an_instance);
224 
225   if (ptr_to_an_instance) {
226   } else {
227     ADD_FAILURE() << "Pointer to an instance should result in true.";
228   }
229 
230   if (!ptr_to_an_instance) {  // check for operator!().
231     ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
232   }
233 
234   scoped_refptr<SelfAssign> null_ptr;
235   EXPECT_FALSE(null_ptr);
236   EXPECT_TRUE(!null_ptr);
237 
238   if (null_ptr) {
239     ADD_FAILURE() << "Null pointer should result in false.";
240   }
241 
242   if (!null_ptr) {  // check for operator!().
243   } else {
244     ADD_FAILURE() << "Null pointer should result in !x being true.";
245   }
246 }
247 
TEST(RefCountedUnitTest,Equality)248 TEST(RefCountedUnitTest, Equality) {
249   scoped_refptr<SelfAssign> p1(new SelfAssign);
250   scoped_refptr<SelfAssign> p2(new SelfAssign);
251 
252   EXPECT_EQ(p1, p1);
253   EXPECT_EQ(p1.get(), p1);
254   EXPECT_EQ(p1, p1.get());
255 
256   EXPECT_EQ(p2, p2);
257   EXPECT_EQ(p2.get(), p2);
258   EXPECT_EQ(p2, p2.get());
259 
260   EXPECT_NE(p1, p2);
261   EXPECT_NE(p1.get(), p2);
262   EXPECT_NE(p1, p2.get());
263 
264   EXPECT_NE(p2, p1);
265   EXPECT_NE(p2.get(), p1);
266   EXPECT_NE(p2, p1.get());
267 }
268 
TEST(RefCountedUnitTest,Ordering)269 TEST(RefCountedUnitTest, Ordering) {
270   scoped_refptr<SelfAssign> p1(new SelfAssign);
271   scoped_refptr<SelfAssign> p2(new SelfAssign);
272   EXPECT_NE(p1, p2);
273 
274   if (p1.get() > p2.get()) {
275     p1.swap(p2);
276   }
277 
278   EXPECT_LT(p1, p2);
279   EXPECT_LT(p1.get(), p2);
280   EXPECT_LT(p1, p2.get());
281 
282   EXPECT_GT(p2, p1);
283   EXPECT_GT(p2.get(), p1);
284   EXPECT_GT(p2, p1.get());
285 }
286 
TEST(RefCountedUnitTest,NullptrEquality)287 TEST(RefCountedUnitTest, NullptrEquality) {
288   scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign);
289   scoped_refptr<SelfAssign> ptr_to_nullptr;
290 
291   EXPECT_NE(nullptr, ptr_to_an_instance);
292   EXPECT_NE(ptr_to_an_instance, nullptr);
293   EXPECT_EQ(nullptr, ptr_to_nullptr);
294   EXPECT_EQ(ptr_to_nullptr, nullptr);
295 }
296 
TEST(RefCountedUnitTest,NullptrOrdering)297 TEST(RefCountedUnitTest, NullptrOrdering) {
298   scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign);
299 
300   EXPECT_LT(nullptr, ptr_to_an_instance);
301   EXPECT_GT(ptr_to_an_instance, nullptr);
302 }
303 
TEST(RefCountedUnitTest,ConvertibleEquality)304 TEST(RefCountedUnitTest, ConvertibleEquality) {
305   scoped_refptr<Derived> p1(new Derived);
306   scoped_refptr<SelfAssign> p2;
307 
308   EXPECT_NE(p1, p2);
309   EXPECT_NE(p2, p1);
310 
311   p2 = p1;
312 
313   EXPECT_EQ(p1, p2);
314   EXPECT_EQ(p2, p1);
315 }
316 
TEST(RefCountedUnitTest,MoveAssignment1)317 TEST(RefCountedUnitTest, MoveAssignment1) {
318   ScopedRefPtrCountBase::reset_count();
319 
320   {
321     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
322     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
323     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
324     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
325 
326     {
327       scoped_refptr<ScopedRefPtrCountBase> p2;
328 
329       p2 = std::move(p1);
330       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
331       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
332       EXPECT_EQ(nullptr, p1.get());
333       EXPECT_EQ(raw, p2.get());
334 
335       // p2 goes out of scope.
336     }
337     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
338     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
339 
340     // p1 goes out of scope.
341   }
342   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
343   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
344 }
345 
TEST(RefCountedUnitTest,MoveAssignment2)346 TEST(RefCountedUnitTest, MoveAssignment2) {
347   ScopedRefPtrCountBase::reset_count();
348 
349   {
350     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
351     scoped_refptr<ScopedRefPtrCountBase> p1;
352     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
353     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
354 
355     {
356       scoped_refptr<ScopedRefPtrCountBase> p2(raw);
357       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
358       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
359 
360       p1 = std::move(p2);
361       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
362       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
363       EXPECT_EQ(raw, p1.get());
364       EXPECT_EQ(nullptr, p2.get());
365 
366       // p2 goes out of scope.
367     }
368     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
369     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
370 
371     // p1 goes out of scope.
372   }
373   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
374   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
375 }
376 
TEST(RefCountedUnitTest,MoveAssignmentSameInstance1)377 TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
378   ScopedRefPtrCountBase::reset_count();
379 
380   {
381     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
382     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
383     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
384     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
385 
386     {
387       scoped_refptr<ScopedRefPtrCountBase> p2(p1);
388       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
389       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
390 
391       p1 = std::move(p2);
392       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
393       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
394       EXPECT_EQ(raw, p1.get());
395       EXPECT_EQ(nullptr, p2.get());
396 
397       // p2 goes out of scope.
398     }
399     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
400     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
401 
402     // p1 goes out of scope.
403   }
404   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
405   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
406 }
407 
TEST(RefCountedUnitTest,MoveAssignmentSameInstance2)408 TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
409   ScopedRefPtrCountBase::reset_count();
410 
411   {
412     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
413     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
414     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
415     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
416 
417     {
418       scoped_refptr<ScopedRefPtrCountBase> p2(p1);
419       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
420       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
421 
422       p2 = std::move(p1);
423       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
424       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
425       EXPECT_EQ(nullptr, p1.get());
426       EXPECT_EQ(raw, p2.get());
427 
428       // p2 goes out of scope.
429     }
430     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
431     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
432 
433     // p1 goes out of scope.
434   }
435   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
436   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
437 }
438 
TEST(RefCountedUnitTest,MoveAssignmentDifferentInstances)439 TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
440   ScopedRefPtrCountBase::reset_count();
441 
442   {
443     ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
444     scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
445     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
446     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
447 
448     {
449       ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
450       scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
451       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
452       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
453 
454       p1 = std::move(p2);
455       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
456       EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
457       EXPECT_EQ(raw2, p1.get());
458       EXPECT_EQ(nullptr, p2.get());
459 
460       // p2 goes out of scope.
461     }
462     EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
463     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
464 
465     // p1 goes out of scope.
466   }
467   EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
468   EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
469 }
470 
TEST(RefCountedUnitTest,MoveAssignmentSelfMove)471 TEST(RefCountedUnitTest, MoveAssignmentSelfMove) {
472   ScopedRefPtrCountBase::reset_count();
473 
474   {
475     ScopedRefPtrCountBase* raw = new ScopedRefPtrCountBase;
476     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
477     scoped_refptr<ScopedRefPtrCountBase>& p1_ref = p1;
478 
479     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
480     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
481 
482     p1 = std::move(p1_ref);
483 
484     // |p1| is "valid but unspecified", so don't bother inspecting its
485     // contents, just ensure that we don't crash.
486   }
487 
488   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
489   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
490 }
491 
TEST(RefCountedUnitTest,MoveAssignmentDerived)492 TEST(RefCountedUnitTest, MoveAssignmentDerived) {
493   ScopedRefPtrCountBase::reset_count();
494   ScopedRefPtrCountDerived::reset_count();
495 
496   {
497     ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
498     scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
499     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
500     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
501     EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
502     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
503 
504     {
505       ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
506       scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
507       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
508       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
509       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
510       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
511 
512       p1 = std::move(p2);
513       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
514       EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
515       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
516       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
517       EXPECT_EQ(raw2, p1.get());
518       EXPECT_EQ(nullptr, p2.get());
519 
520       // p2 goes out of scope.
521     }
522     EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
523     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
524     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
525     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
526 
527     // p1 goes out of scope.
528   }
529   EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
530   EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
531   EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
532   EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
533 }
534 
TEST(RefCountedUnitTest,MoveConstructor)535 TEST(RefCountedUnitTest, MoveConstructor) {
536   ScopedRefPtrCountBase::reset_count();
537 
538   {
539     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
540     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
541     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
542     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
543 
544     {
545       scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
546       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
547       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
548       EXPECT_EQ(nullptr, p1.get());
549       EXPECT_EQ(raw, p2.get());
550 
551       // p2 goes out of scope.
552     }
553     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
554     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
555 
556     // p1 goes out of scope.
557   }
558   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
559   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
560 }
561 
TEST(RefCountedUnitTest,MoveConstructorDerived)562 TEST(RefCountedUnitTest, MoveConstructorDerived) {
563   ScopedRefPtrCountBase::reset_count();
564   ScopedRefPtrCountDerived::reset_count();
565 
566   {
567     ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
568     scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
569     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
570     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
571     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
572     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
573 
574     {
575       scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
576       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
577       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
578       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
579       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
580       EXPECT_EQ(nullptr, p1.get());
581       EXPECT_EQ(raw1, p2.get());
582 
583       // p2 goes out of scope.
584     }
585     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
586     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
587     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
588     EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
589 
590     // p1 goes out of scope.
591   }
592   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
593   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
594   EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
595   EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
596 }
597 
TEST(RefCountedUnitTest,TestOverloadResolutionCopy)598 TEST(RefCountedUnitTest, TestOverloadResolutionCopy) {
599   const scoped_refptr<Derived> derived(new Derived);
600   const scoped_refptr<SelfAssign> expected(derived);
601   EXPECT_EQ(expected, Overloaded(derived));
602 
603   const scoped_refptr<Other> other(new Other);
604   EXPECT_EQ(other, Overloaded(other));
605 }
606 
TEST(RefCountedUnitTest,TestOverloadResolutionMove)607 TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
608   scoped_refptr<Derived> derived(new Derived);
609   const scoped_refptr<SelfAssign> expected(derived);
610   EXPECT_EQ(expected, Overloaded(std::move(derived)));
611 
612   scoped_refptr<Other> other(new Other);
613   const scoped_refptr<Other> other2(other);
614   EXPECT_EQ(other2, Overloaded(std::move(other)));
615 }
616 
TEST(RefCountedUnitTest,TestMakeRefCounted)617 TEST(RefCountedUnitTest, TestMakeRefCounted) {
618   scoped_refptr<Derived> derived = new Derived;
619   EXPECT_TRUE(derived->HasOneRef());
620   derived.reset();
621 
622   scoped_refptr<Derived> derived2 = base::MakeRefCounted<Derived>();
623   EXPECT_TRUE(derived2->HasOneRef());
624   derived2.reset();
625 }
626 
TEST(RefCountedUnitTest,TestInitialRefCountIsOne)627 TEST(RefCountedUnitTest, TestInitialRefCountIsOne) {
628   scoped_refptr<InitialRefCountIsOne> obj =
629       base::MakeRefCounted<InitialRefCountIsOne>();
630   EXPECT_TRUE(obj->HasOneRef());
631   obj.reset();
632 
633   scoped_refptr<InitialRefCountIsOne> obj2 =
634       base::AdoptRef(new InitialRefCountIsOne);
635   EXPECT_TRUE(obj2->HasOneRef());
636   obj2.reset();
637 
638   scoped_refptr<Other> obj3 = base::MakeRefCounted<Other>();
639   EXPECT_TRUE(obj3->HasOneRef());
640   obj3.reset();
641 }
642 
TEST(RefCountedUnitTest,TestPrivateDestructorWithDeleter)643 TEST(RefCountedUnitTest, TestPrivateDestructorWithDeleter) {
644   // Ensure that RefCounted doesn't need the access to the pointee dtor when
645   // a custom deleter is given.
646   scoped_refptr<HasPrivateDestructorWithDeleter> obj =
647       base::MakeRefCounted<HasPrivateDestructorWithDeleter>();
648 }
649 
TEST(RefCountedUnitTest,TestReset)650 TEST(RefCountedUnitTest, TestReset) {
651   ScopedRefPtrCountBase::reset_count();
652 
653   // Create ScopedRefPtrCountBase that is referenced by |obj1| and |obj2|.
654   scoped_refptr<ScopedRefPtrCountBase> obj1 =
655       base::MakeRefCounted<ScopedRefPtrCountBase>();
656   scoped_refptr<ScopedRefPtrCountBase> obj2 = obj1;
657   EXPECT_NE(obj1.get(), nullptr);
658   EXPECT_NE(obj2.get(), nullptr);
659   EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
660   EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0);
661 
662   // Check that calling reset() on |obj1| resets it. |obj2| still has a
663   // reference to the ScopedRefPtrCountBase so it shouldn't be reset.
664   obj1.reset();
665   EXPECT_EQ(obj1.get(), nullptr);
666   EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
667   EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0);
668 
669   // Check that calling reset() on |obj2| resets it and causes the deletion of
670   // the ScopedRefPtrCountBase.
671   obj2.reset();
672   EXPECT_EQ(obj2.get(), nullptr);
673   EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
674   EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 1);
675 }
676 
TEST(RefCountedUnitTest,TestResetAlreadyNull)677 TEST(RefCountedUnitTest, TestResetAlreadyNull) {
678   // Check that calling reset() on a null scoped_refptr does nothing.
679   scoped_refptr<ScopedRefPtrCountBase> obj;
680   obj.reset();
681   // |obj| should still be null after calling reset().
682   EXPECT_EQ(obj.get(), nullptr);
683 }
684 
TEST(RefCountedUnitTest,TestResetByNullptrAssignment)685 TEST(RefCountedUnitTest, TestResetByNullptrAssignment) {
686   // Check that assigning nullptr resets the object.
687   auto obj = base::MakeRefCounted<ScopedRefPtrCountBase>();
688   EXPECT_NE(obj.get(), nullptr);
689 
690   obj = nullptr;
691   EXPECT_EQ(obj.get(), nullptr);
692 }
693 
TEST(RefCountedUnitTest,CheckScopedRefptrNullBeforeObjectDestruction)694 TEST(RefCountedUnitTest, CheckScopedRefptrNullBeforeObjectDestruction) {
695   scoped_refptr<CheckRefptrNull> obj = base::MakeRefCounted<CheckRefptrNull>();
696   obj->set_scoped_refptr(&obj);
697 
698   // Check that when reset() is called the scoped_refptr internal pointer is set
699   // to null before the reference counted object is destroyed. This check is
700   // done by the CheckRefptrNull destructor.
701   obj.reset();
702   EXPECT_EQ(obj.get(), nullptr);
703 }
704 
TEST(RefCountedDeathTest,TestAdoptRef)705 TEST(RefCountedDeathTest, TestAdoptRef) {
706   // Check that WrapRefCounted() DCHECKs if passed a type that defines
707   // REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE.
708   EXPECT_DCHECK_DEATH(base::WrapRefCounted(new InitialRefCountIsOne));
709 
710   // Check that AdoptRef() DCHECKs if passed a nullptr.
711   InitialRefCountIsOne* ptr = nullptr;
712   EXPECT_DCHECK_DEATH(base::AdoptRef(ptr));
713 
714   // Check that AdoptRef() DCHECKs if passed an object that doesn't need to be
715   // adopted.
716   scoped_refptr<InitialRefCountIsOne> obj =
717       base::MakeRefCounted<InitialRefCountIsOne>();
718   EXPECT_DCHECK_DEATH(base::AdoptRef(obj.get()));
719 }
720 
721 #if defined(ARCH_CPU_64_BITS)
722 class RefCountedOverflowTest : public ::testing::Test {
723  public:
GetMutableRefCount(RefCountedBase * ref_counted)724   static uint32_t& GetMutableRefCount(RefCountedBase* ref_counted) {
725     return ref_counted->ref_count_;
726   }
727 
GetMutableRefCount(RefCountedThreadSafeBase * ref_counted)728   static std::atomic_int& GetMutableRefCount(
729       RefCountedThreadSafeBase* ref_counted) {
730     return ref_counted->ref_count_.ref_count_;
731   }
732 };
733 
TEST_F(RefCountedOverflowTest,NonThreadSafeStartFromZero)734 TEST_F(RefCountedOverflowTest, NonThreadSafeStartFromZero) {
735   class Overflow : public base::RefCounted<Overflow> {
736    public:
737     Overflow() { EXPECT_FALSE(HasOneRef()); }
738 
739    private:
740     friend class base::RefCounted<Overflow>;
741     ~Overflow() = default;
742   };
743 
744   auto p = base::MakeRefCounted<Overflow>();
745   GetMutableRefCount(p.get()) = std::numeric_limits<uint32_t>::max();
746   EXPECT_CHECK_DEATH(p->AddRef());
747   // Ensure `p` doesn't leak and fail lsan builds.
748   GetMutableRefCount(p.get()) = 1;
749 }
750 
TEST_F(RefCountedOverflowTest,NonThreadSafeStartFromOne)751 TEST_F(RefCountedOverflowTest, NonThreadSafeStartFromOne) {
752   class Overflow : public base::RefCounted<Overflow> {
753    public:
754     REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
755 
756     Overflow() { EXPECT_TRUE(HasOneRef()); }
757 
758    private:
759     friend class base::RefCounted<Overflow>;
760     ~Overflow() = default;
761   };
762 
763   auto p = base::MakeRefCounted<Overflow>();
764   GetMutableRefCount(p.get()) = std::numeric_limits<uint32_t>::max();
765   EXPECT_CHECK_DEATH(p->AddRef());
766   // Ensure `p` doesn't leak and fail lsan builds.
767   GetMutableRefCount(p.get()) = 1;
768 }
769 
TEST_F(RefCountedOverflowTest,ThreadSafeStartFromZero)770 TEST_F(RefCountedOverflowTest, ThreadSafeStartFromZero) {
771   class Overflow : public base::RefCountedThreadSafe<Overflow> {
772    public:
773     Overflow() { EXPECT_FALSE(HasOneRef()); }
774 
775    private:
776     friend class base::RefCountedThreadSafe<Overflow>;
777     ~Overflow() = default;
778   };
779 
780   auto p = base::MakeRefCounted<Overflow>();
781   GetMutableRefCount(p.get()) = std::numeric_limits<int>::max();
782   EXPECT_CHECK_DEATH(p->AddRef());
783   // Ensure `p` doesn't leak and fail lsan builds.
784   GetMutableRefCount(p.get()) = 1;
785 }
786 
TEST_F(RefCountedOverflowTest,ThreadSafeStartFromOne)787 TEST_F(RefCountedOverflowTest, ThreadSafeStartFromOne) {
788   class Overflow : public base::RefCountedThreadSafe<Overflow> {
789    public:
790     REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
791 
792     Overflow() { EXPECT_TRUE(HasOneRef()); }
793 
794    private:
795     friend class base::RefCountedThreadSafe<Overflow>;
796     ~Overflow() = default;
797   };
798 
799   auto p = base::MakeRefCounted<Overflow>();
800   GetMutableRefCount(p.get()) = std::numeric_limits<int>::max();
801   EXPECT_CHECK_DEATH(p->AddRef());
802   // Ensure `p` doesn't leak and fail lsan builds.
803   GetMutableRefCount(p.get()) = 1;
804 }
805 #endif
806 
807 }  // namespace subtle
808 }  // namespace base
809