Skip to content

Commit 08cbb76

Browse files
committed
Bug 1708643 - Add QM_OR_ELSE_WARN_IF/QM_OR_ELSE_NOTE_IF/QM_OR_ELSE_LOG_IF macros; r=dom-storage-reviewers,asuth
Differential Revision: https://phabricator.services.mozilla.com/D114844
1 parent 243596a commit 08cbb76

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

dom/quota/QuotaCommon.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,69 @@ class NotNull;
894894
*/
895895
#define QM_OR_ELSE_LOG(...) QM_OR_ELSE_REPORT(Log, __VA_ARGS__)
896896

897+
namespace mozilla::dom::quota {
898+
899+
// XXX Support orElseIf directly in mozilla::Result
900+
template <typename V, typename E, typename P, typename F>
901+
auto OrElseIf(Result<V, E>&& aResult, P&& aPred, F&& aFunc) -> Result<V, E> {
902+
return MOZ_UNLIKELY(aResult.isErr())
903+
? (std::forward<P>(aPred)(aResult.inspectErr()))
904+
? std::forward<F>(aFunc)(aResult.unwrapErr())
905+
: aResult.propagateErr()
906+
: aResult.unwrap();
907+
}
908+
909+
} // namespace mozilla::dom::quota
910+
911+
// QM_OR_ELSE_REPORT_IF macro is an implementation detail of
912+
// QM_OR_ELSE_WARN_IF/QM_OR_ELSE_NOTE_IF/QM_OR_ELSE_LOG_IF and shouldn't be
913+
// used directly.
914+
915+
#define QM_OR_ELSE_REPORT_IF(severity, expr, predicate, fallback) \
916+
mozilla::dom::quota::OrElseIf( \
917+
(expr), \
918+
[&](const auto& firstRes) { \
919+
bool res = predicate(firstRes); \
920+
mozilla::dom::quota::QM_HANDLE_ERROR( \
921+
#expr, firstRes, \
922+
res ? mozilla::dom::quota::Severity::severity \
923+
: mozilla::dom::quota::Severity::Error); \
924+
return res; \
925+
}, \
926+
fallback)
927+
928+
/*
929+
* QM_OR_ELSE_WARN_IF(expr, predicate, fallback) evaluates expr first, which
930+
* must produce a Result value. On Success, it just moves the success over.
931+
* On error, it calls a predicate function (passed as the second argument) and
932+
* then it either calls HandleError (with the Warning severity) and a fallback
933+
* function (passed as the third argument) which produces a new result if the
934+
* predicate returned true. Or it calls HandleError (with the Error severity)
935+
* and propagates the error result if the predicate returned false. So failed
936+
* expr can be reported as a warning or as an error depending on the predicate.
937+
* QM_OR_ELSE_WARN_IF is a sub macro and is intended to be used along with one
938+
* of the main macros such as QM_TRY.
939+
*/
940+
#define QM_OR_ELSE_WARN_IF(...) QM_OR_ELSE_REPORT_IF(Warning, __VA_ARGS__)
941+
942+
/**
943+
* QM_OR_ELSE_NOTE_IF is like QM_OR_ELSE_WARN_IF. The only difference is that
944+
* failures are reported using a lower level of severity relative to failures
945+
* reported by QM_OR_ELSE_WARN_IF.
946+
*/
947+
#define QM_OR_ELSE_NOTE_IF(...) QM_OR_ELSE_REPORT_IF(Note, __VA_ARGS__)
948+
949+
/**
950+
* QM_OR_ELSE_LOG_IF is like QM_OR_ELSE_WARN_IF. The only difference is that
951+
* failures are reported using the lowest severity which is currently ignored
952+
* in LogError, so nothing goes to the console, browser console and telemetry.
953+
* Since nothing goes to the telemetry, the macro can't signal the end of the
954+
* underlying error stack or change the type of the error stack in the
955+
* telemetry. For that reason, the expression shouldn't contain nested QM_TRY
956+
* macro uses.
957+
*/
958+
#define QM_OR_ELSE_LOG_IF(...) QM_OR_ELSE_REPORT_IF(Log, __VA_ARGS__)
959+
897960
// Telemetry probes to collect number of failure during the initialization.
898961
#ifdef NIGHTLY_BUILD
899962
# define RECORD_IN_NIGHTLY(_recorder, _status) \

dom/quota/test/gtest/TestQuotaCommon.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,118 @@ TEST(QuotaCommon_OrElseWarn, Failure_MappedToError)
12441244
EXPECT_FALSE(tryContinued);
12451245
}
12461246

