Bug 1801364 - Introduce QuotaManagerDependencyFixture; r=dom-storage-reviewers,jari

TestFileSystemDataManager.cpp invented a way to access QuotaManager in a gtest.
New tests are being added which need the same infrastructure so this patch
creates a base class which can be reused by multiple gtests.

Differential Revision: https://phabricator.services.mozilla.com/D165678
This commit is contained in:
Jan Varga 2023-01-10 12:44:15 +00:00
Родитель ddae862344
Коммит c42b582029
10 изменённых файлов: 970 добавлений и 1229 удалений

Просмотреть файл

@ -1,24 +0,0 @@
/* -*- 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 "QuotaManagerDependencyFixture.h"
#include "TestHelpers.h"
namespace mozilla::dom::fs::test {
NS_IMPL_ISUPPORTS(QuotaManagerDependencyFixture::RequestResolver,
nsIQuotaCallback)
const quota::OriginMetadata& QuotaManagerDependencyFixture::GetOriginMetadata()
const {
static const auto testMetadata = GetTestOriginMetadata();
return testMetadata;
}
nsCOMPtr<nsISerialEventTarget> QuotaManagerDependencyFixture::sBackgroundTarget;
} // namespace mozilla::dom::fs::test

Просмотреть файл

@ -1,204 +0,0 @@
/* -*- 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/. */
#ifndef DOM_FS_TEST_GTEST_QUOTAMANAGERDEPENDENCYFIXTURE_H_
#define DOM_FS_TEST_GTEST_QUOTAMANAGERDEPENDENCYFIXTURE_H_
#include "gtest/gtest.h"
#include "mozIStorageService.h"
#include "mozStorageCID.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/dom/ScriptSettings.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/gtest/MozAssertions.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIQuotaCallbacks.h"
#include "nsIQuotaRequests.h"
#include "nsScriptSecurityManager.h"
namespace mozilla::dom::fs::test {
class QuotaManagerDependencyFixture : public ::testing::Test {
public:
class RequestResolver final : public nsIQuotaCallback {
public:
RequestResolver() : mDone(false) {}
bool Done() const { return mDone; }
NS_DECL_ISUPPORTS
NS_IMETHOD OnComplete(nsIQuotaRequest* aRequest) override {
mDone = true;
return NS_OK;
}
private:
~RequestResolver() = default;
bool mDone;
};
virtual const quota::OriginMetadata& GetOriginMetadata() const;
protected:
void SetUp() override {
// The first initialization of storage service must be done on the main
// thread.
nsCOMPtr<mozIStorageService> storageService =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
ASSERT_TRUE(storageService);
nsIObserver* observer = quota::QuotaManager::GetObserver();
ASSERT_TRUE(observer);
nsresult rv = observer->Observe(nullptr, "profile-do-change", nullptr);
ASSERT_NS_SUCCEEDED(rv);
AutoJSAPI jsapi;
bool ok = jsapi.Init(xpc::PrivilegedJunkScope());
ASSERT_TRUE(ok);
quota::OriginMetadata originMeta = GetOriginMetadata();
nsCOMPtr<nsIScriptSecurityManager> ssm =
nsScriptSecurityManager::GetScriptSecurityManager();
ASSERT_TRUE(ssm);
nsCOMPtr<nsIPrincipal> principal;
rv = ssm->CreateContentPrincipalFromOrigin(originMeta.mOrigin,
getter_AddRefs(principal));
ASSERT_NS_SUCCEEDED(rv);
nsCOMPtr<nsIQuotaManagerService> qms =
quota::QuotaManagerService::GetOrCreate();
ASSERT_TRUE(qms);
nsCOMPtr<nsIQuotaRequest> clearRequest;
RefPtr<RequestResolver> clearResolver = new RequestResolver();
ASSERT_TRUE(clearResolver);
const nsAutoString clientType = NS_ConvertUTF8toUTF16(
quota::Client::TypeToText(quota::Client::Type::FILESYSTEM));
rv = qms->ClearStoragesForPrincipal(
principal,
quota::PersistenceTypeToString(
quota::PersistenceType::PERSISTENCE_TYPE_DEFAULT),
clientType,
/* aClearAll */ true, getter_AddRefs(clearRequest));
ASSERT_NS_SUCCEEDED(rv);
rv = clearRequest->SetCallback(clearResolver);
ASSERT_NS_SUCCEEDED(rv);
SpinEventLoopUntil("Promise is fulfilled"_ns,
[&clearResolver]() { return clearResolver->Done(); });
// QuotaManagerService::Initialized fails if the testing pref is not set.
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
prefs->SetBoolPref("dom.quotaManager.testing", true);
nsCOMPtr<nsIQuotaRequest> request;
rv = qms->StorageInitialized(getter_AddRefs(request));
ASSERT_NS_SUCCEEDED(rv);
RefPtr<RequestResolver> resolver = new RequestResolver();
rv = request->SetCallback(resolver);
ASSERT_NS_SUCCEEDED(rv);
SpinEventLoopUntil("Promise is fulfilled"_ns,
[&resolver]() { return resolver->Done(); });
prefs->SetBoolPref("dom.quotaManager.testing", false);
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
ASSERT_TRUE(quotaManager);
ASSERT_TRUE(quotaManager->OwningThread());
sBackgroundTarget = quotaManager->OwningThread();
}
void TearDown() override {
nsIObserver* observer = quota::QuotaManager::GetObserver();
ASSERT_TRUE(observer);
nsresult rv =
observer->Observe(nullptr, "profile-before-change-qm", nullptr);
ASSERT_NS_SUCCEEDED(rv);
PerformOnBackgroundTarget([]() {
quota::QuotaManager::Reset();
return BoolPromise::CreateAndResolve(true, __func__);
});
sBackgroundTarget = nullptr;
}
/* Convenience method for tasks which must be called on background target */
template <class Invokable, class... Args>
static void PerformOnBackgroundTarget(Invokable&& aInvokable,
Args&&... aArgs) {
bool done = false;
auto boundTask =
// For c++17, bind is cleaner than tuple for parameter pack forwarding
// NOLINTNEXTLINE(modernize-avoid-bind)
std::bind(std::forward<Invokable>(aInvokable),
std::forward<Args>(aArgs)...);
InvokeAsync(BackgroundTargetStrongRef(), __func__, std::move(boundTask))
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& /* aValue */) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
}
/* Convenience method for tasks which must be executed on IO thread */
template <class Invokable, class... Args>
static void PerformOnIOThread(Invokable&& aInvokable, Args&&... aArgs) {
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
ASSERT_TRUE(quotaManager);
bool done = false;
auto boundTask =
// For c++17, bind is cleaner than tuple for parameter pack forwarding
// NOLINTNEXTLINE(modernize-avoid-bind)
std::bind(std::forward<Invokable>(aInvokable),
std::forward<Args>(aArgs)...);
InvokeAsync(quotaManager->IOThread(), __func__,
[ioTask = std::move(boundTask)]() {
ioTask();
return BoolPromise::CreateAndResolve(true, __func__);
})
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& value) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
}
static const nsCOMPtr<nsISerialEventTarget>& BackgroundTargetStrongRef() {
return sBackgroundTarget;
}
private:
static nsCOMPtr<nsISerialEventTarget> sBackgroundTarget;
};
} // namespace mozilla::dom::fs::test
#endif // DOM_FS_TEST_GTEST_QUOTAMANAGERDEPENDENCYFIXTURE_H_

