tor-browser

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

TestSimpleFileInfo.cpp (7675B)


      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 <array>
      6 
      7 #include "FileInfo.h"
      8 #include "FileInfoImpl.h"
      9 #include "FileInfoManager.h"
     10 #include "gtest/gtest.h"
     11 #include "mozilla/ArrayAlgorithm.h"
     12 #include "mozilla/StaticMutex.h"
     13 #include "nsTArray.h"
     14 
     15 using namespace mozilla;
     16 using namespace mozilla::dom::indexedDB;
     17 
     18 class SimpleFileManager;
     19 
     20 using SimpleFileInfo = FileInfo<SimpleFileManager>;
     21 
     22 struct SimpleFileManagerStats final {
     23  // XXX We don't keep track of the specific aFileId parameters here, should we?
     24 
     25  size_t mAsyncDeleteFileCalls = 0;
     26  size_t mSyncDeleteFileCalls = 0;
     27 };
     28 
     29 class SimpleFileManager final : public FileInfoManager<SimpleFileManager>,
     30                                public AtomicSafeRefCounted<SimpleFileManager> {
     31 public:
     32  using FileInfoManager<SimpleFileManager>::MutexType;
     33 
     34  MOZ_DECLARE_REFCOUNTED_TYPENAME(SimpleFileManager)
     35 
     36  // SimpleFileManager functions that are used by SimpleFileInfo
     37 
     38  [[nodiscard]] nsresult AsyncDeleteFile(const int64_t aFileId) {
     39    MOZ_RELEASE_ASSERT(!ContainsFileInfo(aFileId));
     40 
     41    if (mStats) {
     42      ++mStats->mAsyncDeleteFileCalls;
     43    }
     44 
     45    return NS_OK;
     46  }
     47 
     48  [[nodiscard]] nsresult SyncDeleteFile(const int64_t aFileId) {
     49    MOZ_RELEASE_ASSERT(!ContainsFileInfo(aFileId));
     50 
     51    if (mStats) {
     52      ++mStats->mSyncDeleteFileCalls;
     53    }
     54    return NS_OK;
     55  }
     56 
     57  // Test-specific functions
     58  explicit SimpleFileManager(SimpleFileManagerStats* aStats = nullptr)
     59      : mStats{aStats} {}
     60 
     61  void CreateDBOnlyFileInfos() {
     62    for (const auto id : kDBOnlyFileInfoIds) {
     63      // Copied from within DatabaseFileManager::Init.
     64 
     65      MOZ_RELEASE_ASSERT(CreateFileInfo(Some(id), static_cast<nsrefcnt>(1)));
     66    }
     67  }
     68 
     69  static MutexType& MutexInstance() MOZ_RETURN_CAPABILITY(sMutex) {
     70    return sMutex;
     71  }
     72 
     73  static constexpr auto kDBOnlyFileInfoIds =
     74      std::array<int64_t, 3>{{10, 20, 30}};
     75 
     76 private:
     77  inline static MutexType sMutex;
     78 
     79  SimpleFileManagerStats* const mStats;
     80 };
     81 
     82 // These tests test the SimpleFileManager itself, to ensure the SimpleFileInfo
     83 // tests below are valid.
     84 
     85 TEST(DOM_IndexedDB_SimpleFileManager, Invalidate)
     86 {
     87  const auto fileManager = MakeSafeRefPtr<SimpleFileManager>();
     88 
     89  fileManager->Invalidate();
     90 
     91  ASSERT_TRUE(fileManager->Invalidated());
     92 }
     93 
     94 // These tests mainly test SimpleFileInfo, which is a simplified version of
     95 // DatabaseFileInfo (SimpleFileInfo doesn't work with real files stored on
     96 // disk). The actual objects, DatabaseFileInfo and DatabaseFileManager are not
     97 // tested here.
     98 
     99 TEST(DOM_IndexedDB_SimpleFileInfo, Create)
    100 {
    101  auto stats = SimpleFileManagerStats{};
    102 
    103  {
    104    const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
    105    auto fileInfo = fileManager->CreateFileInfo();
    106 
    107    int32_t memRefCnt, dbRefCnt;
    108    fileInfo->GetReferences(&memRefCnt, &dbRefCnt);
    109 
    110    ASSERT_EQ(fileManager, &fileInfo->Manager());
    111 
    112    ASSERT_EQ(1, memRefCnt);
    113    ASSERT_EQ(0, dbRefCnt);
    114  }
    115 
    116  ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
    117  ASSERT_EQ(1u, stats.mAsyncDeleteFileCalls);
    118 }
    119 
    120 TEST(DOM_IndexedDB_SimpleFileInfo, CreateWithInitialDBRefCnt)
    121 {
    122  auto stats = SimpleFileManagerStats{};
    123 
    124  {
    125    const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
    126    fileManager->CreateDBOnlyFileInfos();
    127 
    128    for (const auto id : SimpleFileManager::kDBOnlyFileInfoIds) {
    129      const auto fileInfo = fileManager->GetFileInfo(id);
    130      ASSERT_NE(nullptr, fileInfo);
    131 
    132      int32_t memRefCnt, dbRefCnt;
    133      fileInfo->GetReferences(&memRefCnt, &dbRefCnt);
    134 
    135      ASSERT_EQ(fileManager, &fileInfo->Manager());
    136 
    137      ASSERT_EQ(1, memRefCnt);  // we hold one in fileInfo ourselves
    138      ASSERT_EQ(1, dbRefCnt);
    139    }
    140  }
    141 
    142  ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
    143  // Since the files have still non-zero dbRefCnt, nothing must be deleted.
    144  ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
    145 }
    146 
    147 TEST(DOM_IndexedDB_SimpleFileInfo, CreateWithInitialDBRefCnt_Invalidate)
    148 {
    149  auto stats = SimpleFileManagerStats{};
    150 
    151  {
    152    const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
    153    fileManager->CreateDBOnlyFileInfos();
    154 
    155    const auto fileInfos = TransformIntoNewArray(
    156        SimpleFileManager::kDBOnlyFileInfoIds,
    157        [&fileManager](const auto id) { return fileManager->GetFileInfo(id); });
    158 
    159    fileManager->Invalidate();
    160 
    161    for (const auto& fileInfo : fileInfos) {
    162      int32_t memRefCnt, dbRefCnt;
    163      fileInfo->GetReferences(&memRefCnt, &dbRefCnt);
    164 
    165      ASSERT_EQ(1, memRefCnt);  // we hold one in fileInfo ourselves
    166      ASSERT_EQ(0, dbRefCnt);   // dbRefCnt was cleared by Invalidate
    167    }
    168  }
    169 
    170  ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
    171  // Since the files have still non-zero dbRefCnt, nothing must be deleted.
    172  ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
    173 }
    174 
    175 TEST(DOM_IndexedDB_SimpleFileInfo, CreateWithInitialDBRefCnt_UpdateDBRefsToZero)
    176 {
    177  auto stats = SimpleFileManagerStats{};
    178 
    179  {
    180    const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
    181    fileManager->CreateDBOnlyFileInfos();
    182 
    183    const auto fileInfo =
    184        fileManager->GetFileInfo(SimpleFileManager::kDBOnlyFileInfoIds[0]);
    185    fileInfo->UpdateDBRefs(-1);
    186 
    187    int32_t memRefCnt, dbRefCnt;
    188    fileInfo->GetReferences(&memRefCnt, &dbRefCnt);
    189 
    190    ASSERT_EQ(1, memRefCnt);  // we hold one in fileInfo ourselves
    191    ASSERT_EQ(0, dbRefCnt);
    192  }
    193 
    194  ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
    195  ASSERT_EQ(1u, stats.mAsyncDeleteFileCalls);
    196 }
    197 
    198 TEST(DOM_IndexedDB_SimpleFileInfo, ReleaseWithFileManagerCleanup)
    199 {
    200  auto stats = SimpleFileManagerStats{};
    201  {
    202    const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
    203    fileManager->CreateDBOnlyFileInfos();
    204 
    205    auto* fileInfo = fileManager->CreateFileInfo().forget().take();
    206    fileInfo->Release(/* aSyncDeleteFile */ true);
    207 
    208    // This was the only reference and SimpleFileManager was not invalidated,
    209    // so SimpleFileManager::Cleanup should have been called.
    210    ASSERT_EQ(1u, stats.mSyncDeleteFileCalls);
    211  }
    212  ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
    213 }
    214 
    215 #ifndef DEBUG
    216 // These tests cause assertion failures in DEBUG builds.
    217 
    218 TEST(DOM_IndexedDB_SimpleFileInfo, Invalidate_CreateFileInfo)
    219 {
    220  auto stats = SimpleFileManagerStats{};
    221  {
    222    const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
    223 
    224    fileManager->Invalidate();
    225 
    226    const auto fileInfo = fileManager->CreateFileInfo();
    227    (void)fileInfo;
    228 
    229    ASSERT_EQ(nullptr, fileInfo);
    230  }
    231 
    232  ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
    233  ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
    234 }
    235 #endif
    236 
    237 TEST(DOM_IndexedDB_SimpleFileInfo, Invalidate_Release)
    238 {
    239  auto stats = SimpleFileManagerStats{};
    240  {
    241    const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
    242 
    243    const auto fileInfo = fileManager->CreateFileInfo();
    244    (void)fileInfo;
    245 
    246    fileManager->Invalidate();
    247 
    248    // SimpleFileManager was invalidated, so Release does not do any cleanup.
    249  }
    250 
    251  ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
    252  ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
    253 }
    254 
    255 TEST(DOM_IndexedDB_SimpleFileInfo, Invalidate_ReleaseWithFileManagerCleanup)
    256 {
    257  auto stats = SimpleFileManagerStats{};
    258  {
    259    const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
    260 
    261    auto* fileInfo = fileManager->CreateFileInfo().forget().take();
    262 
    263    fileManager->Invalidate();
    264 
    265    // SimpleFileManager was invalidated, so Release does not do any cleanup.
    266    fileInfo->Release(/* aSyncDeleteFile */ true);
    267  }
    268 
    269  ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
    270  ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
    271 }
    272 
    273 // XXX Add test for GetFileForFileInfo