• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(p2, p2);
254 
255   EXPECT_NE(p1, p2);
256   EXPECT_NE(p2, p1);
257 }
258 
TEST(RefCountedUnitTest,NullptrEquality)259 TEST(RefCountedUnitTest, NullptrEquality) {
260   scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign);
261   scoped_refptr<SelfAssign> ptr_to_nullptr;
262 
263   EXPECT_NE(nullptr, ptr_to_an_instance);
264   EXPECT_NE(ptr_to_an_instance, nullptr);
265   EXPECT_EQ(nullptr, ptr_to_nullptr);
266   EXPECT_EQ(ptr_to_nullptr, nullptr);
267 }
268 
TEST(RefCountedUnitTest,ConvertibleEquality)269 TEST(RefCountedUnitTest, ConvertibleEquality) {
270   scoped_refptr<Derived> p1(new Derived);
271   scoped_refptr<SelfAssign> p2;
272 
273   EXPECT_NE(p1, p2);
274   EXPECT_NE(p2, p1);
275 
276   p2 = p1;
277 
278   EXPECT_EQ(p1, p2);
279   EXPECT_EQ(p2, p1);
280 }
281 
TEST(RefCountedUnitTest,MoveAssignment1)282 TEST(RefCountedUnitTest, MoveAssignment1) {
283   ScopedRefPtrCountBase::reset_count();
284 
285   {
286     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
287     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
288     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
289     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
290 
291     {
292       scoped_refptr<ScopedRefPtrCountBase> p2;
293 
294       p2 = std::move(p1);
295       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
296       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
297       EXPECT_EQ(nullptr, p1.get());
298       EXPECT_EQ(raw, p2.get());
299 
300       // p2 goes out of scope.
301     }
302     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
303     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
304 
305     // p1 goes out of scope.
306   }
307   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
308   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
309 }
310 
TEST(RefCountedUnitTest,MoveAssignment2)311 TEST(RefCountedUnitTest, MoveAssignment2) {
312   ScopedRefPtrCountBase::reset_count();
313 
314   {
315     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
316     scoped_refptr<ScopedRefPtrCountBase> p1;
317     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
318     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
319 
320     {
321       scoped_refptr<ScopedRefPtrCountBase> p2(raw);
322       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
323       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
324 
325       p1 = std::move(p2);
326       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
327       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
328       EXPECT_EQ(raw, p1.get());
329       EXPECT_EQ(nullptr, p2.get());
330 
331       // p2 goes out of scope.
332     }
333     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
334     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
335 
336     // p1 goes out of scope.
337   }
338   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
339   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
340 }
341 
TEST(RefCountedUnitTest,MoveAssignmentSameInstance1)342 TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
343   ScopedRefPtrCountBase::reset_count();
344 
345   {
346     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
347     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
348     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
349     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
350 
351     {
352       scoped_refptr<ScopedRefPtrCountBase> p2(p1);
353       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
354       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
355 
356       p1 = std::move(p2);
357       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
358       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
359       EXPECT_EQ(raw, p1.get());
360       EXPECT_EQ(nullptr, p2.get());
361 
362       // p2 goes out of scope.
363     }
364     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
365     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
366 
367     // p1 goes out of scope.
368   }
369   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
370   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
371 }
372 
TEST(RefCountedUnitTest,MoveAssignmentSameInstance2)373 TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
374   ScopedRefPtrCountBase::reset_count();
375 
376   {
377     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
378     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
379     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
380     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
381 
382     {
383       scoped_refptr<ScopedRefPtrCountBase> p2(p1);
384       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
385       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
386 
387       p2 = std::move(p1);
388       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
389       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
390       EXPECT_EQ(nullptr, p1.get());
391       EXPECT_EQ(raw, p2.get());
392 
393       // p2 goes out of scope.
394     }
395     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
396     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
397 
398     // p1 goes out of scope.
399   }
400   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
401   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
402 }
403 
TEST(RefCountedUnitTest,MoveAssignmentDifferentInstances)404 TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
405   ScopedRefPtrCountBase::reset_count();
406 
407   {
408     ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
409     scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
410     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
411     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
412 
413     {
414       ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
415       scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
416       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
417       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
418 
419       p1 = std::move(p2);
420       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
421       EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
422       EXPECT_EQ(raw2, p1.get());
423       EXPECT_EQ(nullptr, p2.get());
424 
425       // p2 goes out of scope.
426     }
427     EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
428     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
429 
430     // p1 goes out of scope.
431   }
432   EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
433   EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
434 }
435 
TEST(RefCountedUnitTest,MoveAssignmentSelfMove)436 TEST(RefCountedUnitTest, MoveAssignmentSelfMove) {
437   ScopedRefPtrCountBase::reset_count();
438 
439   {
440     ScopedRefPtrCountBase* raw = new ScopedRefPtrCountBase;
441     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
442     scoped_refptr<ScopedRefPtrCountBase>& p1_ref = p1;
443 
444     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
445     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
446 
447     p1 = std::move(p1_ref);
448 
449     // |p1| is "valid but unspecified", so don't bother inspecting its
450     // contents, just ensure that we don't crash.
451   }
452 
453   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
454   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
455 }
456 
TEST(RefCountedUnitTest,MoveAssignmentDerived)457 TEST(RefCountedUnitTest, MoveAssignmentDerived) {
458   ScopedRefPtrCountBase::reset_count();
459   ScopedRefPtrCountDerived::reset_count();
460 
461   {
462     ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
463     scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
464     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
465     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
466     EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
467     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
468 
469     {
470       ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
471       scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
472       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
473       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
474       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
475       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
476 
477       p1 = std::move(p2);
478       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
479       EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
480       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
481       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
482       EXPECT_EQ(raw2, p1.get());
483       EXPECT_EQ(nullptr, p2.get());
484 
485       // p2 goes out of scope.
486     }
487     EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
488     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
489     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
490     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
491 
492     // p1 goes out of scope.
493   }
494   EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
495   EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
496   EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
497   EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
498 }
499 
TEST(RefCountedUnitTest,MoveConstructor)500 TEST(RefCountedUnitTest, MoveConstructor) {
501   ScopedRefPtrCountBase::reset_count();
502 
503   {
504     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
505     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
506     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
507     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
508 
509     {
510       scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
511       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
512       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
513       EXPECT_EQ(nullptr, p1.get());
514       EXPECT_EQ(raw, p2.get());
515 
516       // p2 goes out of scope.
517     }
518     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
519     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
520 
521     // p1 goes out of scope.
522   }
523   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
524   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
525 }
526 
TEST(RefCountedUnitTest,MoveConstructorDerived)527 TEST(RefCountedUnitTest, MoveConstructorDerived) {
528   ScopedRefPtrCountBase::reset_count();
529   ScopedRefPtrCountDerived::reset_count();
530 
531   {
532     ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
533     scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
534     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
535     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
536     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
537     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
538 
539     {
540       scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
541       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
542       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
543       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
544       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
545       EXPECT_EQ(nullptr, p1.get());
546       EXPECT_EQ(raw1, p2.get());
547 
548       // p2 goes out of scope.
549     }
550     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
551     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
552     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
553     EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
554 
555     // p1 goes out of scope.
556   }
557   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
558   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
559   EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
560   EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
561 }
562 
TEST(RefCountedUnitTest,TestOverloadResolutionCopy)563 TEST(RefCountedUnitTest, TestOverloadResolutionCopy) {
564   const scoped_refptr<Derived> derived(new Derived);
565   const scoped_refptr<SelfAssign> expected(derived);
566   EXPECT_EQ(expected, Overloaded(derived));
567 
568   const scoped_refptr<Other> other(new Other);
569   EXPECT_EQ(other, Overloaded(other));
570 }
571 
TEST(RefCountedUnitTest,TestOverloadResolutionMove)572 TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
573   scoped_refptr<Derived> derived(new Derived);
574   const scoped_refptr<SelfAssign> expected(derived);
575   EXPECT_EQ(expected, Overloaded(std::move(derived)));
576 
577   scoped_refptr<Other> other(new Other);
578   const scoped_refptr<Other> other2(other);
579   EXPECT_EQ(other2, Overloaded(std::move(other)));
580 }
581 
TEST(RefCountedUnitTest,TestMakeRefCounted)582 TEST(RefCountedUnitTest, TestMakeRefCounted) {
583   scoped_refptr<Derived> derived = new Derived;
584   EXPECT_TRUE(derived->HasOneRef());
585   derived.reset();
586 
587   scoped_refptr<Derived> derived2 = base::MakeRefCounted<Derived>();
588   EXPECT_TRUE(derived2->HasOneRef());
589   derived2.reset();
590 }
591 
TEST(RefCountedUnitTest,TestInitialRefCountIsOne)592 TEST(RefCountedUnitTest, TestInitialRefCountIsOne) {
593   scoped_refptr<InitialRefCountIsOne> obj =
594       base::MakeRefCounted<InitialRefCountIsOne>();
595   EXPECT_TRUE(obj->HasOneRef());
596   obj.reset();
597 
598   scoped_refptr<InitialRefCountIsOne> obj2 =
599       base::AdoptRef(new InitialRefCountIsOne);
600   EXPECT_TRUE(obj2->HasOneRef());
601   obj2.reset();
602 
603   scoped_refptr<Other> obj3 = base::MakeRefCounted<Other>();
604   EXPECT_TRUE(obj3->HasOneRef());
605   obj3.reset();
606 }
607 
TEST(RefCountedUnitTest,TestPrivateDestructorWithDeleter)608 TEST(RefCountedUnitTest, TestPrivateDestructorWithDeleter) {
609   // Ensure that RefCounted doesn't need the access to the pointee dtor when
610   // a custom deleter is given.
611   scoped_refptr<HasPrivateDestructorWithDeleter> obj =
612       base::MakeRefCounted<HasPrivateDestructorWithDeleter>();
613 }
614 
TEST(RefCountedUnitTest,TestReset)615 TEST(RefCountedUnitTest, TestReset) {
616   ScopedRefPtrCountBase::reset_count();
617 
618   // Create ScopedRefPtrCountBase that is referenced by |obj1| and |obj2|.
619   scoped_refptr<ScopedRefPtrCountBase> obj1 =
620       base::MakeRefCounted<ScopedRefPtrCountBase>();
621   scoped_refptr<ScopedRefPtrCountBase> obj2 = obj1;
622   EXPECT_NE(obj1.get(), nullptr);
623   EXPECT_NE(obj2.get(), nullptr);
624   EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
625   EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0);
626 
627   // Check that calling reset() on |obj1| resets it. |obj2| still has a
628   // reference to the ScopedRefPtrCountBase so it shouldn't be reset.
629   obj1.reset();
630   EXPECT_EQ(obj1.get(), nullptr);
631   EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
632   EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0);
633 
634   // Check that calling reset() on |obj2| resets it and causes the deletion of
635   // the ScopedRefPtrCountBase.
636   obj2.reset();
637   EXPECT_EQ(obj2.get(), nullptr);
638   EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
639   EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 1);
640 }
641 
TEST(RefCountedUnitTest,TestResetAlreadyNull)642 TEST(RefCountedUnitTest, TestResetAlreadyNull) {
643   // Check that calling reset() on a null scoped_refptr does nothing.
644   scoped_refptr<ScopedRefPtrCountBase> obj;
645   obj.reset();
646   // |obj| should still be null after calling reset().
647   EXPECT_EQ(obj.get(), nullptr);
648 }
649 
TEST(RefCountedUnitTest,TestResetByNullptrAssignment)650 TEST(RefCountedUnitTest, TestResetByNullptrAssignment) {
651   // Check that assigning nullptr resets the object.
652   auto obj = base::MakeRefCounted<ScopedRefPtrCountBase>();
653   EXPECT_NE(obj.get(), nullptr);
654 
655   obj = nullptr;
656   EXPECT_EQ(obj.get(), nullptr);
657 }
658 
TEST(RefCountedUnitTest,CheckScopedRefptrNullBeforeObjectDestruction)659 TEST(RefCountedUnitTest, CheckScopedRefptrNullBeforeObjectDestruction) {
660   scoped_refptr<CheckRefptrNull> obj = base::MakeRefCounted<CheckRefptrNull>();
661   obj->set_scoped_refptr(&obj);
662 
663   // Check that when reset() is called the scoped_refptr internal pointer is set
664   // to null before the reference counted object is destroyed. This check is
665   // done by the CheckRefptrNull destructor.
666   obj.reset();
667   EXPECT_EQ(obj.get(), nullptr);
668 }
669 
TEST(RefCountedDeathTest,TestAdoptRef)670 TEST(RefCountedDeathTest, TestAdoptRef) {
671   // Check that WrapRefCounted() DCHECKs if passed a type that defines
672   // REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE.
673   EXPECT_DCHECK_DEATH(base::WrapRefCounted(new InitialRefCountIsOne));
674 
675   // Check that AdoptRef() DCHECKs if passed a nullptr.
676   InitialRefCountIsOne* ptr = nullptr;
677   EXPECT_DCHECK_DEATH(base::AdoptRef(ptr));
678 
679   // Check that AdoptRef() DCHECKs if passed an object that doesn't need to be
680   // adopted.
681   scoped_refptr<InitialRefCountIsOne> obj =
682       base::MakeRefCounted<InitialRefCountIsOne>();
683   EXPECT_DCHECK_DEATH(base::AdoptRef(obj.get()));
684 }
685 
686 #if defined(ARCH_CPU_64_BITS)
687 class RefCountedOverflowTest : public ::testing::Test {
688  public:
GetMutableRefCount(RefCountedBase * ref_counted)689   static uint32_t& GetMutableRefCount(RefCountedBase* ref_counted) {
690     return ref_counted->ref_count_;
691   }
692 
GetMutableRefCount(RefCountedThreadSafeBase * ref_counted)693   static std::atomic_int& GetMutableRefCount(
694       RefCountedThreadSafeBase* ref_counted) {
695     return ref_counted->ref_count_.ref_count_;
696   }
697 };
698 
TEST_F(RefCountedOverflowTest,NonThreadSafeStartFromZero)699 TEST_F(RefCountedOverflowTest, NonThreadSafeStartFromZero) {
700   class Overflow : public base::RefCounted<Overflow> {
701    public:
702     Overflow() { EXPECT_FALSE(HasOneRef()); }
703 
704    private:
705     friend class base::RefCounted<Overflow>;
706     ~Overflow() = default;
707   };
708 
709   auto p = base::MakeRefCounted<Overflow>();
710   GetMutableRefCount(p.get()) = std::numeric_limits<uint32_t>::max();
711   EXPECT_CHECK_DEATH(p->AddRef());
712   // Ensure `p` doesn't leak and fail lsan builds.
713   GetMutableRefCount(p.get()) = 1;
714 }
715 
TEST_F(RefCountedOverflowTest,NonThreadSafeStartFromOne)716 TEST_F(RefCountedOverflowTest, NonThreadSafeStartFromOne) {
717   class Overflow : public base::RefCounted<Overflow> {
718    public:
719     REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
720 
721     Overflow() { EXPECT_TRUE(HasOneRef()); }
722 
723    private:
724     friend class base::RefCounted<Overflow>;
725     ~Overflow() = default;
726   };
727 
728   auto p = base::MakeRefCounted<Overflow>();
729   GetMutableRefCount(p.get()) = std::numeric_limits<uint32_t>::max();
730   EXPECT_CHECK_DEATH(p->AddRef());
731   // Ensure `p` doesn't leak and fail lsan builds.
732   GetMutableRefCount(p.get()) = 1;
733 }
734 
TEST_F(RefCountedOverflowTest,ThreadSafeStartFromZero)735 TEST_F(RefCountedOverflowTest, ThreadSafeStartFromZero) {
736   class Overflow : public base::RefCountedThreadSafe<Overflow> {
737    public:
738     Overflow() { EXPECT_FALSE(HasOneRef()); }
739 
740    private:
741     friend class base::RefCountedThreadSafe<Overflow>;
742     ~Overflow() = default;
743   };
744 
745   auto p = base::MakeRefCounted<Overflow>();
746   GetMutableRefCount(p.get()) = std::numeric_limits<int>::max();
747   EXPECT_CHECK_DEATH(p->AddRef());
748   // Ensure `p` doesn't leak and fail lsan builds.
749   GetMutableRefCount(p.get()) = 1;
750 }
751 
TEST_F(RefCountedOverflowTest,ThreadSafeStartFromOne)752 TEST_F(RefCountedOverflowTest, ThreadSafeStartFromOne) {
753   class Overflow : public base::RefCountedThreadSafe<Overflow> {
754    public:
755     REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
756 
757     Overflow() { EXPECT_TRUE(HasOneRef()); }
758 
759    private:
760     friend class base::RefCountedThreadSafe<Overflow>;
761     ~Overflow() = default;
762   };
763 
764   auto p = base::MakeRefCounted<Overflow>();
765   GetMutableRefCount(p.get()) = std::numeric_limits<int>::max();
766   EXPECT_CHECK_DEATH(p->AddRef());
767   // Ensure `p` doesn't leak and fail lsan builds.
768   GetMutableRefCount(p.get()) = 1;
769 }
770 #endif
771 
772 }  // namespace subtle
773 }  // namespace base
774