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.
4
5 #include "base/memory/scoped_ptr.h"
6
7 #include <stddef.h>
8
9 #include <sstream>
10
11 #include <gtest/gtest.h>
12
13 #include "base/bind.h"
14 #include "base/callback.h"
15 #include "base/macros.h"
16 #include "build/build_config.h"
17
18 namespace {
19
20 // Used to test depth subtyping.
21 class ConDecLoggerParent {
22 public:
~ConDecLoggerParent()23 virtual ~ConDecLoggerParent() {}
24
25 virtual void SetPtr(int* ptr) = 0;
26
27 virtual int SomeMeth(int x) const = 0;
28 };
29
30 class ConDecLogger : public ConDecLoggerParent {
31 public:
ConDecLogger()32 ConDecLogger() : ptr_(NULL) { }
ConDecLogger(int * ptr)33 explicit ConDecLogger(int* ptr) { SetPtr(ptr); }
~ConDecLogger()34 ~ConDecLogger() override { --*ptr_; }
35
SetPtr(int * ptr)36 void SetPtr(int* ptr) override {
37 ptr_ = ptr;
38 ++*ptr_;
39 }
40
SomeMeth(int x) const41 int SomeMeth(int x) const override { return x; }
42
43 private:
44 int* ptr_;
45
46 DISALLOW_COPY_AND_ASSIGN(ConDecLogger);
47 };
48
49 struct CountingDeleter {
CountingDeleter__anon54d8b8d30111::CountingDeleter50 explicit CountingDeleter(int* count) : count_(count) {}
operator ()__anon54d8b8d30111::CountingDeleter51 inline void operator()(double* ptr) const {
52 (*count_)++;
53 }
54 int* count_;
55 };
56
57 // Used to test assignment of convertible deleters.
58 struct CountingDeleterChild : public CountingDeleter {
CountingDeleterChild__anon54d8b8d30111::CountingDeleterChild59 explicit CountingDeleterChild(int* count) : CountingDeleter(count) {}
60 };
61
62 class OverloadedNewAndDelete {
63 public:
operator new(size_t size)64 void* operator new(size_t size) {
65 g_new_count++;
66 return malloc(size);
67 }
68
operator delete(void * ptr)69 void operator delete(void* ptr) {
70 g_delete_count++;
71 free(ptr);
72 }
73
ResetCounters()74 static void ResetCounters() {
75 g_new_count = 0;
76 g_delete_count = 0;
77 }
78
new_count()79 static int new_count() { return g_new_count; }
delete_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
87 int OverloadedNewAndDelete::g_new_count = 0;
88 int OverloadedNewAndDelete::g_delete_count = 0;
89
PassThru(scoped_ptr<ConDecLogger> logger)90 scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) {
91 return logger;
92 }
93
GrabAndDrop(scoped_ptr<ConDecLogger> logger)94 void 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.
TestReturnOfType(int * constructed)99 scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) {
100 return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed));
101 }
102
103 } // namespace
104
TEST(ScopedPtrTest,ScopedPtr)105 TEST(ScopedPtrTest, ScopedPtr) {
106 int constructed = 0;
107
108 // Ensure size of scoped_ptr<> doesn't increase unexpectedly.
109 static_assert(sizeof(int*) >= sizeof(scoped_ptr<int>),
110 "scoped_ptr shouldn't be larger than the raw pointer");
111
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
153 // Test swap().
154 {
155 scoped_ptr<ConDecLogger> scoper1;
156 scoped_ptr<ConDecLogger> scoper2;
157 EXPECT_TRUE(scoper1.get() == scoper2.get());
158 EXPECT_FALSE(scoper1.get() != scoper2.get());
159
160 ConDecLogger* logger = new ConDecLogger(&constructed);
161 scoper1.reset(logger);
162 EXPECT_EQ(logger, scoper1.get());
163 EXPECT_FALSE(scoper2.get());
164 EXPECT_FALSE(scoper1.get() == scoper2.get());
165 EXPECT_TRUE(scoper1.get() != scoper2.get());
166
167 scoper2.swap(scoper1);
168 EXPECT_EQ(logger, scoper2.get());
169 EXPECT_FALSE(scoper1.get());
170 EXPECT_FALSE(scoper1.get() == scoper2.get());
171 EXPECT_TRUE(scoper1.get() != scoper2.get());
172 }
173 EXPECT_EQ(0, constructed);
174 }
175
TEST(ScopedPtrTest,ScopedPtrDepthSubtyping)176 TEST(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
185 scoped_ptr<ConDecLoggerParent> scoper_parent(std::move(scoper));
186 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;
203 scoper_parent = std::move(scoper);
204 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
216 scoped_ptr<const ConDecLogger> scoper_const(std::move(scoper));
217 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;
234 scoper_const = std::move(scoper);
235 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.
258 scoper = std::move(scoper_child);
259 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);
274 scoped_ptr<double, CountingDeleter> scoper_construct(
275 std::move(scoper_child));
276 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
TEST(ScopedPtrTest,ScopedPtrWithArray)287 TEST(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
335 // Test swap() and type-safe Boolean.
336 {
337 scoped_ptr<ConDecLogger[]> scoper1;
338 scoped_ptr<ConDecLogger[]> scoper2;
339 EXPECT_TRUE(scoper1.get() == scoper2.get());
340 EXPECT_FALSE(scoper1.get() != scoper2.get());
341
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());
351 EXPECT_FALSE(scoper1.get() == scoper2.get());
352 EXPECT_TRUE(scoper1.get() != scoper2.get());
353
354 scoper2.swap(scoper1);
355 EXPECT_EQ(loggers, scoper2.get());
356 EXPECT_FALSE(scoper1.get());
357 EXPECT_FALSE(scoper1.get() == scoper2.get());
358 EXPECT_TRUE(scoper1.get() != scoper2.get());
359 }
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
371 // Test moving with constructor;
372 scoped_ptr<ConDecLogger[]> scoper2(std::move(scoper));
373 EXPECT_EQ(kNumLoggers, constructed);
374
375 // Test moving with assignment;
376 scoped_ptr<ConDecLogger[]> scoper3;
377 scoper3 = std::move(scoper2);
378 EXPECT_EQ(kNumLoggers, constructed);
379 EXPECT_FALSE(scoper);
380 EXPECT_FALSE(scoper2);
381 EXPECT_TRUE(scoper3);
382 }
383 EXPECT_EQ(0, constructed);
384 }
385
TEST(ScopedPtrTest,MoveBehavior)386 TEST(ScopedPtrTest, MoveBehavior) {
387 int constructed = 0;
388 {
389 ConDecLogger* logger = new ConDecLogger(&constructed);
390 scoped_ptr<ConDecLogger> scoper(logger);
391 EXPECT_EQ(1, constructed);
392
393 // Test moving with constructor;
394 scoped_ptr<ConDecLogger> scoper2(std::move(scoper));
395 EXPECT_EQ(1, constructed);
396
397 // Test moving with assignment;
398 scoped_ptr<ConDecLogger> scoper3;
399 scoper3 = std::move(scoper2);
400 EXPECT_EQ(1, constructed);
401 EXPECT_FALSE(scoper.get());
402 EXPECT_FALSE(scoper2.get());
403 EXPECT_TRUE(scoper3.get());
404 }
405
406 #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().
410 {
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);
422 #endif
423
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.
431 GrabAndDrop(std::move(scoper));
432 EXPECT_FALSE(scoper.get());
433 }
434 EXPECT_EQ(0, constructed);
435 }
436
TEST(ScopedPtrTest,ReturnTypeBehavior)437 TEST(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
446 PassThru(std::move(scoper));
447 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.
458 PassThru(std::move(scoper));
459 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
TEST(ScopedPtrTest,CustomDeleter)471 TEST(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.
549 scoped_ptr<double, CountingDeleter> scoper3(std::move(scoper2));
550 scoper = std::move(scoper3);
551 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
561 // Test swap(), and type-safe Boolean.
562 {
563 scoped_ptr<double, CountingDeleter> scoper1(NULL,
564 CountingDeleter(&deletes));
565 scoped_ptr<double, CountingDeleter> scoper2(NULL,
566 CountingDeleter(&deletes));
567 EXPECT_TRUE(scoper1.get() == scoper2.get());
568 EXPECT_FALSE(scoper1.get() != scoper2.get());
569
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());
575 EXPECT_FALSE(scoper1.get() == scoper2.get());
576 EXPECT_TRUE(scoper1.get() != scoper2.get());
577
578 scoper2.swap(scoper1);
579 EXPECT_EQ(&dummy_value, scoper2.get());
580 EXPECT_FALSE(scoper1.get());
581 EXPECT_FALSE(scoper1.get() == scoper2.get());
582 EXPECT_TRUE(scoper1.get() != scoper2.get());
583 }
584 }
585
586 // Sanity check test for overloaded new and delete operators. Does not do full
587 // coverage of reset/release/move operations as that is redundant with the
588 // above.
TEST(ScopedPtrTest,OverloadedNewAndDelete)589 TEST(ScopedPtrTest, OverloadedNewAndDelete) {
590 {
591 OverloadedNewAndDelete::ResetCounters();
592 scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete());
593 EXPECT_TRUE(scoper.get());
594
595 scoped_ptr<OverloadedNewAndDelete> scoper2(std::move(scoper));
596 }
597 EXPECT_EQ(1, OverloadedNewAndDelete::delete_count());
598 EXPECT_EQ(1, OverloadedNewAndDelete::new_count());
599 }
600
NullIntReturn()601 scoped_ptr<int> NullIntReturn() {
602 return nullptr;
603 }
604
TEST(ScopedPtrTest,Nullptr)605 TEST(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
NullIntArrayReturn()617 scoped_ptr<int[]> NullIntArrayReturn() {
618 return nullptr;
619 }
620
TEST(ScopedPtrTest,NullptrArray)621 TEST(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
633 class Super {};
634 class Sub : public Super {};
635
SubClassReturn()636 scoped_ptr<Sub> SubClassReturn() {
637 return make_scoped_ptr(new Sub);
638 }
639
TEST(ScopedPtrTest,Conversion)640 TEST(ScopedPtrTest, Conversion) {
641 scoped_ptr<Sub> sub1(new Sub);
642 scoped_ptr<Sub> sub2(new Sub);
643
644 // Upcast with move works.
645 scoped_ptr<Super> super1 = std::move(sub1);
646 super1 = std::move(sub2);
647
648 // Upcast with an rvalue works.
649 scoped_ptr<Super> super2 = SubClassReturn();
650 super2 = SubClassReturn();
651 }
652
653 // Logging a scoped_ptr<T> to an ostream shouldn't convert it to a boolean
654 // value first.
TEST(ScopedPtrTest,LoggingDoesntConvertToBoolean)655 TEST(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 }
665
TEST(ScopedPtrTest,ReferenceCycle)666 TEST(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
TEST(ScopedPtrTest,Operators)699 TEST(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
TEST(ScopedPtrTest,ArrayOperators)772 TEST(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 }
844