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