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