1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/memory/ref_counted.h"
7 #include "base/test/opaque_ref_counted.h"
8 #include "testing/gtest/include/gtest/gtest.h"
12 class SelfAssign
: public base::RefCounted
<SelfAssign
> {
14 virtual ~SelfAssign() {}
17 friend class base::RefCounted
<SelfAssign
>;
20 class Derived
: public SelfAssign
{
22 ~Derived() override
{}
25 friend class base::RefCounted
<Derived
>;
28 class CheckDerivedMemberAccess
: public scoped_refptr
<SelfAssign
> {
30 CheckDerivedMemberAccess() {
31 // This shouldn't compile if we don't have access to the member variable.
32 SelfAssign
** pptr
= &ptr_
;
33 EXPECT_EQ(*pptr
, ptr_
);
37 class ScopedRefPtrToSelf
: public base::RefCounted
<ScopedRefPtrToSelf
> {
39 ScopedRefPtrToSelf() : self_ptr_(this) {}
41 static bool was_destroyed() { return was_destroyed_
; }
43 static void reset_was_destroyed() { was_destroyed_
= false; }
45 scoped_refptr
<ScopedRefPtrToSelf
> self_ptr_
;
48 friend class base::RefCounted
<ScopedRefPtrToSelf
>;
49 ~ScopedRefPtrToSelf() { was_destroyed_
= true; }
51 static bool was_destroyed_
;
54 bool ScopedRefPtrToSelf::was_destroyed_
= false;
56 class ScopedRefPtrCountBase
: public base::RefCounted
<ScopedRefPtrCountBase
> {
58 ScopedRefPtrCountBase() { ++constructor_count_
; }
60 static int constructor_count() { return constructor_count_
; }
62 static int destructor_count() { return destructor_count_
; }
64 static void reset_count() {
65 constructor_count_
= 0;
66 destructor_count_
= 0;
70 virtual ~ScopedRefPtrCountBase() { ++destructor_count_
; }
73 friend class base::RefCounted
<ScopedRefPtrCountBase
>;
75 static int constructor_count_
;
76 static int destructor_count_
;
79 int ScopedRefPtrCountBase::constructor_count_
= 0;
80 int ScopedRefPtrCountBase::destructor_count_
= 0;
82 class ScopedRefPtrCountDerived
: public ScopedRefPtrCountBase
{
84 ScopedRefPtrCountDerived() { ++constructor_count_
; }
86 static int constructor_count() { return constructor_count_
; }
88 static int destructor_count() { return destructor_count_
; }
90 static void reset_count() {
91 constructor_count_
= 0;
92 destructor_count_
= 0;
96 ~ScopedRefPtrCountDerived() override
{ ++destructor_count_
; }
99 friend class base::RefCounted
<ScopedRefPtrCountDerived
>;
101 static int constructor_count_
;
102 static int destructor_count_
;
105 int ScopedRefPtrCountDerived::constructor_count_
= 0;
106 int ScopedRefPtrCountDerived::destructor_count_
= 0;
110 TEST(RefCountedUnitTest
, TestSelfAssignment
) {
111 SelfAssign
* p
= new SelfAssign
;
112 scoped_refptr
<SelfAssign
> var(p
);
114 EXPECT_EQ(var
.get(), p
);
117 TEST(RefCountedUnitTest
, ScopedRefPtrMemberAccess
) {
118 CheckDerivedMemberAccess check
;
121 TEST(RefCountedUnitTest
, ScopedRefPtrToSelfPointerAssignment
) {
122 ScopedRefPtrToSelf::reset_was_destroyed();
124 ScopedRefPtrToSelf
* check
= new ScopedRefPtrToSelf();
125 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
126 check
->self_ptr_
= nullptr;
127 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
130 TEST(RefCountedUnitTest
, ScopedRefPtrToSelfMoveAssignment
) {
131 ScopedRefPtrToSelf::reset_was_destroyed();
133 ScopedRefPtrToSelf
* check
= new ScopedRefPtrToSelf();
134 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
135 // Releasing |check->self_ptr_| will delete |check|.
136 // The move assignment operator must assign |check->self_ptr_| first then
137 // release |check->self_ptr_|.
138 check
->self_ptr_
= scoped_refptr
<ScopedRefPtrToSelf
>();
139 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
142 TEST(RefCountedUnitTest
, ScopedRefPtrToOpaque
) {
143 scoped_refptr
<base::OpaqueRefCounted
> p
= base::MakeOpaqueRefCounted();
144 base::TestOpaqueRefCounted(p
);
146 scoped_refptr
<base::OpaqueRefCounted
> q
;
148 base::TestOpaqueRefCounted(p
);
149 base::TestOpaqueRefCounted(q
);
152 TEST(RefCountedUnitTest
, BooleanTesting
) {
153 scoped_refptr
<SelfAssign
> p
;
159 TEST(RefCountedUnitTest
, Equality
) {
160 scoped_refptr
<SelfAssign
> p1(new SelfAssign
);
161 scoped_refptr
<SelfAssign
> p2(new SelfAssign
);
170 TEST(RefCountedUnitTest
, ConvertibleEquality
) {
171 scoped_refptr
<Derived
> p1(new Derived
);
172 scoped_refptr
<SelfAssign
> p2
;
183 TEST(RefCountedUnitTest
, SelfMoveAssignment
) {
184 ScopedRefPtrCountBase::reset_count();
187 ScopedRefPtrCountBase
*raw
= new ScopedRefPtrCountBase();
188 scoped_refptr
<ScopedRefPtrCountBase
> p(raw
);
189 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
190 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
193 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
194 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
195 EXPECT_EQ(raw
, p
.get());
197 // p goes out of scope.
199 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
200 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
203 TEST(RefCountedUnitTest
, MoveAssignment1
) {
204 ScopedRefPtrCountBase::reset_count();
207 ScopedRefPtrCountBase
*raw
= new ScopedRefPtrCountBase();
208 scoped_refptr
<ScopedRefPtrCountBase
> p1(raw
);
209 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
210 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
213 scoped_refptr
<ScopedRefPtrCountBase
> p2
;
216 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
217 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
218 EXPECT_EQ(nullptr, p1
.get());
219 EXPECT_EQ(raw
, p2
.get());
221 // p2 goes out of scope.
223 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
224 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
226 // p1 goes out of scope.
228 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
229 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
232 TEST(RefCountedUnitTest
, MoveAssignment2
) {
233 ScopedRefPtrCountBase::reset_count();
236 ScopedRefPtrCountBase
*raw
= new ScopedRefPtrCountBase();
237 scoped_refptr
<ScopedRefPtrCountBase
> p1
;
238 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
239 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
242 scoped_refptr
<ScopedRefPtrCountBase
> p2(raw
);
243 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
244 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
247 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
248 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
249 EXPECT_EQ(raw
, p1
.get());
250 EXPECT_EQ(nullptr, p2
.get());
252 // p2 goes out of scope.
254 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
255 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
257 // p1 goes out of scope.
259 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
260 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
263 TEST(RefCountedUnitTest
, MoveAssignmentSameInstance1
) {
264 ScopedRefPtrCountBase::reset_count();
267 ScopedRefPtrCountBase
*raw
= new ScopedRefPtrCountBase();
268 scoped_refptr
<ScopedRefPtrCountBase
> p1(raw
);
269 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
270 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
273 scoped_refptr
<ScopedRefPtrCountBase
> p2(p1
);
274 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
275 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
278 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
279 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
280 EXPECT_EQ(raw
, p1
.get());
281 EXPECT_EQ(nullptr, p2
.get());
283 // p2 goes out of scope.
285 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
286 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
288 // p1 goes out of scope.
290 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
291 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
294 TEST(RefCountedUnitTest
, MoveAssignmentSameInstance2
) {
295 ScopedRefPtrCountBase::reset_count();
298 ScopedRefPtrCountBase
*raw
= new ScopedRefPtrCountBase();
299 scoped_refptr
<ScopedRefPtrCountBase
> p1(raw
);
300 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
301 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
304 scoped_refptr
<ScopedRefPtrCountBase
> p2(p1
);
305 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
306 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
309 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
310 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
311 EXPECT_EQ(nullptr, p1
.get());
312 EXPECT_EQ(raw
, p2
.get());
314 // p2 goes out of scope.
316 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
317 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
319 // p1 goes out of scope.
321 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
322 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
325 TEST(RefCountedUnitTest
, MoveAssignmentDifferentInstances
) {
326 ScopedRefPtrCountBase::reset_count();
329 ScopedRefPtrCountBase
*raw1
= new ScopedRefPtrCountBase();
330 scoped_refptr
<ScopedRefPtrCountBase
> p1(raw1
);
331 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
332 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
335 ScopedRefPtrCountBase
*raw2
= new ScopedRefPtrCountBase();
336 scoped_refptr
<ScopedRefPtrCountBase
> p2(raw2
);
337 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
338 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
341 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
342 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
343 EXPECT_EQ(raw2
, p1
.get());
344 EXPECT_EQ(nullptr, p2
.get());
346 // p2 goes out of scope.
348 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
349 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
351 // p1 goes out of scope.
353 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
354 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
357 TEST(RefCountedUnitTest
, MoveAssignmentDerived
) {
358 ScopedRefPtrCountBase::reset_count();
359 ScopedRefPtrCountDerived::reset_count();
362 ScopedRefPtrCountBase
*raw1
= new ScopedRefPtrCountBase();
363 scoped_refptr
<ScopedRefPtrCountBase
> p1(raw1
);
364 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
365 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
366 EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
367 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
370 ScopedRefPtrCountDerived
*raw2
= new ScopedRefPtrCountDerived();
371 scoped_refptr
<ScopedRefPtrCountDerived
> p2(raw2
);
372 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
373 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
374 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
375 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
378 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
379 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
380 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
381 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
382 EXPECT_EQ(raw2
, p1
.get());
383 EXPECT_EQ(nullptr, p2
.get());
385 // p2 goes out of scope.
387 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
388 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
389 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
390 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
392 // p1 goes out of scope.
394 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
395 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
396 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
397 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
400 TEST(RefCountedUnitTest
, MoveConstructor
) {
401 ScopedRefPtrCountBase::reset_count();
404 ScopedRefPtrCountBase
*raw
= new ScopedRefPtrCountBase();
405 scoped_refptr
<ScopedRefPtrCountBase
> p1(raw
);
406 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
407 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
410 scoped_refptr
<ScopedRefPtrCountBase
> p2(p1
.Pass());
411 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
412 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
413 EXPECT_EQ(nullptr, p1
.get());
414 EXPECT_EQ(raw
, p2
.get());
416 // p2 goes out of scope.
418 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
419 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
421 // p1 goes out of scope.
423 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
424 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
427 TEST(RefCountedUnitTest
, MoveConstructorDerived
) {
428 ScopedRefPtrCountBase::reset_count();
429 ScopedRefPtrCountDerived::reset_count();
432 ScopedRefPtrCountDerived
*raw1
= new ScopedRefPtrCountDerived();
433 scoped_refptr
<ScopedRefPtrCountDerived
> p1(raw1
);
434 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
435 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
436 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
437 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
440 scoped_refptr
<ScopedRefPtrCountBase
> p2(p1
.Pass());
441 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
442 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
443 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
444 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
445 EXPECT_EQ(nullptr, p1
.get());
446 EXPECT_EQ(raw1
, p2
.get());
448 // p2 goes out of scope.
450 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
451 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
452 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
453 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
455 // p1 goes out of scope.
457 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
458 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
459 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
460 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());