474 lines
19 KiB
C++
474 lines
19 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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 "FileSystemParentTypes.h"
|
|
#include "TestHelpers.h"
|
|
#include "datamodel/FileSystemDataManager.h"
|
|
#include "datamodel/FileSystemDatabaseManager.h"
|
|
#include "datamodel/FileSystemFileManager.h"
|
|
#include "gtest/gtest.h"
|
|
#include "mozIStorageService.h"
|
|
#include "mozStorageCID.h"
|
|
#include "mozilla/SpinEventLoopUntil.h"
|
|
#include "mozilla/dom/FileSystemQuotaClientFactory.h"
|
|
#include "mozilla/dom/PFileSystemManager.h"
|
|
#include "mozilla/dom/ScriptSettings.h"
|
|
#include "mozilla/dom/quota/FileStreams.h"
|
|
#include "mozilla/dom/quota/QuotaCommon.h"
|
|
#include "mozilla/dom/quota/QuotaManager.h"
|
|
#include "mozilla/dom/quota/QuotaManagerService.h"
|
|
#include "mozilla/dom/quota/ResultExtensions.h"
|
|
#include "mozilla/dom/quota/UsageInfo.h"
|
|
#include "mozilla/dom/quota/test/QuotaManagerDependencyFixture.h"
|
|
#include "mozilla/gtest/MozAssertions.h"
|
|
#include "nsIFile.h"
|
|
#include "nsIFileURL.h"
|
|
#include "nsIPrefBranch.h"
|
|
#include "nsIPrefService.h"
|
|
#include "nsIQuotaCallbacks.h"
|
|
#include "nsIQuotaRequests.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsScriptSecurityManager.h"
|
|
|
|
namespace mozilla::dom::fs::test {
|
|
|
|
quota::OriginMetadata GetTestQuotaOriginMetadata() {
|
|
return quota::OriginMetadata{""_ns,
|
|
"quotaexample.com"_ns,
|
|
"http://quotaexample.com"_ns,
|
|
"http://quotaexample.com"_ns,
|
|
/* aIsPrivate */ false,
|
|
quota::PERSISTENCE_TYPE_DEFAULT};
|
|
}
|
|
|
|
class TestFileSystemQuotaClient
|
|
: public quota::test::QuotaManagerDependencyFixture {
|
|
public:
|
|
static const int sPage = 64 * 512;
|
|
// ExceedsPreallocation value may depend on platform and sqlite version!
|
|
static const int sExceedsPreallocation = sPage;
|
|
|
|
protected:
|
|
void SetUp() override { ASSERT_NO_FATAL_FAILURE(InitializeFixture()); }
|
|
|
|
void TearDown() override {
|
|
EXPECT_NO_FATAL_FAILURE(
|
|
ClearStoragesForOrigin(GetTestQuotaOriginMetadata()));
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownFixture());
|
|
}
|
|
|
|
static const Name& GetTestFileName() {
|
|
static Name testFileName = []() {
|
|
nsCString testCFileName;
|
|
testCFileName.SetLength(sExceedsPreallocation);
|
|
std::fill(testCFileName.BeginWriting(), testCFileName.EndWriting(), 'x');
|
|
return NS_ConvertASCIItoUTF16(testCFileName.BeginReading(),
|
|
sExceedsPreallocation);
|
|
}();
|
|
|
|
return testFileName;
|
|
}
|
|
|
|
static uint64_t BytesOfName(const Name& aName) {
|
|
return static_cast<uint64_t>(aName.Length() * sizeof(Name::char_type));
|
|
}
|
|
|
|
static const nsCString& GetTestData() {
|
|
static const nsCString sTestData = "There is a way out of every box"_ns;
|
|
return sTestData;
|
|
}
|
|
|
|
static void CreateNewEmptyFile(
|
|
data::FileSystemDatabaseManager* const aDatabaseManager,
|
|
const FileSystemChildMetadata& aFileSlot, EntryId& aEntryId) {
|
|
// The file should not exist yet
|
|
Result<EntryId, QMResult> existingTestFile =
|
|
aDatabaseManager->GetOrCreateFile(aFileSlot, /* create */ false);
|
|
ASSERT_TRUE(existingTestFile.isErr());
|
|
ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR,
|
|
ToNSResult(existingTestFile.unwrapErr()));
|
|
|
|
// Create a new file
|
|
TEST_TRY_UNWRAP(aEntryId, aDatabaseManager->GetOrCreateFile(
|
|
aFileSlot, /* create */ true));
|
|
}
|
|
|
|
static void WriteDataToFile(
|
|
data::FileSystemDatabaseManager* const aDatabaseManager,
|
|
const EntryId& aEntryId, const nsCString& aData) {
|
|
TEST_TRY_UNWRAP(FileId fileId, aDatabaseManager->EnsureFileId(aEntryId));
|
|
ASSERT_FALSE(fileId.IsEmpty());
|
|
|
|
ContentType type;
|
|
TimeStamp lastModMilliS = 0;
|
|
Path path;
|
|
nsCOMPtr<nsIFile> fileObj;
|
|
ASSERT_NSEQ(NS_OK,
|
|
aDatabaseManager->GetFile(aEntryId, fileId, FileMode::EXCLUSIVE,
|
|
type, lastModMilliS, path, fileObj));
|
|
|
|
uint32_t written = 0;
|
|
ASSERT_NE(written, aData.Length());
|
|
|
|
const quota::OriginMetadata& testOriginMeta = GetTestQuotaOriginMetadata();
|
|
|
|
TEST_TRY_UNWRAP(nsCOMPtr<nsIOutputStream> fileStream,
|
|
quota::CreateFileOutputStream(
|
|
quota::PERSISTENCE_TYPE_DEFAULT, testOriginMeta,
|
|
quota::Client::FILESYSTEM, fileObj));
|
|
|
|
auto finallyClose = MakeScopeExit(
|
|
[&fileStream]() { ASSERT_NSEQ(NS_OK, fileStream->Close()); });
|
|
ASSERT_NSEQ(NS_OK,
|
|
fileStream->Write(aData.get(), aData.Length(), &written));
|
|
|
|
ASSERT_EQ(aData.Length(), written);
|
|
}
|
|
|
|
/* Static for use in callbacks */
|
|
static void CreateRegisteredDataManager(
|
|
Registered<data::FileSystemDataManager>& aRegisteredDataManager) {
|
|
bool done = false;
|
|
|
|
data::FileSystemDataManager::GetOrCreateFileSystemDataManager(
|
|
GetTestQuotaOriginMetadata())
|
|
->Then(
|
|
GetCurrentSerialEventTarget(), __func__,
|
|
[&aRegisteredDataManager,
|
|
&done](Registered<data::FileSystemDataManager>
|
|
registeredDataManager) mutable {
|
|
auto doneOnReturn = MakeScopeExit([&done]() { done = true; });
|
|
|
|
ASSERT_TRUE(registeredDataManager->IsOpen());
|
|
aRegisteredDataManager = std::move(registeredDataManager);
|
|
},
|
|
[&done](nsresult rejectValue) {
|
|
auto doneOnReturn = MakeScopeExit([&done]() { done = true; });
|
|
|
|
ASSERT_NSEQ(NS_OK, rejectValue);
|
|
});
|
|
|
|
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
|
|
|
|
ASSERT_TRUE(aRegisteredDataManager);
|
|
ASSERT_TRUE(aRegisteredDataManager->IsOpen());
|
|
ASSERT_TRUE(aRegisteredDataManager->MutableDatabaseManagerPtr());
|
|
}
|
|
|
|
static void CheckUsageEqualTo(const quota::UsageInfo& aUsage,
|
|
uint64_t expected) {
|
|
EXPECT_TRUE(aUsage.FileUsage().isNothing());
|
|
auto dbUsage = aUsage.DatabaseUsage();
|
|
ASSERT_TRUE(dbUsage.isSome());
|
|
const auto actual = dbUsage.value();
|
|
ASSERT_EQ(actual, expected);
|
|
}
|
|
|
|
static void CheckUsageGreaterThan(const quota::UsageInfo& aUsage,
|
|
uint64_t expected) {
|
|
EXPECT_TRUE(aUsage.FileUsage().isNothing());
|
|
auto dbUsage = aUsage.DatabaseUsage();
|
|
ASSERT_TRUE(dbUsage.isSome());
|
|
const auto actual = dbUsage.value();
|
|
ASSERT_GT(actual, expected);
|
|
}
|
|
};
|
|
|
|
TEST_F(TestFileSystemQuotaClient, CheckUsageBeforeAnyFilesOnDisk) {
|
|
auto backgroundTask = []() {
|
|
mozilla::Atomic<bool> isCanceled{false};
|
|
auto ioTask = [&isCanceled](const RefPtr<quota::Client>& quotaClient,
|
|
data::FileSystemDatabaseManager* dbm) {
|
|
ASSERT_FALSE(isCanceled);
|
|
const quota::OriginMetadata& testOriginMeta =
|
|
GetTestQuotaOriginMetadata();
|
|
const Origin& testOrigin = testOriginMeta.mOrigin;
|
|
|
|
// After initialization,
|
|
// * database size is not zero
|
|
// * GetUsageForOrigin and InitOrigin should agree
|
|
TEST_TRY_UNWRAP(quota::UsageInfo usageNow,
|
|
quotaClient->InitOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageGreaterThan(usageNow, 0u));
|
|
const auto initialDbUsage = usageNow.DatabaseUsage().value();
|
|
|
|
TEST_TRY_UNWRAP(usageNow, quotaClient->GetUsageForOrigin(
|
|
quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, initialDbUsage));
|
|
|
|
// Create a new file
|
|
TEST_TRY_UNWRAP(const EntryId rootId, data::GetRootHandle(testOrigin));
|
|
FileSystemChildMetadata fileData(rootId, GetTestFileName());
|
|
|
|
EntryId testFileId;
|
|
ASSERT_NO_FATAL_FAILURE(CreateNewEmptyFile(dbm, fileData, testFileId));
|
|
|
|
// After a new file has been created (only in the database),
|
|
// * database size has increased
|
|
// * GetUsageForOrigin and InitOrigin should agree
|
|
const auto expectedUse = initialDbUsage + 2 * sPage;
|
|
|
|
TEST_TRY_UNWRAP(usageNow, quotaClient->GetUsageForOrigin(
|
|
quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, expectedUse));
|
|
|
|
TEST_TRY_UNWRAP(usageNow,
|
|
quotaClient->InitOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, expectedUse));
|
|
};
|
|
|
|
RefPtr<mozilla::dom::quota::Client> quotaClient = fs::CreateQuotaClient();
|
|
ASSERT_TRUE(quotaClient);
|
|
|
|
// For uninitialized database, file usage is nothing
|
|
auto checkTask =
|
|
[&isCanceled](const RefPtr<mozilla::dom::quota::Client>& quotaClient) {
|
|
TEST_TRY_UNWRAP(quota::UsageInfo usageNow,
|
|
quotaClient->GetUsageForOrigin(
|
|
quota::PERSISTENCE_TYPE_DEFAULT,
|
|
GetTestQuotaOriginMetadata(), isCanceled));
|
|
|
|
ASSERT_TRUE(usageNow.DatabaseUsage().isNothing());
|
|
EXPECT_TRUE(usageNow.FileUsage().isNothing());
|
|
};
|
|
|
|
PerformOnIOThread(std::move(checkTask),
|
|
RefPtr<mozilla::dom::quota::Client>{quotaClient});
|
|
|
|
// Initialize database
|
|
Registered<data::FileSystemDataManager> rdm;
|
|
ASSERT_NO_FATAL_FAILURE(CreateRegisteredDataManager(rdm));
|
|
|
|
// Run tests with an initialized database
|
|
PerformOnIOThread(std::move(ioTask), std::move(quotaClient),
|
|
rdm->MutableDatabaseManagerPtr());
|
|
};
|
|
|
|
PerformOnBackgroundThread(std::move(backgroundTask));
|
|
}
|
|
|
|
TEST_F(TestFileSystemQuotaClient, WritesToFilesShouldIncreaseUsage) {
|
|
auto backgroundTask = []() {
|
|
mozilla::Atomic<bool> isCanceled{false};
|
|
auto ioTask = [&isCanceled](
|
|
const RefPtr<mozilla::dom::quota::Client>& quotaClient,
|
|
data::FileSystemDatabaseManager* dbm) {
|
|
const quota::OriginMetadata& testOriginMeta =
|
|
GetTestQuotaOriginMetadata();
|
|
const Origin& testOrigin = testOriginMeta.mOrigin;
|
|
|
|
TEST_TRY_UNWRAP(const EntryId rootId, data::GetRootHandle(testOrigin));
|
|
FileSystemChildMetadata fileData(rootId, GetTestFileName());
|
|
|
|
EntryId testFileId;
|
|
ASSERT_NO_FATAL_FAILURE(CreateNewEmptyFile(dbm, fileData, testFileId));
|
|
// const auto testFileDbUsage = usageNow.DatabaseUsage().value();
|
|
|
|
TEST_TRY_UNWRAP(
|
|
quota::UsageInfo usageNow,
|
|
quotaClient->GetUsageForOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_TRUE(usageNow.DatabaseUsage().isSome());
|
|
const auto testFileDbUsage = usageNow.DatabaseUsage().value();
|
|
|
|
TEST_TRY_UNWRAP(usageNow,
|
|
quotaClient->InitOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, testFileDbUsage));
|
|
|
|
// Fill the file with some content
|
|
const nsCString& testData = GetTestData();
|
|
|
|
ASSERT_NO_FATAL_FAILURE(WriteDataToFile(dbm, testFileId, testData));
|
|
|
|
// In this test we don't lock the file -> no rescan is expected
|
|
// and InitOrigin should return the previous value
|
|
TEST_TRY_UNWRAP(usageNow,
|
|
quotaClient->InitOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, testFileDbUsage));
|
|
|
|
// When data manager unlocks the file, it should call update
|
|
// but in this test we call it directly
|
|
ASSERT_NSEQ(NS_OK, dbm->UpdateUsage(FileId(testFileId)));
|
|
|
|
const auto expectedTotalUsage = testFileDbUsage + testData.Length();
|
|
|
|
// Disk usage should have increased after writing
|
|
TEST_TRY_UNWRAP(usageNow,
|
|
quotaClient->InitOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, expectedTotalUsage));
|
|
|
|
// The usage values should now agree
|
|
TEST_TRY_UNWRAP(usageNow, quotaClient->GetUsageForOrigin(
|
|
quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, expectedTotalUsage));
|
|
};
|
|
|
|
RefPtr<mozilla::dom::quota::Client> quotaClient = fs::CreateQuotaClient();
|
|
ASSERT_TRUE(quotaClient);
|
|
|
|
// Initialize database
|
|
Registered<data::FileSystemDataManager> rdm;
|
|
ASSERT_NO_FATAL_FAILURE(CreateRegisteredDataManager(rdm));
|
|
|
|
// Run tests with an initialized database
|
|
PerformOnIOThread(std::move(ioTask), std::move(quotaClient),
|
|
rdm->MutableDatabaseManagerPtr());
|
|
};
|
|
|
|
PerformOnBackgroundThread(std::move(backgroundTask));
|
|
}
|
|
|
|
TEST_F(TestFileSystemQuotaClient, TrackedFilesOnInitOriginShouldCauseRescan) {
|
|
auto backgroundTask = []() {
|
|
mozilla::Atomic<bool> isCanceled{false};
|
|
EntryId* testFileId = new EntryId();
|
|
auto cleanupFileId = MakeScopeExit([&testFileId] { delete testFileId; });
|
|
|
|
auto fileCreation = [&testFileId](data::FileSystemDatabaseManager* dbm) {
|
|
const Origin& testOrigin = GetTestQuotaOriginMetadata().mOrigin;
|
|
|
|
TEST_TRY_UNWRAP(const EntryId rootId, data::GetRootHandle(testOrigin));
|
|
FileSystemChildMetadata fileData(rootId, GetTestFileName());
|
|
|
|
EntryId someId;
|
|
ASSERT_NO_FATAL_FAILURE(CreateNewEmptyFile(dbm, fileData, someId));
|
|
testFileId->Append(someId);
|
|
};
|
|
|
|
auto writingToFile =
|
|
[&isCanceled, testFileId](
|
|
const RefPtr<mozilla::dom::quota::Client>& quotaClient,
|
|
data::FileSystemDatabaseManager* dbm) {
|
|
const quota::OriginMetadata& testOriginMeta =
|
|
GetTestQuotaOriginMetadata();
|
|
TEST_TRY_UNWRAP(
|
|
quota::UsageInfo usageNow,
|
|
quotaClient->GetUsageForOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_TRUE(usageNow.DatabaseUsage().isSome());
|
|
const auto testFileDbUsage = usageNow.DatabaseUsage().value();
|
|
|
|
// Fill the file with some content
|
|
const auto& testData = GetTestData();
|
|
const auto expectedTotalUsage = testFileDbUsage + testData.Length();
|
|
|
|
ASSERT_NO_FATAL_FAILURE(WriteDataToFile(dbm, *testFileId, testData));
|
|
|
|
// We don't call update now - because the file is tracked and
|
|
// InitOrigin should perform a rescan
|
|
TEST_TRY_UNWRAP(
|
|
usageNow, quotaClient->InitOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
CheckUsageEqualTo(usageNow, expectedTotalUsage));
|
|
|
|
// As always, the cached and scanned values should agree
|
|
TEST_TRY_UNWRAP(usageNow, quotaClient->GetUsageForOrigin(
|
|
quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
CheckUsageEqualTo(usageNow, expectedTotalUsage));
|
|
};
|
|
|
|
RefPtr<mozilla::dom::quota::Client> quotaClient = fs::CreateQuotaClient();
|
|
ASSERT_TRUE(quotaClient);
|
|
|
|
// Initialize database
|
|
Registered<data::FileSystemDataManager> rdm;
|
|
ASSERT_NO_FATAL_FAILURE(CreateRegisteredDataManager(rdm));
|
|
|
|
PerformOnIOThread(std::move(fileCreation),
|
|
rdm->MutableDatabaseManagerPtr());
|
|
|
|
// This should force a rescan
|
|
TEST_TRY_UNWRAP(FileId fileId, rdm->LockExclusive(*testFileId));
|
|
ASSERT_FALSE(fileId.IsEmpty());
|
|
PerformOnIOThread(std::move(writingToFile), std::move(quotaClient),
|
|
rdm->MutableDatabaseManagerPtr());
|
|
};
|
|
|
|
PerformOnBackgroundThread(std::move(backgroundTask));
|
|
}
|
|
|
|
TEST_F(TestFileSystemQuotaClient, RemovingFileShouldDecreaseUsage) {
|
|
auto backgroundTask = []() {
|
|
mozilla::Atomic<bool> isCanceled{false};
|
|
auto ioTask = [&isCanceled](
|
|
const RefPtr<mozilla::dom::quota::Client>& quotaClient,
|
|
data::FileSystemDatabaseManager* dbm) {
|
|
const quota::OriginMetadata& testOriginMeta =
|
|
GetTestQuotaOriginMetadata();
|
|
const Origin& testOrigin = testOriginMeta.mOrigin;
|
|
|
|
TEST_TRY_UNWRAP(const EntryId rootId, data::GetRootHandle(testOrigin));
|
|
FileSystemChildMetadata fileData(rootId, GetTestFileName());
|
|
|
|
EntryId testFileId;
|
|
ASSERT_NO_FATAL_FAILURE(CreateNewEmptyFile(dbm, fileData, testFileId));
|
|
TEST_TRY_UNWRAP(quota::UsageInfo usageNow,
|
|
quotaClient->InitOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_TRUE(usageNow.DatabaseUsage().isSome());
|
|
const auto testFileDbUsage = usageNow.DatabaseUsage().value();
|
|
|
|
// Fill the file with some content
|
|
const nsCString& testData = GetTestData();
|
|
const auto expectedTotalUsage = testFileDbUsage + testData.Length();
|
|
|
|
ASSERT_NO_FATAL_FAILURE(WriteDataToFile(dbm, testFileId, testData));
|
|
|
|
// Currently, usage is expected to be updated on unlock by data manager
|
|
// but here UpdateUsage() is called directly
|
|
ASSERT_NSEQ(NS_OK, dbm->UpdateUsage(FileId(testFileId)));
|
|
|
|
// At least some file disk usage should have appeared after unlocking
|
|
TEST_TRY_UNWRAP(usageNow, quotaClient->GetUsageForOrigin(
|
|
quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, expectedTotalUsage));
|
|
|
|
TEST_TRY_UNWRAP(bool wasRemoved,
|
|
dbm->RemoveFile({rootId, GetTestFileName()}));
|
|
ASSERT_TRUE(wasRemoved);
|
|
|
|
// Removes cascade and usage table should be up to date immediately
|
|
TEST_TRY_UNWRAP(usageNow,
|
|
quotaClient->InitOrigin(quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, testFileDbUsage));
|
|
|
|
// GetUsageForOrigin should agree
|
|
TEST_TRY_UNWRAP(usageNow, quotaClient->GetUsageForOrigin(
|
|
quota::PERSISTENCE_TYPE_DEFAULT,
|
|
testOriginMeta, isCanceled));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, testFileDbUsage));
|
|
};
|
|
|
|
RefPtr<mozilla::dom::quota::Client> quotaClient = fs::CreateQuotaClient();
|
|
ASSERT_TRUE(quotaClient);
|
|
|
|
// Initialize database
|
|
Registered<data::FileSystemDataManager> rdm;
|
|
ASSERT_NO_FATAL_FAILURE(CreateRegisteredDataManager(rdm));
|
|
|
|
// Run tests with an initialized database
|
|
PerformOnIOThread(std::move(ioTask), std::move(quotaClient),
|
|
rdm->MutableDatabaseManagerPtr());
|
|
};
|
|
|
|
PerformOnBackgroundThread(std::move(backgroundTask));
|
|
}
|
|
|
|
} // namespace mozilla::dom::fs::test
|