blob: a44fd65b5ffa06f5a032d7e6b8f0e6e13617c54b [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"
tzik7bb78d32018-08-16 05:31:1511#include "build/build_config.h"
initial.commitd7cae122008-07-26 21:49:3812#include "testing/gtest/include/gtest/gtest.h"
initial.commitd7cae122008-07-26 21:49:3813
tzik7bb78d32018-08-16 05:31:1514namespace base {
15namespace subtle {
[email protected]935f7762009-01-10 00:53:1316namespace {
17
initial.commitd7cae122008-07-26 21:49:3818class SelfAssign : public base::RefCounted<SelfAssign> {
dcheng5ab2ac72014-11-26 02:35:0819 protected:
Chris Watkinsbb7211c2017-11-29 07:16:3820 virtual ~SelfAssign() = default;
[email protected]877d55d2009-11-05 21:53:0821
dcheng5ab2ac72014-11-26 02:35:0822 private:
23 friend class base::RefCounted<SelfAssign>;
24};
25
26class Derived : public SelfAssign {
27 protected:
Chris Watkinsbb7211c2017-11-29 07:16:3828 ~Derived() override = default;
dcheng5ab2ac72014-11-26 02:35:0829
30 private:
31 friend class base::RefCounted<Derived>;
initial.commitd7cae122008-07-26 21:49:3832};
33
[email protected]935f7762009-01-10 00:53:1334class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> {
35 public:
36 CheckDerivedMemberAccess() {
37 // This shouldn't compile if we don't have access to the member variable.
38 SelfAssign** pptr = &ptr_;
39 EXPECT_EQ(*pptr, ptr_);
40 }
41};
42
[email protected]e6130b272012-01-05 10:52:5543class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> {
44 public:
[email protected]c9f977b2013-04-25 12:17:1545 ScopedRefPtrToSelf() : self_ptr_(this) {}
[email protected]e6130b272012-01-05 10:52:5546
47 static bool was_destroyed() { return was_destroyed_; }
48
kkimlabsaa3927982015-04-13 20:49:4349 static void reset_was_destroyed() { was_destroyed_ = false; }
50
51 scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
[email protected]e6130b272012-01-05 10:52:5552
53 private:
54 friend class base::RefCounted<ScopedRefPtrToSelf>;
[email protected]a9aaa9d12012-04-25 00:42:5155 ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
[email protected]e6130b272012-01-05 10:52:5556
57 static bool was_destroyed_;
[email protected]e6130b272012-01-05 10:52:5558};
59
60bool ScopedRefPtrToSelf::was_destroyed_ = false;
61
kkimlabsaa3927982015-04-13 20:49:4362class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
63 public:
64 ScopedRefPtrCountBase() { ++constructor_count_; }
65
66 static int constructor_count() { return constructor_count_; }
67
68 static int destructor_count() { return destructor_count_; }
69
70 static void reset_count() {
71 constructor_count_ = 0;
72 destructor_count_ = 0;
73 }
74
75 protected:
76 virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
77
78 private:
79 friend class base::RefCounted<ScopedRefPtrCountBase>;
80
81 static int constructor_count_;
82 static int destructor_count_;
83};
84
85int ScopedRefPtrCountBase::constructor_count_ = 0;
86int ScopedRefPtrCountBase::destructor_count_ = 0;
87
88class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
89 public:
90 ScopedRefPtrCountDerived() { ++constructor_count_; }
91
92 static int constructor_count() { return constructor_count_; }
93
94 static int destructor_count() { return destructor_count_; }
95
96 static void reset_count() {
97 constructor_count_ = 0;
98 destructor_count_ = 0;
99 }
100
101 protected:
102 ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
103
104 private:
105 friend class base::RefCounted<ScopedRefPtrCountDerived>;
106
107 static int constructor_count_;
108 static int destructor_count_;
109};
110
111int ScopedRefPtrCountDerived::constructor_count_ = 0;
112int ScopedRefPtrCountDerived::destructor_count_ = 0;
113
piman53130922016-04-20 01:04:40114class Other : public base::RefCounted<Other> {
115 private:
116 friend class base::RefCounted<Other>;
117
Chris Watkinsbb7211c2017-11-29 07:16:38118 ~Other() = default;
piman53130922016-04-20 01:04:40119};
120
tzika52799b2017-09-27 17:21:41121class HasPrivateDestructorWithDeleter;
122
123struct Deleter {
124 static void Destruct(const HasPrivateDestructorWithDeleter* x);
125};
126
127class HasPrivateDestructorWithDeleter
128 : public base::RefCounted<HasPrivateDestructorWithDeleter, Deleter> {
129 public:
Chris Watkinsbb7211c2017-11-29 07:16:38130 HasPrivateDestructorWithDeleter() = default;
tzika52799b2017-09-27 17:21:41131
132 private:
133 friend struct Deleter;
Chris Watkinsbb7211c2017-11-29 07:16:38134 ~HasPrivateDestructorWithDeleter() = default;
tzika52799b2017-09-27 17:21:41135};
136
137void Deleter::Destruct(const HasPrivateDestructorWithDeleter* x) {
138 delete x;
139}
140
piman53130922016-04-20 01:04:40141scoped_refptr<Other> Overloaded(scoped_refptr<Other> other) {
142 return other;
143}
144
145scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) {
146 return self_assign;
147}
148
tzik65f396932017-04-03 05:27:34149class InitialRefCountIsOne : public base::RefCounted<InitialRefCountIsOne> {
150 public:
151 REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
152
Chris Watkinsbb7211c2017-11-29 07:16:38153 InitialRefCountIsOne() = default;
tzik65f396932017-04-03 05:27:34154
155 private:
156 friend class base::RefCounted<InitialRefCountIsOne>;
Chris Watkinsbb7211c2017-11-29 07:16:38157 ~InitialRefCountIsOne() = default;
tzik65f396932017-04-03 05:27:34158};
piman53130922016-04-20 01:04:40159
kylechar99ac0ad2018-07-04 22:51:31160// Checks that the scoped_refptr is null before the reference counted object is
161// destroyed.
162class CheckRefptrNull : public base::RefCounted<CheckRefptrNull> {
163 public:
164 // Set the last scoped_refptr that will have a reference to this object.
165 void set_scoped_refptr(scoped_refptr<CheckRefptrNull>* ptr) { ptr_ = ptr; }
166
167 protected:
168 virtual ~CheckRefptrNull() {
169 EXPECT_NE(ptr_, nullptr);
170 EXPECT_EQ(ptr_->get(), nullptr);
171 }
172
173 private:
174 friend class base::RefCounted<CheckRefptrNull>;
175
176 scoped_refptr<CheckRefptrNull>* ptr_ = nullptr;
177};
178
tzik7bb78d32018-08-16 05:31:15179class Overflow : public base::RefCounted<Overflow> {
180 public:
181 Overflow() = default;
182
183 private:
184 friend class base::RefCounted<Overflow>;
185 ~Overflow() = default;
186};
187
188} // namespace
[email protected]935f7762009-01-10 00:53:13189
initial.commitd7cae122008-07-26 21:49:38190TEST(RefCountedUnitTest, TestSelfAssignment) {
191 SelfAssign* p = new SelfAssign;
[email protected]ad8e04a2010-11-01 04:16:27192 scoped_refptr<SelfAssign> var(p);
Hans Wennborg792903f2018-04-09 11:20:06193 var = *&var; // The *& defeats Clang's -Wself-assign warning.
initial.commitd7cae122008-07-26 21:49:38194 EXPECT_EQ(var.get(), p);
François Degros017f0ce2017-12-14 05:29:05195 var = std::move(var);
196 EXPECT_EQ(var.get(), p);
197 var.swap(var);
198 EXPECT_EQ(var.get(), p);
199 swap(var, var);
200 EXPECT_EQ(var.get(), p);
initial.commitd7cae122008-07-26 21:49:38201}
license.botbf09a502008-08-24 00:55:55202
[email protected]935f7762009-01-10 00:53:13203TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
204 CheckDerivedMemberAccess check;
205}
[email protected]e6130b272012-01-05 10:52:55206
kkimlabsaa3927982015-04-13 20:49:43207TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
208 ScopedRefPtrToSelf::reset_was_destroyed();
209
[email protected]e6130b272012-01-05 10:52:55210 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
211 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
kkimlabsaa3927982015-04-13 20:49:43212 check->self_ptr_ = nullptr;
213 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
214}
215
216TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
217 ScopedRefPtrToSelf::reset_was_destroyed();
218
219 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
220 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
221 // Releasing |check->self_ptr_| will delete |check|.
222 // The move assignment operator must assign |check->self_ptr_| first then
223 // release |check->self_ptr_|.
224 check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
[email protected]e6130b272012-01-05 10:52:55225 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
226}
mdempsky3d16d9f62014-10-09 22:17:09227
dcheng5ab2ac72014-11-26 02:35:08228TEST(RefCountedUnitTest, BooleanTesting) {
scheib28aacfca2016-02-23 20:57:19229 scoped_refptr<SelfAssign> ptr_to_an_instance = new SelfAssign;
230 EXPECT_TRUE(ptr_to_an_instance);
231 EXPECT_FALSE(!ptr_to_an_instance);
232
233 if (ptr_to_an_instance) {
234 } else {
235 ADD_FAILURE() << "Pointer to an instance should result in true.";
236 }
237
238 if (!ptr_to_an_instance) { // check for operator!().
239 ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
240 }
241
242 scoped_refptr<SelfAssign> null_ptr;
243 EXPECT_FALSE(null_ptr);
244 EXPECT_TRUE(!null_ptr);
245
246 if (null_ptr) {
247 ADD_FAILURE() << "Null pointer should result in false.";
248 }
249
250 if (!null_ptr) { // check for operator!().
251 } else {
252 ADD_FAILURE() << "Null pointer should result in !x being true.";
253 }
dcheng5ab2ac72014-11-26 02:35:08254}
255
256TEST(RefCountedUnitTest, Equality) {
257 scoped_refptr<SelfAssign> p1(new SelfAssign);
258 scoped_refptr<SelfAssign> p2(new SelfAssign);
259
260 EXPECT_EQ(p1, p1);
261 EXPECT_EQ(p2, p2);
262
263 EXPECT_NE(p1, p2);
264 EXPECT_NE(p2, p1);
265}
266
robpercival3d1a0002016-05-19 00:48:51267TEST(RefCountedUnitTest, NullptrEquality) {
268 scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign);
269 scoped_refptr<SelfAssign> ptr_to_nullptr;
270
271 EXPECT_NE(nullptr, ptr_to_an_instance);
272 EXPECT_NE(ptr_to_an_instance, nullptr);
273 EXPECT_EQ(nullptr, ptr_to_nullptr);
274 EXPECT_EQ(ptr_to_nullptr, nullptr);
275}
276
dcheng5ab2ac72014-11-26 02:35:08277TEST(RefCountedUnitTest, ConvertibleEquality) {
278 scoped_refptr<Derived> p1(new Derived);
279 scoped_refptr<SelfAssign> p2;
280
281 EXPECT_NE(p1, p2);
282 EXPECT_NE(p2, p1);
283
284 p2 = p1;
285
286 EXPECT_EQ(p1, p2);
287 EXPECT_EQ(p2, p1);
288}
kkimlabsaa3927982015-04-13 20:49:43289
kkimlabsaa3927982015-04-13 20:49:43290TEST(RefCountedUnitTest, MoveAssignment1) {
291 ScopedRefPtrCountBase::reset_count();
292
293 {
294 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
295 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
296 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
297 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
298
299 {
300 scoped_refptr<ScopedRefPtrCountBase> p2;
301
danakj0c8d4aa2015-11-25 05:29:58302 p2 = std::move(p1);
kkimlabsaa3927982015-04-13 20:49:43303 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
304 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
305 EXPECT_EQ(nullptr, p1.get());
306 EXPECT_EQ(raw, p2.get());
307
308 // p2 goes out of scope.
309 }
310 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
311 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
312
313 // p1 goes out of scope.
314 }
315 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
316 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
317}
318
319TEST(RefCountedUnitTest, MoveAssignment2) {
320 ScopedRefPtrCountBase::reset_count();
321
322 {
323 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
324 scoped_refptr<ScopedRefPtrCountBase> p1;
325 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
326 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
327
328 {
329 scoped_refptr<ScopedRefPtrCountBase> p2(raw);
330 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
331 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
332
danakj0c8d4aa2015-11-25 05:29:58333 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43334 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
335 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
336 EXPECT_EQ(raw, p1.get());
337 EXPECT_EQ(nullptr, p2.get());
338
339 // p2 goes out of scope.
340 }
341 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
342 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
343
344 // p1 goes out of scope.
345 }
346 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
347 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
348}
349
350TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
351 ScopedRefPtrCountBase::reset_count();
352
353 {
354 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
355 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
356 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
357 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
358
359 {
360 scoped_refptr<ScopedRefPtrCountBase> p2(p1);
361 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
362 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
363
danakj0c8d4aa2015-11-25 05:29:58364 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43365 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
366 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
367 EXPECT_EQ(raw, p1.get());
368 EXPECT_EQ(nullptr, p2.get());
369
370 // p2 goes out of scope.
371 }
372 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
373 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
374
375 // p1 goes out of scope.
376 }
377 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
378 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
379}
380
381TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
382 ScopedRefPtrCountBase::reset_count();
383
384 {
385 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
386 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
387 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
388 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
389
390 {
391 scoped_refptr<ScopedRefPtrCountBase> p2(p1);
392 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
393 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
394
danakj0c8d4aa2015-11-25 05:29:58395 p2 = std::move(p1);
kkimlabsaa3927982015-04-13 20:49:43396 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
397 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
398 EXPECT_EQ(nullptr, p1.get());
399 EXPECT_EQ(raw, p2.get());
400
401 // p2 goes out of scope.
402 }
403 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
404 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
405
406 // p1 goes out of scope.
407 }
408 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
409 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
410}
411
412TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
413 ScopedRefPtrCountBase::reset_count();
414
415 {
416 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
417 scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
418 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
419 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
420
421 {
422 ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
423 scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
424 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
425 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
426
danakj0c8d4aa2015-11-25 05:29:58427 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43428 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
429 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
430 EXPECT_EQ(raw2, p1.get());
431 EXPECT_EQ(nullptr, p2.get());
432
433 // p2 goes out of scope.
434 }
435 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
436 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
437
438 // p1 goes out of scope.
439 }
440 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
441 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
442}
443
Kevin Marshall7273edd2017-06-20 22:19:36444TEST(RefCountedUnitTest, MoveAssignmentSelfMove) {
445 ScopedRefPtrCountBase::reset_count();
446
447 {
448 ScopedRefPtrCountBase* raw = new ScopedRefPtrCountBase;
449 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
450 scoped_refptr<ScopedRefPtrCountBase>& p1_ref = p1;
451
452 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
453 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
454
455 p1 = std::move(p1_ref);
456
457 // |p1| is "valid but unspecified", so don't bother inspecting its
458 // contents, just ensure that we don't crash.
459 }
460
461 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
462 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
463}
464
kkimlabsaa3927982015-04-13 20:49:43465TEST(RefCountedUnitTest, MoveAssignmentDerived) {
466 ScopedRefPtrCountBase::reset_count();
467 ScopedRefPtrCountDerived::reset_count();
468
469 {
470 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
471 scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
472 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
473 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
474 EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
475 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
476
477 {
478 ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
479 scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
480 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
481 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
482 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
483 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
484
danakj0c8d4aa2015-11-25 05:29:58485 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43486 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
487 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
488 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
489 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
490 EXPECT_EQ(raw2, p1.get());
491 EXPECT_EQ(nullptr, p2.get());
492
493 // p2 goes out of scope.
494 }
495 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
496 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
497 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
498 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
499
500 // p1 goes out of scope.
501 }
502 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
503 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
504 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
505 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
506}
507
508TEST(RefCountedUnitTest, MoveConstructor) {
509 ScopedRefPtrCountBase::reset_count();
510
511 {
512 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
513 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
514 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
515 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
516
517 {
danakj0c8d4aa2015-11-25 05:29:58518 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
kkimlabsaa3927982015-04-13 20:49:43519 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
520 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
521 EXPECT_EQ(nullptr, p1.get());
522 EXPECT_EQ(raw, p2.get());
523
524 // p2 goes out of scope.
525 }
526 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
527 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
528
529 // p1 goes out of scope.
530 }
531 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
532 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
533}
534
535TEST(RefCountedUnitTest, MoveConstructorDerived) {
536 ScopedRefPtrCountBase::reset_count();
537 ScopedRefPtrCountDerived::reset_count();
538
539 {
540 ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
541 scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
542 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
543 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
544 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
545 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
546
547 {
danakj0c8d4aa2015-11-25 05:29:58548 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
kkimlabsaa3927982015-04-13 20:49:43549 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
550 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
551 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
552 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
553 EXPECT_EQ(nullptr, p1.get());
554 EXPECT_EQ(raw1, p2.get());
555
556 // p2 goes out of scope.
557 }
558 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
559 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
560 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
561 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
562
563 // p1 goes out of scope.
564 }
565 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
566 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
567 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
568 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
569}
570
piman53130922016-04-20 01:04:40571TEST(RefCountedUnitTest, TestOverloadResolutionCopy) {
François Degros017f0ce2017-12-14 05:29:05572 const scoped_refptr<Derived> derived(new Derived);
573 const scoped_refptr<SelfAssign> expected(derived);
piman53130922016-04-20 01:04:40574 EXPECT_EQ(expected, Overloaded(derived));
575
François Degros017f0ce2017-12-14 05:29:05576 const scoped_refptr<Other> other(new Other);
piman53130922016-04-20 01:04:40577 EXPECT_EQ(other, Overloaded(other));
578}
579
580TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
581 scoped_refptr<Derived> derived(new Derived);
François Degros017f0ce2017-12-14 05:29:05582 const scoped_refptr<SelfAssign> expected(derived);
piman53130922016-04-20 01:04:40583 EXPECT_EQ(expected, Overloaded(std::move(derived)));
584
585 scoped_refptr<Other> other(new Other);
François Degros017f0ce2017-12-14 05:29:05586 const scoped_refptr<Other> other2(other);
piman53130922016-04-20 01:04:40587 EXPECT_EQ(other2, Overloaded(std::move(other)));
588}
tzik65f396932017-04-03 05:27:34589
Lei Zhang6cce3ba952017-11-17 05:05:46590TEST(RefCountedUnitTest, TestMakeRefCounted) {
591 scoped_refptr<Derived> derived = new Derived;
592 EXPECT_TRUE(derived->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31593 derived.reset();
Lei Zhang6cce3ba952017-11-17 05:05:46594
595 scoped_refptr<Derived> derived2 = base::MakeRefCounted<Derived>();
596 EXPECT_TRUE(derived2->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31597 derived2.reset();
Lei Zhang6cce3ba952017-11-17 05:05:46598}
599
tzik65f396932017-04-03 05:27:34600TEST(RefCountedUnitTest, TestInitialRefCountIsOne) {
601 scoped_refptr<InitialRefCountIsOne> obj =
Taiju Tsuiki36c517d2017-05-18 06:45:43602 base::MakeRefCounted<InitialRefCountIsOne>();
tzik65f396932017-04-03 05:27:34603 EXPECT_TRUE(obj->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31604 obj.reset();
tzik65f396932017-04-03 05:27:34605
606 scoped_refptr<InitialRefCountIsOne> obj2 =
607 base::AdoptRef(new InitialRefCountIsOne);
608 EXPECT_TRUE(obj2->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31609 obj2.reset();
tzik65f396932017-04-03 05:27:34610
Taiju Tsuiki36c517d2017-05-18 06:45:43611 scoped_refptr<Other> obj3 = base::MakeRefCounted<Other>();
tzik65f396932017-04-03 05:27:34612 EXPECT_TRUE(obj3->HasOneRef());
kylechar99ac0ad2018-07-04 22:51:31613 obj3.reset();
614}
615
616TEST(RefCountedUnitTest, TestPrivateDestructorWithDeleter) {
617 // Ensure that RefCounted doesn't need the access to the pointee dtor when
618 // a custom deleter is given.
619 scoped_refptr<HasPrivateDestructorWithDeleter> obj =
620 base::MakeRefCounted<HasPrivateDestructorWithDeleter>();
621}
622
623TEST(RefCountedUnitTest, TestReset) {
624 ScopedRefPtrCountBase::reset_count();
625
626 // Create ScopedRefPtrCountBase that is referenced by |obj1| and |obj2|.
627 scoped_refptr<ScopedRefPtrCountBase> obj1 =
628 base::MakeRefCounted<ScopedRefPtrCountBase>();
629 scoped_refptr<ScopedRefPtrCountBase> obj2 = obj1;
630 EXPECT_NE(obj1.get(), nullptr);
631 EXPECT_NE(obj2.get(), nullptr);
632 EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
633 EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0);
634
635 // Check that calling reset() on |obj1| resets it. |obj2| still has a
636 // reference to the ScopedRefPtrCountBase so it shouldn't be reset.
637 obj1.reset();
638 EXPECT_EQ(obj1.get(), nullptr);
639 EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
640 EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 0);
641
642 // Check that calling reset() on |obj2| resets it and causes the deletion of
643 // the ScopedRefPtrCountBase.
644 obj2.reset();
645 EXPECT_EQ(obj2.get(), nullptr);
646 EXPECT_EQ(ScopedRefPtrCountBase::constructor_count(), 1);
647 EXPECT_EQ(ScopedRefPtrCountBase::destructor_count(), 1);
648}
649
650TEST(RefCountedUnitTest, TestResetAlreadyNull) {
651 // Check that calling reset() on a null scoped_refptr does nothing.
652 scoped_refptr<ScopedRefPtrCountBase> obj;
653 obj.reset();
654 // |obj| should still be null after calling reset().
655 EXPECT_EQ(obj.get(), nullptr);
656}
657
kylecharde7f5a22019-11-20 17:25:57658TEST(RefCountedUnitTest, TestResetByNullptrAssignment) {
659 // Check that assigning nullptr resets the object.
660 auto obj = base::MakeRefCounted<ScopedRefPtrCountBase>();
661 EXPECT_NE(obj.get(), nullptr);
662
663 obj = nullptr;
664 EXPECT_EQ(obj.get(), nullptr);
665}
666
kylechar99ac0ad2018-07-04 22:51:31667TEST(RefCountedUnitTest, CheckScopedRefptrNullBeforeObjectDestruction) {
668 scoped_refptr<CheckRefptrNull> obj = base::MakeRefCounted<CheckRefptrNull>();
669 obj->set_scoped_refptr(&obj);
670
671 // Check that when reset() is called the scoped_refptr internal pointer is set
672 // to null before the reference counted object is destroyed. This check is
673 // done by the CheckRefptrNull destructor.
674 obj.reset();
675 EXPECT_EQ(obj.get(), nullptr);
tzik65f396932017-04-03 05:27:34676}
677
678TEST(RefCountedDeathTest, TestAdoptRef) {
kylechar973a0412017-09-26 18:40:29679 // Check that WrapRefCounted() DCHECKs if passed a type that defines
680 // REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE.
681 EXPECT_DCHECK_DEATH(base::WrapRefCounted(new InitialRefCountIsOne));
tzik65f396932017-04-03 05:27:34682
kylechar973a0412017-09-26 18:40:29683 // Check that AdoptRef() DCHECKs if passed a nullptr.
tzik65f396932017-04-03 05:27:34684 InitialRefCountIsOne* ptr = nullptr;
685 EXPECT_DCHECK_DEATH(base::AdoptRef(ptr));
686
kylechar973a0412017-09-26 18:40:29687 // Check that AdoptRef() DCHECKs if passed an object that doesn't need to be
688 // adopted.
tzik65f396932017-04-03 05:27:34689 scoped_refptr<InitialRefCountIsOne> obj =
Taiju Tsuiki36c517d2017-05-18 06:45:43690 base::MakeRefCounted<InitialRefCountIsOne>();
tzik65f396932017-04-03 05:27:34691 EXPECT_DCHECK_DEATH(base::AdoptRef(obj.get()));
692}
tzik7bb78d32018-08-16 05:31:15693
694#if defined(ARCH_CPU_64_BITS)
695TEST(RefCountedDeathTest, TestOverflowCheck) {
kylecharde4637742021-03-05 14:01:19696 auto p = base::MakeRefCounted<Overflow>();
697 p->ref_count_ = std::numeric_limits<uint32_t>::max();
698 EXPECT_CHECK_DEATH(p->AddRef());
699 // Ensure `p` doesn't leak and fail lsan builds.
700 p->ref_count_ = 1;
tzik7bb78d32018-08-16 05:31:15701}
702#endif
703
704} // namespace subtle
705} // namespace base