Просмотреть файл

@ -5,7 +5,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FileSystemQuotaClient.h"
#include "QuotaManagerDependencyFixture.h"
#include "TestHelpers.h"
#include "datamodel/FileSystemDataManager.h"
#include "datamodel/FileSystemDatabaseManager.h"
@ -22,6 +21,7 @@
#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"
@ -32,41 +32,6 @@
#include "nsNetUtil.h"
#include "nsScriptSecurityManager.h"
// Promise returning test task helpers
#define TEST_PROMISE_ASSERT_CHECK_META(didFail, someAssert, ...) \
bool MOZ_REMOVE_PAREN(didFail) = true; \
[&] { \
MOZ_REMOVE_PAREN(someAssert)(__VA_ARGS__); \
MOZ_REMOVE_PAREN(didFail) = false; \
}(); \
if (MOZ_REMOVE_PAREN(didFail)) { \
return BoolPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); \
}
#define TEST_PROMISE_ASSERT_CHECK(...) \
TEST_PROMISE_ASSERT_CHECK_META(MOZ_UNIQUE_VAR(testVar), __VA_ARGS__)
// Promise returning test assertions
#define TEST_PROMISE_ASSERT_TRUE(expr) \
TEST_PROMISE_ASSERT_CHECK(ASSERT_TRUE, expr)
#define TEST_PROMISE_ASSERT_NSEQ(lhs, rhs) \
TEST_PROMISE_ASSERT_CHECK(ASSERT_NSEQ, lhs, rhs)
#define TEST_PROMISE_ASSERT_SUCCESS(rhs) TEST_PROMISE_ASSERT_NSEQ(NS_OK, rhs)
#define TEST_TRY_PROMISE_UNWRAP_META(tempVar, target, expr) \
auto MOZ_REMOVE_PAREN(tempVar) = (expr); \
if (!MOZ_REMOVE_PAREN(tempVar).isOk()) { \
EXPECT_TRUE(MOZ_REMOVE_PAREN(tempVar).isOk()); \
return BoolPromise::CreateAndReject( \
ToNSResult(MOZ_REMOVE_PAREN(tempVar).unwrapErr()), __func__); \
} \
MOZ_REMOVE_PAREN(target) = MOZ_REMOVE_PAREN(tempVar).unwrap();
#define TEST_TRY_PROMISE_UNWRAP(target, expr) \
TEST_TRY_PROMISE_UNWRAP_META(MOZ_UNIQUE_VAR(testVar), target, expr)
namespace mozilla::dom::fs::test {
quota::OriginMetadata GetTestQuotaOriginMetadata() {
@ -75,18 +40,15 @@ quota::OriginMetadata GetTestQuotaOriginMetadata() {
quota::PERSISTENCE_TYPE_DEFAULT};
}
class TestFileSystemQuotaClient : public QuotaManagerDependencyFixture {
class TestFileSystemQuotaClient
: public quota::test::QuotaManagerDependencyFixture {
public:
// ExceedsPreallocation value may depend on platform and sqlite version!
static const int sExceedsPreallocation = 32 * 1024;
const quota::OriginMetadata& GetOriginMetadata() const override {
static const auto& testMetadata = GetTestQuotaOriginMetadata();
return testMetadata;
}
protected:
void SetUp() override { ASSERT_NO_FATAL_FAILURE(InitializeFixture()); }
void TearDown() override {
PerformOnIOThread([]() {
// We use QM_TRY here to avoid failures if this cleanup is unnecessary
@ -115,13 +77,15 @@ class TestFileSystemQuotaClient : public QuotaManagerDependencyFixture {
ASSERT_FALSE(exists);
});
QuotaManagerDependencyFixture::TearDown();
ASSERT_NO_FATAL_FAILURE(
ClearStoragesForOrigin(GetTestQuotaOriginMetadata()));
ASSERT_NO_FATAL_FAILURE(ShutdownFixture());
}
static void InitializeStorage() {
auto backgroundTask = []() -> RefPtr<BoolPromise> {
auto backgroundTask = []() {
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
TEST_PROMISE_ASSERT_TRUE(quotaManager);
ASSERT_TRUE(quotaManager);
quotaManager->IOThread()->Dispatch(
NS_NewRunnableFunction(
@ -146,11 +110,9 @@ class TestFileSystemQuotaClient : public QuotaManagerDependencyFixture {
qm->EnsureQuotaForOrigin(testOriginMeta);
}),
NS_DISPATCH_SYNC);
return BoolPromise::CreateAndResolve(true, __func__);
};
PerformOnBackgroundTarget(std::move(backgroundTask));
PerformOnBackgroundThread(std::move(backgroundTask));
}
static const Name& GetTestFileName() {
@ -268,7 +230,7 @@ class TestFileSystemQuotaClient : public QuotaManagerDependencyFixture {
};
TEST_F(TestFileSystemQuotaClient, CheckUsageBeforeAnyFilesOnDisk) {
auto backgroundTask = []() -> RefPtr<BoolPromise> {
auto backgroundTask = []() {
mozilla::Atomic<bool> isCanceled{false};
auto ioTask = [&isCanceled](const RefPtr<quota::Client>& quotaClient,
data::FileSystemDatabaseManager* dbm) {
@ -315,7 +277,7 @@ TEST_F(TestFileSystemQuotaClient, CheckUsageBeforeAnyFilesOnDisk) {
};
RefPtr<mozilla::dom::quota::Client> quotaClient = fs::CreateQuotaClient();
TEST_PROMISE_ASSERT_TRUE(quotaClient);
ASSERT_TRUE(quotaClient);
// For uninitialized database, file usage is nothing
auto checkTask =
@ -334,21 +296,18 @@ TEST_F(TestFileSystemQuotaClient, CheckUsageBeforeAnyFilesOnDisk) {
// Initialize database
Registered<data::FileSystemDataManager> rdm;
CreateRegisteredDataManager(rdm);
TEST_PROMISE_ASSERT_TRUE(!HasFatalFailure());
ASSERT_NO_FATAL_FAILURE(CreateRegisteredDataManager(rdm));
// Run tests with an initialized database
PerformOnIOThread(std::move(ioTask), std::move(quotaClient),
rdm->MutableDatabaseManagerPtr());
return BoolPromise::CreateAndResolve(true, __func__);
};
PerformOnBackgroundTarget(std::move(backgroundTask));
PerformOnBackgroundThread(std::move(backgroundTask));
}
TEST_F(TestFileSystemQuotaClient, WritesToFilesShouldIncreaseUsage) {
auto backgroundTask = []() -> RefPtr<BoolPromise> {
auto backgroundTask = []() {
mozilla::Atomic<bool> isCanceled{false};
auto ioTask = [&isCanceled](
const RefPtr<mozilla::dom::quota::Client>& quotaClient,
@ -407,30 +366,26 @@ TEST_F(TestFileSystemQuotaClient, WritesToFilesShouldIncreaseUsage) {
};
RefPtr<mozilla::dom::quota::Client> quotaClient = fs::CreateQuotaClient();
TEST_PROMISE_ASSERT_TRUE(quotaClient);
ASSERT_TRUE(quotaClient);
// Storage initialization
InitializeStorage();
TEST_PROMISE_ASSERT_TRUE(!HasFatalFailure());
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
// Initialize database
Registered<data::FileSystemDataManager> rdm;
CreateRegisteredDataManager(rdm);
TEST_PROMISE_ASSERT_TRUE(!HasFatalFailure());
ASSERT_NO_FATAL_FAILURE(CreateRegisteredDataManager(rdm));
// Run tests with an initialized database
PerformOnIOThread(std::move(ioTask), std::move(quotaClient),
rdm->MutableDatabaseManagerPtr());
return BoolPromise::CreateAndResolve(true, __func__);
};
PerformOnBackgroundTarget(std::move(backgroundTask));
PerformOnBackgroundThread(std::move(backgroundTask));
}
TEST_F(TestFileSystemQuotaClient,
DISABLED_TrackedFilesOnInitOriginShouldCauseRescan) {
auto backgroundTask = []() -> RefPtr<BoolPromise> {
auto backgroundTask = []() {
mozilla::Atomic<bool> isCanceled{false};
EntryId* testFileId = new EntryId();
auto cleanupFileId = MakeScopeExit([&testFileId] { delete testFileId; });
@ -482,33 +437,29 @@ TEST_F(TestFileSystemQuotaClient,
};
RefPtr<mozilla::dom::quota::Client> quotaClient = fs::CreateQuotaClient();
TEST_PROMISE_ASSERT_TRUE(quotaClient);
ASSERT_TRUE(quotaClient);
// Storage initialization
InitializeStorage();
TEST_PROMISE_ASSERT_TRUE(!HasFatalFailure());
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
// Initialize database
Registered<data::FileSystemDataManager> rdm;
CreateRegisteredDataManager(rdm);
TEST_PROMISE_ASSERT_TRUE(!HasFatalFailure());
ASSERT_NO_FATAL_FAILURE(CreateRegisteredDataManager(rdm));
PerformOnIOThread(std::move(fileCreation),
rdm->MutableDatabaseManagerPtr());
// This should force a rescan
TEST_PROMISE_ASSERT_TRUE(rdm->LockExclusive(*testFileId));
ASSERT_TRUE(rdm->LockExclusive(*testFileId));
PerformOnIOThread(std::move(writingToFile), std::move(quotaClient),
rdm->MutableDatabaseManagerPtr());
return BoolPromise::CreateAndResolve(true, __func__);
};
PerformOnBackgroundTarget(std::move(backgroundTask));
PerformOnBackgroundThread(std::move(backgroundTask));
}
TEST_F(TestFileSystemQuotaClient, RemovingFileShouldDecreaseUsage) {
auto backgroundTask = []() -> RefPtr<BoolPromise> {
auto backgroundTask = []() {
mozilla::Atomic<bool> isCanceled{false};
auto ioTask = [&isCanceled](
const RefPtr<mozilla::dom::quota::Client>& quotaClient,
@ -563,25 +514,21 @@ TEST_F(TestFileSystemQuotaClient, RemovingFileShouldDecreaseUsage) {
};
RefPtr<mozilla::dom::quota::Client> quotaClient = fs::CreateQuotaClient();
TEST_PROMISE_ASSERT_TRUE(quotaClient);
ASSERT_TRUE(quotaClient);
// Storage initialization
InitializeStorage();
TEST_PROMISE_ASSERT_TRUE(!HasFatalFailure());
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
// Initialize database
Registered<data::FileSystemDataManager> rdm;
CreateRegisteredDataManager(rdm);
TEST_PROMISE_ASSERT_TRUE(!HasFatalFailure());
ASSERT_NO_FATAL_FAILURE(CreateRegisteredDataManager(rdm));
// Run tests with an initialized database
PerformOnIOThread(std::move(ioTask), std::move(quotaClient),
rdm->MutableDatabaseManagerPtr());
return BoolPromise::CreateAndResolve(true, __func__);
};
PerformOnBackgroundTarget(std::move(backgroundTask));
PerformOnBackgroundThread(std::move(backgroundTask));
}
} // namespace mozilla::dom::fs::test

Просмотреть файл

@ -6,132 +6,23 @@
#include "FileSystemDataManager.h"
#include "TestHelpers.h"
#include "gtest/gtest.h"
#include "mozIStorageService.h"
#include "mozStorageCID.h"
#include "mozilla/MozPromise.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/QuotaManagerService.h"
#include "mozilla/gtest/MozAssertions.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIQuotaCallbacks.h"
#include "nsIQuotaRequests.h"
#include "mozilla/dom/quota/ForwardDecls.h"
#include "mozilla/dom/quota/test/QuotaManagerDependencyFixture.h"
namespace mozilla::dom::fs::test {
class TestFileSystemDataManager : public ::testing::Test {
class TestFileSystemDataManager
: public quota::test::QuotaManagerDependencyFixture {
public:
class RequestResolver final : public nsIQuotaCallback {
public:
RequestResolver() : mDone(false) {}
static void SetUpTestCase() { ASSERT_NO_FATAL_FAILURE(InitializeFixture()); }
bool Done() const { return mDone; }
NS_DECL_ISUPPORTS
NS_IMETHOD OnComplete(nsIQuotaRequest* aRequest) override {
mDone = true;
return NS_OK;
}
private:
~RequestResolver() = default;
bool mDone;
};
static void SetUpTestCase() {
// The first initialization of storage service must be done on the main
// thread.
nsCOMPtr<mozIStorageService> storageService =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
ASSERT_TRUE(storageService);
nsIObserver* observer = quota::QuotaManager::GetObserver();
ASSERT_TRUE(observer);
nsresult rv = observer->Observe(nullptr, "profile-do-change", nullptr);
ASSERT_NS_SUCCEEDED(rv);
AutoJSAPI jsapi;
bool ok = jsapi.Init(xpc::PrivilegedJunkScope());
ASSERT_TRUE(ok);
nsCOMPtr<nsIQuotaManagerService> qms =
quota::QuotaManagerService::GetOrCreate();
ASSERT_TRUE(qms);
// QuotaManagerService::Initialized fails if the testing pref is not set.
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
prefs->SetBoolPref("dom.quotaManager.testing", true);
nsCOMPtr<nsIQuotaRequest> request;
rv = qms->StorageInitialized(getter_AddRefs(request));
ASSERT_NS_SUCCEEDED(rv);
prefs->SetBoolPref("dom.quotaManager.testing", false);
RefPtr<RequestResolver> resolver = new RequestResolver();
rv = request->SetCallback(resolver);
ASSERT_NS_SUCCEEDED(rv);
SpinEventLoopUntil("Promise is fulfilled"_ns,
[&resolver]() { return resolver->Done(); });
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
ASSERT_TRUE(quotaManager);
ASSERT_TRUE(quotaManager->OwningThread());
sBackgroundTarget = quotaManager->OwningThread();
}
static void TearDownTestCase() {
nsIObserver* observer = quota::QuotaManager::GetObserver();
ASSERT_TRUE(observer);
nsresult rv =
observer->Observe(nullptr, "profile-before-change-qm", nullptr);
ASSERT_NS_SUCCEEDED(rv);
bool done = false;
InvokeAsync(sBackgroundTarget, __func__,
[]() {
quota::QuotaManager::Reset();
return BoolPromise::CreateAndResolve(true, __func__);
})
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& value) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
sBackgroundTarget = nullptr;
}
static const nsCOMPtr<nsISerialEventTarget>& BackgroundTargetStrongRef() {
return sBackgroundTarget;
}
private:
static nsCOMPtr<nsISerialEventTarget> sBackgroundTarget;
static void TearDownTestCase() { ASSERT_NO_FATAL_FAILURE(ShutdownFixture()); }
};
NS_IMPL_ISUPPORTS(TestFileSystemDataManager::RequestResolver, nsIQuotaCallback)
nsCOMPtr<nsISerialEventTarget> TestFileSystemDataManager::sBackgroundTarget;
TEST_F(TestFileSystemDataManager, GetOrCreateFileSystemDataManager) {
auto backgroundTask = []() -> RefPtr<BoolPromise> {
auto backgroundTask = []() {
bool done = false;
data::FileSystemDataManager::GetOrCreateFileSystemDataManager(
@ -154,24 +45,14 @@ TEST_F(TestFileSystemDataManager, GetOrCreateFileSystemDataManager) {
[&done](const BoolPromise::ResolveOrRejectValue&) { done = true; });
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
return BoolPromise::CreateAndResolve(true, __func__);
};
bool done = false;
InvokeAsync(BackgroundTargetStrongRef(), __func__, std::move(backgroundTask))
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& value) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
PerformOnBackgroundThread(std::move(backgroundTask));
}
TEST_F(TestFileSystemDataManager,
GetOrCreateFileSystemDataManager_PendingOpen) {
auto backgroundTask = []() -> RefPtr<BoolPromise> {
auto backgroundTask = []() {
Registered<data::FileSystemDataManager> rdm1;
Registered<data::FileSystemDataManager> rdm2;
@ -232,25 +113,15 @@ TEST_F(TestFileSystemDataManager,
SpinEventLoopUntil("Promise is fulfilled"_ns,
[&done1, &done2]() { return done1 && done2; });
return BoolPromise::CreateAndResolve(true, __func__);
}
};
bool done = false;
InvokeAsync(BackgroundTargetStrongRef(), __func__, std::move(backgroundTask))
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& value) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
PerformOnBackgroundThread(std::move(backgroundTask));
}
TEST_F(TestFileSystemDataManager,
GetOrCreateFileSystemDataManager_PendingClose) {
auto backgroundTask = []() -> RefPtr<BoolPromise> {
auto backgroundTask = []() {
Registered<data::FileSystemDataManager> rdm;
{
@ -302,20 +173,10 @@ TEST_F(TestFileSystemDataManager,
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
return BoolPromise::CreateAndResolve(true, __func__);
}
};
bool done = false;
InvokeAsync(BackgroundTargetStrongRef(), __func__, std::move(backgroundTask))
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& value) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
PerformOnBackgroundThread(std::move(backgroundTask));
}
} // namespace mozilla::dom::fs::test

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -7,7 +7,6 @@
TEST_DIRS += ["datamodel"]
UNIFIED_SOURCES = [
"QuotaManagerDependencyFixture.cpp",
"TestFileSystemHashSource.cpp",
"TestFileSystemQuotaClient.cpp",
]

Просмотреть файл

@ -0,0 +1,160 @@
/* -*- 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 "QuotaManagerDependencyFixture.h"
#include "mozIStorageService.h"
#include "mozStorageCID.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/quota/QuotaManagerService.h"
#include "mozilla/gtest/MozAssertions.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIQuotaCallbacks.h"
#include "nsIQuotaRequests.h"
#include "nsIVariant.h"
#include "nsScriptSecurityManager.h"
namespace mozilla::dom::quota::test {
namespace {
class RequestResolver final : public nsIQuotaCallback {
public:
RequestResolver() : mDone(false) {}
bool Done() const { return mDone; }
NS_DECL_ISUPPORTS
NS_IMETHOD OnComplete(nsIQuotaRequest* aRequest) override {
mDone = true;
return NS_OK;
}
private:
~RequestResolver() = default;
bool mDone;
};
} // namespace
NS_IMPL_ISUPPORTS(RequestResolver, nsIQuotaCallback)
// static
void QuotaManagerDependencyFixture::InitializeFixture() {
// Some QuotaManagerService methods fail if the testing pref is not set.
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
prefs->SetBoolPref("dom.quotaManager.testing", true);
// The first initialization of storage service must be done on the main
// thread.
nsCOMPtr<mozIStorageService> storageService =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
ASSERT_TRUE(storageService);
nsIObserver* observer = QuotaManager::GetObserver();
ASSERT_TRUE(observer);
nsresult rv = observer->Observe(nullptr, "profile-do-change", nullptr);
ASSERT_NS_SUCCEEDED(rv);
ASSERT_NO_FATAL_FAILURE(StorageInitialized());
QuotaManager* quotaManager = QuotaManager::Get();
ASSERT_TRUE(quotaManager);
ASSERT_TRUE(quotaManager->OwningThread());
sBackgroundTarget = quotaManager->OwningThread();
}
// static
void QuotaManagerDependencyFixture::ShutdownFixture() {
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
prefs->SetBoolPref("dom.quotaManager.testing", false);
nsIObserver* observer = QuotaManager::GetObserver();
ASSERT_TRUE(observer);
nsresult rv = observer->Observe(nullptr, "profile-before-change-qm", nullptr);
ASSERT_NS_SUCCEEDED(rv);
PerformOnBackgroundThread([]() { QuotaManager::Reset(); });
sBackgroundTarget = nullptr;
}
// static
void QuotaManagerDependencyFixture::StorageInitialized(bool* aResult) {
AutoJSAPI jsapi;
bool ok = jsapi.Init(xpc::PrivilegedJunkScope());
ASSERT_TRUE(ok);
nsCOMPtr<nsIQuotaManagerService> qms = QuotaManagerService::GetOrCreate();
ASSERT_TRUE(qms);
nsCOMPtr<nsIQuotaRequest> request;
nsresult rv = qms->StorageInitialized(getter_AddRefs(request));
ASSERT_NS_SUCCEEDED(rv);
RefPtr<RequestResolver> resolver = new RequestResolver();
rv = request->SetCallback(resolver);
ASSERT_NS_SUCCEEDED(rv);
SpinEventLoopUntil("Promise is fulfilled"_ns,
[&resolver]() { return resolver->Done(); });
if (aResult) {
nsCOMPtr<nsIVariant> result;
rv = request->GetResult(getter_AddRefs(result));
ASSERT_NS_SUCCEEDED(rv);
rv = result->GetAsBool(aResult);
ASSERT_NS_SUCCEEDED(rv);
}
}
// static
void QuotaManagerDependencyFixture::ClearStoragesForOrigin(
const OriginMetadata& aOriginMetadata) {
nsCOMPtr<nsIQuotaManagerService> qms = QuotaManagerService::GetOrCreate();
ASSERT_TRUE(qms);
nsCOMPtr<nsIScriptSecurityManager> ssm =
nsScriptSecurityManager::GetScriptSecurityManager();
ASSERT_TRUE(ssm);
nsCOMPtr<nsIPrincipal> principal;
nsresult rv = ssm->CreateContentPrincipalFromOrigin(
aOriginMetadata.mOrigin, getter_AddRefs(principal));
ASSERT_NS_SUCCEEDED(rv);
nsCOMPtr<nsIQuotaRequest> request;
rv = qms->ClearStoragesForPrincipal(principal, VoidCString(), VoidString(),
/* aClearAll */ false,
getter_AddRefs(request));
ASSERT_NS_SUCCEEDED(rv);
RefPtr<RequestResolver> resolver = new RequestResolver();
ASSERT_TRUE(resolver);
rv = request->SetCallback(resolver);
ASSERT_NS_SUCCEEDED(rv);
SpinEventLoopUntil("Promise is fulfilled"_ns,
[&resolver]() { return resolver->Done(); });
}
nsCOMPtr<nsISerialEventTarget> QuotaManagerDependencyFixture::sBackgroundTarget;
} // namespace mozilla::dom::quota::test

Просмотреть файл

@ -0,0 +1,87 @@
/* -*- 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/. */
#ifndef DOM_QUOTA_TEST_GTEST_QUOTAMANAGERDEPENDENCYFIXTURE_H_
#define DOM_QUOTA_TEST_GTEST_QUOTAMANAGERDEPENDENCYFIXTURE_H_
#include "gtest/gtest.h"
#include "mozilla/MozPromise.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/dom/quota/ForwardDecls.h"
#include "mozilla/dom/quota/QuotaManager.h"
namespace mozilla::dom::quota::test {
class QuotaManagerDependencyFixture : public testing::Test {
public:
protected:
static void InitializeFixture();
static void ShutdownFixture();
static void StorageInitialized(bool* aResult = nullptr);
static void ClearStoragesForOrigin(const OriginMetadata& aOriginMetadata);
/* Convenience method for tasks which must be called on PBackground thread */
template <class Invokable, class... Args>
static void PerformOnBackgroundThread(Invokable&& aInvokable,
Args&&... aArgs) {
bool done = false;
auto boundTask =
// For c++17, bind is cleaner than tuple for parameter pack forwarding
// NOLINTNEXTLINE(modernize-avoid-bind)
std::bind(std::forward<Invokable>(aInvokable),
std::forward<Args>(aArgs)...);
InvokeAsync(BackgroundTargetStrongRef(), __func__,
[boundTask = std::move(boundTask)] {
boundTask();
return BoolPromise::CreateAndResolve(true, __func__);
})
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& /* aValue */) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
}
/* Convenience method for tasks which must be executed on IO thread */
template <class Invokable, class... Args>
static void PerformOnIOThread(Invokable&& aInvokable, Args&&... aArgs) {
QuotaManager* quotaManager = QuotaManager::Get();
ASSERT_TRUE(quotaManager);
bool done = false;
auto boundTask =
// For c++17, bind is cleaner than tuple for parameter pack forwarding
// NOLINTNEXTLINE(modernize-avoid-bind)
std::bind(std::forward<Invokable>(aInvokable),
std::forward<Args>(aArgs)...);
InvokeAsync(quotaManager->IOThread(), __func__,
[boundTask = std::move(boundTask)]() {
boundTask();
return BoolPromise::CreateAndResolve(true, __func__);
})
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& value) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
}
static const nsCOMPtr<nsISerialEventTarget>& BackgroundTargetStrongRef() {
return sBackgroundTarget;
}
private:
static nsCOMPtr<nsISerialEventTarget> sBackgroundTarget;
};
} // namespace mozilla::dom::quota::test
#endif // DOM_QUOTA_TEST_GTEST_QUOTAMANAGERDEPENDENCYFIXTURE_H_

Просмотреть файл

@ -4,141 +4,39 @@
* 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 "gtest/gtest.h"
#include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/CommonMetadata.h"
#include "mozilla/dom/quota/FileStreams.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/QuotaManagerService.h"
#include "mozilla/dom/quota/QuotaCommon.h"
#include "mozilla/dom/quota/ResultExtensions.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/gtest/MozAssertions.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozIStorageService.h"
#include "mozStorageCID.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIQuotaCallbacks.h"
#include "nsIQuotaRequests.h"
#include "QuotaManagerDependencyFixture.h"
namespace mozilla::dom::quota::test {
// TODO: Refactor this in the scope of Bug 1801364
class TestFileOutputStream : public ::testing::Test {
class TestFileOutputStream : public QuotaManagerDependencyFixture {
public:
class RequestResolver final : public nsIQuotaCallback {
public:
RequestResolver() : mDone(false) {}
bool Done() const { return mDone; }
NS_DECL_ISUPPORTS
NS_IMETHOD OnComplete(nsIQuotaRequest* aRequest) override {
mDone = true;
return NS_OK;
}
private:
~RequestResolver() = default;
bool mDone;
};
static void SetUpTestCase() {
// The first initialization of storage service must be done on the main
// thread.
nsCOMPtr<mozIStorageService> storageService =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
ASSERT_TRUE(storageService);
ASSERT_NO_FATAL_FAILURE(InitializeFixture());
nsIObserver* observer = quota::QuotaManager::GetObserver();
ASSERT_TRUE(observer);
nsresult rv = observer->Observe(nullptr, "profile-do-change", nullptr);
ASSERT_NS_SUCCEEDED(rv);
AutoJSAPI jsapi;
bool ok = jsapi.Init(xpc::PrivilegedJunkScope());
ASSERT_TRUE(ok);
// QuotaManagerService::Initialized fails if the testing pref is not set.
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
prefs->SetBoolPref("dom.quotaManager.testing", true);
prefs->SetIntPref("dom.quotaManager.temporaryStorage.fixedLimit",
mQuotaLimit);
nsCOMPtr<nsIQuotaManagerService> qms =
quota::QuotaManagerService::GetOrCreate();
ASSERT_TRUE(qms);
nsCOMPtr<nsIQuotaRequest> request;
rv = qms->StorageInitialized(getter_AddRefs(request));
ASSERT_NS_SUCCEEDED(rv);
prefs->SetBoolPref("dom.quotaManager.testing", false);
RefPtr<RequestResolver> resolver = new RequestResolver();
rv = request->SetCallback(resolver);
ASSERT_NS_SUCCEEDED(rv);
SpinEventLoopUntil("Promise is fulfilled"_ns,
[&resolver]() { return resolver->Done(); });
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
ASSERT_TRUE(quotaManager);
ASSERT_TRUE(quotaManager->OwningThread());
sBackgroundTarget = quotaManager->OwningThread();
}
static void TearDownTestCase() {
nsIObserver* observer = quota::QuotaManager::GetObserver();
ASSERT_TRUE(observer);
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
nsresult rv =
observer->Observe(nullptr, "profile-before-change-qm", nullptr);
ASSERT_NS_SUCCEEDED(rv);
prefs->ClearUserPref("dom.quotaManager.temporaryStorage.fixedLimit");
bool done = false;
InvokeAsync(sBackgroundTarget, __func__,
[]() {
quota::QuotaManager::Reset();
return BoolPromise::CreateAndResolve(true, __func__);
})
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& value) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
sBackgroundTarget = nullptr;
ASSERT_NO_FATAL_FAILURE(ShutdownFixture());
}
static const nsCOMPtr<nsISerialEventTarget>& BackgroundTargetStrongRef() {
return sBackgroundTarget;
}
static nsCOMPtr<nsISerialEventTarget> sBackgroundTarget;
static const int32_t mQuotaLimit = 8192;
};
NS_IMPL_ISUPPORTS(TestFileOutputStream::RequestResolver, nsIQuotaCallback)
nsCOMPtr<nsISerialEventTarget> TestFileOutputStream::sBackgroundTarget;
TEST_F(TestFileOutputStream, extendFileStreamWithSetEOF) {
auto ioTask = []() {
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
@ -278,21 +176,7 @@ TEST_F(TestFileOutputStream, extendFileStreamWithSetEOF) {
ASSERT_TRUE(0 == avail);
};
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
bool done = false;
InvokeAsync(quotaManager->IOThread(), __func__,
[ioTask = std::move(ioTask)]() {
ioTask();
return BoolPromise::CreateAndResolve(true, __func__);
})
->Then(GetCurrentSerialEventTarget(), __func__,
[&done](const BoolPromise::ResolveOrRejectValue& value) {
done = true;
});
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
PerformOnIOThread(std::move(ioTask));
}
} // namespace mozilla::dom::quota::test

Просмотреть файл

@ -9,8 +9,13 @@ EXPORTS.mozilla.dom.quota += [
"QuotaTestParent.h",
]
EXPORTS.mozilla.dom.quota.test += [
"QuotaManagerDependencyFixture.h",
]
UNIFIED_SOURCES = [
"Common.cpp",
"QuotaManagerDependencyFixture.cpp",
"TestCheckedUnsafePtr.cpp",
"TestClientUsageArray.cpp",
"TestEncryptedStream.cpp",