Files
tubestation/dom/fs/test/gtest/parent/TestFileSystemOriginInitialization.cpp
Jan Varga 7783acd7c8 Bug 1866402 - Make it possible to initialize temporary origins without ensuring origin directories; r=dom-storage-reviewers,jari
LSNG already uses some QuotaManager APIs to achieve that origin directories are
not created if they don't exist during datastore preparation, but the feature
is not easy to use and it's also not generalized enough for use in other quota
clients. Besides that, the way how it's currently done in LSNG complicates
removal of QuotaManager::EnsureTemporaryOriginIsInitializedInternal calls from
LSNG. This patch is about generalizing of the feature, making it available to
all quota clients.

Differential Revision: https://phabricator.services.mozilla.com/D195551
2024-10-12 20:58:36 +00:00

624 lines
22 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 "FileSystemParentTest.h"
#include "FileSystemParentTestHelpers.h"
#include "FileSystemParentTypes.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "mozilla/dom/FileSystemQuotaClient.h"
#include "mozilla/dom/FileSystemQuotaClientFactory.h"
#include "mozilla/dom/quota/UsageInfo.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
// This file is intended for integration tests which verify origin
// initialization.
namespace mozilla::dom::fs::test {
using ::testing::_;
using ::testing::Expectation;
using ::testing::Sequence;
namespace {
class MockFileSystemQuotaClient : public FileSystemQuotaClient {
public:
MOCK_METHOD((Result<quota::UsageInfo, nsresult>), InitOrigin,
(quota::PersistenceType aPersistenceType,
const quota::OriginMetadata& aOriginMetadata,
const AtomicBool& aCanceled),
(override));
MOCK_METHOD((Result<quota::UsageInfo, nsresult>), GetUsageForOrigin,
(quota::PersistenceType aPersistenceType,
const quota::OriginMetadata& aOriginMetadata,
const AtomicBool& aCanceled),
(override));
void DelegateToBase() {
// This exists just to workaround the false positive:
// ERROR: Refcounted variable 'this' of type 'mozilla::dom::fs::test::
// (anonymous namespace)::MockFileSystemQuotaClient' cannot be captured by
// a lambda
bool dummy;
ON_CALL(*this, InitOrigin)
.WillByDefault(
[&dummy, this](quota::PersistenceType aPersistenceType,
const quota::OriginMetadata& aOriginMetadata,
const Atomic<bool>& aCanceled) {
(void)dummy;
return FileSystemQuotaClient::InitOrigin(
aPersistenceType, aOriginMetadata, aCanceled);
});
ON_CALL(*this, GetUsageForOrigin)
.WillByDefault(
[&dummy, this](quota::PersistenceType aPersistenceType,
const quota::OriginMetadata& aOriginMetadata,
const Atomic<bool>& aCanceled) {
(void)dummy;
return FileSystemQuotaClient::GetUsageForOrigin(
aPersistenceType, aOriginMetadata, aCanceled);
});
}
};
class TestFileSystemQuotaClientFactory final
: public FileSystemQuotaClientFactory {
public:
already_AddRefed<MockFileSystemQuotaClient> GetQuotaClient() {
return do_AddRef(mQuotaClient);
}
protected:
already_AddRefed<quota::Client> AllocQuotaClient() override {
mQuotaClient = MakeRefPtr<MockFileSystemQuotaClient>();
mQuotaClient->DelegateToBase();
return do_AddRef(mQuotaClient);
}
RefPtr<MockFileSystemQuotaClient> mQuotaClient;
};
} // namespace
class TestFileSystemOriginInitialization : public FileSystemParentTest {
protected:
static void SetUpTestCase() {
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
prefs->SetBoolPref("dom.quotaManager.loadQuotaFromCache", false);
auto factory = MakeRefPtr<TestFileSystemQuotaClientFactory>();
FileSystemQuotaClientFactory::SetCustomFactory(factory);
ASSERT_NO_FATAL_FAILURE(FileSystemParentTest::SetUpTestCase());
sQuotaClient = factory->GetQuotaClient();
}
static void TearDownTestCase() {
sQuotaClient = nullptr;
ASSERT_NO_FATAL_FAILURE(FileSystemParentTest::TearDownTestCase());
FileSystemQuotaClientFactory::SetCustomFactory(nullptr);
}
static inline RefPtr<MockFileSystemQuotaClient> sQuotaClient;
};
TEST_F(TestFileSystemOriginInitialization, EmptyOriginDirectory) {
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
// Set expectations
{
Sequence s;
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).Times(0).InSequence(s);
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _))
.Times(0)
.InSequence(s);
}
// Initialize origin
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
ASSERT_NO_FATAL_FAILURE(
InitializeTemporaryOrigin(/* aCreateIfNonExistent */ true));
// After initialization,
// * origin usage is nothing
// * cached origin usage is zero
quota::UsageInfo usageNow;
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageIsNothing(usageNow));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
// Shutdown temporary storage
ASSERT_NO_FATAL_FAILURE(ShutdownTemporaryStorage());
// After temporary storage shutdown,
// * origin usage is still nothing
// * cached origin is still zero
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageIsNothing(usageNow));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
// Initialize temporary storage again.
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
// After repeated temporary storage initialization,
// * origin usage is still nothing
// * cached origin is still zero
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageIsNothing(usageNow));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
}
TEST_F(TestFileSystemOriginInitialization, EmptyFileSystemDirectory) {
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
// Set expectations
{
Sequence s;
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).Times(0).InSequence(s);
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _))
.Times(0)
.InSequence(s);
}
// Initialize client
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin());
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryClient());
// After initialization,
// * origin usage is nothing
// * cached origin usage is zero
quota::UsageInfo usageNow;
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageIsNothing(usageNow));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
// Shutdown temporary storage.
ASSERT_NO_FATAL_FAILURE(ShutdownTemporaryStorage());
// After temporary storage shutdown,
// * origin usage is still nothing
// * cached origin usage is still zero
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageIsNothing(usageNow));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
// Initialize temporary storage again.
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
// After repeated temporary storage initialization,
// * origin usage is still nothing
// * cached origin usage is still zero
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageIsNothing(usageNow));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
}
TEST_F(TestFileSystemOriginInitialization, EmptyFileSystemDatabase) {
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
// Set expectations
{
Sequence s;
// GetOriginUsage check after database initialization.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
// GetOriginUsage check when temporary storage is not initialized.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Repeated temporary storage initialization.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Final GetOriginUsage check.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
}
// Initialize database
ASSERT_NO_FATAL_FAILURE(EnsureDataManager());
// After initialization,
// * origin usage is not zero
// * GetOriginUsage and GetCachedOriginUsage should agree
quota::UsageInfo usageNow;
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageGreaterThan(usageNow, 0u));
uint64_t beforeShutdownUsage;
ASSERT_NO_FATAL_FAILURE(GetUsageValue(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
// Shutdown temporary storage.
ASSERT_NO_FATAL_FAILURE(ReleaseDataManager());
ASSERT_NO_FATAL_FAILURE(ShutdownTemporaryStorage());
// After temporary storage shutdown,
// * origin usage is still the same as before shutdown
// * cached origin usage is zero
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
// Initialize temporary storage again.
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
// After repeated temporary storage initialization,
// * origin usage is still the same as before shutdown
// * GetOriginUsage and GetCachedOriginUsage should agree again
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
}
TEST_F(TestFileSystemOriginInitialization, EmptyFileSystemFile) {
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
// Set expectations
{
Sequence s;
// GetOriginUsage check after file creation.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
// GetOriginUsage check when temporary storage is not initialized.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Repeated temporary storage initialization.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Final GetOriginUsage check.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
}
// Initialize database
ASSERT_NO_FATAL_FAILURE(EnsureDataManager());
// Create a new empty file
EntryId testFileId;
ASSERT_NO_FATAL_FAILURE(CreateNewEmptyFile(testFileId));
// After a new file has been created (only in the database),
// * origin usage is not zero
// * GetOriginUsage and GetCachedOriginUsage should agree
quota::UsageInfo usageNow;
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageGreaterThan(usageNow, 0u));
uint64_t beforeShutdownUsage;
ASSERT_NO_FATAL_FAILURE(GetUsageValue(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
// Shutdown temporary storage.
ASSERT_NO_FATAL_FAILURE(ReleaseDataManager());
ASSERT_NO_FATAL_FAILURE(ShutdownTemporaryStorage());
// After temporary storage shutdown,
// * origin usage is still the same as before shutdown
// * cached origin usage is zero
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
// Initialize temporary storage again.
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
// After repeated temporary storage initialization,
// * origin usage is still the same as before shutdown
// * GetOriginUsage and GetCachedOriginUsage should agree
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
}
TEST_F(TestFileSystemOriginInitialization, NonEmptyFileSystemFile) {
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
// Set expectations
{
Sequence s;
// GetOriginUsage check after filling the file with content.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
// GetOriginUsage check after unlocking the file..
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
// GetOriginUsage check when temporary storage is not initialized.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Repeated temporary storage initialization.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Final GetOriginUsage check.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
}
// Initialize database
ASSERT_NO_FATAL_FAILURE(EnsureDataManager());
// Create a new empty file
EntryId testFileId;
ASSERT_NO_FATAL_FAILURE(CreateNewEmptyFile(testFileId));
// Fill the file with some content
ASSERT_NO_FATAL_FAILURE(LockExclusive(testFileId));
const nsCString& testData = GetTestData();
ASSERT_NO_FATAL_FAILURE(WriteDataToFile(testFileId, testData));
// After the content has been written to the file,
// * origin usage is not zero
// * GetOriginUsage and GetCachedOriginUsage should agree
quota::UsageInfo usageNow;
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageGreaterThan(usageNow, 0u));
uint64_t beforeShutdownUsage;
ASSERT_NO_FATAL_FAILURE(GetUsageValue(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(UnlockExclusive(testFileId));
// After the file has been unlocked,
// * origin usage is still the same as before unlocking
// * GetOriginUsage and GetCachedOriginUsage should still agree
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
// Shutdown temporary storage.
ASSERT_NO_FATAL_FAILURE(ReleaseDataManager());
ASSERT_NO_FATAL_FAILURE(ShutdownTemporaryStorage());
// After temporary storage shutdown,
// * origin usage is still the same as before shutdown
// * cached origin usage is zero
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
// Initialize temporary storage again.
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
// After repeated temporary storage initialization,
// * origin usage is still the same as before shutdown
// * GetOriginUsage and GetCachedOriginUsage should agree again
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
}
TEST_F(TestFileSystemOriginInitialization,
NonEmptyFileSystemFile_UncleanShutdown) {
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
// Set expectations
{
Sequence s;
// GetOriginUsage check after file creation.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
// GetOriginUsage check after filling the file with content.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
// GetOriginUsage check when temporary storage is not initialized.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Repeated temporary storage initialization.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Final GetOriginUsage check.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
}
// Initialize database
ASSERT_NO_FATAL_FAILURE(EnsureDataManager());
// Create a new empty file
EntryId testFileId;
ASSERT_NO_FATAL_FAILURE(CreateNewEmptyFile(testFileId));
// After a new file has been created (only in the database),
// * origin usage is not zero
// * GetOriginUsage and GetCachedOriginUsage should agree
quota::UsageInfo usageNow;
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageGreaterThan(usageNow, 0u));
uint64_t beforeWriteUsage;
ASSERT_NO_FATAL_FAILURE(GetUsageValue(usageNow, beforeWriteUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeWriteUsage));
// Fill the file with some content
ASSERT_NO_FATAL_FAILURE(LockExclusive(testFileId));
const nsCString& testData = GetTestData();
ASSERT_NO_FATAL_FAILURE(WriteDataToFile(testFileId, testData));
// After the content has been written to the file,
// * origin usage is not the same as before writing
// * GetOriginUsage and GetCachedOriginUsage should still agree
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageGreaterThan(usageNow, beforeWriteUsage));
uint64_t beforeShutdownUsage;
ASSERT_NO_FATAL_FAILURE(GetUsageValue(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
// UnlockExclusive is not called here on purpose to simmulate unclean
// shutdown.
// Shutdown temporary storage.
ASSERT_NO_FATAL_FAILURE(ReleaseDataManager());
ASSERT_NO_FATAL_FAILURE(ShutdownTemporaryStorage());
// After temporary storage shutdown,
// * static database usage is the same as before writing
// * origin usage is still the same as before shutdown
// * cached origin usage is zero
ASSERT_NO_FATAL_FAILURE(GetStaticDatabaseUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeWriteUsage));
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
// Initialize temporary storage again.
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
// After repeated temporary storage initialization,
// * static database usage is the same as before shutdown
// * GetStaticDatabaseUsage, GetOriginUsage and GetCachedOriginUsage should
// all agree again
ASSERT_NO_FATAL_FAILURE(GetStaticDatabaseUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
}
TEST_F(TestFileSystemOriginInitialization, RemovedFileSystemFile) {
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
// Set expectations
{
Sequence s;
// GetOriginUsage check after removing the file..
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
// GetOriginUsage check when temporary storage is not initialized.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Repeated temporary storage initialization.
EXPECT_CALL(*sQuotaClient, InitOrigin(_, _, _)).InSequence(s);
// Final GetOriginUsage check.
EXPECT_CALL(*sQuotaClient, GetUsageForOrigin(_, _, _)).InSequence(s);
}
// Initialize database
ASSERT_NO_FATAL_FAILURE(EnsureDataManager());
// Create a new empty file
EntryId testFileId;
ASSERT_NO_FATAL_FAILURE(CreateNewEmptyFile(testFileId));
// Fill the file with some content
ASSERT_NO_FATAL_FAILURE(LockExclusive(testFileId));
const nsCString& testData = GetTestData();
ASSERT_NO_FATAL_FAILURE(WriteDataToFile(testFileId, testData));
ASSERT_NO_FATAL_FAILURE(UnlockExclusive(testFileId));
// Remove the file
bool wasRemoved;
ASSERT_NO_FATAL_FAILURE(RemoveFile(wasRemoved));
ASSERT_TRUE(wasRemoved);
// After the file has been removed,
// * origin usage is not zero
// * GetOriginUsage and GetCachedOriginUsage should agree
quota::UsageInfo usageNow;
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageGreaterThan(usageNow, 0u));
uint64_t beforeShutdownUsage;
ASSERT_NO_FATAL_FAILURE(GetUsageValue(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
// Shutdown temporary storage.
ASSERT_NO_FATAL_FAILURE(ReleaseDataManager());
ASSERT_NO_FATAL_FAILURE(ShutdownTemporaryStorage());
// After temporary storage shutdown,
// * origin usage is still the same as before shutdown
// * cached origin usage is zero
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, 0u));
// Initialize temporary storage again.
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
// After repeated temporary storage initialization,
// * origin usage is still the same as before shutdown
// * GetOriginUsage and GetCachedOriginUsage should agree again
ASSERT_NO_FATAL_FAILURE(GetOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
ASSERT_NO_FATAL_FAILURE(GetCachedOriginUsage(usageNow));
ASSERT_NO_FATAL_FAILURE(CheckUsageEqualTo(usageNow, beforeShutdownUsage));
}
} // namespace mozilla::dom::fs::test