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