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/basictypes.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "testing/gtest/include/gtest/gtest.h"
11 // Used to test depth subtyping.
12 class ConDecLoggerParent
{
14 virtual ~ConDecLoggerParent() {}
16 virtual void SetPtr(int* ptr
) = 0;
18 virtual int SomeMeth(int x
) const = 0;
21 class ConDecLogger
: public ConDecLoggerParent
{
23 ConDecLogger() : ptr_(NULL
) { }
24 explicit ConDecLogger(int* ptr
) { SetPtr(ptr
); }
25 virtual ~ConDecLogger() { --*ptr_
; }
27 virtual void SetPtr(int* ptr
) OVERRIDE
{ ptr_
= ptr
; ++*ptr_
; }
29 virtual int SomeMeth(int x
) const OVERRIDE
{ return x
; }
34 DISALLOW_COPY_AND_ASSIGN(ConDecLogger
);
37 scoped_ptr
<ConDecLogger
> PassThru(scoped_ptr
<ConDecLogger
> logger
) {
41 void GrabAndDrop(scoped_ptr
<ConDecLogger
> logger
) {
44 // Do not delete this function! It's existence is to test that you can
45 // return a temporarily constructed version of the scoper.
46 scoped_ptr
<ConDecLogger
> TestReturnOfType(int* constructed
) {
47 return scoped_ptr
<ConDecLogger
>(new ConDecLogger(constructed
));
50 scoped_ptr
<ConDecLoggerParent
> UpcastUsingPassAs(
51 scoped_ptr
<ConDecLogger
> object
) {
52 return object
.PassAs
<ConDecLoggerParent
>();
57 TEST(ScopedPtrTest
, ScopedPtr
) {
61 scoped_ptr
<ConDecLogger
> scoper(new ConDecLogger(&constructed
));
62 EXPECT_EQ(1, constructed
);
63 EXPECT_TRUE(scoper
.get());
65 EXPECT_EQ(10, scoper
->SomeMeth(10));
66 EXPECT_EQ(10, scoper
.get()->SomeMeth(10));
67 EXPECT_EQ(10, (*scoper
).SomeMeth(10));
69 EXPECT_EQ(0, constructed
);
71 // Test reset() and release()
73 scoped_ptr
<ConDecLogger
> scoper(new ConDecLogger(&constructed
));
74 EXPECT_EQ(1, constructed
);
75 EXPECT_TRUE(scoper
.get());
77 scoper
.reset(new ConDecLogger(&constructed
));
78 EXPECT_EQ(1, constructed
);
79 EXPECT_TRUE(scoper
.get());
82 EXPECT_EQ(0, constructed
);
83 EXPECT_FALSE(scoper
.get());
85 scoper
.reset(new ConDecLogger(&constructed
));
86 EXPECT_EQ(1, constructed
);
87 EXPECT_TRUE(scoper
.get());
89 ConDecLogger
* take
= scoper
.release();
90 EXPECT_EQ(1, constructed
);
91 EXPECT_FALSE(scoper
.get());
93 EXPECT_EQ(0, constructed
);
95 scoper
.reset(new ConDecLogger(&constructed
));
96 EXPECT_EQ(1, constructed
);
97 EXPECT_TRUE(scoper
.get());
99 EXPECT_EQ(0, constructed
);
101 // Test swap(), == and !=
103 scoped_ptr
<ConDecLogger
> scoper1
;
104 scoped_ptr
<ConDecLogger
> scoper2
;
105 EXPECT_TRUE(scoper1
== scoper2
.get());
106 EXPECT_FALSE(scoper1
!= scoper2
.get());
108 ConDecLogger
* logger
= new ConDecLogger(&constructed
);
109 scoper1
.reset(logger
);
110 EXPECT_EQ(logger
, scoper1
.get());
111 EXPECT_FALSE(scoper2
.get());
112 EXPECT_FALSE(scoper1
== scoper2
.get());
113 EXPECT_TRUE(scoper1
!= scoper2
.get());
115 scoper2
.swap(scoper1
);
116 EXPECT_EQ(logger
, scoper2
.get());
117 EXPECT_FALSE(scoper1
.get());
118 EXPECT_FALSE(scoper1
== scoper2
.get());
119 EXPECT_TRUE(scoper1
!= scoper2
.get());
121 EXPECT_EQ(0, constructed
);
124 TEST(ScopedPtrTest
, ScopedPtrDepthSubtyping
) {
127 // Test construction from a scoped_ptr to a derived class.
129 scoped_ptr
<ConDecLogger
> scoper(new ConDecLogger(&constructed
));
130 EXPECT_EQ(1, constructed
);
131 EXPECT_TRUE(scoper
.get());
133 scoped_ptr
<ConDecLoggerParent
> scoper_parent(scoper
.Pass());
134 EXPECT_EQ(1, constructed
);
135 EXPECT_TRUE(scoper_parent
.get());
136 EXPECT_FALSE(scoper
.get());
138 EXPECT_EQ(10, scoper_parent
->SomeMeth(10));
139 EXPECT_EQ(10, scoper_parent
.get()->SomeMeth(10));
140 EXPECT_EQ(10, (*scoper_parent
).SomeMeth(10));
142 EXPECT_EQ(0, constructed
);
144 // Test assignment from a scoped_ptr to a derived class.
146 scoped_ptr
<ConDecLogger
> scoper(new ConDecLogger(&constructed
));
147 EXPECT_EQ(1, constructed
);
148 EXPECT_TRUE(scoper
.get());
150 scoped_ptr
<ConDecLoggerParent
> scoper_parent
;
151 scoper_parent
= scoper
.Pass();
152 EXPECT_EQ(1, constructed
);
153 EXPECT_TRUE(scoper_parent
.get());
154 EXPECT_FALSE(scoper
.get());
156 EXPECT_EQ(0, constructed
);
158 // Test construction of a scoped_ptr with an additional const annotation.
160 scoped_ptr
<ConDecLogger
> scoper(new ConDecLogger(&constructed
));
161 EXPECT_EQ(1, constructed
);
162 EXPECT_TRUE(scoper
.get());
164 scoped_ptr
<const ConDecLogger
> scoper_const(scoper
.Pass());
165 EXPECT_EQ(1, constructed
);
166 EXPECT_TRUE(scoper_const
.get());
167 EXPECT_FALSE(scoper
.get());
169 EXPECT_EQ(10, scoper_const
->SomeMeth(10));
170 EXPECT_EQ(10, scoper_const
.get()->SomeMeth(10));
171 EXPECT_EQ(10, (*scoper_const
).SomeMeth(10));
173 EXPECT_EQ(0, constructed
);
175 // Test assignment to a scoped_ptr with an additional const annotation.
177 scoped_ptr
<ConDecLogger
> scoper(new ConDecLogger(&constructed
));
178 EXPECT_EQ(1, constructed
);
179 EXPECT_TRUE(scoper
.get());
181 scoped_ptr
<const ConDecLogger
> scoper_const
;
182 scoper_const
= scoper
.Pass();
183 EXPECT_EQ(1, constructed
);
184 EXPECT_TRUE(scoper_const
.get());
185 EXPECT_FALSE(scoper
.get());
187 EXPECT_EQ(0, constructed
);
190 TEST(ScopedPtrTest
, ScopedArray
) {
191 static const int kNumLoggers
= 12;
196 scoped_array
<ConDecLogger
> scoper(new ConDecLogger
[kNumLoggers
]);
197 EXPECT_TRUE(scoper
.get());
198 EXPECT_EQ(&scoper
[0], scoper
.get());
199 for (int i
= 0; i
< kNumLoggers
; ++i
) {
200 scoper
[i
].SetPtr(&constructed
);
202 EXPECT_EQ(12, constructed
);
204 EXPECT_EQ(10, scoper
.get()->SomeMeth(10));
205 EXPECT_EQ(10, scoper
[2].SomeMeth(10));
207 EXPECT_EQ(0, constructed
);
209 // Test reset() and release()
211 scoped_array
<ConDecLogger
> scoper
;
212 EXPECT_FALSE(scoper
.get());
213 EXPECT_FALSE(scoper
.release());
214 EXPECT_FALSE(scoper
.get());
216 EXPECT_FALSE(scoper
.get());
218 scoper
.reset(new ConDecLogger
[kNumLoggers
]);
219 for (int i
= 0; i
< kNumLoggers
; ++i
) {
220 scoper
[i
].SetPtr(&constructed
);
222 EXPECT_EQ(12, constructed
);
224 EXPECT_EQ(0, constructed
);
226 scoper
.reset(new ConDecLogger
[kNumLoggers
]);
227 for (int i
= 0; i
< kNumLoggers
; ++i
) {
228 scoper
[i
].SetPtr(&constructed
);
230 EXPECT_EQ(12, constructed
);
231 ConDecLogger
* ptr
= scoper
.release();
232 EXPECT_EQ(12, constructed
);
234 EXPECT_EQ(0, constructed
);
236 EXPECT_EQ(0, constructed
);
238 // Test swap(), == and !=
240 scoped_array
<ConDecLogger
> scoper1
;
241 scoped_array
<ConDecLogger
> scoper2
;
242 EXPECT_TRUE(scoper1
== scoper2
.get());
243 EXPECT_FALSE(scoper1
!= scoper2
.get());
245 ConDecLogger
* loggers
= new ConDecLogger
[kNumLoggers
];
246 for (int i
= 0; i
< kNumLoggers
; ++i
) {
247 loggers
[i
].SetPtr(&constructed
);
249 scoper1
.reset(loggers
);
250 EXPECT_EQ(loggers
, scoper1
.get());
251 EXPECT_FALSE(scoper2
.get());
252 EXPECT_FALSE(scoper1
== scoper2
.get());
253 EXPECT_TRUE(scoper1
!= scoper2
.get());
255 scoper2
.swap(scoper1
);
256 EXPECT_EQ(loggers
, scoper2
.get());
257 EXPECT_FALSE(scoper1
.get());
258 EXPECT_FALSE(scoper1
== scoper2
.get());
259 EXPECT_TRUE(scoper1
!= scoper2
.get());
261 EXPECT_EQ(0, constructed
);
264 TEST(ScopedPtrTest
, PassBehavior
) {
267 ConDecLogger
* logger
= new ConDecLogger(&constructed
);
268 scoped_ptr
<ConDecLogger
> scoper(logger
);
269 EXPECT_EQ(1, constructed
);
271 // Test Pass() with constructor;
272 scoped_ptr
<ConDecLogger
> scoper2(scoper
.Pass());
273 EXPECT_EQ(1, constructed
);
275 // Test Pass() with assignment;
276 scoped_ptr
<ConDecLogger
> scoper3
;
277 scoper3
= scoper2
.Pass();
278 EXPECT_EQ(1, constructed
);
279 EXPECT_FALSE(scoper
.get());
280 EXPECT_FALSE(scoper2
.get());
281 EXPECT_TRUE(scoper3
.get());
284 // Test uncaught Pass() does not leak.
286 ConDecLogger
* logger
= new ConDecLogger(&constructed
);
287 scoped_ptr
<ConDecLogger
> scoper(logger
);
288 EXPECT_EQ(1, constructed
);
290 // Should auto-destruct logger by end of scope.
292 EXPECT_FALSE(scoper
.get());
294 EXPECT_EQ(0, constructed
);
296 // Test that passing to function which does nothing does not leak.
298 ConDecLogger
* logger
= new ConDecLogger(&constructed
);
299 scoped_ptr
<ConDecLogger
> scoper(logger
);
300 EXPECT_EQ(1, constructed
);
302 // Should auto-destruct logger by end of scope.
303 GrabAndDrop(scoper
.Pass());
304 EXPECT_FALSE(scoper
.get());
306 EXPECT_EQ(0, constructed
);
309 TEST(ScopedPtrTest
, ReturnTypeBehavior
) {
312 // Test that we can return a scoped_ptr.
314 ConDecLogger
* logger
= new ConDecLogger(&constructed
);
315 scoped_ptr
<ConDecLogger
> scoper(logger
);
316 EXPECT_EQ(1, constructed
);
318 PassThru(scoper
.Pass());
319 EXPECT_FALSE(scoper
.get());
321 EXPECT_EQ(0, constructed
);
323 // Test uncaught return type not leak.
325 ConDecLogger
* logger
= new ConDecLogger(&constructed
);
326 scoped_ptr
<ConDecLogger
> scoper(logger
);
327 EXPECT_EQ(1, constructed
);
329 // Should auto-destruct logger by end of scope.
330 PassThru(scoper
.Pass());
331 EXPECT_FALSE(scoper
.get());
333 EXPECT_EQ(0, constructed
);
335 // Call TestReturnOfType() so the compiler doesn't warn for an unused
338 TestReturnOfType(&constructed
);
340 EXPECT_EQ(0, constructed
);
343 TEST(ScopedPtrTest
, PassAs
) {
346 scoped_ptr
<ConDecLogger
> scoper(new ConDecLogger(&constructed
));
347 EXPECT_EQ(1, constructed
);
348 EXPECT_TRUE(scoper
.get());
350 scoped_ptr
<ConDecLoggerParent
> scoper_parent
;
351 scoper_parent
= UpcastUsingPassAs(scoper
.Pass());
352 EXPECT_EQ(1, constructed
);
353 EXPECT_TRUE(scoper_parent
.get());
354 EXPECT_FALSE(scoper
.get());
356 EXPECT_EQ(0, constructed
);
359 // TODO scoped_ptr_malloc