blob: 9eda8137b80f7908ba96a79747314b655104f907 [file] [log] [blame]
Vitaly Bukacbed2062015-08-17 12:54:05 -07001// 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.
4
5#include "base/memory/ref_counted.h"
6
Vitaly Buka8750b272015-08-18 18:39:08 -07007#include <gtest/gtest.h>
Vitaly Bukacbed2062015-08-17 12:54:05 -07008
9namespace {
10
11class SelfAssign : public base::RefCounted<SelfAssign> {
12 protected:
13 virtual ~SelfAssign() {}
14
15 private:
16 friend class base::RefCounted<SelfAssign>;
17};
18
19class Derived : public SelfAssign {
20 protected:
21 ~Derived() override {}
22
23 private:
24 friend class base::RefCounted<Derived>;
25};
26
27class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> {
28 public:
29 CheckDerivedMemberAccess() {
30 // This shouldn't compile if we don't have access to the member variable.
31 SelfAssign** pptr = &ptr_;
32 EXPECT_EQ(*pptr, ptr_);
33 }
34};
35
36class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> {
37 public:
38 ScopedRefPtrToSelf() : self_ptr_(this) {}
39
40 static bool was_destroyed() { return was_destroyed_; }
41
42 static void reset_was_destroyed() { was_destroyed_ = false; }
43
44 scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
45
46 private:
47 friend class base::RefCounted<ScopedRefPtrToSelf>;
48 ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
49
50 static bool was_destroyed_;
51};
52
53bool ScopedRefPtrToSelf::was_destroyed_ = false;
54
55class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
56 public:
57 ScopedRefPtrCountBase() { ++constructor_count_; }
58
59 static int constructor_count() { return constructor_count_; }
60
61 static int destructor_count() { return destructor_count_; }
62
63 static void reset_count() {
64 constructor_count_ = 0;
65 destructor_count_ = 0;
66 }
67
68 protected:
69 virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
70
71 private:
72 friend class base::RefCounted<ScopedRefPtrCountBase>;
73
74 static int constructor_count_;
75 static int destructor_count_;
76};
77
78int ScopedRefPtrCountBase::constructor_count_ = 0;
79int ScopedRefPtrCountBase::destructor_count_ = 0;
80
81class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
82 public:
83 ScopedRefPtrCountDerived() { ++constructor_count_; }
84
85 static int constructor_count() { return constructor_count_; }
86
87 static int destructor_count() { return destructor_count_; }
88
89 static void reset_count() {
90 constructor_count_ = 0;
91 destructor_count_ = 0;
92 }
93
94 protected:
95 ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
96
97 private:
98 friend class base::RefCounted<ScopedRefPtrCountDerived>;
99
100 static int constructor_count_;
101 static int destructor_count_;
102};
103
104int ScopedRefPtrCountDerived::constructor_count_ = 0;
105int ScopedRefPtrCountDerived::destructor_count_ = 0;
106
107} // end namespace
108
109TEST(RefCountedUnitTest, TestSelfAssignment) {
110 SelfAssign* p = new SelfAssign;
111 scoped_refptr<SelfAssign> var(p);
112 var = var;
113 EXPECT_EQ(var.get(), p);
114}
115
116TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
117 CheckDerivedMemberAccess check;
118}
119
120TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
121 ScopedRefPtrToSelf::reset_was_destroyed();
122
123 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
124 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
125 check->self_ptr_ = nullptr;
126 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
127}
128
129TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
130 ScopedRefPtrToSelf::reset_was_destroyed();
131
132 ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
133 EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
134 // Releasing |check->self_ptr_| will delete |check|.
135 // The move assignment operator must assign |check->self_ptr_| first then
136 // release |check->self_ptr_|.
137 check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
138 EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
139}
140
Vitaly Bukacbed2062015-08-17 12:54:05 -0700141TEST(RefCountedUnitTest, BooleanTesting) {
142 scoped_refptr<SelfAssign> p;
143 EXPECT_FALSE(p);
144 p = new SelfAssign;
145 EXPECT_TRUE(p);
146}
147
148TEST(RefCountedUnitTest, Equality) {
149 scoped_refptr<SelfAssign> p1(new SelfAssign);
150 scoped_refptr<SelfAssign> p2(new SelfAssign);
151
152 EXPECT_EQ(p1, p1);
153 EXPECT_EQ(p2, p2);
154
155 EXPECT_NE(p1, p2);
156 EXPECT_NE(p2, p1);
157}
158
159TEST(RefCountedUnitTest, ConvertibleEquality) {
160 scoped_refptr<Derived> p1(new Derived);
161 scoped_refptr<SelfAssign> p2;
162
163 EXPECT_NE(p1, p2);
164 EXPECT_NE(p2, p1);
165
166 p2 = p1;
167
168 EXPECT_EQ(p1, p2);
169 EXPECT_EQ(p2, p1);
170}
171
172TEST(RefCountedUnitTest, SelfMoveAssignment) {
173 ScopedRefPtrCountBase::reset_count();
174
175 {
176 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
177 scoped_refptr<ScopedRefPtrCountBase> p(raw);
178 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
179 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
180
181 p = p.Pass();
182 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
183 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
184 EXPECT_EQ(raw, p.get());
185
186 // p goes out of scope.
187 }
188 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
189 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
190}
191
192TEST(RefCountedUnitTest, MoveAssignment1) {
193 ScopedRefPtrCountBase::reset_count();
194
195 {
196 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
197 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
198 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
199 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
200
201 {
202 scoped_refptr<ScopedRefPtrCountBase> p2;
203
204 p2 = p1.Pass();
205 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
206 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
207 EXPECT_EQ(nullptr, p1.get());
208 EXPECT_EQ(raw, p2.get());
209
210 // p2 goes out of scope.
211 }
212 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
213 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
214
215 // p1 goes out of scope.
216 }
217 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
218 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
219}
220
221TEST(RefCountedUnitTest, MoveAssignment2) {
222 ScopedRefPtrCountBase::reset_count();
223
224 {
225 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
226 scoped_refptr<ScopedRefPtrCountBase> p1;
227 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
228 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
229
230 {
231 scoped_refptr<ScopedRefPtrCountBase> p2(raw);
232 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
233 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
234
235 p1 = p2.Pass();
236 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
237 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
238 EXPECT_EQ(raw, p1.get());
239 EXPECT_EQ(nullptr, p2.get());
240
241 // p2 goes out of scope.
242 }
243 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
244 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
245
246 // p1 goes out of scope.
247 }
248 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
249 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
250}
251
252TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
253 ScopedRefPtrCountBase::reset_count();
254
255 {
256 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
257 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
258 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
259 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
260
261 {
262 scoped_refptr<ScopedRefPtrCountBase> p2(p1);
263 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
264 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
265
266 p1 = p2.Pass();
267 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
268 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
269 EXPECT_EQ(raw, p1.get());
270 EXPECT_EQ(nullptr, p2.get());
271
272 // p2 goes out of scope.
273 }
274 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
275 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
276
277 // p1 goes out of scope.
278 }
279 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
280 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
281}
282
283TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
284 ScopedRefPtrCountBase::reset_count();
285
286 {
287 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
288 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
289 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
290 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
291
292 {
293 scoped_refptr<ScopedRefPtrCountBase> p2(p1);
294 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
295 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
296
297 p2 = p1.Pass();
298 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
299 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
300 EXPECT_EQ(nullptr, p1.get());
301 EXPECT_EQ(raw, p2.get());
302
303 // p2 goes out of scope.
304 }
305 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
306 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
307
308 // p1 goes out of scope.
309 }
310 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
311 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
312}
313
314TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
315 ScopedRefPtrCountBase::reset_count();
316
317 {
318 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
319 scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
320 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
321 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
322
323 {
324 ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
325 scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
326 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
327 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
328
329 p1 = p2.Pass();
330 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
331 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
332 EXPECT_EQ(raw2, p1.get());
333 EXPECT_EQ(nullptr, p2.get());
334
335 // p2 goes out of scope.
336 }
337 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
338 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
339
340 // p1 goes out of scope.
341 }
342 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
343 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
344}
345
346TEST(RefCountedUnitTest, MoveAssignmentDerived) {
347 ScopedRefPtrCountBase::reset_count();
348 ScopedRefPtrCountDerived::reset_count();
349
350 {
351 ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
352 scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
353 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
354 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
355 EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
356 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
357
358 {
359 ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
360 scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
361 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
362 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
363 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
364 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
365
366 p1 = p2.Pass();
367 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
368 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
369 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
370 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
371 EXPECT_EQ(raw2, p1.get());
372 EXPECT_EQ(nullptr, p2.get());
373
374 // p2 goes out of scope.
375 }
376 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
377 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
378 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
379 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
380
381 // p1 goes out of scope.
382 }
383 EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
384 EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
385 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
386 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
387}
388
389TEST(RefCountedUnitTest, MoveConstructor) {
390 ScopedRefPtrCountBase::reset_count();
391
392 {
393 ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
394 scoped_refptr<ScopedRefPtrCountBase> p1(raw);
395 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
396 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
397
398 {
399 scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass());
400 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
401 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
402 EXPECT_EQ(nullptr, p1.get());
403 EXPECT_EQ(raw, p2.get());
404
405 // p2 goes out of scope.
406 }
407 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
408 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
409
410 // p1 goes out of scope.
411 }
412 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
413 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
414}
415
416TEST(RefCountedUnitTest, MoveConstructorDerived) {
417 ScopedRefPtrCountBase::reset_count();
418 ScopedRefPtrCountDerived::reset_count();
419
420 {
421 ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
422 scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
423 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
424 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
425 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
426 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
427
428 {
429 scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass());
430 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
431 EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
432 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
433 EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
434 EXPECT_EQ(nullptr, p1.get());
435 EXPECT_EQ(raw1, p2.get());
436
437 // p2 goes out of scope.
438 }
439 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
440 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
441 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
442 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
443
444 // p1 goes out of scope.
445 }
446 EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
447 EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
448 EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
449 EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
450}
451