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