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