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