blob: df1c30f843de99321abdd4e76a846a69accb039d [file] [log] [blame]
[email protected]e6130b272012-01-05 10:52:551// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
[email protected]3b63f8f42011-03-28 01:54:155#include "base/memory/ref_counted.h"
mdempsky3d16d9f62014-10-09 22:17:096
François Degros017f0ce2017-12-14 05:29:057#include <type_traits>
gab37af9ea62016-10-31 17:03:208#include <utility>
9
tzik65f396932017-04-03 05:27:3410#include "base/test/gtest_util.h"
initial.commitd7cae122008-07-26 21:49:3811#include "testing/gtest/include/gtest/gtest.h"
initial.commitd7cae122008-07-26 21:49:3812
[email protected]935f7762009-01-10 00:53:1313namespace {
14
initial.commitd7cae122008-07-26 21:49:3815class SelfAssign : public base::RefCounted<SelfAssign> {
dcheng5ab2ac72014-11-26 02:35:0816 protected:
Chris Watkinsbb7211c2017-11-29 07:16:3817 virtual ~SelfAssign() = default;
[email protected]877d55d2009-11-05 21:53:0818
dcheng5ab2ac72014-11-26 02:35:0819 private:
20 friend class base::RefCounted<SelfAssign>;
21};
22
23class Derived : public SelfAssign {
24 protected:
Chris Watkinsbb7211c2017-11-29 07:16:3825 ~Derived() override = default;
dcheng5ab2ac72014-11-26 02:35:0826
27 private:
28 friend class base::RefCounted<Derived>;
initial.commitd7cae122008-07-26 21:49:3829};
30
[email protected]935f7762009-01-10 00:53:1331class 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
[email protected]e6130b272012-01-05 10:52:5540class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> {
41 public:
[email protected]c9f977b2013-04-25 12:17:1542 ScopedRefPtrToSelf() : self_ptr_(this) {}
[email protected]e6130b272012-01-05 10:52:5543
44 static bool was_destroyed() { return was_destroyed_; }
45
kkimlabsaa3927982015-04-13 20:49:4346 static void reset_was_destroyed() { was_destroyed_ = false; }
47
48 scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
[email protected]e6130b272012-01-05 10:52:5549
50 private:
51 friend class base::RefCounted<ScopedRefPtrToSelf>;
[email protected]a9aaa9d12012-04-25 00:42:5152 ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
[email protected]e6130b272012-01-05 10:52:5553
54 static bool was_destroyed_;
[email protected]e6130b272012-01-05 10:52:5555};
56
57bool ScopedRefPtrToSelf::was_destroyed_ = false;
58
kkimlabsaa3927982015-04-13 20:49:4359class 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
piman53130922016-04-20 01:04:40111class Other : public base::RefCounted<Other> {
112 private:
113 friend class base::RefCounted<Other>;
114
Chris Watkinsbb7211c2017-11-29 07:16:38115 ~Other() = default;
piman53130922016-04-20 01:04:40116};
117
tzika52799b2017-09-27 17:21:41118class HasPrivateDestructorWithDeleter;
119
120struct Deleter {
121 static void Destruct(const HasPrivateDestructorWithDeleter* x);
122};
123
124class HasPrivateDestructorWithDeleter
125 : public base::RefCounted<HasPrivateDestructorWithDeleter, Deleter> {
126 public:
Chris Watkinsbb7211c2017-11-29 07:16:38127 HasPrivateDestructorWithDeleter() = default;
tzika52799b2017-09-27 17:21:41128
129 private:
130 friend struct Deleter;
Chris Watkinsbb7211c2017-11-29 07:16:38131 ~HasPrivateDestructorWithDeleter() = default;
tzika52799b2017-09-27 17:21:41132};
133
134void Deleter::Destruct(const HasPrivateDestructorWithDeleter* x) {
135 delete x;
136}
137
piman53130922016-04-20 01:04:40138scoped_refptr<Other> Overloaded(scoped_refptr<Other> other) {
139 return other;
140}
141
142scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) {
143 return self_assign;
144}
145
tzik65f396932017-04-03 05:27:34146class InitialRefCountIsOne : public base::RefCounted<InitialRefCountIsOne> {
147 public:
148 REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
149
Chris Watkinsbb7211c2017-11-29 07:16:38150 InitialRefCountIsOne() = default;
tzik65f396932017-04-03 05:27:34151
152 private:
153 friend class base::RefCounted<InitialRefCountIsOne>;
Chris Watkinsbb7211c2017-11-29 07:16:38154 ~InitialRefCountIsOne() = default;
tzik65f396932017-04-03 05:27:34155};
piman53130922016-04-20 01:04:40156
kylechar99ac0ad2018-07-04 22:51:31157// Checks that the scoped_refptr is null before the reference counted object is
158// destroyed.
159class CheckRefptrNull : public base::RefCounted<CheckRefptrNull> {
160 public:
161 // Set the last scoped_refptr that will have a reference to this object.
162 void set_scoped_refptr(scoped_refptr<CheckRefptrNull>* ptr) { ptr_ = ptr; }
163
164 protected:
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
[email protected]935f7762009-01-10 00:53:13176} // end namespace
177
initial.commitd7cae122008-07-26 21:49:38178TEST(RefCountedUnitTest, TestSelfAssignment) {
179 SelfAssign* p = new SelfAssign;
[email protected]ad8e04a2010-11-01 04:16:27180 scoped_refptr<SelfAssign> var(p);
Hans Wennborg792903f2018-04-09 11:20:06181 var = *&var; // The *& defeats Clang's -Wself-assign warning.
initial.commitd7cae122008-07-26 21:49:38182 EXPECT_EQ(var.get(), p);
François Degros017f0ce2017-12-14 05:29:05183 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);
initial.commitd7cae122008-07-26 21:49:38189}
license.botbf09a502008-08-24 00:55:55190
[email protected]935f7762009-01-10 00:53:13191TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
192 CheckDerivedMemberAccess check;
193}
[email protected]e6130b272012-01-05 10:52:55194
kkimlabsaa3927982015-04-13 20:49:43195TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
196 ScopedRefPtrToSelf::reset_was_destroyed();
197
[email protected]e6130b272012-01-05 10:52:55198 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
199 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
kkimlabsaa3927982015-04-13 20:49:43200 check->self_ptr_ = nullptr;
201 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
202}
203
204TEST(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>();
[email protected]e6130b272012-01-05 10:52:55213 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
214}
mdempsky3d16d9f62014-10-09 22:17:09215
dcheng5ab2ac72014-11-26 02:35:08216TEST(RefCountedUnitTest, BooleanTesting) {
scheib28aacfca2016-02-23 20:57:19217 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 }
dcheng5ab2ac72014-11-26 02:35:08242}
243
244TEST(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
robpercival3d1a0002016-05-19 00:48:51255TEST(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
dcheng5ab2ac72014-11-26 02:35:08265TEST(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}
kkimlabsaa3927982015-04-13 20:49:43277
kkimlabsaa3927982015-04-13 20:49:43278TEST(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
danakj0c8d4aa2015-11-25 05:29:58290 p2 = std::move(p1);
kkimlabsaa3927982015-04-13 20:49:43291 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
307TEST(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
danakj0c8d4aa2015-11-25 05:29:58321 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43322 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
338TEST(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
danakj0c8d4aa2015-11-25 05:29:58352 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43353 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
369TEST(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
danakj0c8d4aa2015-11-25 05:29:58383 p2 = std::move(p1);
kkimlabsaa3927982015-04-13 20:49:43384 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
400TEST(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
danakj0c8d4aa2015-11-25 05:29:58415 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43416 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
Kevin Marshall7273edd2017-06-20 22:19:36432TEST(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
kkimlabsaa3927982015-04-13 20:49:43453TEST(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
danakj0c8d4aa2015-11-25 05:29:58473 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43474 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
496TEST(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 {
danakj0c8d4aa2015-11-25 05:29:58506 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
kkimlabsaa3927982015-04-13 20:49:43507 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
523TEST(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 {
danakj0c8d4aa2015-11-25 05:29:58536 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
kkimlabsaa3927982015-04-13 20:49:43537 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
piman53130922016-04-20 01:04:40559TEST(RefCountedUnitTest, TestOverloadResolutionCopy) {
François Degros017f0ce2017-12-14 05:29:05560 const scoped_refptr<Derived> derived(new Derived);
561 const scoped_refptr<SelfAssign> expected(derived);
piman53130922016-04-20 01:04:40562 EXPECT_EQ(expected, Overloaded(derived));
563
François Degros017f0ce2017-12-14 05:29:05564 const scoped_refptr<Other> other(new Other);
piman53130922016-04-20 01:04:40565 EXPECT_EQ(other, Overloaded(other));
566}
567
568TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
569 scoped_refptr<Derived> derived(new Derived);
François Degros017f0ce2017-12-14 05:29:05570 const scoped_refptr<SelfAssign> expected(derived);
piman53130922016-04-20 01:04:40571 EXPECT_EQ(expected, Overloaded(std::move(derived)));
572
573 scoped_refptr<Other> other(new Other);
François Degros017f0ce2017-12-14 05:29:05574 const scoped_refptr<Other> other2(other);
piman53130922016-04-20 01:04:40575 EXPECT_EQ(other2, Overloaded(std::move(other)));
576}
tzik65f396932017-04-03 05:27:34577
Lei Zhang6cce3ba952017-11-17 05:05:46578TEST(RefCountedUnitTest, TestMakeRefCounted) {
579 scoped_refptr<Derived> derived = new Derived;
580 EXPECT_TRUE(derived->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31581 derived.reset();
Lei Zhang6cce3ba952017-11-17 05:05:46582
583 scoped_refptr<Derived> derived2 = base::MakeRefCounted<Derived>();
584 EXPECT_TRUE(derived2->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31585 derived2.reset();
Lei Zhang6cce3ba952017-11-17 05:05:46586}
587
tzik65f396932017-04-03 05:27:34588TEST(RefCountedUnitTest, TestInitialRefCountIsOne) {
589 scoped_refptr<InitialRefCountIsOne> obj =
Taiju Tsuiki36c517d2017-05-18 06:45:43590 base::MakeRefCounted<InitialRefCountIsOne>();
tzik65f396932017-04-03 05:27:34591 EXPECT_TRUE(obj->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31592 obj.reset();
tzik65f396932017-04-03 05:27:34593
594 scoped_refptr<InitialRefCountIsOne> obj2 =
595 base::AdoptRef(new InitialRefCountIsOne);
596 EXPECT_TRUE(obj2->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31597 obj2.reset();
tzik65f396932017-04-03 05:27:34598
Taiju Tsuiki36c517d2017-05-18 06:45:43599 scoped_refptr<Other> obj3 = base::MakeRefCounted<Other>();
tzik65f396932017-04-03 05:27:34600 EXPECT_TRUE(obj3->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31601 obj3.reset();
602}
603
604TEST(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
611TEST(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
638TEST(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
646TEST(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);
tzik65f396932017-04-03 05:27:34655}
656
657TEST(RefCountedDeathTest, TestAdoptRef) {
kylechar973a0412017-09-26 18:40:29658 // Check that WrapRefCounted() DCHECKs if passed a type that defines
659 // REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE.
660 EXPECT_DCHECK_DEATH(base::WrapRefCounted(new InitialRefCountIsOne));
tzik65f396932017-04-03 05:27:34661
kylechar973a0412017-09-26 18:40:29662 // Check that AdoptRef() DCHECKs if passed a nullptr.
tzik65f396932017-04-03 05:27:34663 InitialRefCountIsOne* ptr = nullptr;
664 EXPECT_DCHECK_DEATH(base::AdoptRef(ptr));
665
kylechar973a0412017-09-26 18:40:29666 // Check that AdoptRef() DCHECKs if passed an object that doesn't need to be
667 // adopted.
tzik65f396932017-04-03 05:27:34668 scoped_refptr<InitialRefCountIsOne> obj =
Taiju Tsuiki36c517d2017-05-18 06:45:43669 base::MakeRefCounted<InitialRefCountIsOne>();
tzik65f396932017-04-03 05:27:34670 EXPECT_DCHECK_DEATH(base::AdoptRef(obj.get()));
671}