tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestSafeRefPtr.cpp (6948B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "gtest/gtest.h"
      8 #include "mozilla/RefCounted.h"
      9 #include "mozilla/dom/SafeRefPtr.h"
     10 
     11 using namespace mozilla;
     12 
     13 class SafeBase : public SafeRefCounted<SafeBase> {
     14 public:
     15  MOZ_DECLARE_REFCOUNTED_TYPENAME(SafeBase)
     16 
     17  SafeBase() : mDead(false) {}
     18 
     19  static inline int sNumDestroyed;
     20 
     21  ~SafeBase() {
     22    MOZ_RELEASE_ASSERT(!mDead);
     23    mDead = true;
     24    sNumDestroyed++;
     25  }
     26 
     27 private:
     28  bool mDead;
     29 };
     30 struct SafeDerived : public SafeBase {};
     31 
     32 class Base : public RefCounted<Base> {
     33 public:
     34  MOZ_DECLARE_REFCOUNTED_TYPENAME(Base)
     35 
     36  Base() : mDead(false) {}
     37 
     38  static inline int sNumDestroyed;
     39 
     40  ~Base() {
     41    MOZ_RELEASE_ASSERT(!mDead);
     42    mDead = true;
     43    sNumDestroyed++;
     44  }
     45 
     46 private:
     47  bool mDead;
     48 };
     49 
     50 struct Derived : public Base {};
     51 
     52 already_AddRefed<Base> NewFoo() {
     53  RefPtr<Base> ptr(new Base());
     54  return ptr.forget();
     55 }
     56 
     57 already_AddRefed<Base> NewBar() {
     58  RefPtr<Derived> bar = new Derived();
     59  return bar.forget();
     60 }
     61 
     62 TEST(DOM_IndexedDB_SafeRefPtr, Construct_Default)
     63 {
     64  Base::sNumDestroyed = 0;
     65  {
     66    SafeRefPtr<Base> ptr;
     67    ASSERT_FALSE(ptr);
     68    ASSERT_EQ(0, Base::sNumDestroyed);
     69  }
     70  ASSERT_EQ(0, Base::sNumDestroyed);
     71 }
     72 
     73 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromNullPtr)
     74 {
     75  Base::sNumDestroyed = 0;
     76  {
     77    SafeRefPtr<Base> ptr = nullptr;
     78    ASSERT_FALSE(ptr);
     79    ASSERT_EQ(0, Base::sNumDestroyed);
     80  }
     81  ASSERT_EQ(0, Base::sNumDestroyed);
     82 }
     83 
     84 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromMakeSafeRefPtr_SafeRefCounted)
     85 {
     86  SafeBase::sNumDestroyed = 0;
     87  {
     88    SafeRefPtr<SafeBase> ptr = MakeSafeRefPtr<SafeBase>();
     89    ASSERT_TRUE(ptr);
     90    ASSERT_EQ(1u, ptr->refCount());
     91  }
     92  ASSERT_EQ(1, SafeBase::sNumDestroyed);
     93 }
     94 
     95 TEST(DOM_IndexedDB_SafeRefPtr,
     96     Construct_FromMakeSafeRefPtr_SafeRefCounted_DerivedType)
     97 {
     98  SafeBase::sNumDestroyed = 0;
     99  {
    100    SafeRefPtr<SafeBase> ptr = MakeSafeRefPtr<SafeDerived>();
    101    ASSERT_TRUE(ptr);
    102    ASSERT_EQ(1u, ptr->refCount());
    103  }
    104  ASSERT_EQ(1, SafeBase::sNumDestroyed);
    105 }
    106 
    107 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromMakeSafeRefPtr_RefCounted)
    108 {
    109  Base::sNumDestroyed = 0;
    110  {
    111    SafeRefPtr<Base> ptr = MakeSafeRefPtr<Base>();
    112    ASSERT_TRUE(ptr);
    113    ASSERT_EQ(1u, ptr->refCount());
    114  }
    115  ASSERT_EQ(1, Base::sNumDestroyed);
    116 }
    117 
    118 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromRefPtr)
    119 {
    120  Base::sNumDestroyed = 0;
    121  {
    122    SafeRefPtr<Base> ptr = SafeRefPtr{MakeRefPtr<Base>()};
    123    ASSERT_TRUE(ptr);
    124    ASSERT_EQ(1u, ptr->refCount());
    125  }
    126  ASSERT_EQ(1, Base::sNumDestroyed);
    127 }
    128 
    129 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromRefPtr_DerivedType)
    130 {
    131  Base::sNumDestroyed = 0;
    132  {
    133    SafeRefPtr<Base> ptr = SafeRefPtr{MakeRefPtr<Derived>()};
    134    ASSERT_TRUE(ptr);
    135    ASSERT_EQ(1u, ptr->refCount());
    136  }
    137  ASSERT_EQ(1, Base::sNumDestroyed);
    138 }
    139 
    140 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromAlreadyAddRefed)
    141 {
    142  Base::sNumDestroyed = 0;
    143  {
    144    SafeRefPtr<Base> ptr1 = SafeRefPtr{NewFoo()};
    145    SafeRefPtr<Base> ptr2(NewFoo());
    146    ASSERT_TRUE(ptr1);
    147    ASSERT_TRUE(ptr2);
    148    ASSERT_EQ(0, Base::sNumDestroyed);
    149  }
    150  ASSERT_EQ(2, Base::sNumDestroyed);
    151 }
    152 
    153 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromAlreadyAddRefed_DerivedType)
    154 {
    155  Base::sNumDestroyed = 0;
    156  {
    157    SafeRefPtr<Base> ptr = SafeRefPtr{NewBar()};
    158    ASSERT_TRUE(ptr);
    159    ASSERT_EQ(1u, ptr->refCount());
    160    ASSERT_EQ(0, Base::sNumDestroyed);
    161  }
    162  ASSERT_EQ(1, Base::sNumDestroyed);
    163 }
    164 
    165 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromRawPtr)
    166 {
    167  Base::sNumDestroyed = 0;
    168  {
    169    SafeRefPtr<Base> ptr = SafeRefPtr{new Base(), AcquireStrongRefFromRawPtr{}};
    170    ASSERT_TRUE(ptr);
    171    ASSERT_EQ(1u, ptr->refCount());
    172    ASSERT_EQ(0, Base::sNumDestroyed);
    173  }
    174  ASSERT_EQ(1, Base::sNumDestroyed);
    175 }
    176 
    177 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromRawPtr_Dervied)
    178 {
    179  Base::sNumDestroyed = 0;
    180  {
    181    SafeRefPtr<Base> ptr =
    182        SafeRefPtr{new Derived(), AcquireStrongRefFromRawPtr{}};
    183    ASSERT_TRUE(ptr);
    184    ASSERT_EQ(1u, ptr->refCount());
    185    ASSERT_EQ(0, Base::sNumDestroyed);
    186  }
    187  ASSERT_EQ(1, Base::sNumDestroyed);
    188 }
    189 
    190 TEST(DOM_IndexedDB_SafeRefPtr, ClonePtr)
    191 {
    192  Base::sNumDestroyed = 0;
    193  {
    194    SafeRefPtr<Base> ptr1;
    195    {
    196      ptr1 = MakeSafeRefPtr<Base>();
    197      const SafeRefPtr<Base> ptr2 = ptr1.clonePtr();
    198      SafeRefPtr<Base> f3 = ptr2.clonePtr();
    199 
    200      ASSERT_EQ(3u, ptr1->refCount());
    201      ASSERT_EQ(0, Base::sNumDestroyed);
    202    }
    203    ASSERT_EQ(1u, ptr1->refCount());
    204    ASSERT_EQ(0, Base::sNumDestroyed);
    205  }
    206  ASSERT_EQ(1, Base::sNumDestroyed);
    207 }
    208 
    209 TEST(DOM_IndexedDB_SafeRefPtr, Forget)
    210 {
    211  Base::sNumDestroyed = 0;
    212  {
    213    SafeRefPtr<Base> ptr1 = MakeSafeRefPtr<Base>();
    214    SafeRefPtr<Base> ptr2 = SafeRefPtr{ptr1.forget()};
    215 
    216    ASSERT_FALSE(ptr1);
    217    ASSERT_TRUE(ptr2);
    218    ASSERT_EQ(1u, ptr2->refCount());
    219  }
    220  ASSERT_EQ(1, Base::sNumDestroyed);
    221 }
    222 
    223 TEST(DOM_IndexedDB_SafeRefPtr, Downcast)
    224 {
    225  Base::sNumDestroyed = 0;
    226  {
    227    SafeRefPtr<Base> ptr1 = MakeSafeRefPtr<Derived>();
    228    SafeRefPtr<Derived> ptr2 = std::move(ptr1).downcast<Derived>();
    229 
    230    ASSERT_FALSE(ptr1);
    231    ASSERT_TRUE(ptr2);
    232    ASSERT_EQ(1u, ptr2->refCount());
    233  }
    234  ASSERT_EQ(1, Base::sNumDestroyed);
    235 }
    236 
    237 struct SafeTest final : SafeBase {
    238  template <typename Func>
    239  explicit SafeTest(Func aCallback) {
    240    aCallback(SafeRefPtrFromThis());
    241  }
    242 };
    243 
    244 TEST(DOM_IndexedDB_SafeRefPtr, SafeRefPtrFromThis_StoreFromCtor)
    245 {
    246  SafeBase::sNumDestroyed = 0;
    247  {
    248    SafeRefPtr<SafeBase> ptr1;
    249    {
    250      SafeRefPtr<SafeTest> ptr2 =
    251          MakeSafeRefPtr<SafeTest>([&ptr1](SafeRefPtr<SafeBase> ptr) {
    252            ptr1 = std::move(ptr);
    253            EXPECT_EQ(2u, ptr1->refCount());
    254          });
    255      ASSERT_EQ(2u, ptr2->refCount());
    256    }
    257    ASSERT_EQ(0, SafeBase::sNumDestroyed);
    258    ASSERT_EQ(1u, ptr1->refCount());
    259  }
    260  ASSERT_EQ(1, SafeBase::sNumDestroyed);
    261 }
    262 
    263 TEST(DOM_IndexedDB_SafeRefPtr, SafeRefPtrFromThis_DiscardInCtor)
    264 {
    265  SafeBase::sNumDestroyed = 0;
    266  {
    267    SafeRefPtr<SafeTest> ptr = MakeSafeRefPtr<SafeTest>(
    268        [](SafeRefPtr<SafeBase> ptr) { EXPECT_EQ(2u, ptr->refCount()); });
    269    ASSERT_EQ(1u, ptr->refCount());
    270    ASSERT_EQ(0, SafeBase::sNumDestroyed);
    271  }
    272  ASSERT_EQ(1, SafeBase::sNumDestroyed);
    273 }
    274 
    275 TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromSelf)
    276 {
    277  SafeBase::sNumDestroyed = 0;
    278  {
    279    SafeRefPtr<SafeBase> ptr = MakeSafeRefPtr<SafeBase>();
    280    ptr = std::move(static_cast<SafeRefPtr<SafeBase>&>(ptr));
    281    ASSERT_EQ(1u, ptr->refCount());
    282    ASSERT_EQ(0, SafeBase::sNumDestroyed);
    283  }
    284  ASSERT_EQ(1, SafeBase::sNumDestroyed);
    285 }
    286 
    287 static_assert(
    288    std::is_same_v<SafeRefPtr<Base>,
    289                   decltype(std::declval<bool>() ? MakeSafeRefPtr<Derived>()
    290                                                 : MakeSafeRefPtr<Base>())>);