Home | History | Annotate | Download | only in memory
      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:
     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:
     32   ConDecLogger() : ptr_(NULL) { }
     33   explicit ConDecLogger(int* ptr) { SetPtr(ptr); }
     34   ~ConDecLogger() override { --*ptr_; }
     35 
     36   void SetPtr(int* ptr) override {
     37     ptr_ = ptr;
     38     ++*ptr_;
     39   }
     40 
     41   int SomeMeth(int x) const override { return x; }
     42 
     43  private:
     44   int* ptr_;
     45 
     46   DISALLOW_COPY_AND_ASSIGN(ConDecLogger);
     47 };
     48 
     49 struct CountingDeleter {
     50   explicit CountingDeleter(int* count) : count_(count) {}
     51   inline void operator()(double* ptr) const {
     52     (*count_)++;
     53   }
     54   int* count_;
     55 };
     56 
     57 // Used to test assignment of convertible deleters.
     58 struct CountingDeleterChild : public CountingDeleter {
     59   explicit CountingDeleterChild(int* count) : CountingDeleter(count) {}
     60 };
     61 
     62 class OverloadedNewAndDelete {
     63  public:
     64   void* operator new(size_t size) {
     65     g_new_count++;
     66     return malloc(size);
     67   }
     68 
     69   void operator delete(void* ptr) {
     70     g_delete_count++;
     71     free(ptr);
     72   }
     73 
     74   static void ResetCounters() {
     75     g_new_count = 0;
     76     g_delete_count = 0;
     77   }
     78 
     79   static int new_count() { return g_new_count; }
     80   static int delete_count() { return g_delete_count; }
     81 
     82  private:
     83   static int g_new_count;
     84   static int g_delete_count;
     85 };
     86 
     87 int OverloadedNewAndDelete::g_new_count = 0;
     88 int OverloadedNewAndDelete::g_delete_count = 0;
     89 
     90 scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) {
     91   return logger;
     92 }
     93 
     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.
     99 scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) {
    100   return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed));
    101 }
    102 
    103 }  // namespace
    104 
    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 
    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 
    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 
    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 
    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 
    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.
    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 
    601 scoped_ptr<int> NullIntReturn() {
    602   return nullptr;
    603 }
    604 
    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 
    617 scoped_ptr<int[]> NullIntArrayReturn() {
    618   return nullptr;
    619 }
    620 
    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 
    636 scoped_ptr<Sub> SubClassReturn() {
    637   return make_scoped_ptr(new Sub);
    638 }
    639 
    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.
    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 
    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 
    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 
    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