tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestQuotaCommon.cpp (62853B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <array>
      8 #include <cstddef>
      9 #include <cstdint>
     10 #include <new>
     11 #include <ostream>
     12 #include <type_traits>
     13 #include <utility>
     14 #include <vector>
     15 
     16 #include "ErrorList.h"
     17 #include "gtest/gtest.h"
     18 #include "mozilla/Assertions.h"
     19 #include "mozilla/Result.h"
     20 #include "mozilla/ResultExtensions.h"
     21 #include "mozilla/ResultVariant.h"
     22 #include "mozilla/dom/quota/QuotaCommon.h"
     23 #include "mozilla/dom/quota/QuotaTestParent.h"
     24 #include "mozilla/dom/quota/ResultExtensions.h"
     25 #include "nsCOMPtr.h"
     26 #include "nsDirectoryServiceDefs.h"
     27 #include "nsDirectoryServiceUtils.h"
     28 #include "nsIFile.h"
     29 #include "nsLiteralString.h"
     30 #include "nsString.h"
     31 #include "nsStringFwd.h"
     32 #include "nsTLiteralString.h"
     33 
     34 class nsISupports;
     35 
     36 namespace mozilla::dom::quota {
     37 
     38 namespace {
     39 
     40 void CheckUnknownFileEntry(nsIFile& aBase, const nsAString& aName,
     41                           const bool aWarnIfFile, const bool aWarnIfDir) {
     42  nsCOMPtr<nsIFile> file;
     43  nsresult rv = aBase.Clone(getter_AddRefs(file));
     44  ASSERT_EQ(rv, NS_OK);
     45 
     46  rv = file->Append(aName);
     47  ASSERT_EQ(rv, NS_OK);
     48 
     49  rv = file->Create(nsIFile::NORMAL_FILE_TYPE, 0600);
     50  ASSERT_EQ(rv, NS_OK);
     51 
     52  auto okOrErr = WARN_IF_FILE_IS_UNKNOWN(*file);
     53  ASSERT_TRUE(okOrErr.isOk());
     54 
     55 #ifdef DEBUG
     56  EXPECT_TRUE(okOrErr.inspect() == aWarnIfFile);
     57 #else
     58  EXPECT_TRUE(okOrErr.inspect() == false);
     59 #endif
     60 
     61  rv = file->Remove(false);
     62  ASSERT_EQ(rv, NS_OK);
     63 
     64  rv = file->Create(nsIFile::DIRECTORY_TYPE, 0700);
     65  ASSERT_EQ(rv, NS_OK);
     66 
     67  okOrErr = WARN_IF_FILE_IS_UNKNOWN(*file);
     68  ASSERT_TRUE(okOrErr.isOk());
     69 
     70 #ifdef DEBUG
     71  EXPECT_TRUE(okOrErr.inspect() == aWarnIfDir);
     72 #else
     73  EXPECT_TRUE(okOrErr.inspect() == false);
     74 #endif
     75 
     76  rv = file->Remove(false);
     77  ASSERT_EQ(rv, NS_OK);
     78 }
     79 
     80 }  // namespace
     81 
     82 TEST(QuotaCommon_WarnIfFileIsUnknown, Basics)
     83 {
     84  nsCOMPtr<nsIFile> base;
     85  nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(base));
     86  ASSERT_EQ(rv, NS_OK);
     87 
     88  rv = base->Append(u"mozquotatests"_ns);
     89  ASSERT_EQ(rv, NS_OK);
     90 
     91  base->Remove(true);
     92 
     93  rv = base->Create(nsIFile::DIRECTORY_TYPE, 0700);
     94  ASSERT_EQ(rv, NS_OK);
     95 
     96  CheckUnknownFileEntry(*base, u"foo.bar"_ns, true, true);
     97  CheckUnknownFileEntry(*base, u".DS_Store"_ns, false, true);
     98  CheckUnknownFileEntry(*base, u".desktop"_ns, false, true);
     99  CheckUnknownFileEntry(*base, u"desktop.ini"_ns, false, true);
    100  CheckUnknownFileEntry(*base, u"DESKTOP.INI"_ns, false, true);
    101  CheckUnknownFileEntry(*base, u"thumbs.db"_ns, false, true);
    102  CheckUnknownFileEntry(*base, u"THUMBS.DB"_ns, false, true);
    103  CheckUnknownFileEntry(*base, u".xyz"_ns, false, true);
    104 
    105  rv = base->Remove(true);
    106  ASSERT_EQ(rv, NS_OK);
    107 }
    108 
    109 mozilla::ipc::IPCResult QuotaTestParent::RecvTry_Success_CustomErr_QmIpcFail(
    110    bool* aTryDidNotReturn) {
    111  QM_TRY(MOZ_TO_RESULT(NS_OK), QM_IPC_FAIL(this));
    112 
    113  *aTryDidNotReturn = true;
    114 
    115  return IPC_OK();
    116 }
    117 
    118 mozilla::ipc::IPCResult QuotaTestParent::RecvTry_Success_CustomErr_IpcFail(
    119    bool* aTryDidNotReturn) {
    120  QM_TRY(MOZ_TO_RESULT(NS_OK), IPC_FAIL(this, "Custom why"));
    121 
    122  *aTryDidNotReturn = true;
    123 
    124  return IPC_OK();
    125 }
    126 
    127 mozilla::ipc::IPCResult
    128 QuotaTestParent::RecvTryInspect_Success_CustomErr_QmIpcFail(
    129    bool* aTryDidNotReturn) {
    130  QM_TRY_INSPECT(const auto& x, (mozilla::Result<int32_t, nsresult>{42}),
    131                 QM_IPC_FAIL(this));
    132  (void)x;
    133 
    134  *aTryDidNotReturn = true;
    135 
    136  return IPC_OK();
    137 }
    138 
    139 mozilla::ipc::IPCResult
    140 QuotaTestParent::RecvTryInspect_Success_CustomErr_IpcFail(
    141    bool* aTryDidNotReturn) {
    142  QM_TRY_INSPECT(const auto& x, (mozilla::Result<int32_t, nsresult>{42}),
    143                 IPC_FAIL(this, "Custom why"));
    144  (void)x;
    145 
    146  *aTryDidNotReturn = true;
    147 
    148  return IPC_OK();
    149 }
    150 
    151 #ifdef __clang__
    152 #  pragma clang diagnostic push
    153 #  pragma clang diagnostic ignored "-Wunreachable-code"
    154 #endif
    155 
    156 TEST(QuotaCommon_Try, Success)
    157 {
    158  bool tryDidNotReturn = false;
    159 
    160  nsresult rv = [&tryDidNotReturn]() -> nsresult {
    161    QM_TRY(MOZ_TO_RESULT(NS_OK));
    162 
    163    tryDidNotReturn = true;
    164 
    165    return NS_OK;
    166  }();
    167 
    168  EXPECT_TRUE(tryDidNotReturn);
    169  EXPECT_EQ(rv, NS_OK);
    170 }
    171 
    172 TEST(QuotaCommon_Try, Success_CustomErr_QmIpcFail)
    173 {
    174  auto foo = MakeRefPtr<QuotaTestParent>();
    175 
    176  bool tryDidNotReturn = false;
    177 
    178  auto res = foo->RecvTry_Success_CustomErr_QmIpcFail(&tryDidNotReturn);
    179 
    180  EXPECT_TRUE(tryDidNotReturn);
    181  EXPECT_TRUE(res);
    182 }
    183 
    184 TEST(QuotaCommon_Try, Success_CustomErr_IpcFail)
    185 {
    186  auto foo = MakeRefPtr<QuotaTestParent>();
    187 
    188  bool tryDidNotReturn = false;
    189 
    190  auto res = foo->RecvTry_Success_CustomErr_IpcFail(&tryDidNotReturn);
    191 
    192  EXPECT_TRUE(tryDidNotReturn);
    193  EXPECT_TRUE(res);
    194 }
    195 
    196 #ifdef DEBUG
    197 TEST(QuotaCommon_Try, Success_CustomErr_AssertUnreachable)
    198 {
    199  bool tryDidNotReturn = false;
    200 
    201  nsresult rv = [&tryDidNotReturn]() -> nsresult {
    202    QM_TRY(MOZ_TO_RESULT(NS_OK), QM_ASSERT_UNREACHABLE);
    203 
    204    tryDidNotReturn = true;
    205 
    206    return NS_OK;
    207  }();
    208 
    209  EXPECT_TRUE(tryDidNotReturn);
    210  EXPECT_EQ(rv, NS_OK);
    211 }
    212 
    213 TEST(QuotaCommon_Try, Success_NoErr_AssertUnreachable)
    214 {
    215  bool tryDidNotReturn = false;
    216 
    217  [&tryDidNotReturn]() -> void {
    218    QM_TRY(MOZ_TO_RESULT(NS_OK), QM_ASSERT_UNREACHABLE_VOID);
    219 
    220    tryDidNotReturn = true;
    221  }();
    222 
    223  EXPECT_TRUE(tryDidNotReturn);
    224 }
    225 #else
    226 #  if defined(QM_ASSERT_UNREACHABLE) || defined(QM_ASSERT_UNREACHABLE_VOID)
    227 #error QM_ASSERT_UNREACHABLE and QM_ASSERT_UNREACHABLE_VOID should not be defined.
    228 #  endif
    229 #endif
    230 
    231 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
    232 TEST(QuotaCommon_Try, Success_CustomErr_DiagnosticAssertUnreachable)
    233 {
    234  bool tryDidNotReturn = false;
    235 
    236  nsresult rv = [&tryDidNotReturn]() -> nsresult {
    237    QM_TRY(MOZ_TO_RESULT(NS_OK), QM_DIAGNOSTIC_ASSERT_UNREACHABLE);
    238 
    239    tryDidNotReturn = true;
    240 
    241    return NS_OK;
    242  }();
    243 
    244  EXPECT_TRUE(tryDidNotReturn);
    245  EXPECT_EQ(rv, NS_OK);
    246 }
    247 
    248 TEST(QuotaCommon_Try, Success_NoErr_DiagnosticAssertUnreachable)
    249 {
    250  bool tryDidNotReturn = false;
    251 
    252  [&tryDidNotReturn]() -> void {
    253    QM_TRY(MOZ_TO_RESULT(NS_OK), QM_DIAGNOSTIC_ASSERT_UNREACHABLE_VOID);
    254 
    255    tryDidNotReturn = true;
    256  }();
    257 
    258  EXPECT_TRUE(tryDidNotReturn);
    259 }
    260 #else
    261 #  if defined(QM_DIAGNOSTIC_ASSERT_UNREACHABLE) || \
    262      defined(QM_DIAGNOSTIC_ASSERT_UNREACHABLE_VOID)
    263 #error QM_DIAGNOSTIC_ASSERT_UNREACHABLE and QM_DIAGNOSTIC_ASSERT_UNREACHABLE_VOID should not be defined.
    264 #  endif
    265 #endif
    266 
    267 TEST(QuotaCommon_Try, Success_CustomErr_CustomLambda)
    268 {
    269 #define SUBTEST(...)                                                 \
    270  {                                                                  \
    271    bool tryDidNotReturn = false;                                    \
    272                                                                     \
    273    nsresult rv = [&tryDidNotReturn]() -> nsresult {                 \
    274      QM_TRY(MOZ_TO_RESULT(NS_OK), [](__VA_ARGS__) { return aRv; }); \
    275                                                                     \
    276      tryDidNotReturn = true;                                        \
    277                                                                     \
    278      return NS_OK;                                                  \
    279    }();                                                             \
    280                                                                     \
    281    EXPECT_TRUE(tryDidNotReturn);                                    \
    282    EXPECT_EQ(rv, NS_OK);                                            \
    283  }
    284 
    285  SUBTEST(const char*, nsresult aRv);
    286  SUBTEST(nsresult aRv);
    287 
    288 #undef SUBTEST
    289 }
    290 
    291 TEST(QuotaCommon_Try, Success_WithCleanup)
    292 {
    293  bool tryCleanupRan = false;
    294  bool tryDidNotReturn = false;
    295 
    296  nsresult rv = [&tryCleanupRan, &tryDidNotReturn]() -> nsresult {
    297    QM_TRY(MOZ_TO_RESULT(NS_OK), QM_PROPAGATE,
    298           [&tryCleanupRan](const auto&) { tryCleanupRan = true; });
    299 
    300    tryDidNotReturn = true;
    301 
    302    return NS_OK;
    303  }();
    304 
    305  EXPECT_FALSE(tryCleanupRan);
    306  EXPECT_TRUE(tryDidNotReturn);
    307  EXPECT_EQ(rv, NS_OK);
    308 }
    309 
    310 TEST(QuotaCommon_Try, Failure_PropagateErr)
    311 {
    312  bool tryDidNotReturn = false;
    313 
    314  nsresult rv = [&tryDidNotReturn]() -> nsresult {
    315    QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE));
    316 
    317    tryDidNotReturn = true;
    318 
    319    return NS_OK;
    320  }();
    321 
    322  EXPECT_FALSE(tryDidNotReturn);
    323  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    324 }
    325 
    326 TEST(QuotaCommon_Try, Failure_CustomErr)
    327 {
    328  bool tryDidNotReturn = false;
    329 
    330  nsresult rv = [&tryDidNotReturn]() -> nsresult {
    331    QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE), NS_ERROR_UNEXPECTED);
    332 
    333    tryDidNotReturn = true;
    334 
    335    return NS_OK;
    336  }();
    337 
    338  EXPECT_FALSE(tryDidNotReturn);
    339  EXPECT_EQ(rv, NS_ERROR_UNEXPECTED);
    340 }
    341 
    342 TEST(QuotaCommon_Try, Failure_CustomErr_CustomLambda)
    343 {
    344 #define SUBTEST(...)                                           \
    345  {                                                            \
    346    bool tryDidNotReturn = false;                              \
    347                                                               \
    348    nsresult rv = [&tryDidNotReturn]() -> nsresult {           \
    349      QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE),                  \
    350             [](__VA_ARGS__) { return NS_ERROR_UNEXPECTED; }); \
    351                                                               \
    352      tryDidNotReturn = true;                                  \
    353                                                               \
    354      return NS_OK;                                            \
    355    }();                                                       \
    356                                                               \
    357    EXPECT_FALSE(tryDidNotReturn);                             \
    358    EXPECT_EQ(rv, NS_ERROR_UNEXPECTED);                        \
    359  }
    360 
    361  SUBTEST(const char* aFunc, nsresult);
    362  SUBTEST(nsresult rv);
    363 
    364 #undef SUBTEST
    365 }
    366 
    367 TEST(QuotaCommon_Try, Failure_NoErr)
    368 {
    369  bool tryDidNotReturn = false;
    370 
    371  [&tryDidNotReturn]() -> void {
    372    QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE), QM_VOID);
    373 
    374    tryDidNotReturn = true;
    375  }();
    376 
    377  EXPECT_FALSE(tryDidNotReturn);
    378 }
    379 
    380 TEST(QuotaCommon_Try, Failure_WithCleanup)
    381 {
    382  bool tryCleanupRan = false;
    383  bool tryDidNotReturn = false;
    384 
    385  nsresult rv = [&tryCleanupRan, &tryDidNotReturn]() -> nsresult {
    386    QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE), QM_PROPAGATE,
    387           [&tryCleanupRan](const auto& result) {
    388             EXPECT_EQ(result, NS_ERROR_FAILURE);
    389 
    390             tryCleanupRan = true;
    391           });
    392 
    393    tryDidNotReturn = true;
    394 
    395    return NS_OK;
    396  }();
    397 
    398  EXPECT_TRUE(tryCleanupRan);
    399  EXPECT_FALSE(tryDidNotReturn);
    400  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    401 }
    402 
    403 TEST(QuotaCommon_Try, Failure_WithCleanup_UnwrapErr)
    404 {
    405  bool tryCleanupRan = false;
    406  bool tryDidNotReturn = false;
    407 
    408  nsresult rv;
    409 
    410  [&tryCleanupRan, &tryDidNotReturn](nsresult& aRv) -> void {
    411    QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE), QM_VOID,
    412           ([&tryCleanupRan, &aRv](auto& result) {
    413             EXPECT_EQ(result, NS_ERROR_FAILURE);
    414 
    415             aRv = result;
    416 
    417             tryCleanupRan = true;
    418           }));
    419 
    420    tryDidNotReturn = true;
    421 
    422    aRv = NS_OK;
    423  }(rv);
    424 
    425  EXPECT_TRUE(tryCleanupRan);
    426  EXPECT_FALSE(tryDidNotReturn);
    427  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    428 }
    429 
    430 TEST(QuotaCommon_Try, Failure_WithCleanupAndPredicate)
    431 {
    432  auto predicate = []() {
    433    static bool calledOnce = false;
    434    const bool result = !calledOnce;
    435    calledOnce = true;
    436    return result;
    437  };
    438 
    439  {
    440    bool tryDidNotReturn = false;
    441 
    442    nsresult rv = [&predicate, &tryDidNotReturn]() -> nsresult {
    443      QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE), QM_PROPAGATE, QM_NO_CLEANUP,
    444             predicate);
    445 
    446      tryDidNotReturn = true;
    447 
    448      return NS_OK;
    449    }();
    450 
    451    EXPECT_FALSE(tryDidNotReturn);
    452    EXPECT_EQ(rv, NS_ERROR_FAILURE);
    453  }
    454 
    455  {
    456    bool tryDidNotReturn = false;
    457 
    458    nsresult rv = [&predicate, &tryDidNotReturn]() -> nsresult {
    459      QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE), QM_PROPAGATE, QM_NO_CLEANUP,
    460             predicate);
    461 
    462      tryDidNotReturn = true;
    463 
    464      return NS_OK;
    465    }();
    466 
    467    EXPECT_FALSE(tryDidNotReturn);
    468    EXPECT_EQ(rv, NS_ERROR_FAILURE);
    469  }
    470 }
    471 
    472 TEST(QuotaCommon_Try, SameLine)
    473 {
    474  // clang-format off
    475  QM_TRY(MOZ_TO_RESULT(NS_OK), QM_VOID); QM_TRY(MOZ_TO_RESULT(NS_OK), QM_VOID);
    476  // clang-format on
    477 }
    478 
    479 TEST(QuotaCommon_Try, NestingMadness_Success)
    480 {
    481  bool nestedTryDidNotReturn = false;
    482  bool tryDidNotReturn = false;
    483 
    484  nsresult rv = [&nestedTryDidNotReturn, &tryDidNotReturn]() -> nsresult {
    485    QM_TRY(([&nestedTryDidNotReturn]() -> Result<Ok, nsresult> {
    486      QM_TRY(MOZ_TO_RESULT(NS_OK));
    487 
    488      nestedTryDidNotReturn = true;
    489 
    490      return Ok();
    491    }()));
    492 
    493    tryDidNotReturn = true;
    494 
    495    return NS_OK;
    496  }();
    497 
    498  EXPECT_TRUE(nestedTryDidNotReturn);
    499  EXPECT_TRUE(tryDidNotReturn);
    500  EXPECT_EQ(rv, NS_OK);
    501 }
    502 
    503 TEST(QuotaCommon_Try, NestingMadness_Failure)
    504 {
    505  bool nestedTryDidNotReturn = false;
    506  bool tryDidNotReturn = false;
    507 
    508  nsresult rv = [&nestedTryDidNotReturn, &tryDidNotReturn]() -> nsresult {
    509    QM_TRY(([&nestedTryDidNotReturn]() -> Result<Ok, nsresult> {
    510      QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE));
    511 
    512      nestedTryDidNotReturn = true;
    513 
    514      return Ok();
    515    }()));
    516 
    517    tryDidNotReturn = true;
    518 
    519    return NS_OK;
    520  }();
    521 
    522  EXPECT_FALSE(nestedTryDidNotReturn);
    523  EXPECT_FALSE(tryDidNotReturn);
    524  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    525 }
    526 
    527 TEST(QuotaCommon_Try, NestingMadness_Multiple_Success)
    528 {
    529  bool nestedTry1DidNotReturn = false;
    530  bool nestedTry2DidNotReturn = false;
    531  bool tryDidNotReturn = false;
    532 
    533  nsresult rv = [&nestedTry1DidNotReturn, &nestedTry2DidNotReturn,
    534                 &tryDidNotReturn]() -> nsresult {
    535    QM_TRY(([&nestedTry1DidNotReturn,
    536             &nestedTry2DidNotReturn]() -> Result<Ok, nsresult> {
    537      QM_TRY(MOZ_TO_RESULT(NS_OK));
    538 
    539      nestedTry1DidNotReturn = true;
    540 
    541      QM_TRY(MOZ_TO_RESULT(NS_OK));
    542 
    543      nestedTry2DidNotReturn = true;
    544 
    545      return Ok();
    546    }()));
    547 
    548    tryDidNotReturn = true;
    549 
    550    return NS_OK;
    551  }();
    552 
    553  EXPECT_TRUE(nestedTry1DidNotReturn);
    554  EXPECT_TRUE(nestedTry2DidNotReturn);
    555  EXPECT_TRUE(tryDidNotReturn);
    556  EXPECT_EQ(rv, NS_OK);
    557 }
    558 
    559 TEST(QuotaCommon_Try, NestingMadness_Multiple_Failure1)
    560 {
    561  bool nestedTry1DidNotReturn = false;
    562  bool nestedTry2DidNotReturn = false;
    563  bool tryDidNotReturn = false;
    564 
    565  nsresult rv = [&nestedTry1DidNotReturn, &nestedTry2DidNotReturn,
    566                 &tryDidNotReturn]() -> nsresult {
    567    QM_TRY(([&nestedTry1DidNotReturn,
    568             &nestedTry2DidNotReturn]() -> Result<Ok, nsresult> {
    569      QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE));
    570 
    571      nestedTry1DidNotReturn = true;
    572 
    573      QM_TRY(MOZ_TO_RESULT(NS_OK));
    574 
    575      nestedTry2DidNotReturn = true;
    576 
    577      return Ok();
    578    }()));
    579 
    580    tryDidNotReturn = true;
    581 
    582    return NS_OK;
    583  }();
    584 
    585  EXPECT_FALSE(nestedTry1DidNotReturn);
    586  EXPECT_FALSE(nestedTry2DidNotReturn);
    587  EXPECT_FALSE(tryDidNotReturn);
    588  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    589 }
    590 
    591 TEST(QuotaCommon_Try, NestingMadness_Multiple_Failure2)
    592 {
    593  bool nestedTry1DidNotReturn = false;
    594  bool nestedTry2DidNotReturn = false;
    595  bool tryDidNotReturn = false;
    596 
    597  nsresult rv = [&nestedTry1DidNotReturn, &nestedTry2DidNotReturn,
    598                 &tryDidNotReturn]() -> nsresult {
    599    QM_TRY(([&nestedTry1DidNotReturn,
    600             &nestedTry2DidNotReturn]() -> Result<Ok, nsresult> {
    601      QM_TRY(MOZ_TO_RESULT(NS_OK));
    602 
    603      nestedTry1DidNotReturn = true;
    604 
    605      QM_TRY(MOZ_TO_RESULT(NS_ERROR_FAILURE));
    606 
    607      nestedTry2DidNotReturn = true;
    608 
    609      return Ok();
    610    }()));
    611 
    612    tryDidNotReturn = true;
    613 
    614    return NS_OK;
    615  }();
    616 
    617  EXPECT_TRUE(nestedTry1DidNotReturn);
    618  EXPECT_FALSE(nestedTry2DidNotReturn);
    619  EXPECT_FALSE(tryDidNotReturn);
    620  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    621 }
    622 
    623 TEST(QuotaCommon_TryInspect, Success)
    624 {
    625  bool tryInspectDidNotReturn = false;
    626 
    627  nsresult rv = [&tryInspectDidNotReturn]() -> nsresult {
    628    QM_TRY_INSPECT(const auto& x, (Result<int32_t, nsresult>{42}));
    629    EXPECT_EQ(x, 42);
    630 
    631    tryInspectDidNotReturn = true;
    632 
    633    return NS_OK;
    634  }();
    635 
    636  EXPECT_TRUE(tryInspectDidNotReturn);
    637  EXPECT_EQ(rv, NS_OK);
    638 }
    639 
    640 TEST(QuotaCommon_TryInspect, Success_CustomErr_QmIpcFail)
    641 {
    642  auto foo = MakeRefPtr<QuotaTestParent>();
    643 
    644  bool tryDidNotReturn = false;
    645 
    646  auto res = foo->RecvTryInspect_Success_CustomErr_QmIpcFail(&tryDidNotReturn);
    647 
    648  EXPECT_TRUE(tryDidNotReturn);
    649  EXPECT_TRUE(res);
    650 }
    651 
    652 TEST(QuotaCommon_TryInspect, Success_CustomErr_IpcFail)
    653 {
    654  auto foo = MakeRefPtr<QuotaTestParent>();
    655 
    656  bool tryDidNotReturn = false;
    657 
    658  auto res = foo->RecvTryInspect_Success_CustomErr_IpcFail(&tryDidNotReturn);
    659 
    660  EXPECT_TRUE(tryDidNotReturn);
    661  EXPECT_TRUE(res);
    662 }
    663 
    664 #ifdef DEBUG
    665 TEST(QuotaCommon_TryInspect, Success_CustomErr_AssertUnreachable)
    666 {
    667  bool tryInspectDidNotReturn = false;
    668 
    669  nsresult rv = [&tryInspectDidNotReturn]() -> nsresult {
    670    QM_TRY_INSPECT(const auto& x, (Result<int32_t, nsresult>{42}),
    671                   QM_ASSERT_UNREACHABLE);
    672    EXPECT_EQ(x, 42);
    673 
    674    tryInspectDidNotReturn = true;
    675 
    676    return NS_OK;
    677  }();
    678 
    679  EXPECT_TRUE(tryInspectDidNotReturn);
    680  EXPECT_EQ(rv, NS_OK);
    681 }
    682 
    683 TEST(QuotaCommon_TryInspect, Success_NoErr_AssertUnreachable)
    684 {
    685  bool tryInspectDidNotReturn = false;
    686 
    687  [&tryInspectDidNotReturn]() -> void {
    688    QM_TRY_INSPECT(const auto& x, (Result<int32_t, nsresult>{42}),
    689                   QM_ASSERT_UNREACHABLE_VOID);
    690    EXPECT_EQ(x, 42);
    691 
    692    tryInspectDidNotReturn = true;
    693  }();
    694 
    695  EXPECT_TRUE(tryInspectDidNotReturn);
    696 }
    697 #endif
    698 
    699 TEST(QuotaCommon_TryInspect, Success_CustomErr_CustomLambda)
    700 {
    701 #define SUBTEST(...)                                                 \
    702  {                                                                  \
    703    bool tryInspectDidNotReturn = false;                             \
    704                                                                     \
    705    nsresult rv = [&tryInspectDidNotReturn]() -> nsresult {          \
    706      QM_TRY_INSPECT(const auto& x, (Result<int32_t, nsresult>{42}), \
    707                     [](__VA_ARGS__) { return aRv; });               \
    708      EXPECT_EQ(x, 42);                                              \
    709                                                                     \
    710      tryInspectDidNotReturn = true;                                 \
    711                                                                     \
    712      return NS_OK;                                                  \
    713    }();                                                             \
    714                                                                     \
    715    EXPECT_TRUE(tryInspectDidNotReturn);                             \
    716    EXPECT_EQ(rv, NS_OK);                                            \
    717  }
    718 
    719  SUBTEST(const char*, nsresult aRv);
    720  SUBTEST(nsresult aRv);
    721 
    722 #undef SUBTEST
    723 }
    724 
    725 TEST(QuotaCommon_TryInspect, Success_WithCleanup)
    726 {
    727  bool tryInspectCleanupRan = false;
    728  bool tryInspectDidNotReturn = false;
    729 
    730  nsresult rv = [&tryInspectCleanupRan, &tryInspectDidNotReturn]() -> nsresult {
    731    QM_TRY_INSPECT(
    732        const auto& x, (Result<int32_t, nsresult>{42}), QM_PROPAGATE,
    733        [&tryInspectCleanupRan](const auto&) { tryInspectCleanupRan = true; });
    734    EXPECT_EQ(x, 42);
    735 
    736    tryInspectDidNotReturn = true;
    737 
    738    return NS_OK;
    739  }();
    740 
    741  EXPECT_FALSE(tryInspectCleanupRan);
    742  EXPECT_TRUE(tryInspectDidNotReturn);
    743  EXPECT_EQ(rv, NS_OK);
    744 }
    745 
    746 TEST(QuotaCommon_TryInspect, Failure_PropagateErr)
    747 {
    748  bool tryInspectDidNotReturn = false;
    749 
    750  nsresult rv = [&tryInspectDidNotReturn]() -> nsresult {
    751    QM_TRY_INSPECT(const auto& x,
    752                   (Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}));
    753    (void)x;
    754 
    755    tryInspectDidNotReturn = true;
    756 
    757    return NS_OK;
    758  }();
    759 
    760  EXPECT_FALSE(tryInspectDidNotReturn);
    761  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    762 }
    763 
    764 TEST(QuotaCommon_TryInspect, Failure_CustomErr)
    765 {
    766  bool tryInspectDidNotReturn = false;
    767 
    768  nsresult rv = [&tryInspectDidNotReturn]() -> nsresult {
    769    QM_TRY_INSPECT(const auto& x,
    770                   (Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}),
    771                   NS_ERROR_UNEXPECTED);
    772    (void)x;
    773 
    774    tryInspectDidNotReturn = true;
    775 
    776    return NS_OK;
    777  }();
    778 
    779  EXPECT_FALSE(tryInspectDidNotReturn);
    780  EXPECT_EQ(rv, NS_ERROR_UNEXPECTED);
    781 }
    782 
    783 TEST(QuotaCommon_TryInspect, Failure_CustomErr_CustomLambda)
    784 {
    785 #define SUBTEST(...)                                                     \
    786  {                                                                      \
    787    bool tryInspectDidNotReturn = false;                                 \
    788                                                                         \
    789    nsresult rv = [&tryInspectDidNotReturn]() -> nsresult {              \
    790      QM_TRY_INSPECT(const auto& x,                                      \
    791                     (Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}), \
    792                     [](__VA_ARGS__) { return NS_ERROR_UNEXPECTED; });   \
    793      (void)x;                                                           \
    794                                                                         \
    795      tryInspectDidNotReturn = true;                                     \
    796                                                                         \
    797      return NS_OK;                                                      \
    798    }();                                                                 \
    799                                                                         \
    800    EXPECT_FALSE(tryInspectDidNotReturn);                                \
    801    EXPECT_EQ(rv, NS_ERROR_UNEXPECTED);                                  \
    802  }
    803 
    804  SUBTEST(const char*, nsresult);
    805  SUBTEST(nsresult);
    806 
    807 #undef SUBTEST
    808 }
    809 
    810 TEST(QuotaCommon_TryInspect, Failure_NoErr)
    811 {
    812  bool tryInspectDidNotReturn = false;
    813 
    814  [&tryInspectDidNotReturn]() -> void {
    815    QM_TRY_INSPECT(const auto& x,
    816                   (Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}), QM_VOID);
    817    (void)x;
    818 
    819    tryInspectDidNotReturn = true;
    820  }();
    821 
    822  EXPECT_FALSE(tryInspectDidNotReturn);
    823 }
    824 
    825 TEST(QuotaCommon_TryInspect, Failure_WithCleanup)
    826 {
    827  bool tryInspectCleanupRan = false;
    828  bool tryInspectDidNotReturn = false;
    829 
    830  nsresult rv = [&tryInspectCleanupRan, &tryInspectDidNotReturn]() -> nsresult {
    831    QM_TRY_INSPECT(const auto& x,
    832                   (Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}),
    833                   QM_PROPAGATE, [&tryInspectCleanupRan](const auto& result) {
    834                     EXPECT_EQ(result, NS_ERROR_FAILURE);
    835 
    836                     tryInspectCleanupRan = true;
    837                   });
    838    (void)x;
    839 
    840    tryInspectDidNotReturn = true;
    841 
    842    return NS_OK;
    843  }();
    844 
    845  EXPECT_TRUE(tryInspectCleanupRan);
    846  EXPECT_FALSE(tryInspectDidNotReturn);
    847  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    848 }
    849 
    850 TEST(QuotaCommon_TryInspect, Failure_WithCleanup_UnwrapErr)
    851 {
    852  bool tryInspectCleanupRan = false;
    853  bool tryInspectDidNotReturn = false;
    854 
    855  nsresult rv;
    856 
    857  [&tryInspectCleanupRan, &tryInspectDidNotReturn](nsresult& aRv) -> void {
    858    QM_TRY_INSPECT(const auto& x,
    859                   (Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}), QM_VOID,
    860                   ([&tryInspectCleanupRan, &aRv](auto& result) {
    861                     EXPECT_EQ(result, NS_ERROR_FAILURE);
    862 
    863                     aRv = result;
    864 
    865                     tryInspectCleanupRan = true;
    866                   }));
    867    (void)x;
    868 
    869    tryInspectDidNotReturn = true;
    870 
    871    aRv = NS_OK;
    872  }(rv);
    873 
    874  EXPECT_TRUE(tryInspectCleanupRan);
    875  EXPECT_FALSE(tryInspectDidNotReturn);
    876  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    877 }
    878 
    879 TEST(QuotaCommon_TryInspect, ConstDecl)
    880 {
    881  QM_TRY_INSPECT(const int32_t& x, (Result<int32_t, nsresult>{42}), QM_VOID);
    882 
    883  static_assert(std::is_same_v<decltype(x), const int32_t&>);
    884 
    885  EXPECT_EQ(x, 42);
    886 }
    887 
    888 TEST(QuotaCommon_TryInspect, SameScopeDecl)
    889 {
    890  QM_TRY_INSPECT(const int32_t& x, (Result<int32_t, nsresult>{42}), QM_VOID);
    891  EXPECT_EQ(x, 42);
    892 
    893  QM_TRY_INSPECT(const int32_t& y, (Result<int32_t, nsresult>{42}), QM_VOID);
    894  EXPECT_EQ(y, 42);
    895 }
    896 
    897 TEST(QuotaCommon_TryInspect, SameLine)
    898 {
    899  // clang-format off
    900  QM_TRY_INSPECT(const auto &x, (Result<int32_t, nsresult>{42}), QM_VOID); QM_TRY_INSPECT(const auto &y, (Result<int32_t, nsresult>{42}), QM_VOID);
    901  // clang-format on
    902 
    903  EXPECT_EQ(x, 42);
    904  EXPECT_EQ(y, 42);
    905 }
    906 
    907 TEST(QuotaCommon_TryInspect, NestingMadness_Success)
    908 {
    909  bool nestedTryInspectDidNotReturn = false;
    910  bool tryInspectDidNotReturn = false;
    911 
    912  nsresult rv = [&nestedTryInspectDidNotReturn,
    913                 &tryInspectDidNotReturn]() -> nsresult {
    914    QM_TRY_INSPECT(
    915        const auto& x,
    916        ([&nestedTryInspectDidNotReturn]() -> Result<int32_t, nsresult> {
    917          QM_TRY_INSPECT(const auto& x, (Result<int32_t, nsresult>{42}));
    918 
    919          nestedTryInspectDidNotReturn = true;
    920 
    921          return x;
    922        }()));
    923    EXPECT_EQ(x, 42);
    924 
    925    tryInspectDidNotReturn = true;
    926 
    927    return NS_OK;
    928  }();
    929 
    930  EXPECT_TRUE(nestedTryInspectDidNotReturn);
    931  EXPECT_TRUE(tryInspectDidNotReturn);
    932  EXPECT_EQ(rv, NS_OK);
    933 }
    934 
    935 TEST(QuotaCommon_TryInspect, NestingMadness_Failure)
    936 {
    937  bool nestedTryInspectDidNotReturn = false;
    938  bool tryInspectDidNotReturn = false;
    939 
    940  nsresult rv = [&nestedTryInspectDidNotReturn,
    941                 &tryInspectDidNotReturn]() -> nsresult {
    942    QM_TRY_INSPECT(
    943        const auto& x,
    944        ([&nestedTryInspectDidNotReturn]() -> Result<int32_t, nsresult> {
    945          QM_TRY_INSPECT(const auto& x,
    946                         (Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}));
    947 
    948          nestedTryInspectDidNotReturn = true;
    949 
    950          return x;
    951        }()));
    952    (void)x;
    953 
    954    tryInspectDidNotReturn = true;
    955 
    956    return NS_OK;
    957  }();
    958 
    959  EXPECT_FALSE(nestedTryInspectDidNotReturn);
    960  EXPECT_FALSE(tryInspectDidNotReturn);
    961  EXPECT_EQ(rv, NS_ERROR_FAILURE);
    962 }
    963 
    964 TEST(QuotaCommon_TryInspect, NestingMadness_Multiple_Success)
    965 {
    966  bool nestedTryInspect1DidNotReturn = false;
    967  bool nestedTryInspect2DidNotReturn = false;
    968  bool tryInspectDidNotReturn = false;
    969 
    970  nsresult rv = [&nestedTryInspect1DidNotReturn, &nestedTryInspect2DidNotReturn,
    971                 &tryInspectDidNotReturn]() -> nsresult {
    972    QM_TRY_INSPECT(
    973        const auto& z,
    974        ([&nestedTryInspect1DidNotReturn,
    975          &nestedTryInspect2DidNotReturn]() -> Result<int32_t, nsresult> {
    976          QM_TRY_INSPECT(const auto& x, (Result<int32_t, nsresult>{42}));
    977 
    978          nestedTryInspect1DidNotReturn = true;
    979 
    980          QM_TRY_INSPECT(const auto& y, (Result<int32_t, nsresult>{42}));
    981 
    982          nestedTryInspect2DidNotReturn = true;
    983 
    984          return x + y;
    985        }()));
    986    EXPECT_EQ(z, 84);
    987 
    988    tryInspectDidNotReturn = true;
    989 
    990    return NS_OK;
    991  }();
    992 
    993  EXPECT_TRUE(nestedTryInspect1DidNotReturn);
    994  EXPECT_TRUE(nestedTryInspect2DidNotReturn);
    995  EXPECT_TRUE(tryInspectDidNotReturn);
    996  EXPECT_EQ(rv, NS_OK);
    997 }
    998 
    999 TEST(QuotaCommon_TryInspect, NestingMadness_Multiple_Failure1)
   1000 {
   1001  bool nestedTryInspect1DidNotReturn = false;
   1002  bool nestedTryInspect2DidNotReturn = false;
   1003  bool tryInspectDidNotReturn = false;
   1004 
   1005  nsresult rv = [&nestedTryInspect1DidNotReturn, &nestedTryInspect2DidNotReturn,
   1006                 &tryInspectDidNotReturn]() -> nsresult {
   1007    QM_TRY_INSPECT(
   1008        const auto& z,
   1009        ([&nestedTryInspect1DidNotReturn,
   1010          &nestedTryInspect2DidNotReturn]() -> Result<int32_t, nsresult> {
   1011          QM_TRY_INSPECT(const auto& x,
   1012                         (Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}));
   1013 
   1014          nestedTryInspect1DidNotReturn = true;
   1015 
   1016          QM_TRY_INSPECT(const auto& y, (Result<int32_t, nsresult>{42}));
   1017 
   1018          nestedTryInspect2DidNotReturn = true;
   1019 
   1020          return x + y;
   1021        }()));
   1022    (void)z;
   1023 
   1024    tryInspectDidNotReturn = true;
   1025 
   1026    return NS_OK;
   1027  }();
   1028 
   1029  EXPECT_FALSE(nestedTryInspect1DidNotReturn);
   1030  EXPECT_FALSE(nestedTryInspect2DidNotReturn);
   1031  EXPECT_FALSE(tryInspectDidNotReturn);
   1032  EXPECT_EQ(rv, NS_ERROR_FAILURE);
   1033 }
   1034 
   1035 TEST(QuotaCommon_TryInspect, NestingMadness_Multiple_Failure2)
   1036 {
   1037  bool nestedTryInspect1DidNotReturn = false;
   1038  bool nestedTryInspect2DidNotReturn = false;
   1039  bool tryInspectDidNotReturn = false;
   1040 
   1041  nsresult rv = [&nestedTryInspect1DidNotReturn, &nestedTryInspect2DidNotReturn,
   1042                 &tryInspectDidNotReturn]() -> nsresult {
   1043    QM_TRY_INSPECT(
   1044        const auto& z,
   1045        ([&nestedTryInspect1DidNotReturn,
   1046          &nestedTryInspect2DidNotReturn]() -> Result<int32_t, nsresult> {
   1047          QM_TRY_INSPECT(const auto& x, (Result<int32_t, nsresult>{42}));
   1048 
   1049          nestedTryInspect1DidNotReturn = true;
   1050 
   1051          QM_TRY_INSPECT(const auto& y,
   1052                         (Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}));
   1053 
   1054          nestedTryInspect2DidNotReturn = true;
   1055 
   1056          return x + y;
   1057        }()));
   1058    (void)z;
   1059 
   1060    tryInspectDidNotReturn = true;
   1061 
   1062    return NS_OK;
   1063  }();
   1064 
   1065  EXPECT_TRUE(nestedTryInspect1DidNotReturn);
   1066  EXPECT_FALSE(nestedTryInspect2DidNotReturn);
   1067  EXPECT_FALSE(tryInspectDidNotReturn);
   1068  EXPECT_EQ(rv, NS_ERROR_FAILURE);
   1069 }
   1070 
   1071 // We are not repeating all QM_TRY_INSPECT test cases for QM_TRY_UNWRAP, since
   1072 // they are largely based on the same implementation. We just add some where
   1073 // inspecting and unwrapping differ.
   1074 
   1075 TEST(QuotaCommon_TryUnwrap, NonConstDecl)
   1076 {
   1077  QM_TRY_UNWRAP(int32_t x, (Result<int32_t, nsresult>{42}), QM_VOID);
   1078 
   1079  static_assert(std::is_same_v<decltype(x), int32_t>);
   1080 
   1081  EXPECT_EQ(x, 42);
   1082 }
   1083 
   1084 TEST(QuotaCommon_TryUnwrap, RvalueDecl)
   1085 {
   1086  QM_TRY_UNWRAP(int32_t&& x, (Result<int32_t, nsresult>{42}), QM_VOID);
   1087 
   1088  static_assert(std::is_same_v<decltype(x), int32_t&&>);
   1089 
   1090  EXPECT_EQ(x, 42);
   1091 }
   1092 
   1093 TEST(QuotaCommon_TryUnwrap, ParenDecl)
   1094 {
   1095  QM_TRY_UNWRAP(
   1096      (auto&& [x, y]),
   1097      (Result<std::pair<int32_t, bool>, nsresult>{std::pair{42, true}}),
   1098      QM_VOID);
   1099 
   1100  static_assert(std::is_same_v<decltype(x), int32_t>);
   1101  static_assert(std::is_same_v<decltype(y), bool>);
   1102 
   1103  EXPECT_EQ(x, 42);
   1104  EXPECT_EQ(y, true);
   1105 }
   1106 
   1107 TEST(QuotaCommon_TryReturn, Success)
   1108 {
   1109  bool tryReturnDidNotReturn = false;
   1110 
   1111  auto res = [&tryReturnDidNotReturn] {
   1112    QM_TRY_RETURN((Result<int32_t, nsresult>{42}));
   1113 
   1114    tryReturnDidNotReturn = true;
   1115  }();
   1116 
   1117  EXPECT_FALSE(tryReturnDidNotReturn);
   1118  EXPECT_TRUE(res.isOk());
   1119  EXPECT_EQ(res.unwrap(), 42);
   1120 }
   1121 
   1122 TEST(QuotaCommon_TryReturn, Success_nsresult)
   1123 {
   1124  bool tryReturnDidNotReturn = false;
   1125 
   1126  auto res = [&tryReturnDidNotReturn] {
   1127    QM_TRY_RETURN(MOZ_TO_RESULT(NS_OK));
   1128 
   1129    tryReturnDidNotReturn = true;
   1130  }();
   1131 
   1132  EXPECT_FALSE(tryReturnDidNotReturn);
   1133  EXPECT_TRUE(res.isOk());
   1134 }
   1135 
   1136 #ifdef DEBUG
   1137 TEST(QuotaCommon_TryReturn, Success_CustomErr_AssertUnreachable)
   1138 {
   1139  bool tryReturnDidNotReturn = false;
   1140 
   1141  auto res = [&tryReturnDidNotReturn]() -> Result<int32_t, nsresult> {
   1142    QM_TRY_RETURN((Result<int32_t, nsresult>{42}), QM_ASSERT_UNREACHABLE);
   1143 
   1144    tryReturnDidNotReturn = true;
   1145  }();
   1146 
   1147  EXPECT_FALSE(tryReturnDidNotReturn);
   1148  EXPECT_TRUE(res.isOk());
   1149  EXPECT_EQ(res.unwrap(), 42);
   1150 }
   1151 #endif
   1152 
   1153 TEST(QuotaCommon_TryReturn, Success_CustomErr_CustomLambda)
   1154 {
   1155 #define SUBTEST(...)                                                \
   1156  {                                                                 \
   1157    bool tryReturnDidNotReturn = false;                             \
   1158                                                                    \
   1159    auto res = [&tryReturnDidNotReturn]() -> Result<Ok, nsresult> { \
   1160      QM_TRY_RETURN(MOZ_TO_RESULT(NS_OK),                           \
   1161                    [](__VA_ARGS__) { return Err(aRv); });          \
   1162                                                                    \
   1163      tryReturnDidNotReturn = true;                                 \
   1164    }();                                                            \
   1165                                                                    \
   1166    EXPECT_FALSE(tryReturnDidNotReturn);                            \
   1167    EXPECT_TRUE(res.isOk());                                        \
   1168  }
   1169 
   1170  SUBTEST(const char*, nsresult aRv);
   1171  SUBTEST(nsresult aRv);
   1172 
   1173 #undef SUBTEST
   1174 }
   1175 
   1176 TEST(QuotaCommon_TryReturn, Success_WithCleanup)
   1177 {
   1178  bool tryReturnCleanupRan = false;
   1179  bool tryReturnDidNotReturn = false;
   1180 
   1181  auto res = [&tryReturnCleanupRan,
   1182              &tryReturnDidNotReturn]() -> Result<int32_t, nsresult> {
   1183    QM_TRY_RETURN(
   1184        (Result<int32_t, nsresult>{42}), QM_PROPAGATE,
   1185        [&tryReturnCleanupRan](const auto&) { tryReturnCleanupRan = true; });
   1186 
   1187    tryReturnDidNotReturn = true;
   1188  }();
   1189 
   1190  EXPECT_FALSE(tryReturnCleanupRan);
   1191  EXPECT_FALSE(tryReturnDidNotReturn);
   1192  EXPECT_TRUE(res.isOk());
   1193  EXPECT_EQ(res.unwrap(), 42);
   1194 }
   1195 
   1196 TEST(QuotaCommon_TryReturn, Failure_PropagateErr)
   1197 {
   1198  bool tryReturnDidNotReturn = false;
   1199 
   1200  auto res = [&tryReturnDidNotReturn] {
   1201    QM_TRY_RETURN((Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}));
   1202 
   1203    tryReturnDidNotReturn = true;
   1204  }();
   1205 
   1206  EXPECT_FALSE(tryReturnDidNotReturn);
   1207  EXPECT_TRUE(res.isErr());
   1208  EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE);
   1209 }
   1210 
   1211 TEST(QuotaCommon_TryReturn, Failure_PropagateErr_nsresult)
   1212 {
   1213  bool tryReturnDidNotReturn = false;
   1214 
   1215  auto res = [&tryReturnDidNotReturn] {
   1216    QM_TRY_RETURN(MOZ_TO_RESULT(NS_ERROR_FAILURE));
   1217 
   1218    tryReturnDidNotReturn = true;
   1219  }();
   1220 
   1221  EXPECT_FALSE(tryReturnDidNotReturn);
   1222  EXPECT_TRUE(res.isErr());
   1223  EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE);
   1224 }
   1225 
   1226 TEST(QuotaCommon_TryReturn, Failure_CustomErr)
   1227 {
   1228  bool tryReturnDidNotReturn = false;
   1229 
   1230  auto res = [&tryReturnDidNotReturn]() -> Result<int32_t, nsresult> {
   1231    QM_TRY_RETURN((Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}),
   1232                  Err(NS_ERROR_UNEXPECTED));
   1233 
   1234    tryReturnDidNotReturn = true;
   1235  }();
   1236 
   1237  EXPECT_FALSE(tryReturnDidNotReturn);
   1238  EXPECT_TRUE(res.isErr());
   1239  EXPECT_EQ(res.unwrapErr(), NS_ERROR_UNEXPECTED);
   1240 }
   1241 
   1242 TEST(QuotaCommon_TryReturn, Failure_CustomErr_CustomLambda)
   1243 {
   1244 #define SUBTEST(...)                                                       \
   1245  {                                                                        \
   1246    bool tryReturnDidNotReturn = false;                                    \
   1247                                                                           \
   1248    auto res = [&tryReturnDidNotReturn]() -> Result<int32_t, nsresult> {   \
   1249      QM_TRY_RETURN((Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}),    \
   1250                    [](__VA_ARGS__) { return Err(NS_ERROR_UNEXPECTED); }); \
   1251                                                                           \
   1252      tryReturnDidNotReturn = true;                                        \
   1253    }();                                                                   \
   1254                                                                           \
   1255    EXPECT_FALSE(tryReturnDidNotReturn);                                   \
   1256    EXPECT_TRUE(res.isErr());                                              \
   1257    EXPECT_EQ(res.unwrapErr(), NS_ERROR_UNEXPECTED);                       \
   1258  }
   1259 
   1260  SUBTEST(const char*, nsresult);
   1261  SUBTEST(nsresult);
   1262 
   1263 #undef SUBTEST
   1264 }
   1265 
   1266 TEST(QuotaCommon_TryReturn, Failure_WithCleanup)
   1267 {
   1268  bool tryReturnCleanupRan = false;
   1269  bool tryReturnDidNotReturn = false;
   1270 
   1271  auto res = [&tryReturnCleanupRan,
   1272              &tryReturnDidNotReturn]() -> Result<int32_t, nsresult> {
   1273    QM_TRY_RETURN((Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}),
   1274                  QM_PROPAGATE, [&tryReturnCleanupRan](const auto& result) {
   1275                    EXPECT_EQ(result, NS_ERROR_FAILURE);
   1276 
   1277                    tryReturnCleanupRan = true;
   1278                  });
   1279 
   1280    tryReturnDidNotReturn = true;
   1281  }();
   1282 
   1283  EXPECT_TRUE(tryReturnCleanupRan);
   1284  EXPECT_FALSE(tryReturnDidNotReturn);
   1285  EXPECT_TRUE(res.isErr());
   1286  EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE);
   1287 }
   1288 
   1289 TEST(QuotaCommon_TryReturn, SameLine)
   1290 {
   1291  // clang-format off
   1292  auto res1 = [] { QM_TRY_RETURN((Result<int32_t, nsresult>{42})); }(); auto res2 = []() -> Result<int32_t, nsresult> { QM_TRY_RETURN((Result<int32_t, nsresult>{42})); }();
   1293  // clang-format on
   1294 
   1295  EXPECT_TRUE(res1.isOk());
   1296  EXPECT_EQ(res1.unwrap(), 42);
   1297  EXPECT_TRUE(res2.isOk());
   1298  EXPECT_EQ(res2.unwrap(), 42);
   1299 }
   1300 
   1301 TEST(QuotaCommon_TryReturn, NestingMadness_Success)
   1302 {
   1303  bool nestedTryReturnDidNotReturn = false;
   1304  bool tryReturnDidNotReturn = false;
   1305 
   1306  auto res = [&nestedTryReturnDidNotReturn, &tryReturnDidNotReturn] {
   1307    QM_TRY_RETURN(([&nestedTryReturnDidNotReturn] {
   1308      QM_TRY_RETURN((Result<int32_t, nsresult>{42}));
   1309 
   1310      nestedTryReturnDidNotReturn = true;
   1311    }()));
   1312 
   1313    tryReturnDidNotReturn = true;
   1314  }();
   1315 
   1316  EXPECT_FALSE(nestedTryReturnDidNotReturn);
   1317  EXPECT_FALSE(tryReturnDidNotReturn);
   1318  EXPECT_TRUE(res.isOk());
   1319  EXPECT_EQ(res.unwrap(), 42);
   1320 }
   1321 
   1322 TEST(QuotaCommon_TryReturn, NestingMadness_Failure)
   1323 {
   1324  bool nestedTryReturnDidNotReturn = false;
   1325  bool tryReturnDidNotReturn = false;
   1326 
   1327  auto res = [&nestedTryReturnDidNotReturn, &tryReturnDidNotReturn] {
   1328    QM_TRY_RETURN(([&nestedTryReturnDidNotReturn] {
   1329      QM_TRY_RETURN((Result<int32_t, nsresult>{Err(NS_ERROR_FAILURE)}));
   1330 
   1331      nestedTryReturnDidNotReturn = true;
   1332    }()));
   1333 
   1334    tryReturnDidNotReturn = true;
   1335  }();
   1336 
   1337  EXPECT_FALSE(nestedTryReturnDidNotReturn);
   1338  EXPECT_FALSE(tryReturnDidNotReturn);
   1339  EXPECT_TRUE(res.isErr());
   1340  EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE);
   1341 }
   1342 
   1343 TEST(QuotaCommon_Fail, ReturnValue)
   1344 {
   1345  bool failDidNotReturn = false;
   1346 
   1347  nsresult rv = [&failDidNotReturn]() -> nsresult {
   1348    QM_FAIL(NS_ERROR_FAILURE);
   1349 
   1350    failDidNotReturn = true;
   1351 
   1352    return NS_OK;
   1353  }();
   1354 
   1355  EXPECT_FALSE(failDidNotReturn);
   1356  EXPECT_EQ(rv, NS_ERROR_FAILURE);
   1357 }
   1358 
   1359 TEST(QuotaCommon_Fail, ReturnValue_WithCleanup)
   1360 {
   1361  bool failCleanupRan = false;
   1362  bool failDidNotReturn = false;
   1363 
   1364  nsresult rv = [&failCleanupRan, &failDidNotReturn]() -> nsresult {
   1365    QM_FAIL(NS_ERROR_FAILURE, [&failCleanupRan]() { failCleanupRan = true; });
   1366 
   1367    failDidNotReturn = true;
   1368 
   1369    return NS_OK;
   1370  }();
   1371 
   1372  EXPECT_TRUE(failCleanupRan);
   1373  EXPECT_FALSE(failDidNotReturn);
   1374  EXPECT_EQ(rv, NS_ERROR_FAILURE);
   1375 }
   1376 
   1377 TEST(QuotaCommon_WarnOnlyTry, Success)
   1378 {
   1379  bool warnOnlyTryDidNotReturn = false;
   1380 
   1381  const auto res =
   1382      [&warnOnlyTryDidNotReturn]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1383    QM_WARNONLY_TRY(OkIf(true));
   1384 
   1385    warnOnlyTryDidNotReturn = true;
   1386    return mozilla::Ok{};
   1387  }();
   1388 
   1389  EXPECT_TRUE(res.isOk());
   1390  EXPECT_TRUE(warnOnlyTryDidNotReturn);
   1391 }
   1392 
   1393 TEST(QuotaCommon_WarnOnlyTry, Success_WithCleanup)
   1394 {
   1395  bool warnOnlyTryCleanupRan = false;
   1396  bool warnOnlyTryDidNotReturn = false;
   1397 
   1398  const auto res =
   1399      [&warnOnlyTryCleanupRan,
   1400       &warnOnlyTryDidNotReturn]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1401    QM_WARNONLY_TRY(OkIf(true), [&warnOnlyTryCleanupRan](const auto&) {
   1402      warnOnlyTryCleanupRan = true;
   1403    });
   1404 
   1405    warnOnlyTryDidNotReturn = true;
   1406    return mozilla::Ok{};
   1407  }();
   1408 
   1409  EXPECT_TRUE(res.isOk());
   1410  EXPECT_FALSE(warnOnlyTryCleanupRan);
   1411  EXPECT_TRUE(warnOnlyTryDidNotReturn);
   1412 }
   1413 
   1414 TEST(QuotaCommon_WarnOnlyTry, Failure)
   1415 {
   1416  bool warnOnlyTryDidNotReturn = false;
   1417 
   1418  const auto res =
   1419      [&warnOnlyTryDidNotReturn]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1420    QM_WARNONLY_TRY(OkIf(false));
   1421 
   1422    warnOnlyTryDidNotReturn = true;
   1423    return mozilla::Ok{};
   1424  }();
   1425 
   1426  EXPECT_TRUE(res.isOk());
   1427  EXPECT_TRUE(warnOnlyTryDidNotReturn);
   1428 }
   1429 
   1430 TEST(QuotaCommon_WarnOnlyTry, Failure_WithCleanup)
   1431 {
   1432  bool warnOnlyTryCleanupRan = false;
   1433  bool warnOnlyTryDidNotReturn = false;
   1434 
   1435  const auto res =
   1436      [&warnOnlyTryCleanupRan,
   1437       &warnOnlyTryDidNotReturn]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1438    QM_WARNONLY_TRY(OkIf(false), ([&warnOnlyTryCleanupRan](const auto&) {
   1439                      warnOnlyTryCleanupRan = true;
   1440                    }));
   1441 
   1442    warnOnlyTryDidNotReturn = true;
   1443    return mozilla::Ok{};
   1444  }();
   1445 
   1446  EXPECT_TRUE(res.isOk());
   1447  EXPECT_TRUE(warnOnlyTryCleanupRan);
   1448  EXPECT_TRUE(warnOnlyTryDidNotReturn);
   1449 }
   1450 
   1451 TEST(QuotaCommon_WarnOnlyTryUnwrap, Success)
   1452 {
   1453  bool warnOnlyTryUnwrapDidNotReturn = false;
   1454 
   1455  const auto res = [&warnOnlyTryUnwrapDidNotReturn]()
   1456      -> mozilla::Result<mozilla::Ok, NotOk> {
   1457    QM_WARNONLY_TRY_UNWRAP(const auto x, (Result<int32_t, NotOk>{42}));
   1458    EXPECT_TRUE(x);
   1459    EXPECT_EQ(*x, 42);
   1460 
   1461    warnOnlyTryUnwrapDidNotReturn = true;
   1462    return mozilla::Ok{};
   1463  }();
   1464 
   1465  EXPECT_TRUE(res.isOk());
   1466  EXPECT_TRUE(warnOnlyTryUnwrapDidNotReturn);
   1467 }
   1468 
   1469 TEST(QuotaCommon_WarnOnlyTryUnwrap, Success_WithCleanup)
   1470 {
   1471  bool warnOnlyTryUnwrapCleanupRan = false;
   1472  bool warnOnlyTryUnwrapDidNotReturn = false;
   1473 
   1474  const auto res = [&warnOnlyTryUnwrapCleanupRan,
   1475                    &warnOnlyTryUnwrapDidNotReturn]()
   1476      -> mozilla::Result<mozilla::Ok, NotOk> {
   1477    QM_WARNONLY_TRY_UNWRAP(const auto x, (Result<int32_t, NotOk>{42}),
   1478                           [&warnOnlyTryUnwrapCleanupRan](const auto&) {
   1479                             warnOnlyTryUnwrapCleanupRan = true;
   1480                           });
   1481    EXPECT_TRUE(x);
   1482    EXPECT_EQ(*x, 42);
   1483 
   1484    warnOnlyTryUnwrapDidNotReturn = true;
   1485    return mozilla::Ok{};
   1486  }();
   1487 
   1488  EXPECT_TRUE(res.isOk());
   1489  EXPECT_FALSE(warnOnlyTryUnwrapCleanupRan);
   1490  EXPECT_TRUE(warnOnlyTryUnwrapDidNotReturn);
   1491 }
   1492 
   1493 TEST(QuotaCommon_WarnOnlyTryUnwrap, Failure)
   1494 {
   1495  bool warnOnlyTryUnwrapDidNotReturn = false;
   1496 
   1497  const auto res = [&warnOnlyTryUnwrapDidNotReturn]()
   1498      -> mozilla::Result<mozilla::Ok, NotOk> {
   1499    QM_WARNONLY_TRY_UNWRAP(const auto x,
   1500                           (Result<int32_t, NotOk>{Err(NotOk{})}));
   1501    EXPECT_FALSE(x);
   1502 
   1503    warnOnlyTryUnwrapDidNotReturn = true;
   1504    return mozilla::Ok{};
   1505  }();
   1506 
   1507  EXPECT_TRUE(res.isOk());
   1508  EXPECT_TRUE(warnOnlyTryUnwrapDidNotReturn);
   1509 }
   1510 
   1511 TEST(QuotaCommon_WarnOnlyTryUnwrap, Failure_WithCleanup)
   1512 {
   1513  bool warnOnlyTryUnwrapCleanupRan = false;
   1514  bool warnOnlyTryUnwrapDidNotReturn = false;
   1515 
   1516  const auto res = [&warnOnlyTryUnwrapCleanupRan,
   1517                    &warnOnlyTryUnwrapDidNotReturn]()
   1518      -> mozilla::Result<mozilla::Ok, NotOk> {
   1519    QM_WARNONLY_TRY_UNWRAP(const auto x, (Result<int32_t, NotOk>{Err(NotOk{})}),
   1520                           [&warnOnlyTryUnwrapCleanupRan](const auto&) {
   1521                             warnOnlyTryUnwrapCleanupRan = true;
   1522                           });
   1523    EXPECT_FALSE(x);
   1524 
   1525    warnOnlyTryUnwrapDidNotReturn = true;
   1526    return mozilla::Ok{};
   1527  }();
   1528 
   1529  EXPECT_TRUE(res.isOk());
   1530  EXPECT_TRUE(warnOnlyTryUnwrapCleanupRan);
   1531  EXPECT_TRUE(warnOnlyTryUnwrapDidNotReturn);
   1532 }
   1533 
   1534 TEST(QuotaCommon_OrElseWarn, Success)
   1535 {
   1536  bool fallbackRun = false;
   1537  bool tryContinued = false;
   1538 
   1539  const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1540    QM_TRY(QM_OR_ELSE_WARN(OkIf(true), ([&fallbackRun](const NotOk) {
   1541                             fallbackRun = true;
   1542                             return mozilla::Result<mozilla::Ok, NotOk>{
   1543                                 mozilla::Ok{}};
   1544                           })));
   1545 
   1546    tryContinued = true;
   1547    return mozilla::Ok{};
   1548  }();
   1549 
   1550  EXPECT_TRUE(res.isOk());
   1551  EXPECT_FALSE(fallbackRun);
   1552  EXPECT_TRUE(tryContinued);
   1553 }
   1554 
   1555 TEST(QuotaCommon_OrElseWarn, Failure_MappedToSuccess)
   1556 {
   1557  bool fallbackRun = false;
   1558  bool tryContinued = false;
   1559 
   1560  // XXX Consider allowing to set a custom error handler, so that we can
   1561  // actually assert that a warning was emitted.
   1562  const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1563    QM_TRY(QM_OR_ELSE_WARN(OkIf(false), ([&fallbackRun](const NotOk) {
   1564                             fallbackRun = true;
   1565                             return mozilla::Result<mozilla::Ok, NotOk>{
   1566                                 mozilla::Ok{}};
   1567                           })));
   1568    tryContinued = true;
   1569    return mozilla::Ok{};
   1570  }();
   1571 
   1572  EXPECT_TRUE(res.isOk());
   1573  EXPECT_TRUE(fallbackRun);
   1574  EXPECT_TRUE(tryContinued);
   1575 }
   1576 
   1577 TEST(QuotaCommon_OrElseWarn, Failure_MappedToError)
   1578 {
   1579  bool fallbackRun = false;
   1580  bool tryContinued = false;
   1581 
   1582  // XXX Consider allowing to set a custom error handler, so that we can
   1583  // actually assert that a warning was emitted.
   1584  const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1585    QM_TRY(QM_OR_ELSE_WARN(OkIf(false), ([&fallbackRun](const NotOk) {
   1586                             fallbackRun = true;
   1587                             return mozilla::Result<mozilla::Ok, NotOk>{
   1588                                 NotOk{}};
   1589                           })));
   1590    tryContinued = true;
   1591    return mozilla::Ok{};
   1592  }();
   1593 
   1594  EXPECT_TRUE(res.isErr());
   1595  EXPECT_TRUE(fallbackRun);
   1596  EXPECT_FALSE(tryContinued);
   1597 }
   1598 
   1599 TEST(QuotaCommon_OrElseWarnIf, Success)
   1600 {
   1601  bool predicateRun = false;
   1602  bool fallbackRun = false;
   1603  bool tryContinued = false;
   1604 
   1605  const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1606    QM_TRY(QM_OR_ELSE_WARN_IF(
   1607        OkIf(true),
   1608        [&predicateRun](const NotOk) {
   1609          predicateRun = true;
   1610          return false;
   1611        },
   1612        ([&fallbackRun](const NotOk) {
   1613          fallbackRun = true;
   1614          return mozilla::Result<mozilla::Ok, NotOk>{mozilla::Ok{}};
   1615        })));
   1616 
   1617    tryContinued = true;
   1618    return mozilla::Ok{};
   1619  }();
   1620 
   1621  EXPECT_TRUE(res.isOk());
   1622  EXPECT_FALSE(predicateRun);
   1623  EXPECT_FALSE(fallbackRun);
   1624  EXPECT_TRUE(tryContinued);
   1625 }
   1626 
   1627 TEST(QuotaCommon_OrElseWarnIf, Failure_PredicateReturnsFalse)
   1628 {
   1629  bool predicateRun = false;
   1630  bool fallbackRun = false;
   1631  bool tryContinued = false;
   1632 
   1633  const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1634    QM_TRY(QM_OR_ELSE_WARN_IF(
   1635        OkIf(false),
   1636        [&predicateRun](const NotOk) {
   1637          predicateRun = true;
   1638          return false;
   1639        },
   1640        ([&fallbackRun](const NotOk) {
   1641          fallbackRun = true;
   1642          return mozilla::Result<mozilla::Ok, NotOk>{mozilla::Ok{}};
   1643        })));
   1644 
   1645    tryContinued = true;
   1646    return mozilla::Ok{};
   1647  }();
   1648 
   1649  EXPECT_TRUE(res.isErr());
   1650  EXPECT_TRUE(predicateRun);
   1651  EXPECT_FALSE(fallbackRun);
   1652  EXPECT_FALSE(tryContinued);
   1653 }
   1654 
   1655 TEST(QuotaCommon_OrElseWarnIf, Failure_PredicateReturnsTrue_MappedToSuccess)
   1656 {
   1657  bool predicateRun = false;
   1658  bool fallbackRun = false;
   1659  bool tryContinued = false;
   1660 
   1661  const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1662    QM_TRY(QM_OR_ELSE_WARN_IF(
   1663        OkIf(false),
   1664        [&predicateRun](const NotOk) {
   1665          predicateRun = true;
   1666          return true;
   1667        },
   1668        ([&fallbackRun](const NotOk) {
   1669          fallbackRun = true;
   1670          return mozilla::Result<mozilla::Ok, NotOk>{mozilla::Ok{}};
   1671        })));
   1672 
   1673    tryContinued = true;
   1674    return mozilla::Ok{};
   1675  }();
   1676 
   1677  EXPECT_TRUE(res.isOk());
   1678  EXPECT_TRUE(predicateRun);
   1679  EXPECT_TRUE(fallbackRun);
   1680  EXPECT_TRUE(tryContinued);
   1681 }
   1682 
   1683 TEST(QuotaCommon_OrElseWarnIf, Failure_PredicateReturnsTrue_MappedToError)
   1684 {
   1685  bool predicateRun = false;
   1686  bool fallbackRun = false;
   1687  bool tryContinued = false;
   1688 
   1689  const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
   1690    QM_TRY(QM_OR_ELSE_WARN_IF(
   1691        OkIf(false),
   1692        [&predicateRun](const NotOk) {
   1693          predicateRun = true;
   1694          return true;
   1695        },
   1696        ([&fallbackRun](const NotOk) {
   1697          fallbackRun = true;
   1698          return mozilla::Result<mozilla::Ok, NotOk>{mozilla::NotOk{}};
   1699        })));
   1700 
   1701    tryContinued = true;
   1702    return mozilla::Ok{};
   1703  }();
   1704 
   1705  EXPECT_TRUE(res.isErr());
   1706  EXPECT_TRUE(predicateRun);
   1707  EXPECT_TRUE(fallbackRun);
   1708  EXPECT_FALSE(tryContinued);
   1709 }
   1710 
   1711 TEST(QuotaCommon_OkIf, True)
   1712 {
   1713  auto res = OkIf(true);
   1714 
   1715  EXPECT_TRUE(res.isOk());
   1716 }
   1717 
   1718 TEST(QuotaCommon_OkIf, False)
   1719 {
   1720  auto res = OkIf(false);
   1721 
   1722  EXPECT_TRUE(res.isErr());
   1723 }
   1724 
   1725 TEST(QuotaCommon_OkToOk, Bool_True)
   1726 {
   1727  auto res = OkToOk<true>(Ok());
   1728  EXPECT_TRUE(res.isOk());
   1729  EXPECT_EQ(res.unwrap(), true);
   1730 }
   1731 
   1732 TEST(QuotaCommon_OkToOk, Bool_False)
   1733 {
   1734  auto res = OkToOk<false>(Ok());
   1735  EXPECT_TRUE(res.isOk());
   1736  EXPECT_EQ(res.unwrap(), false);
   1737 }
   1738 
   1739 TEST(QuotaCommon_OkToOk, Int_42)
   1740 {
   1741  auto res = OkToOk<42>(Ok());
   1742  EXPECT_TRUE(res.isOk());
   1743  EXPECT_EQ(res.unwrap(), 42);
   1744 }
   1745 
   1746 TEST(QuotaCommon_ErrToOkOrErr, Bool_True)
   1747 {
   1748  auto res = ErrToOkOrErr<NS_ERROR_FAILURE, true>(NS_ERROR_FAILURE);
   1749  EXPECT_TRUE(res.isOk());
   1750  EXPECT_EQ(res.unwrap(), true);
   1751 }
   1752 
   1753 TEST(QuotaCommon_ErrToOkOrErr, Bool_True_Err)
   1754 {
   1755  auto res = ErrToOkOrErr<NS_ERROR_FAILURE, true>(NS_ERROR_UNEXPECTED);
   1756  EXPECT_TRUE(res.isErr());
   1757  EXPECT_EQ(res.unwrapErr(), NS_ERROR_UNEXPECTED);
   1758 }
   1759 
   1760 TEST(QuotaCommon_ErrToOkOrErr, Bool_False)
   1761 {
   1762  auto res = ErrToOkOrErr<NS_ERROR_FAILURE, false>(NS_ERROR_FAILURE);
   1763  EXPECT_TRUE(res.isOk());
   1764  EXPECT_EQ(res.unwrap(), false);
   1765 }
   1766 
   1767 TEST(QuotaCommon_ErrToOkOrErr, Bool_False_Err)
   1768 {
   1769  auto res = ErrToOkOrErr<NS_ERROR_FAILURE, false>(NS_ERROR_UNEXPECTED);
   1770  EXPECT_TRUE(res.isErr());
   1771  EXPECT_EQ(res.unwrapErr(), NS_ERROR_UNEXPECTED);
   1772 }
   1773 
   1774 TEST(QuotaCommon_ErrToOkOrErr, Int_42)
   1775 {
   1776  auto res = ErrToOkOrErr<NS_ERROR_FAILURE, 42>(NS_ERROR_FAILURE);
   1777  EXPECT_TRUE(res.isOk());
   1778  EXPECT_EQ(res.unwrap(), 42);
   1779 }
   1780 
   1781 TEST(QuotaCommon_ErrToOkOrErr, Int_42_Err)
   1782 {
   1783  auto res = ErrToOkOrErr<NS_ERROR_FAILURE, 42>(NS_ERROR_UNEXPECTED);
   1784  EXPECT_TRUE(res.isErr());
   1785  EXPECT_EQ(res.unwrapErr(), NS_ERROR_UNEXPECTED);
   1786 }
   1787 
   1788 TEST(QuotaCommon_ErrToOkOrErr, NsCOMPtr_nullptr)
   1789 {
   1790  auto res = ErrToOkOrErr<NS_ERROR_FAILURE, nullptr, nsCOMPtr<nsISupports>>(
   1791      NS_ERROR_FAILURE);
   1792  EXPECT_TRUE(res.isOk());
   1793  EXPECT_EQ(res.unwrap(), nullptr);
   1794 }
   1795 
   1796 TEST(QuotaCommon_ErrToOkOrErr, NsCOMPtr_nullptr_Err)
   1797 {
   1798  auto res = ErrToOkOrErr<NS_ERROR_FAILURE, nullptr, nsCOMPtr<nsISupports>>(
   1799      NS_ERROR_UNEXPECTED);
   1800  EXPECT_TRUE(res.isErr());
   1801  EXPECT_EQ(res.unwrapErr(), NS_ERROR_UNEXPECTED);
   1802 }
   1803 
   1804 TEST(QuotaCommon_ErrToDefaultOkOrErr, Ok)
   1805 {
   1806  auto res = ErrToDefaultOkOrErr<NS_ERROR_FAILURE, Ok>(NS_ERROR_FAILURE);
   1807  EXPECT_TRUE(res.isOk());
   1808 }
   1809 
   1810 TEST(QuotaCommon_ErrToDefaultOkOrErr, Ok_Err)
   1811 {
   1812  auto res = ErrToDefaultOkOrErr<NS_ERROR_FAILURE, Ok>(NS_ERROR_UNEXPECTED);
   1813  EXPECT_TRUE(res.isErr());
   1814  EXPECT_EQ(res.unwrapErr(), NS_ERROR_UNEXPECTED);
   1815 }
   1816 
   1817 TEST(QuotaCommon_ErrToDefaultOkOrErr, NsCOMPtr)
   1818 {
   1819  auto res = ErrToDefaultOkOrErr<NS_ERROR_FAILURE, nsCOMPtr<nsISupports>>(
   1820      NS_ERROR_FAILURE);
   1821  EXPECT_TRUE(res.isOk());
   1822  EXPECT_EQ(res.unwrap(), nullptr);
   1823 }
   1824 
   1825 TEST(QuotaCommon_ErrToDefaultOkOrErr, NsCOMPtr_Err)
   1826 {
   1827  auto res = ErrToDefaultOkOrErr<NS_ERROR_FAILURE, nsCOMPtr<nsISupports>>(
   1828      NS_ERROR_UNEXPECTED);
   1829  EXPECT_TRUE(res.isErr());
   1830  EXPECT_EQ(res.unwrapErr(), NS_ERROR_UNEXPECTED);
   1831 }
   1832 
   1833 TEST(QuotaCommon_IsSpecificError, Match)
   1834 {
   1835  EXPECT_TRUE(IsSpecificError<NS_ERROR_FAILURE>(NS_ERROR_FAILURE));
   1836 }
   1837 
   1838 TEST(QuotaCommon_IsSpecificError, Mismatch)
   1839 {
   1840  EXPECT_FALSE(IsSpecificError<NS_ERROR_FAILURE>(NS_ERROR_UNEXPECTED));
   1841 }
   1842 
   1843 TEST(QuotaCommon_ErrToOk, Bool_True)
   1844 {
   1845  auto res = ErrToOk<true>(NS_ERROR_FAILURE);
   1846  EXPECT_TRUE(res.isOk());
   1847  EXPECT_EQ(res.unwrap(), true);
   1848 }
   1849 
   1850 TEST(QuotaCommon_ErrToOk, Bool_False)
   1851 {
   1852  auto res = ErrToOk<false>(NS_ERROR_FAILURE);
   1853  EXPECT_TRUE(res.isOk());
   1854  EXPECT_EQ(res.unwrap(), false);
   1855 }
   1856 
   1857 TEST(QuotaCommon_ErrToOk, Int_42)
   1858 {
   1859  auto res = ErrToOk<42>(NS_ERROR_FAILURE);
   1860  EXPECT_TRUE(res.isOk());
   1861  EXPECT_EQ(res.unwrap(), 42);
   1862 }
   1863 
   1864 TEST(QuotaCommon_ErrToOk, NsCOMPtr_nullptr)
   1865 {
   1866  auto res = ErrToOk<nullptr, nsCOMPtr<nsISupports>>(NS_ERROR_FAILURE);
   1867  EXPECT_TRUE(res.isOk());
   1868  EXPECT_EQ(res.unwrap(), nullptr);
   1869 }
   1870 
   1871 TEST(QuotaCommon_ErrToDefaultOk, Ok)
   1872 {
   1873  auto res = ErrToDefaultOk<Ok>(NS_ERROR_FAILURE);
   1874  EXPECT_TRUE(res.isOk());
   1875 }
   1876 
   1877 TEST(QuotaCommon_ErrToDefaultOk, NsCOMPtr)
   1878 {
   1879  auto res = ErrToDefaultOk<nsCOMPtr<nsISupports>>(NS_ERROR_FAILURE);
   1880  EXPECT_TRUE(res.isOk());
   1881  EXPECT_EQ(res.unwrap(), nullptr);
   1882 }
   1883 
   1884 class StringPairParameterized
   1885    : public ::testing::TestWithParam<std::pair<const char*, const char*>> {};
   1886 
   1887 TEST_P(StringPairParameterized, AnonymizedOriginString) {
   1888  const auto [in, expectedAnonymized] = GetParam();
   1889  const auto anonymized = AnonymizedOriginString(nsDependentCString(in));
   1890  EXPECT_STREQ(anonymized.get(), expectedAnonymized);
   1891 }
   1892 
   1893 INSTANTIATE_TEST_SUITE_P(
   1894    QuotaCommon, StringPairParameterized,
   1895    ::testing::Values(
   1896        // XXX Do we really want to anonymize about: origins?
   1897        std::pair("about:home", "about:aaaa"),
   1898        std::pair("https://foo.bar.com", "https://aaa.aaa.aaa"),
   1899        std::pair("https://foo.bar.com:8000", "https://aaa.aaa.aaa:DDDD"),
   1900        std::pair("file://UNIVERSAL_FILE_ORIGIN",
   1901                  "file://aaaaaaaaa_aaaa_aaaaaa")));
   1902 
   1903 // BEGIN COPY FROM mfbt/tests/TestResult.cpp
   1904 struct Failed {};
   1905 
   1906 static GenericErrorResult<Failed> Fail() { return Err(Failed()); }
   1907 
   1908 static Result<Ok, Failed> Task1(bool pass) {
   1909  if (!pass) {
   1910    return Fail();  // implicit conversion from GenericErrorResult to Result
   1911  }
   1912  return Ok();
   1913 }
   1914 // END COPY FROM mfbt/tests/TestResult.cpp
   1915 
   1916 static Result<bool, Failed> Condition(bool aNoError, bool aResult) {
   1917  return Task1(aNoError).map([aResult](auto) { return aResult; });
   1918 }
   1919 
   1920 TEST(QuotaCommon_CollectWhileTest, NoFailures)
   1921 {
   1922  const size_t loopCount = 5;
   1923  size_t conditionExecutions = 0;
   1924  size_t bodyExecutions = 0;
   1925  auto result = CollectWhile(
   1926      [&conditionExecutions] {
   1927        ++conditionExecutions;
   1928        return Condition(true, conditionExecutions <= loopCount);
   1929      },
   1930      [&bodyExecutions] {
   1931        ++bodyExecutions;
   1932        return Task1(true);
   1933      });
   1934  static_assert(std::is_same_v<decltype(result), Result<Ok, Failed>>);
   1935  MOZ_RELEASE_ASSERT(result.isOk());
   1936  MOZ_RELEASE_ASSERT(loopCount == bodyExecutions);
   1937  MOZ_RELEASE_ASSERT(1 + loopCount == conditionExecutions);
   1938 }
   1939 
   1940 TEST(QuotaCommon_CollectWhileTest, BodyFailsImmediately)
   1941 {
   1942  size_t conditionExecutions = 0;
   1943  size_t bodyExecutions = 0;
   1944  auto result = CollectWhile(
   1945      [&conditionExecutions] {
   1946        ++conditionExecutions;
   1947        return Condition(true, true);
   1948      },
   1949      [&bodyExecutions] {
   1950        ++bodyExecutions;
   1951        return Task1(false);
   1952      });
   1953  static_assert(std::is_same_v<decltype(result), Result<Ok, Failed>>);
   1954  MOZ_RELEASE_ASSERT(result.isErr());
   1955  MOZ_RELEASE_ASSERT(1 == bodyExecutions);
   1956  MOZ_RELEASE_ASSERT(1 == conditionExecutions);
   1957 }
   1958 
   1959 TEST(QuotaCommon_CollectWhileTest, BodyFailsOnSecondExecution)
   1960 {
   1961  size_t conditionExecutions = 0;
   1962  size_t bodyExecutions = 0;
   1963  auto result = CollectWhile(
   1964      [&conditionExecutions] {
   1965        ++conditionExecutions;
   1966        return Condition(true, true);
   1967      },
   1968      [&bodyExecutions] {
   1969        ++bodyExecutions;
   1970        return Task1(bodyExecutions < 2);
   1971      });
   1972  static_assert(std::is_same_v<decltype(result), Result<Ok, Failed>>);
   1973  MOZ_RELEASE_ASSERT(result.isErr());
   1974  MOZ_RELEASE_ASSERT(2 == bodyExecutions);
   1975  MOZ_RELEASE_ASSERT(2 == conditionExecutions);
   1976 }
   1977 
   1978 TEST(QuotaCommon_CollectWhileTest, ConditionFailsImmediately)
   1979 {
   1980  size_t conditionExecutions = 0;
   1981  size_t bodyExecutions = 0;
   1982  auto result = CollectWhile(
   1983      [&conditionExecutions] {
   1984        ++conditionExecutions;
   1985        return Condition(false, true);
   1986      },
   1987      [&bodyExecutions] {
   1988        ++bodyExecutions;
   1989        return Task1(true);
   1990      });
   1991  static_assert(std::is_same_v<decltype(result), Result<Ok, Failed>>);
   1992  MOZ_RELEASE_ASSERT(result.isErr());
   1993  MOZ_RELEASE_ASSERT(0 == bodyExecutions);
   1994  MOZ_RELEASE_ASSERT(1 == conditionExecutions);
   1995 }
   1996 
   1997 TEST(QuotaCommon_CollectWhileTest, ConditionFailsOnSecondExecution)
   1998 {
   1999  size_t conditionExecutions = 0;
   2000  size_t bodyExecutions = 0;
   2001  auto result = CollectWhile(
   2002      [&conditionExecutions] {
   2003        ++conditionExecutions;
   2004        return Condition(conditionExecutions < 2, true);
   2005      },
   2006      [&bodyExecutions] {
   2007        ++bodyExecutions;
   2008        return Task1(true);
   2009      });
   2010  static_assert(std::is_same_v<decltype(result), Result<Ok, Failed>>);
   2011  MOZ_RELEASE_ASSERT(result.isErr());
   2012  MOZ_RELEASE_ASSERT(1 == bodyExecutions);
   2013  MOZ_RELEASE_ASSERT(2 == conditionExecutions);
   2014 }
   2015 
   2016 TEST(QuotaCommon_CollectEachInRange, Success)
   2017 {
   2018  size_t bodyExecutions = 0;
   2019  const auto result = CollectEachInRange(
   2020      std::array<int, 5>{{1, 2, 3, 4, 5}},
   2021      [&bodyExecutions](const int val) -> Result<Ok, nsresult> {
   2022        ++bodyExecutions;
   2023        return Ok{};
   2024      });
   2025 
   2026  MOZ_RELEASE_ASSERT(result.isOk());
   2027  MOZ_RELEASE_ASSERT(5 == bodyExecutions);
   2028 }
   2029 
   2030 TEST(QuotaCommon_CollectEachInRange, FailureShortCircuit)
   2031 {
   2032  size_t bodyExecutions = 0;
   2033  const auto result = CollectEachInRange(
   2034      std::array<int, 5>{{1, 2, 3, 4, 5}},
   2035      [&bodyExecutions](const int val) -> Result<Ok, nsresult> {
   2036        ++bodyExecutions;
   2037        return val == 3 ? Err(NS_ERROR_FAILURE) : Result<Ok, nsresult>{Ok{}};
   2038      });
   2039 
   2040  MOZ_RELEASE_ASSERT(result.isErr());
   2041  MOZ_RELEASE_ASSERT(NS_ERROR_FAILURE == result.inspectErr());
   2042  MOZ_RELEASE_ASSERT(3 == bodyExecutions);
   2043 }
   2044 
   2045 TEST(QuotaCommon_ReduceEach, Success)
   2046 {
   2047  const auto result = ReduceEach(
   2048      [i = int{0}]() mutable -> Result<int, Failed> {
   2049        if (i < 5) {
   2050          return ++i;
   2051        }
   2052        return 0;
   2053      },
   2054      0, [](int val, int add) -> Result<int, Failed> { return val + add; });
   2055  static_assert(std::is_same_v<decltype(result), const Result<int, Failed>>);
   2056 
   2057  MOZ_RELEASE_ASSERT(result.isOk());
   2058  MOZ_RELEASE_ASSERT(15 == result.inspect());
   2059 }
   2060 
   2061 TEST(QuotaCommon_ReduceEach, StepError)
   2062 {
   2063  const auto result = ReduceEach(
   2064      [i = int{0}]() mutable -> Result<int, Failed> {
   2065        if (i < 5) {
   2066          return ++i;
   2067        }
   2068        return 0;
   2069      },
   2070      0,
   2071      [](int val, int add) -> Result<int, Failed> {
   2072        if (val > 2) {
   2073          return Err(Failed{});
   2074        }
   2075        return val + add;
   2076      });
   2077  static_assert(std::is_same_v<decltype(result), const Result<int, Failed>>);
   2078 
   2079  MOZ_RELEASE_ASSERT(result.isErr());
   2080 }
   2081 
   2082 TEST(QuotaCommon_ReduceEach, GeneratorError)
   2083 {
   2084  size_t generatorExecutions = 0;
   2085  const auto result = ReduceEach(
   2086      [i = int{0}, &generatorExecutions]() mutable -> Result<int, Failed> {
   2087        ++generatorExecutions;
   2088        if (i < 1) {
   2089          return ++i;
   2090        }
   2091        return Err(Failed{});
   2092      },
   2093      0,
   2094      [](int val, int add) -> Result<int, Failed> {
   2095        if (val > 2) {
   2096          return Err(Failed{});
   2097        }
   2098        return val + add;
   2099      });
   2100  static_assert(std::is_same_v<decltype(result), const Result<int, Failed>>);
   2101 
   2102  MOZ_RELEASE_ASSERT(result.isErr());
   2103  MOZ_RELEASE_ASSERT(2 == generatorExecutions);
   2104 }
   2105 
   2106 TEST(QuotaCommon_Reduce, Success)
   2107 {
   2108  const auto range = std::vector{0, 1, 2, 3, 4, 5};
   2109  const auto result = Reduce(
   2110      range, 0, [](int val, Maybe<const int&> add) -> Result<int, Failed> {
   2111        return val + add.ref();
   2112      });
   2113  static_assert(std::is_same_v<decltype(result), const Result<int, Failed>>);
   2114 
   2115  MOZ_RELEASE_ASSERT(result.isOk());
   2116  MOZ_RELEASE_ASSERT(15 == result.inspect());
   2117 }
   2118 
   2119 TEST(QuotaCommon_CallWithDelayedRetriesIfAccessDenied, NoFailures)
   2120 {
   2121  uint32_t tries = 0;
   2122 
   2123  auto res = CallWithDelayedRetriesIfAccessDenied(
   2124      [&tries]() -> Result<Ok, nsresult> {
   2125        ++tries;
   2126        return Ok{};
   2127      },
   2128      10, 2);
   2129 
   2130  EXPECT_EQ(tries, 1u);
   2131  EXPECT_TRUE(res.isOk());
   2132 }
   2133 
   2134 TEST(QuotaCommon_CallWithDelayedRetriesIfAccessDenied, PermanentFailures)
   2135 {
   2136  uint32_t tries = 0;
   2137 
   2138  auto res = CallWithDelayedRetriesIfAccessDenied(
   2139      [&tries]() -> Result<Ok, nsresult> {
   2140        ++tries;
   2141        return Err(NS_ERROR_FILE_IS_LOCKED);
   2142      },
   2143      10, 2);
   2144 
   2145  EXPECT_EQ(tries, 11u);
   2146  EXPECT_TRUE(res.isErr());
   2147 }
   2148 
   2149 TEST(QuotaCommon_CallWithDelayedRetriesIfAccessDenied, FailuresAndSuccess)
   2150 {
   2151  uint32_t tries = 0;
   2152 
   2153  auto res = CallWithDelayedRetriesIfAccessDenied(
   2154      [&tries]() -> Result<Ok, nsresult> {
   2155        if (++tries == 5) {
   2156          return Ok{};
   2157        }
   2158        return Err(NS_ERROR_FILE_ACCESS_DENIED);
   2159      },
   2160      10, 2);
   2161 
   2162  EXPECT_EQ(tries, 5u);
   2163  EXPECT_TRUE(res.isOk());
   2164 }
   2165 
   2166 TEST(QuotaCommon_MakeSourceFileRelativePath, ThisSourceFile)
   2167 {
   2168  static constexpr auto thisSourceFileRelativePath =
   2169      "dom/quota/test/gtest/TestQuotaCommon.cpp"_ns;
   2170 
   2171  const nsCString sourceFileRelativePath{
   2172      mozilla::dom::quota::detail::MakeSourceFileRelativePath(
   2173          nsLiteralCString(__FILE__))};
   2174 
   2175  EXPECT_STREQ(sourceFileRelativePath.get(), thisSourceFileRelativePath.get());
   2176 }
   2177 
   2178 static nsCString MakeTreePath(const nsACString& aBasePath,
   2179                              const nsACString& aRelativePath) {
   2180  nsCString path{aBasePath};
   2181 
   2182  path.Append("/");
   2183  path.Append(aRelativePath);
   2184 
   2185  return path;
   2186 }
   2187 
   2188 static nsCString MakeSourceTreePath(const nsACString& aRelativePath) {
   2189  return MakeTreePath(mozilla::dom::quota::detail::GetSourceTreeBase(),
   2190                      aRelativePath);
   2191 }
   2192 
   2193 static nsCString MakeObjdirDistIncludeTreePath(
   2194    const nsACString& aRelativePath) {
   2195  return MakeTreePath(
   2196      mozilla::dom::quota::detail::GetObjdirDistIncludeTreeBase(),
   2197      aRelativePath);
   2198 }
   2199 
   2200 TEST(QuotaCommon_MakeSourceFileRelativePath, DomQuotaSourceFile)
   2201 {
   2202  static constexpr auto domQuotaSourceFileRelativePath =
   2203      "dom/quota/ActorsParent.cpp"_ns;
   2204 
   2205  const nsCString sourceFileRelativePath{
   2206      mozilla::dom::quota::detail::MakeSourceFileRelativePath(
   2207          MakeSourceTreePath(domQuotaSourceFileRelativePath))};
   2208 
   2209  EXPECT_STREQ(sourceFileRelativePath.get(),
   2210               domQuotaSourceFileRelativePath.get());
   2211 }
   2212 
   2213 TEST(QuotaCommon_MakeSourceFileRelativePath, DomQuotaSourceFile_Exported)
   2214 {
   2215  static constexpr auto mozillaDomQuotaSourceFileRelativePath =
   2216      "mozilla/dom/quota/QuotaCommon.h"_ns;
   2217 
   2218  static constexpr auto domQuotaSourceFileRelativePath =
   2219      "dom/quota/QuotaCommon.h"_ns;
   2220 
   2221  const nsCString sourceFileRelativePath{
   2222      mozilla::dom::quota::detail::MakeSourceFileRelativePath(
   2223          MakeObjdirDistIncludeTreePath(
   2224              mozillaDomQuotaSourceFileRelativePath))};
   2225 
   2226  EXPECT_STREQ(sourceFileRelativePath.get(),
   2227               domQuotaSourceFileRelativePath.get());
   2228 }
   2229 
   2230 TEST(QuotaCommon_MakeSourceFileRelativePath, DomIndexedDBSourceFile)
   2231 {
   2232  static constexpr auto domIndexedDBSourceFileRelativePath =
   2233      "dom/indexedDB/ActorsParent.cpp"_ns;
   2234 
   2235  const nsCString sourceFileRelativePath{
   2236      mozilla::dom::quota::detail::MakeSourceFileRelativePath(
   2237          MakeSourceTreePath(domIndexedDBSourceFileRelativePath))};
   2238 
   2239  EXPECT_STREQ(sourceFileRelativePath.get(),
   2240               domIndexedDBSourceFileRelativePath.get());
   2241 }
   2242 
   2243 TEST(QuotaCommon_MakeSourceFileRelativePath,
   2244     DomLocalstorageSourceFile_Exported_Mapped)
   2245 {
   2246  static constexpr auto mozillaDomSourceFileRelativePath =
   2247      "mozilla/dom/LocalStorageCommon.h"_ns;
   2248 
   2249  static constexpr auto domLocalstorageSourceFileRelativePath =
   2250      "dom/localstorage/LocalStorageCommon.h"_ns;
   2251 
   2252  const nsCString sourceFileRelativePath{
   2253      mozilla::dom::quota::detail::MakeSourceFileRelativePath(
   2254          MakeObjdirDistIncludeTreePath(mozillaDomSourceFileRelativePath))};
   2255 
   2256  EXPECT_STREQ(sourceFileRelativePath.get(),
   2257               domLocalstorageSourceFileRelativePath.get());
   2258 }
   2259 
   2260 TEST(QuotaCommon_MakeSourceFileRelativePath, NonDomSourceFile)
   2261 {
   2262  static constexpr auto nonDomSourceFileRelativePath =
   2263      "storage/mozStorageService.cpp"_ns;
   2264 
   2265  const nsCString sourceFileRelativePath{
   2266      mozilla::dom::quota::detail::MakeSourceFileRelativePath(
   2267          MakeSourceTreePath(nonDomSourceFileRelativePath))};
   2268 
   2269  EXPECT_STREQ(sourceFileRelativePath.get(),
   2270               nonDomSourceFileRelativePath.get());
   2271 }
   2272 
   2273 TEST(QuotaCommon_MakeSourceFileRelativePath, OtherSourceFile)
   2274 {
   2275  constexpr auto otherSourceFilePath = "/foo/bar/Test.cpp"_ns;
   2276  const nsCString sourceFileRelativePath{
   2277      mozilla::dom::quota::detail::MakeSourceFileRelativePath(
   2278          otherSourceFilePath)};
   2279 
   2280  EXPECT_STREQ(sourceFileRelativePath.get(), "Test.cpp");
   2281 }
   2282 
   2283 #ifdef __clang__
   2284 #  pragma clang diagnostic pop
   2285 #endif
   2286 
   2287 }  // namespace mozilla::dom::quota