tor-browser

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

TestCopyOnWrite.cpp (5867B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "gtest/gtest.h"
      6 
      7 #include "CopyOnWrite.h"
      8 
      9 using namespace mozilla;
     10 using namespace mozilla::image;
     11 
     12 struct ValueStats {
     13  int32_t mCopies = 0;
     14  int32_t mFrees = 0;
     15  int32_t mCalls = 0;
     16  int32_t mConstCalls = 0;
     17  int32_t mSerial = 0;
     18 };
     19 
     20 struct Value {
     21  NS_INLINE_DECL_REFCOUNTING(Value)
     22 
     23  explicit Value(ValueStats& aStats)
     24      : mStats(aStats), mSerial(mStats.mSerial++) {}
     25 
     26  Value(const Value& aOther)
     27      : mStats(aOther.mStats), mSerial(mStats.mSerial++) {
     28    mStats.mCopies++;
     29  }
     30 
     31  void Go() { mStats.mCalls++; }
     32  void Go() const { mStats.mConstCalls++; }
     33 
     34  int32_t Serial() const { return mSerial; }
     35 
     36 protected:
     37  ~Value() { mStats.mFrees++; }
     38 
     39 private:
     40  ValueStats& mStats;
     41  int32_t mSerial;
     42 };
     43 
     44 TEST(ImageCopyOnWrite, Read)
     45 {
     46  ValueStats stats;
     47 
     48  {
     49    CopyOnWrite<Value> cow(new Value(stats));
     50 
     51    EXPECT_EQ(0, stats.mCopies);
     52    EXPECT_EQ(0, stats.mFrees);
     53    EXPECT_TRUE(cow.CanRead());
     54 
     55    cow.Read([&](const Value* aValue) {
     56      EXPECT_EQ(0, stats.mCopies);
     57      EXPECT_EQ(0, stats.mFrees);
     58      EXPECT_EQ(0, aValue->Serial());
     59      EXPECT_TRUE(cow.CanRead());
     60      EXPECT_TRUE(cow.CanWrite());
     61 
     62      aValue->Go();
     63 
     64      EXPECT_EQ(0, stats.mCalls);
     65      EXPECT_EQ(1, stats.mConstCalls);
     66    });
     67 
     68    EXPECT_EQ(0, stats.mCopies);
     69    EXPECT_EQ(0, stats.mFrees);
     70    EXPECT_EQ(0, stats.mCalls);
     71    EXPECT_EQ(1, stats.mConstCalls);
     72  }
     73 
     74  EXPECT_EQ(0, stats.mCopies);
     75  EXPECT_EQ(1, stats.mFrees);
     76 }
     77 
     78 TEST(ImageCopyOnWrite, RecursiveRead)
     79 {
     80  ValueStats stats;
     81 
     82  {
     83    CopyOnWrite<Value> cow(new Value(stats));
     84 
     85    EXPECT_EQ(0, stats.mCopies);
     86    EXPECT_EQ(0, stats.mFrees);
     87    EXPECT_TRUE(cow.CanRead());
     88 
     89    cow.Read([&](const Value* aValue) {
     90      EXPECT_EQ(0, stats.mCopies);
     91      EXPECT_EQ(0, stats.mFrees);
     92      EXPECT_EQ(0, aValue->Serial());
     93      EXPECT_TRUE(cow.CanRead());
     94      EXPECT_TRUE(cow.CanWrite());
     95 
     96      // Make sure that Read() inside a Read() succeeds.
     97      cow.Read(
     98          [&](const Value* aValue) {
     99            EXPECT_EQ(0, stats.mCopies);
    100            EXPECT_EQ(0, stats.mFrees);
    101            EXPECT_EQ(0, aValue->Serial());
    102            EXPECT_TRUE(cow.CanRead());
    103            EXPECT_TRUE(cow.CanWrite());
    104 
    105            aValue->Go();
    106 
    107            EXPECT_EQ(0, stats.mCalls);
    108            EXPECT_EQ(1, stats.mConstCalls);
    109          },
    110          []() {
    111            // This gets called if we can't read. We shouldn't get here.
    112            EXPECT_TRUE(false);
    113          });
    114    });
    115 
    116    EXPECT_EQ(0, stats.mCopies);
    117    EXPECT_EQ(0, stats.mFrees);
    118    EXPECT_EQ(0, stats.mCalls);
    119    EXPECT_EQ(1, stats.mConstCalls);
    120  }
    121 
    122  EXPECT_EQ(0, stats.mCopies);
    123  EXPECT_EQ(1, stats.mFrees);
    124 }
    125 
    126 TEST(ImageCopyOnWrite, Write)
    127 {
    128  ValueStats stats;
    129 
    130  {
    131    CopyOnWrite<Value> cow(new Value(stats));
    132 
    133    EXPECT_EQ(0, stats.mCopies);
    134    EXPECT_EQ(0, stats.mFrees);
    135    EXPECT_TRUE(cow.CanRead());
    136    EXPECT_TRUE(cow.CanWrite());
    137 
    138    cow.Write([&](Value* aValue) {
    139      EXPECT_EQ(0, stats.mCopies);
    140      EXPECT_EQ(0, stats.mFrees);
    141      EXPECT_EQ(0, aValue->Serial());
    142      EXPECT_TRUE(!cow.CanRead());
    143      EXPECT_TRUE(!cow.CanWrite());
    144 
    145      aValue->Go();
    146 
    147      EXPECT_EQ(1, stats.mCalls);
    148      EXPECT_EQ(0, stats.mConstCalls);
    149    });
    150 
    151    EXPECT_EQ(0, stats.mCopies);
    152    EXPECT_EQ(0, stats.mFrees);
    153    EXPECT_EQ(1, stats.mCalls);
    154    EXPECT_EQ(0, stats.mConstCalls);
    155  }
    156 
    157  EXPECT_EQ(0, stats.mCopies);
    158  EXPECT_EQ(1, stats.mFrees);
    159 }
    160 
    161 TEST(ImageCopyOnWrite, WriteRecursive)
    162 {
    163  ValueStats stats;
    164 
    165  {
    166    CopyOnWrite<Value> cow(new Value(stats));
    167 
    168    EXPECT_EQ(0, stats.mCopies);
    169    EXPECT_EQ(0, stats.mFrees);
    170    EXPECT_TRUE(cow.CanRead());
    171    EXPECT_TRUE(cow.CanWrite());
    172 
    173    cow.Read([&](const Value* aValue) {
    174      EXPECT_EQ(0, stats.mCopies);
    175      EXPECT_EQ(0, stats.mFrees);
    176      EXPECT_EQ(0, aValue->Serial());
    177      EXPECT_TRUE(cow.CanRead());
    178      EXPECT_TRUE(cow.CanWrite());
    179 
    180      // Make sure Write() inside a Read() succeeds.
    181      cow.Write(
    182          [&](Value* aValue) {
    183            EXPECT_EQ(1, stats.mCopies);
    184            EXPECT_EQ(0, stats.mFrees);
    185            EXPECT_EQ(1, aValue->Serial());
    186            EXPECT_TRUE(!cow.CanRead());
    187            EXPECT_TRUE(!cow.CanWrite());
    188 
    189            aValue->Go();
    190 
    191            EXPECT_EQ(1, stats.mCalls);
    192            EXPECT_EQ(0, stats.mConstCalls);
    193 
    194            // Make sure Read() inside a Write() fails.
    195            cow.Read(
    196                [](const Value* aValue) {
    197                  // This gets called if we can read. We shouldn't get here.
    198                  EXPECT_TRUE(false);
    199                },
    200                []() {
    201                  // This gets called if we can't read. We *should* get here.
    202                  EXPECT_TRUE(true);
    203                });
    204 
    205            // Make sure Write() inside a Write() fails.
    206            cow.Write(
    207                [](Value* aValue) {
    208                  // This gets called if we can write. We shouldn't get here.
    209                  EXPECT_TRUE(false);
    210                },
    211                []() {
    212                  // This gets called if we can't write. We *should* get here.
    213                  EXPECT_TRUE(true);
    214                });
    215          },
    216          []() {
    217            // This gets called if we can't write. We shouldn't get here.
    218            EXPECT_TRUE(false);
    219          });
    220 
    221      aValue->Go();
    222 
    223      EXPECT_EQ(1, stats.mCopies);
    224      EXPECT_EQ(0, stats.mFrees);
    225      EXPECT_EQ(1, stats.mCalls);
    226      EXPECT_EQ(1, stats.mConstCalls);
    227    });
    228 
    229    EXPECT_EQ(1, stats.mCopies);
    230    EXPECT_EQ(1, stats.mFrees);
    231    EXPECT_EQ(1, stats.mCalls);
    232    EXPECT_EQ(1, stats.mConstCalls);
    233  }
    234 
    235  EXPECT_EQ(1, stats.mCopies);
    236  EXPECT_EQ(2, stats.mFrees);
    237 }