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