1247+
TEST(QuotaCommon_OrElseWarnIf, Success)
1248+
{
1249+
bool predicateRun = false;
1250+
bool fallbackRun = false;
1251+
bool tryContinued = false;
1252+
1253+
const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
1254+
QM_TRY(QM_OR_ELSE_WARN_IF(
1255+
OkIf(true),
1256+
[&predicateRun](const NotOk) {
1257+
predicateRun = true;
1258+
return false;
1259+
},
1260+
([&fallbackRun](const NotOk) {
1261+
fallbackRun = true;
1262+
return mozilla::Result<mozilla::Ok, NotOk>{mozilla::Ok{}};
1263+
})));
1264+
1265+
tryContinued = true;
1266+
return mozilla::Ok{};
1267+
}();
1268+
1269+
EXPECT_TRUE(res.isOk());
1270+
EXPECT_FALSE(predicateRun);
1271+
EXPECT_FALSE(fallbackRun);
1272+
EXPECT_TRUE(tryContinued);
1273+
}
1274+
1275+
TEST(QuotaCommon_OrElseWarnIf, Failure_PredicateReturnsFalse)
1276+
{
1277+
bool predicateRun = false;
1278+
bool fallbackRun = false;
1279+
bool tryContinued = false;
1280+
1281+
const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
1282+
QM_TRY(QM_OR_ELSE_WARN_IF(
1283+
OkIf(false),
1284+
[&predicateRun](const NotOk) {
1285+
predicateRun = true;
1286+
return false;
1287+
},
1288+
([&fallbackRun](const NotOk) {
1289+
fallbackRun = true;
1290+
return mozilla::Result<mozilla::Ok, NotOk>{mozilla::Ok{}};
1291+
})));
1292+
1293+
tryContinued = true;
1294+
return mozilla::Ok{};
1295+
}();
1296+
1297+
EXPECT_TRUE(res.isErr());
1298+
EXPECT_TRUE(predicateRun);
1299+
EXPECT_FALSE(fallbackRun);
1300+
EXPECT_FALSE(tryContinued);
1301+
}
1302+
1303+
TEST(QuotaCommon_OrElseWarnIf, Failure_PredicateReturnsTrue_MappedToSuccess)
1304+
{
1305+
bool predicateRun = false;
1306+
bool fallbackRun = false;
1307+
bool tryContinued = false;
1308+
1309+
const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
1310+
QM_TRY(QM_OR_ELSE_WARN_IF(
1311+
OkIf(false),
1312+
[&predicateRun](const NotOk) {
1313+
predicateRun = true;
1314+
return true;
1315+
},
1316+
([&fallbackRun](const NotOk) {
1317+
fallbackRun = true;
1318+
return mozilla::Result<mozilla::Ok, NotOk>{mozilla::Ok{}};
1319+
})));
1320+
1321+
tryContinued = true;
1322+
return mozilla::Ok{};
1323+
}();
1324+
1325+
EXPECT_TRUE(res.isOk());
1326+
EXPECT_TRUE(predicateRun);
1327+
EXPECT_TRUE(fallbackRun);
1328+
EXPECT_TRUE(tryContinued);
1329+
}
1330+
1331+
TEST(QuotaCommon_OrElseWarnIf, Failure_PredicateReturnsTrue_MappedToError)
1332+
{
1333+
bool predicateRun = false;
1334+
bool fallbackRun = false;
1335+
bool tryContinued = false;
1336+
1337+
const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
1338+
QM_TRY(QM_OR_ELSE_WARN_IF(
1339+
OkIf(false),
1340+
[&predicateRun](const NotOk) {
1341+
predicateRun = true;
1342+
return true;
1343+
},
1344+
([&fallbackRun](const NotOk) {
1345+
fallbackRun = true;
1346+
return mozilla::Result<mozilla::Ok, NotOk>{mozilla::NotOk{}};
1347+
})));
1348+
1349+
tryContinued = true;
1350+
return mozilla::Ok{};
1351+
}();
1352+
1353+
EXPECT_TRUE(res.isErr());
1354+
EXPECT_TRUE(predicateRun);
1355+
EXPECT_TRUE(fallbackRun);
1356+
EXPECT_FALSE(tryContinued);
1357+
}
1358+
12471359
TEST(QuotaCommon_OkIf, True)
12481360
{
12491361
auto res = OkIf(true);

0 commit comments

Comments
 (0)