summaryrefslogtreecommitdiffstats
path: root/dom/indexedDB/test/gtest/TestSimpleFileInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/indexedDB/test/gtest/TestSimpleFileInfo.cpp278
1 files changed, 278 insertions, 0 deletions
diff --git a/dom/indexedDB/test/gtest/TestSimpleFileInfo.cpp b/dom/indexedDB/test/gtest/TestSimpleFileInfo.cpp
new file mode 100644
index 0000000000..8971ee54fb
--- /dev/null
+++ b/dom/indexedDB/test/gtest/TestSimpleFileInfo.cpp
@@ -0,0 +1,278 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "FileInfo.h"
+#include "FileInfoImpl.h"
+#include "FileInfoManager.h"
+
+#include "gtest/gtest.h"
+
+#include "mozilla/ArrayAlgorithm.h"
+#include "mozilla/StaticMutex.h"
+#include "nsTArray.h"
+
+#include <array>
+
+using namespace mozilla;
+using namespace mozilla::dom::indexedDB;
+
+class SimpleFileManager;
+
+using SimpleFileInfo = FileInfo<SimpleFileManager>;
+
+struct SimpleFileManagerStats final {
+ // XXX We don't keep track of the specific aFileId parameters here, should we?
+
+ size_t mAsyncDeleteFileCalls = 0;
+ size_t mSyncDeleteFileCalls = 0;
+};
+
+class SimpleFileManager final : public FileInfoManager<SimpleFileManager>,
+ public AtomicSafeRefCounted<SimpleFileManager> {
+ public:
+ using FileInfoManager<SimpleFileManager>::MutexType;
+
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(SimpleFileManager)
+
+ // SimpleFileManager functions that are used by SimpleFileInfo
+
+ [[nodiscard]] nsresult AsyncDeleteFile(const int64_t aFileId) {
+ MOZ_RELEASE_ASSERT(!mFileInfos.Contains(aFileId));
+
+ if (mStats) {
+ ++mStats->mAsyncDeleteFileCalls;
+ }
+
+ return NS_OK;
+ }
+
+ [[nodiscard]] nsresult SyncDeleteFile(const int64_t aFileId) {
+ MOZ_RELEASE_ASSERT(!mFileInfos.Contains(aFileId));
+
+ if (mStats) {
+ ++mStats->mSyncDeleteFileCalls;
+ }
+ return NS_OK;
+ }
+
+ // Test-specific functions
+ explicit SimpleFileManager(SimpleFileManagerStats* aStats = nullptr)
+ : mStats{aStats} {}
+
+ void CreateDBOnlyFileInfos() {
+ for (const auto id : kDBOnlyFileInfoIds) {
+ // Copied from within DatabaseFileManager::Init.
+
+ mFileInfos.InsertOrUpdate(
+ id, MakeNotNull<SimpleFileInfo*>(FileInfoManagerGuard{},
+ SafeRefPtrFromThis(), id,
+ static_cast<nsrefcnt>(1)));
+
+ mLastFileId = std::max(id, mLastFileId);
+ }
+ }
+
+ static MutexType& Mutex() { return sMutex; }
+
+ static constexpr auto kDBOnlyFileInfoIds =
+ std::array<int64_t, 3>{{10, 20, 30}};
+
+ private:
+ inline static MutexType sMutex;
+
+ SimpleFileManagerStats* const mStats;
+};
+
+// These tests test the SimpleFileManager itself, to ensure the SimpleFileInfo
+// tests below are valid.
+
+TEST(DOM_IndexedDB_SimpleFileManager, Invalidate)
+{
+ const auto fileManager = MakeSafeRefPtr<SimpleFileManager>();
+
+ fileManager->Invalidate();
+
+ ASSERT_TRUE(fileManager->Invalidated());
+}
+
+// These tests mainly test SimpleFileInfo, which is a simplified version of
+// DatabaseFileInfo (SimpleFileInfo doesn't work with real files stored on
+// disk). The actual objects, DatabaseFileInfo and DatabaseFileManager are not
+// tested here.
+
+TEST(DOM_IndexedDB_SimpleFileInfo, Create)
+{
+ auto stats = SimpleFileManagerStats{};
+
+ {
+ const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
+ auto fileInfo = fileManager->CreateFileInfo();
+
+ int32_t memRefCnt, dbRefCnt;
+ fileInfo->GetReferences(&memRefCnt, &dbRefCnt);
+
+ ASSERT_EQ(fileManager, &fileInfo->Manager());
+
+ ASSERT_EQ(1, memRefCnt);
+ ASSERT_EQ(0, dbRefCnt);
+ }
+
+ ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
+ ASSERT_EQ(1u, stats.mAsyncDeleteFileCalls);
+}
+
+TEST(DOM_IndexedDB_SimpleFileInfo, CreateWithInitialDBRefCnt)
+{
+ auto stats = SimpleFileManagerStats{};
+
+ {
+ const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
+ fileManager->CreateDBOnlyFileInfos();
+
+ for (const auto id : SimpleFileManager::kDBOnlyFileInfoIds) {
+ const auto fileInfo = fileManager->GetFileInfo(id);
+ ASSERT_NE(nullptr, fileInfo);
+
+ int32_t memRefCnt, dbRefCnt;
+ fileInfo->GetReferences(&memRefCnt, &dbRefCnt);
+
+ ASSERT_EQ(fileManager, &fileInfo->Manager());
+
+ ASSERT_EQ(1, memRefCnt); // we hold one in fileInfo ourselves
+ ASSERT_EQ(1, dbRefCnt);
+ }
+ }
+
+ ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
+ // Since the files have still non-zero dbRefCnt, nothing must be deleted.
+ ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
+}
+
+TEST(DOM_IndexedDB_SimpleFileInfo, CreateWithInitialDBRefCnt_Invalidate)
+{
+ auto stats = SimpleFileManagerStats{};
+
+ {
+ const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
+ fileManager->CreateDBOnlyFileInfos();
+
+ const auto fileInfos = TransformIntoNewArray(
+ SimpleFileManager::kDBOnlyFileInfoIds,
+ [&fileManager](const auto id) { return fileManager->GetFileInfo(id); });
+
+ fileManager->Invalidate();
+
+ for (const auto& fileInfo : fileInfos) {
+ int32_t memRefCnt, dbRefCnt;
+ fileInfo->GetReferences(&memRefCnt, &dbRefCnt);
+
+ ASSERT_EQ(1, memRefCnt); // we hold one in fileInfo ourselves
+ ASSERT_EQ(0, dbRefCnt); // dbRefCnt was cleared by Invalidate
+ }
+ }
+
+ ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
+ // Since the files have still non-zero dbRefCnt, nothing must be deleted.
+ ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
+}
+
+TEST(DOM_IndexedDB_SimpleFileInfo, CreateWithInitialDBRefCnt_UpdateDBRefsToZero)
+{
+ auto stats = SimpleFileManagerStats{};
+
+ {
+ const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
+ fileManager->CreateDBOnlyFileInfos();
+
+ const auto fileInfo =
+ fileManager->GetFileInfo(SimpleFileManager::kDBOnlyFileInfoIds[0]);
+ fileInfo->UpdateDBRefs(-1);
+
+ int32_t memRefCnt, dbRefCnt;
+ fileInfo->GetReferences(&memRefCnt, &dbRefCnt);
+
+ ASSERT_EQ(1, memRefCnt); // we hold one in fileInfo ourselves
+ ASSERT_EQ(0, dbRefCnt);
+ }
+
+ ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
+ ASSERT_EQ(1u, stats.mAsyncDeleteFileCalls);
+}
+
+TEST(DOM_IndexedDB_SimpleFileInfo, ReleaseWithFileManagerCleanup)
+{
+ auto stats = SimpleFileManagerStats{};
+ {
+ const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
+ fileManager->CreateDBOnlyFileInfos();
+
+ auto* fileInfo = fileManager->CreateFileInfo().forget().take();
+ fileInfo->Release(/* aSyncDeleteFile */ true);
+
+ // This was the only reference and SimpleFileManager was not invalidated,
+ // so SimpleFileManager::Cleanup should have been called.
+ ASSERT_EQ(1u, stats.mSyncDeleteFileCalls);
+ }
+ ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
+}
+
+#ifndef DEBUG
+// These tests cause assertion failures in DEBUG builds.
+
+TEST(DOM_IndexedDB_SimpleFileInfo, Invalidate_CreateFileInfo)
+{
+ auto stats = SimpleFileManagerStats{};
+ {
+ const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
+
+ fileManager->Invalidate();
+
+ const auto fileInfo = fileManager->CreateFileInfo();
+ Unused << fileInfo;
+
+ ASSERT_EQ(nullptr, fileInfo);
+ }
+
+ ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
+ ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
+}
+#endif
+
+TEST(DOM_IndexedDB_SimpleFileInfo, Invalidate_Release)
+{
+ auto stats = SimpleFileManagerStats{};
+ {
+ const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
+
+ const auto fileInfo = fileManager->CreateFileInfo();
+ Unused << fileInfo;
+
+ fileManager->Invalidate();
+
+ // SimpleFileManager was invalidated, so Release does not do any cleanup.
+ }
+
+ ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
+ ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
+}
+
+TEST(DOM_IndexedDB_SimpleFileInfo, Invalidate_ReleaseWithFileManagerCleanup)
+{
+ auto stats = SimpleFileManagerStats{};
+ {
+ const auto fileManager = MakeSafeRefPtr<SimpleFileManager>(&stats);
+
+ auto* fileInfo = fileManager->CreateFileInfo().forget().take();
+
+ fileManager->Invalidate();
+
+ // SimpleFileManager was invalidated, so Release does not do any cleanup.
+ fileInfo->Release(/* aSyncDeleteFile */ true);
+ }
+
+ ASSERT_EQ(0u, stats.mSyncDeleteFileCalls);
+ ASSERT_EQ(0u, stats.mAsyncDeleteFileCalls);
+}
+
+// XXX Add test for GetFileForFileInfo