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