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(p1.get(), p1);
254 EXPECT_EQ(p1, p1.get());
255
256 EXPECT_EQ(p2, p2);
257 EXPECT_EQ(p2.get(), p2);
258 EXPECT_EQ(p2, p2.get());
259
260 EXPECT_NE(p1, p2);
261 EXPECT_NE(p1.get(), p2);
262 EXPECT_NE(p1, p2.get());
263
264 EXPECT_NE(p2, p1);
265 EXPECT_NE(p2.get(), p1);
266 EXPECT_NE(p2, p1.get());
267 }
268
TEST(RefCountedUnitTest,Ordering)269 TEST(RefCountedUnitTest, Ordering) {
270 scoped_refptr<SelfAssign> p1(new SelfAssign);
271 scoped_refptr<SelfAssign> p2(new SelfAssign);
272 EXPECT_NE(p1, p2);
273
274 if (p1.get() > p2.get()) {
275 p1.swap(p2);
276 }
277
278 EXPECT_LT(p1, p2);
279 EXPECT_LT(p1.get(), p2);
280 EXPECT_LT(p1, p2.get());
281
282 EXPECT_GT(p2, p1);
283 EXPECT_GT(p2.get(), p1);
284 EXPECT_GT(p2, p1.get());
285 }
286
TEST(RefCountedUnitTest,NullptrEquality)287 TEST(RefCountedUnitTest, NullptrEquality) {
288 scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign);
289 scoped_refptr<SelfAssign> ptr_to_nullptr;
290
291 EXPECT_NE(nullptr, ptr_to_an_instance);
292 EXPECT_NE(ptr_to_an_instance, nullptr);
293 EXPECT_EQ(nullptr, ptr_to_nullptr);
294 EXPECT_EQ(ptr_to_nullptr, nullptr);
295 }
296
TEST(RefCountedUnitTest,NullptrOrdering)297 TEST(RefCountedUnitTest, NullptrOrdering) {
298 scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign);
299
300 EXPECT_LT(nullptr, ptr_to_an_instance);
301 EXPECT_GT(ptr_to_an_instance, nullptr);
302 }
303
TEST(RefCountedUnitTest,ConvertibleEquality)304 TEST(RefCountedUnitTest, ConvertibleEquality) {
305 scoped_refptr<Derived> p1(new Derived);
306 scoped_refptr<SelfAssign> p2;
307
308 EXPECT_NE(p1, p2);
309 EXPECT_NE(p2, p1);
310
311 p2 = p1;
312
313 EXPECT_EQ(p1, p2);
314 EXPECT_EQ(p2, p1);
315 }
316
TEST(RefCountedUnitTest,MoveAssignment1)317 TEST(RefCountedUnitTest, MoveAssignment1) {
318 ScopedRefPtrCountBase::reset_count();
319
320 {
321 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
322 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
323 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
324 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
325
326 {
327 scoped_refptr<ScopedRefPtrCountBase> p2;
328
329 p2 = std::move(p1);
330 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
331 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
332 EXPECT_EQ(nullptr, p1.get());
333 EXPECT_EQ(raw, p2.get());
334
335 // p2 goes out of scope.
336 }
337 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
338 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
339
340 // p1 goes out of scope.
341 }
342 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
343 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
344 }
345
TEST(RefCountedUnitTest,MoveAssignment2)346 TEST(RefCountedUnitTest, MoveAssignment2) {
347 ScopedRefPtrCountBase::reset_count();
348
349 {
350 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
351 scoped_refptr<ScopedRefPtrCountBase> p1;
352 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
353 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
354
355 {
356 scoped_refptr<ScopedRefPtrCountBase> p2(raw);
357 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
358 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
359
360 p1 = std::move(p2);
361 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
362 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
363 EXPECT_EQ(raw, p1.get());
364 EXPECT_EQ(nullptr, p2.get());
365
366 // p2 goes out of scope.
367 }
368 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
369 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
370
371 // p1 goes out of scope.
372 }
373 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
374 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
375 }
376
TEST(RefCountedUnitTest,MoveAssignmentSameInstance1)377 TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
378 ScopedRefPtrCountBase::reset_count();
379
380 {
381 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
382 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
383 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
384 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
385
386 {
387 scoped_refptr<ScopedRefPtrCountBase> p2(p1);
388 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
389 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
390
391 p1 = std::move(p2);
392 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
393 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
394 EXPECT_EQ(raw, p1.get());
395 EXPECT_EQ(nullptr, p2.get());
396
397 // p2 goes out of scope.
398 }
399 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
400 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
401
402 // p1 goes out of scope.
403 }
404 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
405 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
406 }
407
TEST(RefCountedUnitTest,MoveAssignmentSameInstance2)408 TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
409 ScopedRefPtrCountBase::reset_count();
410
411 {
412 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
413 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
414 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
415 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
416
417 {
418 scoped_refptr<ScopedRefPtrCountBase> p2(p1);
419 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
420 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
421
422 p2 = std::move(p1);
423 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
424 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
425 EXPECT_EQ(nullptr, p1.get());
426 EXPECT_EQ(raw, p2.get());
427
428 // p2 goes out of scope.
429 }
430 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
431 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
432
433 // p1 goes out of scope.
434 }
435 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
436 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
437 }
438
TEST(RefCountedUnitTest,MoveAssignmentDifferentInstances)439 TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
440 ScopedRefPtrCountBase::reset_count();
441
442 {
443 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
444 scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
445 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
446 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
447
448 {
449 ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
450 scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
451 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
452 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
453
454 p1 = std::move(p2);
455 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
456 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
457 EXPECT_EQ(raw2, p1.get());
458 EXPECT_EQ(nullptr, p2.get());
459
460 // p2 goes out of scope.
461 }
462 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
463 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
464
465 // p1 goes out of scope.
466 }
467 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
468 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
469 }
470
TEST(RefCountedUnitTest,MoveAssignmentSelfMove)471 TEST(RefCountedUnitTest, MoveAssignmentSelfMove) {
472 ScopedRefPtrCountBase::reset_count();
473
474 {
475 ScopedRefPtrCountBase* raw = new ScopedRefPtrCountBase;
476 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
477 scoped_refptr<ScopedRefPtrCountBase>& p1_ref = p1;
478
479 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
480 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
481
482 p1 = std::move(p1_ref);
483
484 // |p1| is "valid but unspecified", so don't bother inspecting its
485 // contents, just ensure that we don't crash.
486 }
487
488 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
489 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
490 }
491
TEST(RefCountedUnitTest,MoveAssignmentDerived)492 TEST(RefCountedUnitTest, MoveAssignmentDerived) {
493 ScopedRefPtrCountBase::reset_count();
494 ScopedRefPtrCountDerived::reset_count();
495
496 {
497 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
498 scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
499 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
500 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
501 EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
502 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
503
504 {
505 ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
506 scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
507 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
508 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
509 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
510 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
511
512 p1 = std::move(p2);
513 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
514 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
515 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
516 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
517 EXPECT_EQ(raw2, p1.get());
518 EXPECT_EQ(nullptr, p2.get());
519
520 // p2 goes out of scope.
521 }
522 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
523 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
524 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
525 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
526
527 // p1 goes out of scope.
528 }
529 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
530 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
531 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
532 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
533 }
534
TEST(RefCountedUnitTest,MoveConstructor)535 TEST(RefCountedUnitTest, MoveConstructor) {
536 ScopedRefPtrCountBase::reset_count();
537
538 {
539 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
540 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
541 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
542 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
543
544 {
545 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
546 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
547 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
548 EXPECT_EQ(nullptr, p1.get());
549 EXPECT_EQ(raw, p2.get());
550
551 // p2 goes out of scope.
552 }
553 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
554 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
555
556 // p1 goes out of scope.
557 }
558 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
559 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
560 }
561
TEST(RefCountedUnitTest,MoveConstructorDerived)562 TEST(RefCountedUnitTest, MoveConstructorDerived) {
563 ScopedRefPtrCountBase::reset_count();
564 ScopedRefPtrCountDerived::reset_count();
565
566 {
567 ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
568 scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
569 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
570 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
571 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
572 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
573
574 {
575 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
576 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
577 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
578 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
579 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
580 EXPECT_EQ(nullptr, p1.get());
581 EXPECT_EQ(raw1, p2.get());
582
583 // p2 goes out of scope.
584 }
585 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
586 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
587 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
588 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
589
590 // p1 goes out of scope.
591 }
592 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
593 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
594 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
595 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
596 }
597
TEST(RefCountedUnitTest,TestOverloadResolutionCopy)598 TEST(RefCountedUnitTest, TestOverloadResolutionCopy) {
599 const scoped_refptr<Derived> derived(new Derived);
600 const scoped_refptr<SelfAssign> expected(derived);
601 EXPECT_EQ(expected, Overloaded(derived));
602
603 const scoped_refptr<Other> other(new Other);
604 EXPECT_EQ(other, Overloaded(other));
605 }
606
TEST(RefCountedUnitTest,TestOverloadResolutionMove)607 TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
608 scoped_refptr<Derived> derived(new Derived);
609 const scoped_refptr<SelfAssign> expected(derived);
610 EXPECT_EQ(expected, Overloaded(std::move(derived)));
611
612 scoped_refptr<Other> other(new Other);
613 const scoped_refptr<Other> other2(other);
614 EXPECT_EQ(other2, Overloaded(std::move(other)));
615 }
616
TEST(RefCountedUnitTest,TestMakeRefCounted)617 TEST(RefCountedUnitTest, TestMakeRefCounted) {
618 scoped_refptr<Derived> derived = new Derived;
619 EXPECT_TRUE(derived->HasOneRef());
620 derived.reset();
621
622 scoped_refptr<Derived> derived2 = base::MakeRefCounted<Derived>();
623 EXPECT_TRUE(derived2->HasOneRef());
624 derived2.reset();
625 }
626
TEST(RefCountedUnitTest,TestInitialRefCountIsOne)627 TEST(RefCountedUnitTest, TestInitialRefCountIsOne) {
628 scoped_refptr<InitialRefCountIsOne> obj =
629 base::MakeRefCounted<InitialRefCountIsOne>();
630 EXPECT_TRUE(obj->HasOneRef());
631 obj.reset();
632
633 scoped_refptr<InitialRefCountIsOne> obj2 =
634 base::AdoptRef(new InitialRefCountIsOne);
635 EXPECT_TRUE(obj2->HasOneRef());
636 obj2.reset();
637
638 scoped_refptr<Other> obj3 = base::MakeRefCounted<Other>();
639 EXPECT_TRUE(obj3->HasOneRef());
640 obj3.reset();
641 }
642
TEST(RefCountedUnitTest,TestPrivateDestructorWithDeleter)643 TEST(RefCountedUnitTest, TestPrivateDestructorWithDeleter) {
644 // Ensure that RefCounted doesn't need the access to the pointee dtor when
645 // a custom deleter is given.
646 scoped_refptr<HasPrivateDestructorWithDeleter> obj =
647 base::MakeRefCounted<HasPrivateDestructorWithDeleter>();
648 }
649
TEST(RefCountedUnitTest,TestReset)650 TEST(RefCountedUnitTest, TestReset) {
651 ScopedRefPtrCountBase::reset_count();
652
653 // Create ScopedRefPtrCountBase that is referenced by |obj1| and |obj2|.
654 scoped_refptr<ScopedRefPtrCountBase> obj1 =
655 base::MakeRefCounted<ScopedRefPtrCountBase>();
656 scoped_refptr<ScopedRefPtrCountBase> obj2 = obj1;
657 EXPECT_NE(obj1.get(), nullptr);
658 EXPECT_NE(obj2.get(), nullptr);
659 EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
660 EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0);
661
662 // Check that calling reset() on |obj1| resets it. |obj2| still has a
663 // reference to the ScopedRefPtrCountBase so it shouldn't be reset.
664 obj1.reset();
665 EXPECT_EQ(obj1.get(), nullptr);
666 EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
667 EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0);
668
669 // Check that calling reset() on |obj2| resets it and causes the deletion of
670 // the ScopedRefPtrCountBase.
671 obj2.reset();
672 EXPECT_EQ(obj2.get(), nullptr);
673 EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
674 EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 1);
675 }
676
TEST(RefCountedUnitTest,TestResetAlreadyNull)677 TEST(RefCountedUnitTest, TestResetAlreadyNull) {
678 // Check that calling reset() on a null scoped_refptr does nothing.
679 scoped_refptr<ScopedRefPtrCountBase> obj;
680 obj.reset();
681 // |obj| should still be null after calling reset().
682 EXPECT_EQ(obj.get(), nullptr);
683 }
684
TEST(RefCountedUnitTest,TestResetByNullptrAssignment)685 TEST(RefCountedUnitTest, TestResetByNullptrAssignment) {
686 // Check that assigning nullptr resets the object.
687 auto obj = base::MakeRefCounted<ScopedRefPtrCountBase>();
688 EXPECT_NE(obj.get(), nullptr);
689
690 obj = nullptr;
691 EXPECT_EQ(obj.get(), nullptr);
692 }
693
TEST(RefCountedUnitTest,CheckScopedRefptrNullBeforeObjectDestruction)694 TEST(RefCountedUnitTest, CheckScopedRefptrNullBeforeObjectDestruction) {
695 scoped_refptr<CheckRefptrNull> obj = base::MakeRefCounted<CheckRefptrNull>();
696 obj->set_scoped_refptr(&obj);
697
698 // Check that when reset() is called the scoped_refptr internal pointer is set
699 // to null before the reference counted object is destroyed. This check is
700 // done by the CheckRefptrNull destructor.
701 obj.reset();
702 EXPECT_EQ(obj.get(), nullptr);
703 }
704
TEST(RefCountedDeathTest,TestAdoptRef)705 TEST(RefCountedDeathTest, TestAdoptRef) {
706 // Check that WrapRefCounted() DCHECKs if passed a type that defines
707 // REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE.
708 EXPECT_DCHECK_DEATH(base::WrapRefCounted(new InitialRefCountIsOne));
709
710 // Check that AdoptRef() DCHECKs if passed a nullptr.
711 InitialRefCountIsOne* ptr = nullptr;
712 EXPECT_DCHECK_DEATH(base::AdoptRef(ptr));
713
714 // Check that AdoptRef() DCHECKs if passed an object that doesn't need to be
715 // adopted.
716 scoped_refptr<InitialRefCountIsOne> obj =
717 base::MakeRefCounted<InitialRefCountIsOne>();
718 EXPECT_DCHECK_DEATH(base::AdoptRef(obj.get()));
719 }
720
721 #if defined(ARCH_CPU_64_BITS)
722 class RefCountedOverflowTest : public ::testing::Test {
723 public:
GetMutableRefCount(RefCountedBase * ref_counted)724 static uint32_t& GetMutableRefCount(RefCountedBase* ref_counted) {
725 return ref_counted->ref_count_;
726 }
727
GetMutableRefCount(RefCountedThreadSafeBase * ref_counted)728 static std::atomic_int& GetMutableRefCount(
729 RefCountedThreadSafeBase* ref_counted) {
730 return ref_counted->ref_count_.ref_count_;
731 }
732 };
733
TEST_F(RefCountedOverflowTest,NonThreadSafeStartFromZero)734 TEST_F(RefCountedOverflowTest, NonThreadSafeStartFromZero) {
735 class Overflow : public base::RefCounted<Overflow> {
736 public:
737 Overflow() { EXPECT_FALSE(HasOneRef()); }
738
739 private:
740 friend class base::RefCounted<Overflow>;
741 ~Overflow() = default;
742 };
743
744 auto p = base::MakeRefCounted<Overflow>();
745 GetMutableRefCount(p.get()) = std::numeric_limits<uint32_t>::max();
746 EXPECT_CHECK_DEATH(p->AddRef());
747 // Ensure `p` doesn't leak and fail lsan builds.
748 GetMutableRefCount(p.get()) = 1;
749 }
750
TEST_F(RefCountedOverflowTest,NonThreadSafeStartFromOne)751 TEST_F(RefCountedOverflowTest, NonThreadSafeStartFromOne) {
752 class Overflow : public base::RefCounted<Overflow> {
753 public:
754 REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
755
756 Overflow() { EXPECT_TRUE(HasOneRef()); }
757
758 private:
759 friend class base::RefCounted<Overflow>;
760 ~Overflow() = default;
761 };
762
763 auto p = base::MakeRefCounted<Overflow>();
764 GetMutableRefCount(p.get()) = std::numeric_limits<uint32_t>::max();
765 EXPECT_CHECK_DEATH(p->AddRef());
766 // Ensure `p` doesn't leak and fail lsan builds.
767 GetMutableRefCount(p.get()) = 1;
768 }
769
TEST_F(RefCountedOverflowTest,ThreadSafeStartFromZero)770 TEST_F(RefCountedOverflowTest, ThreadSafeStartFromZero) {
771 class Overflow : public base::RefCountedThreadSafe<Overflow> {
772 public:
773 Overflow() { EXPECT_FALSE(HasOneRef()); }
774
775 private:
776 friend class base::RefCountedThreadSafe<Overflow>;
777 ~Overflow() = default;
778 };
779
780 auto p = base::MakeRefCounted<Overflow>();
781 GetMutableRefCount(p.get()) = std::numeric_limits<int>::max();
782 EXPECT_CHECK_DEATH(p->AddRef());
783 // Ensure `p` doesn't leak and fail lsan builds.
784 GetMutableRefCount(p.get()) = 1;
785 }
786
TEST_F(RefCountedOverflowTest,ThreadSafeStartFromOne)787 TEST_F(RefCountedOverflowTest, ThreadSafeStartFromOne) {
788 class Overflow : public base::RefCountedThreadSafe<Overflow> {
789 public:
790 REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
791
792 Overflow() { EXPECT_TRUE(HasOneRef()); }
793
794 private:
795 friend class base::RefCountedThreadSafe<Overflow>;
796 ~Overflow() = default;
797 };
798
799 auto p = base::MakeRefCounted<Overflow>();
800 GetMutableRefCount(p.get()) = std::numeric_limits<int>::max();
801 EXPECT_CHECK_DEATH(p->AddRef());
802 // Ensure `p` doesn't leak and fail lsan builds.
803 GetMutableRefCount(p.get()) = 1;
804 }
805 #endif
806
807 } // namespace subtle
808 } // namespace base
809