blob: c1eb469f7327b273ad2428f9e7b8af4b3b773da1 [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/scoped_ptr.h"
6
Alex Vakulenko674f0eb2016-01-20 08:10:48 -08007#include <stddef.h>
8
Vitaly Bukacbed2062015-08-17 12:54:05 -07009#include <sstream>
10
Vitaly Buka8750b272015-08-18 18:39:08 -070011#include <gtest/gtest.h>
12
Vitaly Bukacbed2062015-08-17 12:54:05 -070013#include "base/bind.h"
14#include "base/callback.h"
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080015#include "base/macros.h"
16#include "build/build_config.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070017
18namespace {
19
20// Used to test depth subtyping.
21class ConDecLoggerParent {
22 public:
23 virtual ~ConDecLoggerParent() {}
24
25 virtual void SetPtr(int* ptr) = 0;
26
27 virtual int SomeMeth(int x) const = 0;
28};
29
30class ConDecLogger : public ConDecLoggerParent {
31 public:
32 ConDecLogger() : ptr_(NULL) { }
33 explicit ConDecLogger(int* ptr) { SetPtr(ptr); }
34 ~ConDecLogger() override { --*ptr_; }
35
36 void SetPtr(int* ptr) override {
37 ptr_ = ptr;
38 ++*ptr_;
39 }
40
41 int SomeMeth(int x) const override { return x; }
42
43 private:
44 int* ptr_;
45
46 DISALLOW_COPY_AND_ASSIGN(ConDecLogger);
47};
48
49struct CountingDeleter {
50 explicit CountingDeleter(int* count) : count_(count) {}
51 inline void operator()(double* ptr) const {
52 (*count_)++;
53 }
54 int* count_;
55};
56
57// Used to test assignment of convertible deleters.
58struct CountingDeleterChild : public CountingDeleter {
59 explicit CountingDeleterChild(int* count) : CountingDeleter(count) {}
60};
61
62class OverloadedNewAndDelete {
63 public:
64 void* operator new(size_t size) {
65 g_new_count++;
66 return malloc(size);
67 }
68
69 void operator delete(void* ptr) {
70 g_delete_count++;
71 free(ptr);
72 }
73
74 static void ResetCounters() {
75 g_new_count = 0;
76 g_delete_count = 0;
77 }
78
79 static int new_count() { return g_new_count; }
80 static int delete_count() { return g_delete_count; }
81
82 private:
83 static int g_new_count;
84 static int g_delete_count;
85};
86
87int OverloadedNewAndDelete::g_new_count = 0;
88int OverloadedNewAndDelete::g_delete_count = 0;
89
90scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) {
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080091 return logger;
Vitaly Bukacbed2062015-08-17 12:54:05 -070092}
93
94void GrabAndDrop(scoped_ptr<ConDecLogger> logger) {
95}
96
97// Do not delete this function! It's existence is to test that you can
98// return a temporarily constructed version of the scoper.
99scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) {
100 return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed));
101}
102
103} // namespace
104
105TEST(ScopedPtrTest, ScopedPtr) {
106 int constructed = 0;
107
108 // Ensure size of scoped_ptr<> doesn't increase unexpectedly.
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800109 static_assert(sizeof(int*) >= sizeof(scoped_ptr<int>),
110 "scoped_ptr shouldn't be larger than the raw pointer");
Vitaly Bukacbed2062015-08-17 12:54:05 -0700111
112 {
113 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
114 EXPECT_EQ(1, constructed);
115 EXPECT_TRUE(scoper.get());
116
117 EXPECT_EQ(10, scoper->SomeMeth(10));
118 EXPECT_EQ(10, scoper.get()->SomeMeth(10));
119 EXPECT_EQ(10, (*scoper).SomeMeth(10));
120 }
121 EXPECT_EQ(0, constructed);
122
123 // Test reset() and release()
124 {
125 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
126 EXPECT_EQ(1, constructed);
127 EXPECT_TRUE(scoper.get());
128
129 scoper.reset(new ConDecLogger(&constructed));
130 EXPECT_EQ(1, constructed);
131 EXPECT_TRUE(scoper.get());
132
133 scoper.reset();
134 EXPECT_EQ(0, constructed);
135 EXPECT_FALSE(scoper.get());
136
137 scoper.reset(new ConDecLogger(&constructed));
138 EXPECT_EQ(1, constructed);
139 EXPECT_TRUE(scoper.get());
140
141 ConDecLogger* take = scoper.release();
142 EXPECT_EQ(1, constructed);
143 EXPECT_FALSE(scoper.get());
144 delete take;
145 EXPECT_EQ(0, constructed);
146
147 scoper.reset(new ConDecLogger(&constructed));
148 EXPECT_EQ(1, constructed);
149 EXPECT_TRUE(scoper.get());
150 }
151 EXPECT_EQ(0, constructed);
152
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800153 // Test swap().
Vitaly Bukacbed2062015-08-17 12:54:05 -0700154 {
155 scoped_ptr<ConDecLogger> scoper1;
156 scoped_ptr<ConDecLogger> scoper2;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800157 EXPECT_TRUE(scoper1.get() == scoper2.get());
158 EXPECT_FALSE(scoper1.get() != scoper2.get());
Vitaly Bukacbed2062015-08-17 12:54:05 -0700159
160 ConDecLogger* logger = new ConDecLogger(&constructed);
161 scoper1.reset(logger);
162 EXPECT_EQ(logger, scoper1.get());
163 EXPECT_FALSE(scoper2.get());
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800164 EXPECT_FALSE(scoper1.get() == scoper2.get());
165 EXPECT_TRUE(scoper1.get() != scoper2.get());
Vitaly Bukacbed2062015-08-17 12:54:05 -0700166
167 scoper2.swap(scoper1);
168 EXPECT_EQ(logger, scoper2.get());
169 EXPECT_FALSE(scoper1.get());
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800170 EXPECT_FALSE(scoper1.get() == scoper2.get());
171 EXPECT_TRUE(scoper1.get() != scoper2.get());
Vitaly Bukacbed2062015-08-17 12:54:05 -0700172 }
173 EXPECT_EQ(0, constructed);
174}
175
176TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) {
177 int constructed = 0;
178
179 // Test construction from a scoped_ptr to a derived class.
180 {
181 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
182 EXPECT_EQ(1, constructed);
183 EXPECT_TRUE(scoper.get());
184
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800185 scoped_ptr<ConDecLoggerParent> scoper_parent(std::move(scoper));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700186 EXPECT_EQ(1, constructed);
187 EXPECT_TRUE(scoper_parent.get());
188 EXPECT_FALSE(scoper.get());
189
190 EXPECT_EQ(10, scoper_parent->SomeMeth(10));
191 EXPECT_EQ(10, scoper_parent.get()->SomeMeth(10));
192 EXPECT_EQ(10, (*scoper_parent).SomeMeth(10));
193 }
194 EXPECT_EQ(0, constructed);
195
196 // Test assignment from a scoped_ptr to a derived class.
197 {
198 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
199 EXPECT_EQ(1, constructed);
200 EXPECT_TRUE(scoper.get());
201
202 scoped_ptr<ConDecLoggerParent> scoper_parent;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800203 scoper_parent = std::move(scoper);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700204 EXPECT_EQ(1, constructed);
205 EXPECT_TRUE(scoper_parent.get());
206 EXPECT_FALSE(scoper.get());
207 }
208 EXPECT_EQ(0, constructed);
209
210 // Test construction of a scoped_ptr with an additional const annotation.
211 {
212 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
213 EXPECT_EQ(1, constructed);
214 EXPECT_TRUE(scoper.get());
215
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800216 scoped_ptr<const ConDecLogger> scoper_const(std::move(scoper));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700217 EXPECT_EQ(1, constructed);
218 EXPECT_TRUE(scoper_const.get());
219 EXPECT_FALSE(scoper.get());
220
221 EXPECT_EQ(10, scoper_const->SomeMeth(10));
222 EXPECT_EQ(10, scoper_const.get()->SomeMeth(10));
223 EXPECT_EQ(10, (*scoper_const).SomeMeth(10));
224 }
225 EXPECT_EQ(0, constructed);
226
227 // Test assignment to a scoped_ptr with an additional const annotation.
228 {
229 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
230 EXPECT_EQ(1, constructed);
231 EXPECT_TRUE(scoper.get());
232
233 scoped_ptr<const ConDecLogger> scoper_const;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800234 scoper_const = std::move(scoper);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700235 EXPECT_EQ(1, constructed);
236 EXPECT_TRUE(scoper_const.get());
237 EXPECT_FALSE(scoper.get());
238 }
239 EXPECT_EQ(0, constructed);
240
241 // Test assignment to a scoped_ptr deleter of parent type.
242 {
243 // Custom deleters never touch these value.
244 double dummy_value, dummy_value2;
245 int deletes = 0;
246 int alternate_deletes = 0;
247 scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
248 CountingDeleter(&deletes));
249 scoped_ptr<double, CountingDeleterChild> scoper_child(
250 &dummy_value2, CountingDeleterChild(&alternate_deletes));
251
252 EXPECT_TRUE(scoper);
253 EXPECT_TRUE(scoper_child);
254 EXPECT_EQ(0, deletes);
255 EXPECT_EQ(0, alternate_deletes);
256
257 // Test this compiles and correctly overwrites the deleter state.
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800258 scoper = std::move(scoper_child);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700259 EXPECT_TRUE(scoper);
260 EXPECT_FALSE(scoper_child);
261 EXPECT_EQ(1, deletes);
262 EXPECT_EQ(0, alternate_deletes);
263
264 scoper.reset();
265 EXPECT_FALSE(scoper);
266 EXPECT_FALSE(scoper_child);
267 EXPECT_EQ(1, deletes);
268 EXPECT_EQ(1, alternate_deletes);
269
270 scoper_child.reset(&dummy_value);
271 EXPECT_TRUE(scoper_child);
272 EXPECT_EQ(1, deletes);
273 EXPECT_EQ(1, alternate_deletes);
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800274 scoped_ptr<double, CountingDeleter> scoper_construct(
275 std::move(scoper_child));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700276 EXPECT_TRUE(scoper_construct);
277 EXPECT_FALSE(scoper_child);
278 EXPECT_EQ(1, deletes);
279 EXPECT_EQ(1, alternate_deletes);
280
281 scoper_construct.reset();
282 EXPECT_EQ(1, deletes);
283 EXPECT_EQ(2, alternate_deletes);
284 }
285}
286
287TEST(ScopedPtrTest, ScopedPtrWithArray) {
288 static const int kNumLoggers = 12;
289
290 int constructed = 0;
291
292 {
293 scoped_ptr<ConDecLogger[]> scoper(new ConDecLogger[kNumLoggers]);
294 EXPECT_TRUE(scoper);
295 EXPECT_EQ(&scoper[0], scoper.get());
296 for (int i = 0; i < kNumLoggers; ++i) {
297 scoper[i].SetPtr(&constructed);
298 }
299 EXPECT_EQ(12, constructed);
300
301 EXPECT_EQ(10, scoper.get()->SomeMeth(10));
302 EXPECT_EQ(10, scoper[2].SomeMeth(10));
303 }
304 EXPECT_EQ(0, constructed);
305
306 // Test reset() and release()
307 {
308 scoped_ptr<ConDecLogger[]> scoper;
309 EXPECT_FALSE(scoper.get());
310 EXPECT_FALSE(scoper.release());
311 EXPECT_FALSE(scoper.get());
312 scoper.reset();
313 EXPECT_FALSE(scoper.get());
314
315 scoper.reset(new ConDecLogger[kNumLoggers]);
316 for (int i = 0; i < kNumLoggers; ++i) {
317 scoper[i].SetPtr(&constructed);
318 }
319 EXPECT_EQ(12, constructed);
320 scoper.reset();
321 EXPECT_EQ(0, constructed);
322
323 scoper.reset(new ConDecLogger[kNumLoggers]);
324 for (int i = 0; i < kNumLoggers; ++i) {
325 scoper[i].SetPtr(&constructed);
326 }
327 EXPECT_EQ(12, constructed);
328 ConDecLogger* ptr = scoper.release();
329 EXPECT_EQ(12, constructed);
330 delete[] ptr;
331 EXPECT_EQ(0, constructed);
332 }
333 EXPECT_EQ(0, constructed);
334
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800335 // Test swap() and type-safe Boolean.
Vitaly Bukacbed2062015-08-17 12:54:05 -0700336 {
337 scoped_ptr<ConDecLogger[]> scoper1;
338 scoped_ptr<ConDecLogger[]> scoper2;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800339 EXPECT_TRUE(scoper1.get() == scoper2.get());
340 EXPECT_FALSE(scoper1.get() != scoper2.get());
Vitaly Bukacbed2062015-08-17 12:54:05 -0700341
342 ConDecLogger* loggers = new ConDecLogger[kNumLoggers];
343 for (int i = 0; i < kNumLoggers; ++i) {
344 loggers[i].SetPtr(&constructed);
345 }
346 scoper1.reset(loggers);
347 EXPECT_TRUE(scoper1);
348 EXPECT_EQ(loggers, scoper1.get());
349 EXPECT_FALSE(scoper2);
350 EXPECT_FALSE(scoper2.get());
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800351 EXPECT_FALSE(scoper1.get() == scoper2.get());
352 EXPECT_TRUE(scoper1.get() != scoper2.get());
Vitaly Bukacbed2062015-08-17 12:54:05 -0700353
354 scoper2.swap(scoper1);
355 EXPECT_EQ(loggers, scoper2.get());
356 EXPECT_FALSE(scoper1.get());
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800357 EXPECT_FALSE(scoper1.get() == scoper2.get());
358 EXPECT_TRUE(scoper1.get() != scoper2.get());
Vitaly Bukacbed2062015-08-17 12:54:05 -0700359 }
360 EXPECT_EQ(0, constructed);
361
362 {
363 ConDecLogger* loggers = new ConDecLogger[kNumLoggers];
364 scoped_ptr<ConDecLogger[]> scoper(loggers);
365 EXPECT_TRUE(scoper);
366 for (int i = 0; i < kNumLoggers; ++i) {
367 scoper[i].SetPtr(&constructed);
368 }
369 EXPECT_EQ(kNumLoggers, constructed);
370
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800371 // Test moving with constructor;
372 scoped_ptr<ConDecLogger[]> scoper2(std::move(scoper));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700373 EXPECT_EQ(kNumLoggers, constructed);
374
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800375 // Test moving with assignment;
Vitaly Bukacbed2062015-08-17 12:54:05 -0700376 scoped_ptr<ConDecLogger[]> scoper3;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800377 scoper3 = std::move(scoper2);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700378 EXPECT_EQ(kNumLoggers, constructed);
379 EXPECT_FALSE(scoper);
380 EXPECT_FALSE(scoper2);
381 EXPECT_TRUE(scoper3);
382 }
383 EXPECT_EQ(0, constructed);
384}
385
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800386TEST(ScopedPtrTest, MoveBehavior) {
Vitaly Bukacbed2062015-08-17 12:54:05 -0700387 int constructed = 0;
388 {
389 ConDecLogger* logger = new ConDecLogger(&constructed);
390 scoped_ptr<ConDecLogger> scoper(logger);
391 EXPECT_EQ(1, constructed);
392
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800393 // Test moving with constructor;
394 scoped_ptr<ConDecLogger> scoper2(std::move(scoper));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700395 EXPECT_EQ(1, constructed);
396
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800397 // Test moving with assignment;
Vitaly Bukacbed2062015-08-17 12:54:05 -0700398 scoped_ptr<ConDecLogger> scoper3;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800399 scoper3 = std::move(scoper2);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700400 EXPECT_EQ(1, constructed);
401 EXPECT_FALSE(scoper.get());
402 EXPECT_FALSE(scoper2.get());
403 EXPECT_TRUE(scoper3.get());
404 }
405
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800406#if !defined(OS_ANDROID) && !defined(OS_LINUX)
407 // Test uncaught Pass() does not have side effects, because Pass()
408 // is implemented by std::move().
409 // TODO(danakj): Remove this test case when we remove Pass().
Vitaly Bukacbed2062015-08-17 12:54:05 -0700410 {
411 ConDecLogger* logger = new ConDecLogger(&constructed);
412 scoped_ptr<ConDecLogger> scoper(logger);
413 EXPECT_EQ(1, constructed);
414
415 // Should auto-destruct logger by end of scope.
416 scoped_ptr<ConDecLogger>&& rvalue = scoper.Pass();
417 // The Pass() function mimics std::move(), which does not have side-effects.
418 EXPECT_TRUE(scoper.get());
419 EXPECT_TRUE(rvalue);
420 }
421 EXPECT_EQ(0, constructed);
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800422#endif
Vitaly Bukacbed2062015-08-17 12:54:05 -0700423
424 // Test that passing to function which does nothing does not leak.
425 {
426 ConDecLogger* logger = new ConDecLogger(&constructed);
427 scoped_ptr<ConDecLogger> scoper(logger);
428 EXPECT_EQ(1, constructed);
429
430 // Should auto-destruct logger by end of scope.
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800431 GrabAndDrop(std::move(scoper));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700432 EXPECT_FALSE(scoper.get());
433 }
434 EXPECT_EQ(0, constructed);
435}
436
437TEST(ScopedPtrTest, ReturnTypeBehavior) {
438 int constructed = 0;
439
440 // Test that we can return a scoped_ptr.
441 {
442 ConDecLogger* logger = new ConDecLogger(&constructed);
443 scoped_ptr<ConDecLogger> scoper(logger);
444 EXPECT_EQ(1, constructed);
445
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800446 PassThru(std::move(scoper));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700447 EXPECT_FALSE(scoper.get());
448 }
449 EXPECT_EQ(0, constructed);
450
451 // Test uncaught return type not leak.
452 {
453 ConDecLogger* logger = new ConDecLogger(&constructed);
454 scoped_ptr<ConDecLogger> scoper(logger);
455 EXPECT_EQ(1, constructed);
456
457 // Should auto-destruct logger by end of scope.
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800458 PassThru(std::move(scoper));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700459 EXPECT_FALSE(scoper.get());
460 }
461 EXPECT_EQ(0, constructed);
462
463 // Call TestReturnOfType() so the compiler doesn't warn for an unused
464 // function.
465 {
466 TestReturnOfType(&constructed);
467 }
468 EXPECT_EQ(0, constructed);
469}
470
471TEST(ScopedPtrTest, CustomDeleter) {
472 double dummy_value; // Custom deleter never touches this value.
473 int deletes = 0;
474 int alternate_deletes = 0;
475
476 // Normal delete support.
477 {
478 deletes = 0;
479 scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
480 CountingDeleter(&deletes));
481 EXPECT_EQ(0, deletes);
482 EXPECT_TRUE(scoper.get());
483 }
484 EXPECT_EQ(1, deletes);
485
486 // Test reset() and release().
487 deletes = 0;
488 {
489 scoped_ptr<double, CountingDeleter> scoper(NULL,
490 CountingDeleter(&deletes));
491 EXPECT_FALSE(scoper.get());
492 EXPECT_FALSE(scoper.release());
493 EXPECT_FALSE(scoper.get());
494 scoper.reset();
495 EXPECT_FALSE(scoper.get());
496 EXPECT_EQ(0, deletes);
497
498 scoper.reset(&dummy_value);
499 scoper.reset();
500 EXPECT_EQ(1, deletes);
501
502 scoper.reset(&dummy_value);
503 EXPECT_EQ(&dummy_value, scoper.release());
504 }
505 EXPECT_EQ(1, deletes);
506
507 // Test get_deleter().
508 deletes = 0;
509 alternate_deletes = 0;
510 {
511 scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
512 CountingDeleter(&deletes));
513 // Call deleter manually.
514 EXPECT_EQ(0, deletes);
515 scoper.get_deleter()(&dummy_value);
516 EXPECT_EQ(1, deletes);
517
518 // Deleter is still there after reset.
519 scoper.reset();
520 EXPECT_EQ(2, deletes);
521 scoper.get_deleter()(&dummy_value);
522 EXPECT_EQ(3, deletes);
523
524 // Deleter can be assigned into (matches C++11 unique_ptr<> spec).
525 scoper.get_deleter() = CountingDeleter(&alternate_deletes);
526 scoper.reset(&dummy_value);
527 EXPECT_EQ(0, alternate_deletes);
528
529 }
530 EXPECT_EQ(3, deletes);
531 EXPECT_EQ(1, alternate_deletes);
532
533 // Test operator= deleter support.
534 deletes = 0;
535 alternate_deletes = 0;
536 {
537 double dummy_value2;
538 scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
539 CountingDeleter(&deletes));
540 scoped_ptr<double, CountingDeleter> scoper2(
541 &dummy_value2,
542 CountingDeleter(&alternate_deletes));
543 EXPECT_EQ(0, deletes);
544 EXPECT_EQ(0, alternate_deletes);
545
546 // Pass the second deleter through a constructor and an operator=. Then
547 // reinitialize the empty scopers to ensure that each one is deleting
548 // properly.
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800549 scoped_ptr<double, CountingDeleter> scoper3(std::move(scoper2));
550 scoper = std::move(scoper3);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700551 EXPECT_EQ(1, deletes);
552
553 scoper2.reset(&dummy_value2);
554 scoper3.reset(&dummy_value2);
555 EXPECT_EQ(0, alternate_deletes);
556
557 }
558 EXPECT_EQ(1, deletes);
559 EXPECT_EQ(3, alternate_deletes);
560
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800561 // Test swap(), and type-safe Boolean.
Vitaly Bukacbed2062015-08-17 12:54:05 -0700562 {
563 scoped_ptr<double, CountingDeleter> scoper1(NULL,
564 CountingDeleter(&deletes));
565 scoped_ptr<double, CountingDeleter> scoper2(NULL,
566 CountingDeleter(&deletes));
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800567 EXPECT_TRUE(scoper1.get() == scoper2.get());
568 EXPECT_FALSE(scoper1.get() != scoper2.get());
Vitaly Bukacbed2062015-08-17 12:54:05 -0700569
570 scoper1.reset(&dummy_value);
571 EXPECT_TRUE(scoper1);
572 EXPECT_EQ(&dummy_value, scoper1.get());
573 EXPECT_FALSE(scoper2);
574 EXPECT_FALSE(scoper2.get());
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800575 EXPECT_FALSE(scoper1.get() == scoper2.get());
576 EXPECT_TRUE(scoper1.get() != scoper2.get());
Vitaly Bukacbed2062015-08-17 12:54:05 -0700577
578 scoper2.swap(scoper1);
579 EXPECT_EQ(&dummy_value, scoper2.get());
580 EXPECT_FALSE(scoper1.get());
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800581 EXPECT_FALSE(scoper1.get() == scoper2.get());
582 EXPECT_TRUE(scoper1.get() != scoper2.get());
Vitaly Bukacbed2062015-08-17 12:54:05 -0700583 }
584}
585
586// Sanity check test for overloaded new and delete operators. Does not do full
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800587// coverage of reset/release/move operations as that is redundant with the
Vitaly Bukacbed2062015-08-17 12:54:05 -0700588// above.
589TEST(ScopedPtrTest, OverloadedNewAndDelete) {
590 {
591 OverloadedNewAndDelete::ResetCounters();
592 scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete());
593 EXPECT_TRUE(scoper.get());
594
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800595 scoped_ptr<OverloadedNewAndDelete> scoper2(std::move(scoper));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700596 }
597 EXPECT_EQ(1, OverloadedNewAndDelete::delete_count());
598 EXPECT_EQ(1, OverloadedNewAndDelete::new_count());
599}
600
601scoped_ptr<int> NullIntReturn() {
602 return nullptr;
603}
604
605TEST(ScopedPtrTest, Nullptr) {
606 scoped_ptr<int> scoper1(nullptr);
607 scoped_ptr<int> scoper2(new int);
608 scoper2 = nullptr;
609 scoped_ptr<int> scoper3(NullIntReturn());
610 scoped_ptr<int> scoper4 = NullIntReturn();
611 EXPECT_EQ(nullptr, scoper1.get());
612 EXPECT_EQ(nullptr, scoper2.get());
613 EXPECT_EQ(nullptr, scoper3.get());
614 EXPECT_EQ(nullptr, scoper4.get());
615}
616
617scoped_ptr<int[]> NullIntArrayReturn() {
618 return nullptr;
619}
620
621TEST(ScopedPtrTest, NullptrArray) {
622 scoped_ptr<int[]> scoper1(nullptr);
623 scoped_ptr<int[]> scoper2(new int[3]);
624 scoper2 = nullptr;
625 scoped_ptr<int[]> scoper3(NullIntArrayReturn());
626 scoped_ptr<int[]> scoper4 = NullIntArrayReturn();
627 EXPECT_EQ(nullptr, scoper1.get());
628 EXPECT_EQ(nullptr, scoper2.get());
629 EXPECT_EQ(nullptr, scoper3.get());
630 EXPECT_EQ(nullptr, scoper4.get());
631}
632
633class Super {};
634class Sub : public Super {};
635
636scoped_ptr<Sub> SubClassReturn() {
637 return make_scoped_ptr(new Sub);
638}
639
640TEST(ScopedPtrTest, Conversion) {
641 scoped_ptr<Sub> sub1(new Sub);
642 scoped_ptr<Sub> sub2(new Sub);
643
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800644 // Upcast with move works.
645 scoped_ptr<Super> super1 = std::move(sub1);
646 super1 = std::move(sub2);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700647
648 // Upcast with an rvalue works.
649 scoped_ptr<Super> super2 = SubClassReturn();
650 super2 = SubClassReturn();
651}
652
Vitaly Bukacbed2062015-08-17 12:54:05 -0700653// Logging a scoped_ptr<T> to an ostream shouldn't convert it to a boolean
654// value first.
655TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) {
656 scoped_ptr<int> x(new int);
657 std::stringstream s1;
658 s1 << x;
659
660 std::stringstream s2;
661 s2 << x.get();
662
663 EXPECT_EQ(s2.str(), s1.str());
664}
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800665
666TEST(ScopedPtrTest, ReferenceCycle) {
667 struct StructB;
668 struct StructA {
669 scoped_ptr<StructB> b;
670 };
671
672 struct StructB {
673 scoped_ptr<StructA> a;
674 };
675
676 // Create a reference cycle.
677 StructA* a = new StructA;
678 a->b.reset(new StructB);
679 a->b->a.reset(a);
680
681 // Break the cycle by calling reset(). This will cause |a| (and hence, |a->b|)
682 // to be deleted before the call to reset() returns. This tests that the
683 // implementation of scoped_ptr::reset() doesn't access |this| after it
684 // deletes the underlying pointer. This behaviour is consistent with the
685 // definition of unique_ptr::reset in C++11.
686 a->b.reset();
687
688 // Go again, but this time, break the cycle by invoking |a|'s destructor. This
689 // tests that the implementation of ~scoped_ptr doesn't infinitely recurse
690 // into the destructors of |a| and |a->b|. Note, deleting |a| instead will
691 // cause |a| to be double-free'd because |a->b| owns |a| and deletes it via
692 // its destructor.
693 a = new StructA;
694 a->b.reset(new StructB);
695 a->b->a.reset(a);
696 a->~StructA();
697}
698
699TEST(ScopedPtrTest, Operators) {
700 struct Parent {};
701 struct Child : public Parent {};
702
703 scoped_ptr<Parent> p(new Parent);
704 scoped_ptr<Parent> p2(new Parent);
705 scoped_ptr<Child> c(new Child);
706 scoped_ptr<Parent> pnull;
707
708 // Operator==.
709 EXPECT_TRUE(p == p);
710 EXPECT_FALSE(p == c);
711 EXPECT_FALSE(p == p2);
712 EXPECT_FALSE(p == pnull);
713
714 EXPECT_FALSE(p == nullptr);
715 EXPECT_FALSE(nullptr == p);
716 EXPECT_TRUE(pnull == nullptr);
717 EXPECT_TRUE(nullptr == pnull);
718
719 // Operator!=.
720 EXPECT_FALSE(p != p);
721 EXPECT_TRUE(p != c);
722 EXPECT_TRUE(p != p2);
723 EXPECT_TRUE(p != pnull);
724
725 EXPECT_TRUE(p != nullptr);
726 EXPECT_TRUE(nullptr != p);
727 EXPECT_FALSE(pnull != nullptr);
728 EXPECT_FALSE(nullptr != pnull);
729
730 // Compare two scoped_ptr<T>.
731 EXPECT_EQ(p.get() < p2.get(), p < p2);
732 EXPECT_EQ(p.get() <= p2.get(), p <= p2);
733 EXPECT_EQ(p.get() > p2.get(), p > p2);
734 EXPECT_EQ(p.get() >= p2.get(), p >= p2);
735 EXPECT_EQ(p2.get() < p.get(), p2 < p);
736 EXPECT_EQ(p2.get() <= p.get(), p2 <= p);
737 EXPECT_EQ(p2.get() > p.get(), p2 > p);
738 EXPECT_EQ(p2.get() >= p.get(), p2 >= p);
739
740 // And convertible scoped_ptr<T> and scoped_ptr<U>.
741 EXPECT_EQ(p.get() < c.get(), p < c);
742 EXPECT_EQ(p.get() <= c.get(), p <= c);
743 EXPECT_EQ(p.get() > c.get(), p > c);
744 EXPECT_EQ(p.get() >= c.get(), p >= c);
745 EXPECT_EQ(c.get() < p.get(), c < p);
746 EXPECT_EQ(c.get() <= p.get(), c <= p);
747 EXPECT_EQ(c.get() > p.get(), c > p);
748 EXPECT_EQ(c.get() >= p.get(), c >= p);
749
750 // Compare to nullptr.
751 EXPECT_TRUE(p > nullptr);
752 EXPECT_FALSE(nullptr > p);
753 EXPECT_FALSE(pnull > nullptr);
754 EXPECT_FALSE(nullptr > pnull);
755
756 EXPECT_TRUE(p >= nullptr);
757 EXPECT_FALSE(nullptr >= p);
758 EXPECT_TRUE(pnull >= nullptr);
759 EXPECT_TRUE(nullptr >= pnull);
760
761 EXPECT_FALSE(p < nullptr);
762 EXPECT_TRUE(nullptr < p);
763 EXPECT_FALSE(pnull < nullptr);
764 EXPECT_FALSE(nullptr < pnull);
765
766 EXPECT_FALSE(p <= nullptr);
767 EXPECT_TRUE(nullptr <= p);
768 EXPECT_TRUE(pnull <= nullptr);
769 EXPECT_TRUE(nullptr <= pnull);
770};
771
772TEST(ScopedPtrTest, ArrayOperators) {
773 struct Parent {};
774 struct Child : public Parent {};
775
776 scoped_ptr<Parent[]> p(new Parent[1]);
777 scoped_ptr<Parent[]> p2(new Parent[1]);
778 scoped_ptr<Child[]> c(new Child[1]);
779 scoped_ptr<Parent[]> pnull;
780
781 // Operator==.
782 EXPECT_TRUE(p == p);
783 EXPECT_FALSE(p == c);
784 EXPECT_FALSE(p == p2);
785 EXPECT_FALSE(p == pnull);
786
787 EXPECT_FALSE(p == nullptr);
788 EXPECT_FALSE(nullptr == p);
789 EXPECT_TRUE(pnull == nullptr);
790 EXPECT_TRUE(nullptr == pnull);
791
792 // Operator!=.
793 EXPECT_FALSE(p != p);
794 EXPECT_TRUE(p != c);
795 EXPECT_TRUE(p != p2);
796 EXPECT_TRUE(p != pnull);
797
798 EXPECT_TRUE(p != nullptr);
799 EXPECT_TRUE(nullptr != p);
800 EXPECT_FALSE(pnull != nullptr);
801 EXPECT_FALSE(nullptr != pnull);
802
803 // Compare two scoped_ptr<T>.
804 EXPECT_EQ(p.get() < p2.get(), p < p2);
805 EXPECT_EQ(p.get() <= p2.get(), p <= p2);
806 EXPECT_EQ(p.get() > p2.get(), p > p2);
807 EXPECT_EQ(p.get() >= p2.get(), p >= p2);
808 EXPECT_EQ(p2.get() < p.get(), p2 < p);
809 EXPECT_EQ(p2.get() <= p.get(), p2 <= p);
810 EXPECT_EQ(p2.get() > p.get(), p2 > p);
811 EXPECT_EQ(p2.get() >= p.get(), p2 >= p);
812
813 // And convertible scoped_ptr<T> and scoped_ptr<U>.
814 EXPECT_EQ(p.get() < c.get(), p < c);
815 EXPECT_EQ(p.get() <= c.get(), p <= c);
816 EXPECT_EQ(p.get() > c.get(), p > c);
817 EXPECT_EQ(p.get() >= c.get(), p >= c);
818 EXPECT_EQ(c.get() < p.get(), c < p);
819 EXPECT_EQ(c.get() <= p.get(), c <= p);
820 EXPECT_EQ(c.get() > p.get(), c > p);
821 EXPECT_EQ(c.get() >= p.get(), c >= p);
822
823 // Compare to nullptr.
824 EXPECT_TRUE(p > nullptr);
825 EXPECT_FALSE(nullptr > p);
826 EXPECT_FALSE(pnull > nullptr);
827 EXPECT_FALSE(nullptr > pnull);
828
829 EXPECT_TRUE(p >= nullptr);
830 EXPECT_FALSE(nullptr >= p);
831 EXPECT_TRUE(pnull >= nullptr);
832 EXPECT_TRUE(nullptr >= pnull);
833
834 EXPECT_FALSE(p < nullptr);
835 EXPECT_TRUE(nullptr < p);
836 EXPECT_FALSE(pnull < nullptr);
837 EXPECT_FALSE(nullptr < pnull);
838
839 EXPECT_FALSE(p <= nullptr);
840 EXPECT_TRUE(nullptr <= p);
841 EXPECT_TRUE(pnull <= nullptr);
842 EXPECT_TRUE(nullptr <= pnull);
843}