blob: 54f62cf4cc579cf0525b23386956144a7753ba09 [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
7#include "base/test/opaque_ref_counted.h"
initial.commitd7cae122008-07-26 21:49:388#include "testing/gtest/include/gtest/gtest.h"
initial.commitd7cae122008-07-26 21:49:389
[email protected]935f7762009-01-10 00:53:1310namespace {
11
initial.commitd7cae122008-07-26 21:49:3812class SelfAssign : public base::RefCounted<SelfAssign> {
dcheng5ab2ac72014-11-26 02:35:0813 protected:
14 virtual ~SelfAssign() {}
[email protected]877d55d2009-11-05 21:53:0815
dcheng5ab2ac72014-11-26 02:35:0816 private:
17 friend class base::RefCounted<SelfAssign>;
18};
19
20class Derived : public SelfAssign {
21 protected:
22 ~Derived() override {}
23
24 private:
25 friend class base::RefCounted<Derived>;
initial.commitd7cae122008-07-26 21:49:3826};
27
[email protected]935f7762009-01-10 00:53:1328class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> {
29 public:
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_);
34 }
35};
36
[email protected]e6130b272012-01-05 10:52:5537class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> {
38 public:
[email protected]c9f977b2013-04-25 12:17:1539 ScopedRefPtrToSelf() : self_ptr_(this) {}
[email protected]e6130b272012-01-05 10:52:5540
41 static bool was_destroyed() { return was_destroyed_; }
42
kkimlabsaa3927982015-04-13 20:49:4343 static void reset_was_destroyed() { was_destroyed_ = false; }
44
45 scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
[email protected]e6130b272012-01-05 10:52:5546
47 private:
48 friend class base::RefCounted<ScopedRefPtrToSelf>;
[email protected]a9aaa9d12012-04-25 00:42:5149 ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
[email protected]e6130b272012-01-05 10:52:5550
51 static bool was_destroyed_;
[email protected]e6130b272012-01-05 10:52:5552};
53
54bool ScopedRefPtrToSelf::was_destroyed_ = false;
55
kkimlabsaa3927982015-04-13 20:49:4356class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
57 public:
58 ScopedRefPtrCountBase() { ++constructor_count_; }
59
60 static int constructor_count() { return constructor_count_; }
61
62 static int destructor_count() { return destructor_count_; }
63
64 static void reset_count() {
65 constructor_count_ = 0;
66 destructor_count_ = 0;
67 }
68
69 protected:
70 virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
71
72 private:
73 friend class base::RefCounted<ScopedRefPtrCountBase>;
74
75 static int constructor_count_;
76 static int destructor_count_;
77};
78
79int ScopedRefPtrCountBase::constructor_count_ = 0;
80int ScopedRefPtrCountBase::destructor_count_ = 0;
81
82class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
83 public:
84 ScopedRefPtrCountDerived() { ++constructor_count_; }
85
86 static int constructor_count() { return constructor_count_; }
87
88 static int destructor_count() { return destructor_count_; }
89
90 static void reset_count() {
91 constructor_count_ = 0;
92 destructor_count_ = 0;
93 }
94
95 protected:
96 ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
97
98 private:
99 friend class base::RefCounted<ScopedRefPtrCountDerived>;
100
101 static int constructor_count_;
102 static int destructor_count_;
103};
104
105int ScopedRefPtrCountDerived::constructor_count_ = 0;
106int ScopedRefPtrCountDerived::destructor_count_ = 0;
107
piman53130922016-04-20 01:04:40108class Other : public base::RefCounted<Other> {
109 private:
110 friend class base::RefCounted<Other>;
111
112 ~Other() {}
113};
114
115scoped_refptr<Other> Overloaded(scoped_refptr<Other> other) {
116 return other;
117}
118
119scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) {
120 return self_assign;
121}
122
123
[email protected]935f7762009-01-10 00:53:13124} // end namespace
125
initial.commitd7cae122008-07-26 21:49:38126TEST(RefCountedUnitTest, TestSelfAssignment) {
127 SelfAssign* p = new SelfAssign;
[email protected]ad8e04a2010-11-01 04:16:27128 scoped_refptr<SelfAssign> var(p);
initial.commitd7cae122008-07-26 21:49:38129 var = var;
130 EXPECT_EQ(var.get(), p);
131}
license.botbf09a502008-08-24 00:55:55132
[email protected]935f7762009-01-10 00:53:13133TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
134 CheckDerivedMemberAccess check;
135}
[email protected]e6130b272012-01-05 10:52:55136
kkimlabsaa3927982015-04-13 20:49:43137TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
138 ScopedRefPtrToSelf::reset_was_destroyed();
139
[email protected]e6130b272012-01-05 10:52:55140 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
141 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
kkimlabsaa3927982015-04-13 20:49:43142 check->self_ptr_ = nullptr;
143 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
144}
145
146TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
147 ScopedRefPtrToSelf::reset_was_destroyed();
148
149 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
150 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
151 // Releasing |check->self_ptr_| will delete |check|.
152 // The move assignment operator must assign |check->self_ptr_| first then
153 // release |check->self_ptr_|.
154 check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
[email protected]e6130b272012-01-05 10:52:55155 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
156}
mdempsky3d16d9f62014-10-09 22:17:09157
158TEST(RefCountedUnitTest, ScopedRefPtrToOpaque) {
159 scoped_refptr<base::OpaqueRefCounted> p = base::MakeOpaqueRefCounted();
160 base::TestOpaqueRefCounted(p);
161
162 scoped_refptr<base::OpaqueRefCounted> q;
163 q = p;
164 base::TestOpaqueRefCounted(p);
165 base::TestOpaqueRefCounted(q);
166}
dcheng5ab2ac72014-11-26 02:35:08167
168TEST(RefCountedUnitTest, BooleanTesting) {
scheib28aacfca2016-02-23 20:57:19169 scoped_refptr<SelfAssign> ptr_to_an_instance = new SelfAssign;
170 EXPECT_TRUE(ptr_to_an_instance);
171 EXPECT_FALSE(!ptr_to_an_instance);
172
173 if (ptr_to_an_instance) {
174 } else {
175 ADD_FAILURE() << "Pointer to an instance should result in true.";
176 }
177
178 if (!ptr_to_an_instance) { // check for operator!().
179 ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
180 }
181
182 scoped_refptr<SelfAssign> null_ptr;
183 EXPECT_FALSE(null_ptr);
184 EXPECT_TRUE(!null_ptr);
185
186 if (null_ptr) {
187 ADD_FAILURE() << "Null pointer should result in false.";
188 }
189
190 if (!null_ptr) { // check for operator!().
191 } else {
192 ADD_FAILURE() << "Null pointer should result in !x being true.";
193 }
dcheng5ab2ac72014-11-26 02:35:08194}
195
196TEST(RefCountedUnitTest, Equality) {
197 scoped_refptr<SelfAssign> p1(new SelfAssign);
198 scoped_refptr<SelfAssign> p2(new SelfAssign);
199
200 EXPECT_EQ(p1, p1);
201 EXPECT_EQ(p2, p2);
202
203 EXPECT_NE(p1, p2);
204 EXPECT_NE(p2, p1);
205}
206
207TEST(RefCountedUnitTest, ConvertibleEquality) {
208 scoped_refptr<Derived> p1(new Derived);
209 scoped_refptr<SelfAssign> p2;
210
211 EXPECT_NE(p1, p2);
212 EXPECT_NE(p2, p1);
213
214 p2 = p1;
215
216 EXPECT_EQ(p1, p2);
217 EXPECT_EQ(p2, p1);
218}
kkimlabsaa3927982015-04-13 20:49:43219
kkimlabsaa3927982015-04-13 20:49:43220TEST(RefCountedUnitTest, MoveAssignment1) {
221 ScopedRefPtrCountBase::reset_count();
222
223 {
224 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
225 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
226 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
227 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
228
229 {
230 scoped_refptr<ScopedRefPtrCountBase> p2;
231
danakj0c8d4aa2015-11-25 05:29:58232 p2 = std::move(p1);
kkimlabsaa3927982015-04-13 20:49:43233 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
234 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
235 EXPECT_EQ(nullptr, p1.get());
236 EXPECT_EQ(raw, p2.get());
237
238 // p2 goes out of scope.
239 }
240 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
241 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
242
243 // p1 goes out of scope.
244 }
245 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
246 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
247}
248
249TEST(RefCountedUnitTest, MoveAssignment2) {
250 ScopedRefPtrCountBase::reset_count();
251
252 {
253 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
254 scoped_refptr<ScopedRefPtrCountBase> p1;
255 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
256 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
257
258 {
259 scoped_refptr<ScopedRefPtrCountBase> p2(raw);
260 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
261 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
262
danakj0c8d4aa2015-11-25 05:29:58263 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43264 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
265 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
266 EXPECT_EQ(raw, p1.get());
267 EXPECT_EQ(nullptr, p2.get());
268
269 // p2 goes out of scope.
270 }
271 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
272 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
273
274 // p1 goes out of scope.
275 }
276 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
277 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
278}
279
280TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
281 ScopedRefPtrCountBase::reset_count();
282
283 {
284 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
285 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
286 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
287 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
288
289 {
290 scoped_refptr<ScopedRefPtrCountBase> p2(p1);
291 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
292 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
293
danakj0c8d4aa2015-11-25 05:29:58294 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43295 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
296 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
297 EXPECT_EQ(raw, p1.get());
298 EXPECT_EQ(nullptr, p2.get());
299
300 // p2 goes out of scope.
301 }
302 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
303 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
304
305 // p1 goes out of scope.
306 }
307 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
308 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
309}
310
311TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
312 ScopedRefPtrCountBase::reset_count();
313
314 {
315 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
316 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
317 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
318 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
319
320 {
321 scoped_refptr<ScopedRefPtrCountBase> p2(p1);
322 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
323 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
324
danakj0c8d4aa2015-11-25 05:29:58325 p2 = std::move(p1);
kkimlabsaa3927982015-04-13 20:49:43326 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
327 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
328 EXPECT_EQ(nullptr, p1.get());
329 EXPECT_EQ(raw, p2.get());
330
331 // p2 goes out of scope.
332 }
333 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
334 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
335
336 // p1 goes out of scope.
337 }
338 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
339 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
340}
341
342TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
343 ScopedRefPtrCountBase::reset_count();
344
345 {
346 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
347 scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
348 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
349 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
350
351 {
352 ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
353 scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
354 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
355 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
356
danakj0c8d4aa2015-11-25 05:29:58357 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43358 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
359 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
360 EXPECT_EQ(raw2, p1.get());
361 EXPECT_EQ(nullptr, p2.get());
362
363 // p2 goes out of scope.
364 }
365 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
366 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
367
368 // p1 goes out of scope.
369 }
370 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
371 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
372}
373
374TEST(RefCountedUnitTest, MoveAssignmentDerived) {
375 ScopedRefPtrCountBase::reset_count();
376 ScopedRefPtrCountDerived::reset_count();
377
378 {
379 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
380 scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
381 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
382 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
383 EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
384 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
385
386 {
387 ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
388 scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
389 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
390 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
391 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
392 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
393
danakj0c8d4aa2015-11-25 05:29:58394 p1 = std::move(p2);
kkimlabsaa3927982015-04-13 20:49:43395 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
396 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
397 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
398 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
399 EXPECT_EQ(raw2, p1.get());
400 EXPECT_EQ(nullptr, p2.get());
401
402 // p2 goes out of scope.
403 }
404 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
405 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
406 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
407 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
408
409 // p1 goes out of scope.
410 }
411 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
412 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
413 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
414 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
415}
416
417TEST(RefCountedUnitTest, MoveConstructor) {
418 ScopedRefPtrCountBase::reset_count();
419
420 {
421 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
422 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
423 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
424 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
425
426 {
danakj0c8d4aa2015-11-25 05:29:58427 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
kkimlabsaa3927982015-04-13 20:49:43428 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
429 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
430 EXPECT_EQ(nullptr, p1.get());
431 EXPECT_EQ(raw, p2.get());
432
433 // p2 goes out of scope.
434 }
435 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
436 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
437
438 // p1 goes out of scope.
439 }
440 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
441 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
442}
443
444TEST(RefCountedUnitTest, MoveConstructorDerived) {
445 ScopedRefPtrCountBase::reset_count();
446 ScopedRefPtrCountDerived::reset_count();
447
448 {
449 ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
450 scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
451 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
452 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
453 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
454 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
455
456 {
danakj0c8d4aa2015-11-25 05:29:58457 scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
kkimlabsaa3927982015-04-13 20:49:43458 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
459 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
460 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
461 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
462 EXPECT_EQ(nullptr, p1.get());
463 EXPECT_EQ(raw1, p2.get());
464
465 // p2 goes out of scope.
466 }
467 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
468 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
469 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
470 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
471
472 // p1 goes out of scope.
473 }
474 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
475 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
476 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
477 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
478}
479
piman53130922016-04-20 01:04:40480TEST(RefCountedUnitTest, TestOverloadResolutionCopy) {
481 scoped_refptr<Derived> derived(new Derived);
482 scoped_refptr<SelfAssign> expected(derived);
483 EXPECT_EQ(expected, Overloaded(derived));
484
485 scoped_refptr<Other> other(new Other);
486 EXPECT_EQ(other, Overloaded(other));
487}
488
489TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
490 scoped_refptr<Derived> derived(new Derived);
491 scoped_refptr<SelfAssign> expected(derived);
492 EXPECT_EQ(expected, Overloaded(std::move(derived)));
493
494 scoped_refptr<Other> other(new Other);
495 scoped_refptr<Other> other2(other);
496 EXPECT_EQ(other2, Overloaded(std::move(other)));
497}