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