• 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 "base/test/opaque_ref_counted.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 
10 namespace {
11 
12 class SelfAssign : public base::RefCounted<SelfAssign> {
13  protected:
~SelfAssign()14   virtual ~SelfAssign() {}
15 
16  private:
17   friend class base::RefCounted<SelfAssign>;
18 };
19 
20 class Derived : public SelfAssign {
21  protected:
~Derived()22   ~Derived() override {}
23 
24  private:
25   friend class base::RefCounted<Derived>;
26 };
27 
28 class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> {
29  public:
CheckDerivedMemberAccess()30   CheckDerivedMemberAccess() {
31     // This shouldn't compile if we don't have access to the member variable.
32     SelfAssign** pptr = &ptr_;
33     EXPECT_EQ(*pptr, ptr_);
34   }
35 };
36 
37 class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> {
38  public:
ScopedRefPtrToSelf()39   ScopedRefPtrToSelf() : self_ptr_(this) {}
40 
was_destroyed()41   static bool was_destroyed() { return was_destroyed_; }
42 
reset_was_destroyed()43   static void reset_was_destroyed() { was_destroyed_ = false; }
44 
45   scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
46 
47  private:
48   friend class base::RefCounted<ScopedRefPtrToSelf>;
~ScopedRefPtrToSelf()49   ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
50 
51   static bool was_destroyed_;
52 };
53 
54 bool ScopedRefPtrToSelf::was_destroyed_ = false;
55 
56 class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
57  public:
ScopedRefPtrCountBase()58   ScopedRefPtrCountBase() { ++constructor_count_; }
59 
constructor_count()60   static int constructor_count() { return constructor_count_; }
61 
destructor_count()62   static int destructor_count() { return destructor_count_; }
63 
reset_count()64   static void reset_count() {
65     constructor_count_ = 0;
66     destructor_count_ = 0;
67   }
68 
69  protected:
~ScopedRefPtrCountBase()70   virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
71 
72  private:
73   friend class base::RefCounted<ScopedRefPtrCountBase>;
74 
75   static int constructor_count_;
76   static int destructor_count_;
77 };
78 
79 int ScopedRefPtrCountBase::constructor_count_ = 0;
80 int ScopedRefPtrCountBase::destructor_count_ = 0;
81 
82 class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
83  public:
ScopedRefPtrCountDerived()84   ScopedRefPtrCountDerived() { ++constructor_count_; }
85 
constructor_count()86   static int constructor_count() { return constructor_count_; }
87 
destructor_count()88   static int destructor_count() { return destructor_count_; }
89 
reset_count()90   static void reset_count() {
91     constructor_count_ = 0;
92     destructor_count_ = 0;
93   }
94 
95  protected:
~ScopedRefPtrCountDerived()96   ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
97 
98  private:
99   friend class base::RefCounted<ScopedRefPtrCountDerived>;
100 
101   static int constructor_count_;
102   static int destructor_count_;
103 };
104 
105 int ScopedRefPtrCountDerived::constructor_count_ = 0;
106 int ScopedRefPtrCountDerived::destructor_count_ = 0;
107 
108 class Other : public base::RefCounted<Other> {
109  private:
110   friend class base::RefCounted<Other>;
111 
~Other()112   ~Other() {}
113 };
114 
Overloaded(scoped_refptr<Other> other)115 scoped_refptr<Other> Overloaded(scoped_refptr<Other> other) {
116   return other;
117 }
118 
Overloaded(scoped_refptr<SelfAssign> self_assign)119 scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) {
120   return self_assign;
121 }
122 
123 
124 }  // end namespace
125 
TEST(RefCountedUnitTest,TestSelfAssignment)126 TEST(RefCountedUnitTest, TestSelfAssignment) {
127   SelfAssign* p = new SelfAssign;
128   scoped_refptr<SelfAssign> var(p);
129   var = var;
130   EXPECT_EQ(var.get(), p);
131 }
132 
TEST(RefCountedUnitTest,ScopedRefPtrMemberAccess)133 TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
134   CheckDerivedMemberAccess check;
135 }
136 
TEST(RefCountedUnitTest,ScopedRefPtrToSelfPointerAssignment)137 TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
138   ScopedRefPtrToSelf::reset_was_destroyed();
139 
140   ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
141   EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
142   check->self_ptr_ = nullptr;
143   EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
144 }
145 
TEST(RefCountedUnitTest,ScopedRefPtrToSelfMoveAssignment)146 TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
147   ScopedRefPtrToSelf::reset_was_destroyed();
148 
149   ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
150   EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
151   // Releasing |check->self_ptr_| will delete |check|.
152   // The move assignment operator must assign |check->self_ptr_| first then
153   // release |check->self_ptr_|.
154   check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
155   EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
156 }
157 
TEST(RefCountedUnitTest,ScopedRefPtrToOpaque)158 TEST(RefCountedUnitTest, ScopedRefPtrToOpaque) {
159   scoped_refptr<base::OpaqueRefCounted> p = base::MakeOpaqueRefCounted();
160   base::TestOpaqueRefCounted(p);
161 
162   scoped_refptr<base::OpaqueRefCounted> q;
163   q = p;
164   base::TestOpaqueRefCounted(p);
165   base::TestOpaqueRefCounted(q);
166 }
167 
TEST(RefCountedUnitTest,BooleanTesting)168 TEST(RefCountedUnitTest, BooleanTesting) {
169   scoped_refptr<SelfAssign> ptr_to_an_instance = new SelfAssign;
170   EXPECT_TRUE(ptr_to_an_instance);
171   EXPECT_FALSE(!ptr_to_an_instance);
172 
173   if (ptr_to_an_instance) {
174   } else {
175     ADD_FAILURE() << "Pointer to an instance should result in true.";
176   }
177 
178   if (!ptr_to_an_instance) {  // check for operator!().
179     ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
180   }
181 
182   scoped_refptr<SelfAssign> null_ptr;
183   EXPECT_FALSE(null_ptr);
184   EXPECT_TRUE(!null_ptr);
185 
186   if (null_ptr) {
187     ADD_FAILURE() << "Null pointer should result in false.";
188   }
189 
190   if (!null_ptr) {  // check for operator!().
191   } else {
192     ADD_FAILURE() << "Null pointer should result in !x being true.";
193   }
194 }
195 
TEST(RefCountedUnitTest,Equality)196 TEST(RefCountedUnitTest, Equality) {
197   scoped_refptr<SelfAssign> p1(new SelfAssign);
198   scoped_refptr<SelfAssign> p2(new SelfAssign);
199 
200   EXPECT_EQ(p1, p1);
201   EXPECT_EQ(p2, p2);
202 
203   EXPECT_NE(p1, p2);
204   EXPECT_NE(p2, p1);
205 }
206 
TEST(RefCountedUnitTest,NullptrEquality)207 TEST(RefCountedUnitTest, NullptrEquality) {
208   scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign);
209   scoped_refptr<SelfAssign> ptr_to_nullptr;
210 
211   EXPECT_NE(nullptr, ptr_to_an_instance);
212   EXPECT_NE(ptr_to_an_instance, nullptr);
213   EXPECT_EQ(nullptr, ptr_to_nullptr);
214   EXPECT_EQ(ptr_to_nullptr, nullptr);
215 }
216 
TEST(RefCountedUnitTest,ConvertibleEquality)217 TEST(RefCountedUnitTest, ConvertibleEquality) {
218   scoped_refptr<Derived> p1(new Derived);
219   scoped_refptr<SelfAssign> p2;
220 
221   EXPECT_NE(p1, p2);
222   EXPECT_NE(p2, p1);
223 
224   p2 = p1;
225 
226   EXPECT_EQ(p1, p2);
227   EXPECT_EQ(p2, p1);
228 }
229 
TEST(RefCountedUnitTest,MoveAssignment1)230 TEST(RefCountedUnitTest, MoveAssignment1) {
231   ScopedRefPtrCountBase::reset_count();
232 
233   {
234     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
235     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
236     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
237     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
238 
239     {
240       scoped_refptr<ScopedRefPtrCountBase> p2;
241 
242       p2 = std::move(p1);
243       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
244       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
245       EXPECT_EQ(nullptr, p1.get());
246       EXPECT_EQ(raw, p2.get());
247 
248       // p2 goes out of scope.
249     }
250     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
251     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
252 
253     // p1 goes out of scope.
254   }
255   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
256   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
257 }
258 
TEST(RefCountedUnitTest,MoveAssignment2)259 TEST(RefCountedUnitTest, MoveAssignment2) {
260   ScopedRefPtrCountBase::reset_count();
261 
262   {
263     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
264     scoped_refptr<ScopedRefPtrCountBase> p1;
265     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
266     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
267 
268     {
269       scoped_refptr<ScopedRefPtrCountBase> p2(raw);
270       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
271       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
272 
273       p1 = std::move(p2);
274       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
275       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
276       EXPECT_EQ(raw, p1.get());
277       EXPECT_EQ(nullptr, p2.get());
278 
279       // p2 goes out of scope.
280     }
281     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
282     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
283 
284     // p1 goes out of scope.
285   }
286   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
287   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
288 }
289 
TEST(RefCountedUnitTest,MoveAssignmentSameInstance1)290 TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
291   ScopedRefPtrCountBase::reset_count();
292 
293   {
294     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
295     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
296     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
297     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
298 
299     {
300       scoped_refptr<ScopedRefPtrCountBase> p2(p1);
301       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
302       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
303 
304       p1 = std::move(p2);
305       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
306       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
307       EXPECT_EQ(raw, p1.get());
308       EXPECT_EQ(nullptr, p2.get());
309 
310       // p2 goes out of scope.
311     }
312     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
313     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
314 
315     // p1 goes out of scope.
316   }
317   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
318   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
319 }
320 
TEST(RefCountedUnitTest,MoveAssignmentSameInstance2)321 TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
322   ScopedRefPtrCountBase::reset_count();
323 
324   {
325     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
326     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
327     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
328     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
329 
330     {
331       scoped_refptr<ScopedRefPtrCountBase> p2(p1);
332       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
333       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
334 
335       p2 = std::move(p1);
336       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
337       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
338       EXPECT_EQ(nullptr, p1.get());
339       EXPECT_EQ(raw, p2.get());
340 
341       // p2 goes out of scope.
342     }
343     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
344     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
345 
346     // p1 goes out of scope.
347   }
348   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
349   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
350 }
351 
TEST(RefCountedUnitTest,MoveAssignmentDifferentInstances)352 TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
353   ScopedRefPtrCountBase::reset_count();
354 
355   {
356     ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
357     scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
358     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
359     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
360 
361     {
362       ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
363       scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
364       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
365       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
366 
367       p1 = std::move(p2);
368       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
369       EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
370       EXPECT_EQ(raw2, p1.get());
371       EXPECT_EQ(nullptr, p2.get());
372 
373       // p2 goes out of scope.
374     }
375     EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
376     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
377 
378     // p1 goes out of scope.
379   }
380   EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
381   EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
382 }
383 
TEST(RefCountedUnitTest,MoveAssignmentDerived)384 TEST(RefCountedUnitTest, MoveAssignmentDerived) {
385   ScopedRefPtrCountBase::reset_count();
386   ScopedRefPtrCountDerived::reset_count();
387 
388   {
389     ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
390     scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
391     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
392     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
393     EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
394     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
395 
396     {
397       ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
398       scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
399       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
400       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
401       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
402       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
403 
404       p1 = std::move(p2);
405       EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
406       EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
407       EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
408       EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
409       EXPECT_EQ(raw2, p1.get());
410       EXPECT_EQ(nullptr, p2.get());
411 
412       // p2 goes out of scope.
413     }
414     EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
415     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
416     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
417     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
418 
419     // p1 goes out of scope.
420   }
421   EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
422   EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
423   EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
424   EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
425 }
426 
TEST(RefCountedUnitTest,MoveConstructor)427 TEST(RefCountedUnitTest, MoveConstructor) {
428   ScopedRefPtrCountBase::reset_count();
429 
430   {
431     ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
432     scoped_refptr<ScopedRefPtrCountBase> p1(raw);
433     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
434     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
435 
436     {
437       scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
438       EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
439       EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
440       EXPECT_EQ(nullptr, p1.get());
441       EXPECT_EQ(raw, p2.get());
442 
443       // p2 goes out of scope.
444     }
445     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
446     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
447 
448     // p1 goes out of scope.
449   }
450   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
451   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
452 }
453 
TEST(RefCountedUnitTest,MoveConstructorDerived)454 TEST(RefCountedUnitTest, MoveConstructorDerived) {
455   ScopedRefPtrCountBase::reset_count();
456   ScopedRefPtrCountDerived::reset_count();
457 
458   {
459     ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
460     scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
461     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
462     EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
463     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
464     EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
465 
466     {
467       scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
468       EXPECT_EQ(1, 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       EXPECT_EQ(nullptr, p1.get());
473       EXPECT_EQ(raw1, p2.get());
474 
475       // p2 goes out of scope.
476     }
477     EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
478     EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
479     EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
480     EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
481 
482     // p1 goes out of scope.
483   }
484   EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
485   EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
486   EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
487   EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
488 }
489 
TEST(RefCountedUnitTest,TestOverloadResolutionCopy)490 TEST(RefCountedUnitTest, TestOverloadResolutionCopy) {
491   scoped_refptr<Derived> derived(new Derived);
492   scoped_refptr<SelfAssign> expected(derived);
493   EXPECT_EQ(expected, Overloaded(derived));
494 
495   scoped_refptr<Other> other(new Other);
496   EXPECT_EQ(other, Overloaded(other));
497 }
498 
TEST(RefCountedUnitTest,TestOverloadResolutionMove)499 TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
500   scoped_refptr<Derived> derived(new Derived);
501   scoped_refptr<SelfAssign> expected(derived);
502   EXPECT_EQ(expected, Overloaded(std::move(derived)));
503 
504   scoped_refptr<Other> other(new Other);
505   scoped_refptr<Other> other2(other);
506   EXPECT_EQ(other2, Overloaded(std::move(other)));
507 }
508