Backed out 4 changesets (bug 1685677) for causing build bustage in TestFlatten. CLOSED TREE DONTBUILD

Backed out changeset 0110eb26213b (bug 1685677)
Backed out changeset e3223c398959 (bug 1685677)
Backed out changeset d1fbaf6882a3 (bug 1685677)
Backed out changeset e1e26422161e (bug 1685677)
This commit is contained in:
smolnar 2021-02-02 14:46:30 +02:00
parent fe6a33b7ec
commit d18d54a300
6 changed files with 140 additions and 420 deletions

View File

@ -7,7 +7,6 @@
#include "ActorsParent.h"
// Local includes
#include "Flatten.h"
#include "InitializationTypes.h"
#include "OriginScope.h"
#include "QuotaCommon.h"
@ -951,15 +950,15 @@ class OriginInfo final {
bool mDirectoryExists;
};
class OriginInfoAccessTimeComparator {
class OriginInfoLRUComparator {
public:
bool Equals(const NotNull<RefPtr<const OriginInfo>>& a,
const NotNull<RefPtr<const OriginInfo>>& b) const {
bool Equals(const NotNull<RefPtr<OriginInfo>>& a,
const NotNull<RefPtr<OriginInfo>>& b) const {
return a->LockedAccessTime() == b->LockedAccessTime();
}
bool LessThan(const NotNull<RefPtr<const OriginInfo>>& a,
const NotNull<RefPtr<const OriginInfo>>& b) const {
bool LessThan(const NotNull<RefPtr<OriginInfo>>& a,
const NotNull<RefPtr<OriginInfo>>& b) const {
return a->LockedAccessTime() < b->LockedAccessTime();
}
};
@ -1024,11 +1023,14 @@ class GroupInfoPair {
MOZ_COUNTED_DTOR(GroupInfoPair)
private:
RefPtr<GroupInfo> LockedGetGroupInfo(PersistenceType aPersistenceType) {
already_AddRefed<GroupInfo> LockedGetGroupInfo(
PersistenceType aPersistenceType) {
AssertCurrentThreadOwnsQuotaMutex();
MOZ_ASSERT(aPersistenceType != PERSISTENCE_TYPE_PERSISTENT);
return GetGroupInfoForPersistenceType(aPersistenceType);
RefPtr<GroupInfo> groupInfo =
GetGroupInfoForPersistenceType(aPersistenceType);
return groupInfo.forget();
}
void LockedSetGroupInfo(PersistenceType aPersistenceType,
@ -3781,8 +3783,8 @@ uint64_t QuotaManager::CollectOriginsForEviction(
static void GetInactiveOriginInfos(
const nsTArray<NotNull<RefPtr<OriginInfo>>>& aOriginInfos,
const nsTArray<NotNull<DirectoryLockImpl*>>& aLocks,
OriginInfosFlatTraversable& aInactiveOriginInfos) {
for (const auto& originInfo : aOriginInfos) {
nsTArray<NotNull<RefPtr<OriginInfo>>>& aInactiveOriginInfos) {
for (const NotNull<RefPtr<OriginInfo>>& originInfo : aOriginInfos) {
MOZ_ASSERT(originInfo->mGroupInfo->mPersistenceType !=
PERSISTENCE_TYPE_PERSISTENT);
@ -3801,8 +3803,8 @@ uint64_t QuotaManager::CollectOriginsForEviction(
if (!match) {
MOZ_ASSERT(!originInfo->mQuotaObjects.Count(),
"Inactive origin shouldn't have open files!");
aInactiveOriginInfos.InsertElementSorted(
originInfo, OriginInfoAccessTimeComparator());
aInactiveOriginInfos.InsertElementSorted(originInfo,
OriginInfoLRUComparator());
}
}
}
@ -3830,7 +3832,7 @@ uint64_t QuotaManager::CollectOriginsForEviction(
}
}
OriginInfosFlatTraversable inactiveOrigins;
nsTArray<NotNull<RefPtr<OriginInfo>>> inactiveOrigins;
// Enumerate and process inactive origins. This must be protected by the
// mutex.
@ -6437,8 +6439,8 @@ QuotaManager::EnsurePersistentOriginIsInitialized(const QuotaInfo& aQuotaInfo) {
return std::pair(std::move(directory), created);
}();
if (auto& info = mOriginInitializationInfos.GetOrInsert(aQuotaInfo.mOrigin);
!info.mPersistentOriginAttempted) {
auto& info = mOriginInitializationInfos.GetOrInsert(aQuotaInfo.mOrigin);
if (!info.mPersistentOriginAttempted) {
Telemetry::Accumulate(Telemetry::QM_FIRST_INITIALIZATION_ATTEMPT,
kPersistentOriginTelemetryKey,
static_cast<uint32_t>(res.isOk()));
@ -6547,7 +6549,7 @@ nsresult QuotaManager::EnsureTemporaryStorageIsInitialized() {
mTemporaryStorageLimit = GetTemporaryStorageLimit(
/* aAvailableSpaceBytes */ diskSpaceAvailable + mTemporaryStorageUsage);
CleanupTemporaryStorage();
CheckTemporaryStorageLimits();
return NS_OK;
}
@ -7038,8 +7040,8 @@ void QuotaManager::LockedRemoveQuotaForOrigin(
MOZ_ASSERT(pair);
if (RefPtr<GroupInfo> groupInfo =
pair->LockedGetGroupInfo(aPersistenceType)) {
RefPtr<GroupInfo> groupInfo = pair->LockedGetGroupInfo(aPersistenceType);
if (groupInfo) {
groupInfo->LockedRemoveOriginInfo(aGroupAndOrigin.mOrigin);
if (!groupInfo->LockedHasOriginInfos()) {
@ -7089,219 +7091,150 @@ already_AddRefed<OriginInfo> QuotaManager::LockedGetOriginInfo(
return nullptr;
}
template <typename Iterator, typename Pred>
void QuotaManager::MaybeInsertOriginInfos(
Iterator aDest, const RefPtr<GroupInfo>& aTemporaryGroupInfo,
const RefPtr<GroupInfo>& aDefaultGroupInfo, Pred&& aPred) {
const auto copy = [&aDest, &aPred](const GroupInfo& groupInfo) {
std::copy_if(groupInfo.mOriginInfos.cbegin(), groupInfo.mOriginInfos.cend(),
aDest, aPred);
};
void QuotaManager::CheckTemporaryStorageLimits() {
AssertIsOnIOThread();
if (aTemporaryGroupInfo) {
MOZ_ASSERT(PERSISTENCE_TYPE_TEMPORARY ==
aTemporaryGroupInfo->GetPersistenceType());
const auto doomedOrigins = [this] {
const auto doomedOriginInfos = [this] {
nsTArray<NotNull<RefPtr<OriginInfo>>> doomedOriginInfos;
MutexAutoLock lock(mQuotaMutex);
copy(*aTemporaryGroupInfo);
}
if (aDefaultGroupInfo) {
MOZ_ASSERT(PERSISTENCE_TYPE_DEFAULT ==
aDefaultGroupInfo->GetPersistenceType());
for (const auto& entry : mGroupInfoPairs) {
const auto& pair = entry.GetData();
copy(*aDefaultGroupInfo);
}
}
MOZ_ASSERT(!entry.GetKey().IsEmpty());
MOZ_ASSERT(pair);
template <typename Collect, typename Pred>
QuotaManager::OriginInfosFlatTraversable
QuotaManager::CollectLRUOriginInfosUntil(Collect&& aCollect, Pred&& aPred) {
OriginInfosFlatTraversable originInfos;
uint64_t groupUsage = 0;
std::forward<Collect>(aCollect)(MakeBackInserter(originInfos));
RefPtr<GroupInfo> temporaryGroupInfo =
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
if (temporaryGroupInfo) {
groupUsage += temporaryGroupInfo->mUsage;
}
originInfos.Sort(OriginInfoAccessTimeComparator());
RefPtr<GroupInfo> defaultGroupInfo =
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
if (defaultGroupInfo) {
groupUsage += defaultGroupInfo->mUsage;
}
const auto foundIt = std::find_if(originInfos.cbegin(), originInfos.cend(),
std::forward<Pred>(aPred));
if (groupUsage > 0) {
QuotaManager* quotaManager = QuotaManager::Get();
MOZ_ASSERT(quotaManager, "Shouldn't be null!");
originInfos.TruncateLength(foundIt - originInfos.cbegin());
if (groupUsage > quotaManager->GetGroupLimit()) {
nsTArray<NotNull<RefPtr<OriginInfo>>> originInfos;
if (temporaryGroupInfo) {
originInfos.AppendElements(temporaryGroupInfo->mOriginInfos);
}
if (defaultGroupInfo) {
originInfos.AppendElements(defaultGroupInfo->mOriginInfos);
}
originInfos.Sort(OriginInfoLRUComparator());
return originInfos;
}
for (uint32_t i = 0; i < originInfos.Length(); i++) {
const NotNull<RefPtr<OriginInfo>>& originInfo = originInfos[i];
if (originInfo->LockedPersisted()) {
continue;
}
QuotaManager::OriginInfosNestedTraversable
QuotaManager::LockedGetOriginInfosExceedingGroupLimit() const {
mQuotaMutex.AssertCurrentThreadOwns();
OriginInfosNestedTraversable originInfos;
for (const auto& entry : mGroupInfoPairs) {
const auto& pair = entry.GetData();
MOZ_ASSERT(!entry.GetKey().IsEmpty());
MOZ_ASSERT(pair);
uint64_t groupUsage = 0;
const RefPtr<GroupInfo> temporaryGroupInfo =
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
if (temporaryGroupInfo) {
groupUsage += temporaryGroupInfo->mUsage;
}
const RefPtr<GroupInfo> defaultGroupInfo =
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
if (defaultGroupInfo) {
groupUsage += defaultGroupInfo->mUsage;
}
if (groupUsage > 0) {
QuotaManager* quotaManager = QuotaManager::Get();
MOZ_ASSERT(quotaManager, "Shouldn't be null!");
if (groupUsage > quotaManager->GetGroupLimit()) {
originInfos.AppendElement(CollectLRUOriginInfosUntil(
[&temporaryGroupInfo, &defaultGroupInfo](auto inserter) {
MaybeInsertOriginInfos(std::move(inserter), temporaryGroupInfo,
defaultGroupInfo,
[](const auto& originInfo) {
return !originInfo->LockedPersisted();
});
},
[&groupUsage, quotaManager](const auto& originInfo) {
doomedOriginInfos.AppendElement(originInfo);
groupUsage -= originInfo->LockedUsage();
return groupUsage <= quotaManager->GetGroupLimit();
}));
if (groupUsage <= quotaManager->GetGroupLimit()) {
break;
}
}
}
}
}
}
}
return originInfos;
}
uint64_t usage = std::accumulate(
doomedOriginInfos.cbegin(), doomedOriginInfos.cend(), uint64_t(0),
[](uint64_t oldValue, const auto& originInfo) {
return oldValue + originInfo->LockedUsage();
});
QuotaManager::OriginInfosFlatTraversable
QuotaManager::LockedGetOriginInfosExceedingGlobalLimit(
const OriginInfosNestedTraversable& aAlreadyDoomedOriginInfos,
const uint64_t aAlreadyDoomedUsage) const {
mQuotaMutex.AssertCurrentThreadOwns();
if (mTemporaryStorageUsage - usage > mTemporaryStorageLimit) {
nsTArray<NotNull<RefPtr<OriginInfo>>> originInfos;
return CollectLRUOriginInfosUntil(
[this, &aAlreadyDoomedOriginInfos](auto inserter) {
for (const auto& entry : mGroupInfoPairs) {
const auto& pair = entry.GetData();
MOZ_ASSERT(!entry.GetKey().IsEmpty());
MOZ_ASSERT(pair);
MaybeInsertOriginInfos(
inserter, pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY),
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT),
[&aAlreadyDoomedOriginInfos](const auto& originInfo) {
return !std::any_of(aAlreadyDoomedOriginInfos.cbegin(),
aAlreadyDoomedOriginInfos.cend(),
// XXX This should capture originInfo by
// value, but it can't due to Bug 1421435.
[&originInfo](const auto& array) {
return array.Contains(originInfo);
}) &&
!originInfo->LockedPersisted();
});
}
},
[temporaryStorageUsage = mTemporaryStorageUsage - aAlreadyDoomedUsage,
temporaryStorageLimit = mTemporaryStorageLimit,
doomedUsage = uint64_t{0}](const auto& originInfo) mutable {
if (temporaryStorageUsage - doomedUsage <= temporaryStorageLimit) {
return true;
RefPtr<GroupInfo> groupInfo =
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
if (groupInfo) {
originInfos.AppendElements(groupInfo->mOriginInfos);
}
groupInfo = pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
if (groupInfo) {
originInfos.AppendElements(groupInfo->mOriginInfos);
}
}
doomedUsage += originInfo->LockedUsage();
return false;
});
}
originInfos.RemoveElementsBy(
[&doomedOriginInfos](const auto& originInfo) {
return doomedOriginInfos.Contains(originInfo) ||
originInfo->LockedPersisted();
});
QuotaManager::OriginInfosNestedTraversable
QuotaManager::GetOriginInfosExceedingLimits() const {
MutexAutoLock lock(mQuotaMutex);
originInfos.Sort(OriginInfoLRUComparator());
auto originInfos = LockedGetOriginInfosExceedingGroupLimit();
for (uint32_t i = 0; i < originInfos.Length(); i++) {
if (mTemporaryStorageUsage - usage <= mTemporaryStorageLimit) {
originInfos.TruncateLength(i);
break;
}
const uint64_t doomedUsage = std::accumulate(
originInfos.cbegin(), originInfos.cend(), uint64_t(0),
[](uint64_t oldValue, const auto& currentOriginInfos) {
return std::accumulate(currentOriginInfos.cbegin(),
currentOriginInfos.cend(), oldValue,
[](uint64_t oldValue, const auto& originInfo) {
return oldValue + originInfo->LockedUsage();
});
});
usage += originInfos[i]->LockedUsage();
}
// Evicting origins that exceed their group limit also affects the global
// temporary storage usage. If the global temporary storage limit would still
// be exceeded after evicting the origins that were already selected, we need
// to specifically evict origins to get below the global limit.
if (mTemporaryStorageUsage - doomedUsage > mTemporaryStorageLimit) {
originInfos.AppendElement(
LockedGetOriginInfosExceedingGlobalLimit(originInfos, doomedUsage));
}
doomedOriginInfos.AppendElements(originInfos);
}
return originInfos;
}
return doomedOriginInfos;
}();
void QuotaManager::ClearOrigins(
const OriginInfosNestedTraversable& aDoomedOriginInfos) {
AssertIsOnIOThread();
// XXX Does this need to be done a) in order and/or b) sequentially?
for (const auto& doomedOriginInfo :
Flatten<OriginInfosFlatTraversable::elem_type>(aDoomedOriginInfos)) {
for (const auto& doomedOriginInfo : doomedOriginInfos) {
#ifdef DEBUG
{
MutexAutoLock lock(mQuotaMutex);
MOZ_ASSERT(!doomedOriginInfo->LockedPersisted());
}
{
MutexAutoLock lock(mQuotaMutex);
MOZ_ASSERT(!doomedOriginInfo->LockedPersisted());
}
#endif
DeleteFilesForOrigin(doomedOriginInfo->mGroupInfo->mPersistenceType,
doomedOriginInfo->mOrigin);
}
struct OriginParams {
nsCString mOrigin;
PersistenceType mPersistenceType;
};
nsTArray<OriginParams> clearedOrigins;
{
MutexAutoLock lock(mQuotaMutex);
for (const auto& doomedOriginInfo :
Flatten<OriginInfosFlatTraversable::elem_type>(aDoomedOriginInfos)) {
// LockedRemoveQuotaForOrigin might remove the group info;
// OriginInfo::mGroupInfo is only a raw pointer, so we need to store the
// information for calling OriginClearCompleted below in a separate array.
clearedOrigins.AppendElement(
OriginParams{doomedOriginInfo->mOrigin,
doomedOriginInfo->mGroupInfo->mPersistenceType});
LockedRemoveQuotaForOrigin(
doomedOriginInfo->mGroupInfo->mPersistenceType,
{doomedOriginInfo->mGroupInfo->mGroup, doomedOriginInfo->mOrigin});
DeleteFilesForOrigin(doomedOriginInfo->mGroupInfo->mPersistenceType,
doomedOriginInfo->mOrigin);
}
}
for (const auto& clearedOrigin : clearedOrigins) {
OriginClearCompleted(clearedOrigin.mPersistenceType, clearedOrigin.mOrigin,
nsTArray<OriginParams> doomedOrigins;
{
MutexAutoLock lock(mQuotaMutex);
for (const auto& doomedOriginInfo : doomedOriginInfos) {
PersistenceType persistenceType =
doomedOriginInfo->mGroupInfo->mPersistenceType;
const GroupAndOrigin groupAndOrigin = {
doomedOriginInfo->mGroupInfo->mGroup, doomedOriginInfo->mOrigin};
LockedRemoveQuotaForOrigin(persistenceType, groupAndOrigin);
doomedOrigins.EmplaceBack(
OriginParams(persistenceType, groupAndOrigin.mOrigin));
}
}
return doomedOrigins;
}();
for (const OriginParams& doomedOrigin : doomedOrigins) {
OriginClearCompleted(doomedOrigin.mPersistenceType, doomedOrigin.mOrigin,
Nullable<Client::Type>());
}
}
void QuotaManager::CleanupTemporaryStorage() {
AssertIsOnIOThread();
ClearOrigins(GetOriginInfosExceedingLimits());
if (mTemporaryStorageUsage > mTemporaryStorageLimit) {
// If disk space is still low after origin clear, notify storage pressure.
@ -7376,8 +7309,8 @@ bool QuotaManager::IsSanitizedOriginValid(const nsACString& aSanitizedOrigin) {
int64_t QuotaManager::GenerateDirectoryLockId() {
const int64_t directorylockId = mNextDirectoryLockId;
if (CheckedInt64 result = CheckedInt64(mNextDirectoryLockId) + 1;
result.isValid()) {
CheckedInt64 result = CheckedInt64(mNextDirectoryLockId) + 1;
if (result.isValid()) {
mNextDirectoryLockId = result.value();
} else {
NS_WARNING("Quota manager has run out of ids for directory locks!");

View File

@ -1,118 +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_QUOTA_FLATTEN_H_
#define DOM_QUOTA_FLATTEN_H_
#include <iterator>
#include <type_traits>
#include <utility>
// XXX This should be moved to MFBT.
namespace mozilla::dom::quota {
namespace detail {
using std::begin;
using std::end;
template <typename T, typename NestedRange>
auto Flatten(NestedRange&& aRange) -> std::enable_if_t<
std::is_same_v<T, std::decay_t<typename decltype(begin(
std::declval<const NestedRange&>()))::value_type>>,
std::conditional_t<std::is_rvalue_reference_v<NestedRange>,
std::decay_t<NestedRange>, NestedRange>> {
return std::forward<NestedRange>(aRange);
}
template <typename T, typename NestedRange>
struct FlatIter {
using OuterIterator =
decltype(begin(std::declval<const std::decay_t<NestedRange>&>()));
using InnerIterator =
decltype(begin(*begin(std::declval<const std::decay_t<NestedRange>&>())));
explicit FlatIter(const NestedRange& aRange, OuterIterator aIter)
: mOuterIter{std::move(aIter)}, mOuterEnd{end(aRange)} {
InitInner();
}
const T& operator*() const { return *mInnerIter; }
FlatIter& operator++() {
++mInnerIter;
if (mInnerIter == mInnerEnd) {
++mOuterIter;
InitInner();
}
return *this;
}
bool operator!=(const FlatIter& aOther) const {
return mOuterIter != aOther.mOuterIter ||
(mOuterIter != mOuterEnd && mInnerIter != aOther.mInnerIter);
}
private:
void InitInner() {
while (mOuterIter != mOuterEnd) {
const typename OuterIterator::value_type& innerRange = *mOuterIter;
mInnerIter = begin(innerRange);
mInnerEnd = end(innerRange);
if (mInnerIter != mInnerEnd) {
break;
}
++mOuterIter;
}
}
OuterIterator mOuterIter;
const OuterIterator mOuterEnd;
InnerIterator mInnerIter;
InnerIterator mInnerEnd;
};
template <typename T, typename NestedRange>
struct FlatRange {
explicit FlatRange(NestedRange aRange) : mRange{std::move(aRange)} {}
auto begin() const {
using std::begin;
return FlatIter<T, NestedRange>{mRange, begin(mRange)};
}
auto end() const {
using std::end;
return FlatIter<T, NestedRange>{mRange, end(mRange)};
}
private:
NestedRange mRange;
};
template <typename T, typename NestedRange>
auto Flatten(NestedRange&& aRange) -> std::enable_if_t<
!std::is_same_v<
T, std::decay_t<typename decltype(begin(
std::declval<const std::decay_t<NestedRange>&>()))::value_type>>,
FlatRange<T, NestedRange>> {
return FlatRange<T, NestedRange>{std::forward<NestedRange>(aRange)};
}
} // namespace detail
template <typename T, typename NestedRange>
auto Flatten(NestedRange&& aRange) -> decltype(auto) {
return detail::Flatten<T>(std::forward<NestedRange>(aRange));
}
} // namespace mozilla::dom::quota
#endif

View File

@ -114,6 +114,14 @@ class NS_NO_VTABLE OpenDirectoryListener : public RefCountedObject {
virtual ~OpenDirectoryListener() = default;
};
struct OriginParams {
OriginParams(PersistenceType aPersistenceType, const nsACString& aOrigin)
: mOrigin(aOrigin), mPersistenceType(aPersistenceType) {}
nsCString mOrigin;
PersistenceType mPersistenceType;
};
class QuotaManager final : public BackgroundThreadObject {
friend class DirectoryLockImpl;
friend class GroupInfo;
@ -558,23 +566,7 @@ class QuotaManager final : public BackgroundThreadObject {
int64_t aAccessTime, bool aPersisted,
nsIFile* aDirectory);
using OriginInfosFlatTraversable =
nsTArray<NotNull<RefPtr<const OriginInfo>>>;
using OriginInfosNestedTraversable =
nsTArray<nsTArray<NotNull<RefPtr<const OriginInfo>>>>;
OriginInfosNestedTraversable LockedGetOriginInfosExceedingGroupLimit() const;
OriginInfosFlatTraversable LockedGetOriginInfosExceedingGlobalLimit(
const OriginInfosNestedTraversable& aAlreadyDoomedOriginInfos,
uint64_t aAlreadyDoomedUsage) const;
OriginInfosNestedTraversable GetOriginInfosExceedingLimits() const;
void ClearOrigins(const OriginInfosNestedTraversable& aDoomedOriginInfos);
void CleanupTemporaryStorage();
void CheckTemporaryStorageLimits();
void DeleteFilesForOrigin(PersistenceType aPersistenceType,
const nsACString& aOrigin);
@ -598,15 +590,6 @@ class QuotaManager final : public BackgroundThreadObject {
void MaybeRecordShutdownStep(Maybe<Client::Type> aClientType,
const nsACString& aStepDescription);
template <typename Iterator, typename Pred>
static void MaybeInsertOriginInfos(
Iterator aDest, const RefPtr<GroupInfo>& aTemporaryGroupInfo,
const RefPtr<GroupInfo>& aDefaultGroupInfo, Pred&& aPred);
template <typename Collect, typename Pred>
static OriginInfosFlatTraversable CollectLRUOriginInfosUntil(
Collect&& aCollect, Pred&& aPred);
// Thread on which IO is performed.
LazyInitializedOnceNotNull<const nsCOMPtr<nsIThread>> mIOThread;
@ -622,7 +605,7 @@ class QuotaManager final : public BackgroundThreadObject {
// Accesses to mQuotaManagerShutdownSteps must be protected by mQuotaMutex.
nsCString mQuotaManagerShutdownSteps;
mutable mozilla::Mutex mQuotaMutex;
mozilla::Mutex mQuotaMutex;
nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs;

View File

@ -1,74 +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 "Flatten.h"
#include "gtest/gtest.h"
#include "mozilla/Unused.h"
#include "nsTArray.h"
namespace mozilla::dom::quota {
TEST(Flatten, FlatEmpty)
{
for (const auto& item : Flatten<int>(nsTArray<int>{})) {
Unused << item;
FAIL();
}
}
TEST(Flatten, NestedOuterEmpty)
{
for (const auto& item : Flatten<int>(nsTArray<CopyableTArray<int>>{})) {
Unused << item;
FAIL();
}
}
TEST(Flatten, NestedInnerEmpty)
{
for (const auto& item :
Flatten<int>(nsTArray<CopyableTArray<int>>{CopyableTArray<int>{}})) {
Unused << item;
FAIL();
}
}
TEST(Flatten, NestedInnerSingular)
{
nsTArray<int> flattened;
for (const auto& item :
Flatten<int>(nsTArray<CopyableTArray<int>>{CopyableTArray<int>{1}})) {
flattened.AppendElement(item);
}
EXPECT_EQ(nsTArray{1}, flattened);
}
TEST(Flatten, NestedInnerSingulars)
{
nsTArray<int> flattened;
for (const auto& item : Flatten<int>(nsTArray<CopyableTArray<int>>{
CopyableTArray<int>{1}, CopyableTArray<int>{2}})) {
flattened.AppendElement(item);
}
EXPECT_EQ((nsTArray{1, 2}), flattened);
}
TEST(Flatten, NestedInnerNonSingulars)
{
nsTArray<int> flattened;
for (const auto& item : Flatten<int>(nsTArray<CopyableTArray<int>>{
CopyableTArray<int>{1, 2}, CopyableTArray<int>{3, 4}})) {
flattened.AppendElement(item);
}
EXPECT_EQ((nsTArray{1, 2, 3, 4}), flattened);
}
} // namespace mozilla::dom::quota

View File

@ -7,7 +7,6 @@
UNIFIED_SOURCES = [
"TestCheckedUnsafePtr.cpp",
"TestEncryptedStream.cpp",
"TestFlatten.cpp",
"TestQuotaCommon.cpp",
"TestQuotaManager.cpp",
"TestUsageInfo.cpp",

View File

@ -77,10 +77,7 @@ struct CopyablePtr {
T mPtr;
template <typename U>
explicit CopyablePtr(U&& aPtr) : mPtr{std::forward<U>(aPtr)} {}
template <typename U>
explicit CopyablePtr(CopyablePtr<U> aPtr) : mPtr{std::move(aPtr.mPtr)} {}
explicit CopyablePtr(U aPtr) : mPtr{std::move(aPtr)} {}
};
} // namespace detail