TestResultExtensions.cpp (17783B)
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 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "gtest/gtest.h" 8 9 #include "mozilla/ResultExtensions.h" 10 #include "nsLocalFile.h" 11 12 #include <functional> 13 14 using namespace mozilla; 15 16 namespace { 17 class TestClass { 18 public: 19 static constexpr int kTestValue = 42; 20 21 nsresult NonOverloadedNoInput(int* aOut) { 22 *aOut = kTestValue; 23 return NS_OK; 24 } 25 nsresult NonOverloadedNoInputFails(int* aOut) { return NS_ERROR_FAILURE; } 26 27 nsresult NonOverloadedNoInputConst(int* aOut) const { 28 *aOut = kTestValue; 29 return NS_OK; 30 } 31 nsresult NonOverloadedNoInputFailsConst(int* aOut) const { 32 return NS_ERROR_FAILURE; 33 } 34 35 nsresult NonOverloadedNoInputRef(int& aOut) { 36 aOut = kTestValue; 37 return NS_OK; 38 } 39 nsresult NonOverloadedNoInputFailsRef(int& aOut) { return NS_ERROR_FAILURE; } 40 41 nsresult NonOverloadedNoInputComplex(std::pair<int, int>* aOut) { 42 *aOut = std::pair{kTestValue, kTestValue}; 43 return NS_OK; 44 } 45 nsresult NonOverloadedNoInputFailsComplex(std::pair<int, int>* aOut) { 46 return NS_ERROR_FAILURE; 47 } 48 49 nsresult NonOverloadedWithInput(int aIn, int* aOut) { 50 *aOut = aIn; 51 return NS_OK; 52 } 53 nsresult NonOverloadedWithInputFails(int aIn, int* aOut) { 54 return NS_ERROR_FAILURE; 55 } 56 57 nsresult NonOverloadedNoOutput(int aIn) { return NS_OK; } 58 nsresult NonOverloadedNoOutputFails(int aIn) { return NS_ERROR_FAILURE; } 59 60 nsresult PolymorphicNoInput(nsIFile** aOut) { 61 *aOut = MakeAndAddRef<nsLocalFile>().take(); 62 return NS_OK; 63 } 64 nsresult PolymorphicNoInputFails(nsIFile** aOut) { return NS_ERROR_FAILURE; } 65 }; 66 67 class RefCountedTestClass { 68 public: 69 NS_INLINE_DECL_REFCOUNTING(RefCountedTestClass); 70 71 static constexpr int kTestValue = 42; 72 73 nsresult NonOverloadedNoInput(int* aOut) { 74 *aOut = kTestValue; 75 return NS_OK; 76 } 77 nsresult NonOverloadedNoInputFails(int* aOut) { return NS_ERROR_FAILURE; } 78 79 private: 80 ~RefCountedTestClass() = default; 81 }; 82 83 // Check that DerefedType deduces the types as expected 84 static_assert(std::is_same_v<mozilla::detail::DerefedType<RefCountedTestClass&>, 85 RefCountedTestClass>); 86 static_assert(std::is_same_v<mozilla::detail::DerefedType<RefCountedTestClass*>, 87 RefCountedTestClass>); 88 static_assert( 89 std::is_same_v<mozilla::detail::DerefedType<RefPtr<RefCountedTestClass>>, 90 RefCountedTestClass>); 91 92 static_assert(std::is_same_v<mozilla::detail::DerefedType<nsIFile&>, nsIFile>); 93 static_assert(std::is_same_v<mozilla::detail::DerefedType<nsIFile*>, nsIFile>); 94 static_assert( 95 std::is_same_v<mozilla::detail::DerefedType<nsCOMPtr<nsIFile>>, nsIFile>); 96 } // namespace 97 98 TEST(ResultExtensions_ToResultInvoke, Lambda_NoInput) 99 { 100 TestClass foo; 101 102 // success 103 { 104 auto valOrErr = ToResultInvoke<int>( 105 [&foo](int* out) { return foo.NonOverloadedNoInput(out); }); 106 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 107 ASSERT_TRUE(valOrErr.isOk()); 108 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 109 } 110 111 // failure 112 { 113 auto valOrErr = ToResultInvoke<int>( 114 [&foo](int* out) { return foo.NonOverloadedNoInputFails(out); }); 115 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 116 ASSERT_TRUE(valOrErr.isErr()); 117 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 118 } 119 } 120 121 TEST(ResultExtensions_ToResultInvoke, MemFn_NoInput) 122 { 123 TestClass foo; 124 125 // success 126 { 127 auto valOrErr = 128 ToResultInvoke<int>(std::mem_fn(&TestClass::NonOverloadedNoInput), foo); 129 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 130 ASSERT_TRUE(valOrErr.isOk()); 131 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 132 } 133 134 // failure 135 { 136 auto valOrErr = ToResultInvoke<int>( 137 std::mem_fn(&TestClass::NonOverloadedNoInputFails), foo); 138 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 139 ASSERT_TRUE(valOrErr.isErr()); 140 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 141 } 142 } 143 144 TEST(ResultExtensions_ToResultInvoke, MemFn_Polymorphic_NoInput) 145 { 146 TestClass foo; 147 148 // success 149 { 150 auto valOrErr = ToResultInvoke<nsCOMPtr<nsIFile>>( 151 std::mem_fn(&TestClass::PolymorphicNoInput), foo); 152 static_assert(std::is_same_v<decltype(valOrErr), 153 Result<nsCOMPtr<nsIFile>, nsresult>>); 154 ASSERT_TRUE(valOrErr.isOk()); 155 ASSERT_NE(nullptr, valOrErr.inspect()); 156 157 ASSERT_EQ(ToResultInvoke<nsString>(std::mem_fn(&nsIFile::GetPath), 158 *MakeRefPtr<nsLocalFile>()) 159 .inspect(), 160 ToResultInvoke<nsString>(std::mem_fn(&nsIFile::GetPath), 161 valOrErr.inspect()) 162 .inspect()); 163 } 164 165 // failure 166 { 167 auto valOrErr = ToResultInvoke<nsCOMPtr<nsIFile>>( 168 std::mem_fn(&TestClass::PolymorphicNoInputFails), foo); 169 static_assert(std::is_same_v<decltype(valOrErr), 170 Result<nsCOMPtr<nsIFile>, nsresult>>); 171 ASSERT_TRUE(valOrErr.isErr()); 172 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 173 } 174 } 175 176 TEST(ResultExtensions_ToResultInvokeMember, NoInput) 177 { 178 TestClass foo; 179 180 // success 181 { 182 auto valOrErr = ToResultInvokeMember(foo, &TestClass::NonOverloadedNoInput); 183 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 184 ASSERT_TRUE(valOrErr.isOk()); 185 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 186 } 187 188 // failure 189 { 190 auto valOrErr = 191 ToResultInvokeMember(foo, &TestClass::NonOverloadedNoInputFails); 192 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 193 ASSERT_TRUE(valOrErr.isErr()); 194 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 195 } 196 } 197 198 TEST(ResultExtensions_ToResultInvokeMember, NoInput_Const) 199 { 200 const TestClass foo; 201 202 // success 203 { 204 auto valOrErr = 205 ToResultInvokeMember(foo, &TestClass::NonOverloadedNoInputConst); 206 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 207 ASSERT_TRUE(valOrErr.isOk()); 208 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 209 } 210 211 // failure 212 { 213 auto valOrErr = 214 ToResultInvokeMember(foo, &TestClass::NonOverloadedNoInputFailsConst); 215 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 216 ASSERT_TRUE(valOrErr.isErr()); 217 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 218 } 219 } 220 221 TEST(ResultExtensions_ToResultInvokeMember, NoInput_Ref) 222 { 223 TestClass foo; 224 225 // success 226 { 227 auto valOrErr = 228 ToResultInvokeMember(foo, &TestClass::NonOverloadedNoInputRef); 229 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 230 ASSERT_TRUE(valOrErr.isOk()); 231 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 232 } 233 234 // failure 235 { 236 auto valOrErr = 237 ToResultInvokeMember(foo, &TestClass::NonOverloadedNoInputFailsRef); 238 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 239 ASSERT_TRUE(valOrErr.isErr()); 240 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 241 } 242 } 243 244 TEST(ResultExtensions_ToResultInvokeMember, NoInput_Complex) 245 { 246 TestClass foo; 247 248 // success 249 { 250 auto valOrErr = 251 ToResultInvokeMember(foo, &TestClass::NonOverloadedNoInputComplex); 252 static_assert(std::is_same_v<decltype(valOrErr), 253 Result<std::pair<int, int>, nsresult>>); 254 ASSERT_TRUE(valOrErr.isOk()); 255 ASSERT_EQ((std::pair{TestClass::kTestValue, TestClass::kTestValue}), 256 valOrErr.unwrap()); 257 } 258 259 // failure 260 { 261 auto valOrErr = 262 ToResultInvokeMember(foo, &TestClass::NonOverloadedNoInputFailsComplex); 263 static_assert(std::is_same_v<decltype(valOrErr), 264 Result<std::pair<int, int>, nsresult>>); 265 ASSERT_TRUE(valOrErr.isErr()); 266 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 267 } 268 } 269 270 TEST(ResultExtensions_ToResultInvokeMember, WithInput) 271 { 272 TestClass foo; 273 274 // success 275 { 276 auto valOrErr = ToResultInvokeMember( 277 foo, &TestClass::NonOverloadedWithInput, -TestClass::kTestValue); 278 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 279 ASSERT_TRUE(valOrErr.isOk()); 280 ASSERT_EQ(-TestClass::kTestValue, valOrErr.unwrap()); 281 } 282 283 // failure 284 { 285 auto valOrErr = ToResultInvokeMember( 286 foo, &TestClass::NonOverloadedWithInputFails, -TestClass::kTestValue); 287 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 288 ASSERT_TRUE(valOrErr.isErr()); 289 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 290 } 291 } 292 293 TEST(ResultExtensions_ToResultInvokeMember, NoOutput) 294 { 295 TestClass foo; 296 297 // success 298 { 299 auto valOrErr = ToResultInvokeMember(foo, &TestClass::NonOverloadedNoOutput, 300 -TestClass::kTestValue); 301 static_assert(std::is_same_v<decltype(valOrErr), Result<Ok, nsresult>>); 302 ASSERT_TRUE(valOrErr.isOk()); 303 } 304 305 // failure 306 { 307 auto valOrErr = ToResultInvokeMember( 308 foo, &TestClass::NonOverloadedNoOutputFails, -TestClass::kTestValue); 309 static_assert(std::is_same_v<decltype(valOrErr), Result<Ok, nsresult>>); 310 ASSERT_TRUE(valOrErr.isErr()); 311 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 312 } 313 } 314 315 TEST(ResultExtensions_ToResultInvokeMember, NoInput_Macro) 316 { 317 TestClass foo; 318 319 // success 320 { 321 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInput); 322 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 323 ASSERT_TRUE(valOrErr.isOk()); 324 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 325 } 326 327 // failure 328 { 329 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInputFails); 330 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 331 ASSERT_TRUE(valOrErr.isErr()); 332 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 333 } 334 } 335 336 TEST(ResultExtensions_ToResultInvokeMember, NoInput_Const_Macro) 337 { 338 const TestClass foo; 339 340 // success 341 { 342 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInputConst); 343 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 344 ASSERT_TRUE(valOrErr.isOk()); 345 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 346 } 347 348 // failure 349 { 350 auto valOrErr = 351 MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInputFailsConst); 352 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 353 ASSERT_TRUE(valOrErr.isErr()); 354 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 355 } 356 } 357 358 TEST(ResultExtensions_ToResultInvokeMember, NoInput_Ref_Macro) 359 { 360 TestClass foo; 361 362 // success 363 { 364 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInputRef); 365 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 366 ASSERT_TRUE(valOrErr.isOk()); 367 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 368 } 369 370 // failure 371 { 372 auto valOrErr = 373 MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInputFailsRef); 374 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 375 ASSERT_TRUE(valOrErr.isErr()); 376 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 377 } 378 } 379 380 TEST(ResultExtensions_ToResultInvokeMember, NoInput_Complex_Macro) 381 { 382 TestClass foo; 383 384 // success 385 { 386 auto valOrErr = 387 MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInputComplex); 388 static_assert(std::is_same_v<decltype(valOrErr), 389 Result<std::pair<int, int>, nsresult>>); 390 ASSERT_TRUE(valOrErr.isOk()); 391 ASSERT_EQ((std::pair{TestClass::kTestValue, TestClass::kTestValue}), 392 valOrErr.unwrap()); 393 } 394 395 // failure 396 { 397 auto valOrErr = 398 MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInputFailsComplex); 399 400 static_assert(std::is_same_v<decltype(valOrErr), 401 Result<std::pair<int, int>, nsresult>>); 402 ASSERT_TRUE(valOrErr.isErr()); 403 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 404 } 405 } 406 407 TEST(ResultExtensions_ToResultInvokeMember, WithInput_Macro) 408 { 409 TestClass foo; 410 411 // success 412 { 413 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedWithInput, 414 -TestClass::kTestValue); 415 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 416 ASSERT_TRUE(valOrErr.isOk()); 417 ASSERT_EQ(-TestClass::kTestValue, valOrErr.unwrap()); 418 } 419 420 // failure 421 { 422 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER( 423 foo, NonOverloadedWithInputFails, -TestClass::kTestValue); 424 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 425 ASSERT_TRUE(valOrErr.isErr()); 426 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 427 } 428 } 429 430 TEST(ResultExtensions_ToResultInvokeMember, NoOutput_Macro) 431 { 432 TestClass foo; 433 434 // success 435 { 436 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoOutput, 437 -TestClass::kTestValue); 438 static_assert(std::is_same_v<decltype(valOrErr), Result<Ok, nsresult>>); 439 ASSERT_TRUE(valOrErr.isOk()); 440 } 441 442 // failure 443 { 444 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoOutputFails, 445 -TestClass::kTestValue); 446 static_assert(std::is_same_v<decltype(valOrErr), Result<Ok, nsresult>>); 447 ASSERT_TRUE(valOrErr.isErr()); 448 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 449 } 450 } 451 452 TEST(ResultExtensions_ToResultInvokeMember, NoInput_Complex_Macro_Typed) 453 { 454 TestClass foo; 455 456 // success 457 { 458 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER_TYPED( 459 (std::pair<int, int>), foo, NonOverloadedNoInputComplex); 460 static_assert(std::is_same_v<decltype(valOrErr), 461 Result<std::pair<int, int>, nsresult>>); 462 ASSERT_TRUE(valOrErr.isOk()); 463 ASSERT_EQ((std::pair{TestClass::kTestValue, TestClass::kTestValue}), 464 valOrErr.unwrap()); 465 } 466 467 // failure 468 { 469 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER_TYPED( 470 (std::pair<int, int>), foo, NonOverloadedNoInputFailsComplex); 471 static_assert(std::is_same_v<decltype(valOrErr), 472 Result<std::pair<int, int>, nsresult>>); 473 ASSERT_TRUE(valOrErr.isErr()); 474 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 475 } 476 } 477 478 TEST(ResultExtensions_ToResultInvokeMember, RefPtr_NoInput) 479 { 480 auto foo = MakeRefPtr<RefCountedTestClass>(); 481 482 // success 483 { 484 auto valOrErr = 485 ToResultInvokeMember(foo, &RefCountedTestClass::NonOverloadedNoInput); 486 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 487 ASSERT_TRUE(valOrErr.isOk()); 488 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 489 } 490 491 // failure 492 { 493 auto valOrErr = ToResultInvokeMember( 494 foo, &RefCountedTestClass::NonOverloadedNoInputFails); 495 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 496 ASSERT_TRUE(valOrErr.isErr()); 497 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 498 } 499 } 500 501 TEST(ResultExtensions_ToResultInvokeMember, RefPtr_NoInput_Macro) 502 { 503 auto foo = MakeRefPtr<RefCountedTestClass>(); 504 505 // success 506 { 507 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInput); 508 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 509 ASSERT_TRUE(valOrErr.isOk()); 510 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 511 } 512 513 // failure 514 { 515 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(foo, NonOverloadedNoInputFails); 516 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 517 ASSERT_TRUE(valOrErr.isErr()); 518 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 519 } 520 } 521 522 TEST(ResultExtensions_ToResultInvokeMember, RawPtr_NoInput_Macro) 523 { 524 auto foo = MakeRefPtr<RefCountedTestClass>(); 525 auto* fooPtr = foo.get(); 526 527 // success 528 { 529 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(fooPtr, NonOverloadedNoInput); 530 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 531 ASSERT_TRUE(valOrErr.isOk()); 532 ASSERT_EQ(TestClass::kTestValue, valOrErr.unwrap()); 533 } 534 535 // failure 536 { 537 auto valOrErr = 538 MOZ_TO_RESULT_INVOKE_MEMBER(fooPtr, NonOverloadedNoInputFails); 539 static_assert(std::is_same_v<decltype(valOrErr), Result<int, nsresult>>); 540 ASSERT_TRUE(valOrErr.isErr()); 541 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 542 } 543 } 544 545 TEST(ResultExtensions_ToResultInvokeMember, nsCOMPtr_AbstractClass_WithInput) 546 { 547 nsCOMPtr<nsIFile> file = MakeAndAddRef<nsLocalFile>(); 548 549 auto valOrErr = ToResultInvokeMember(file, &nsIFile::Equals, file); 550 static_assert(std::is_same_v<decltype(valOrErr), Result<bool, nsresult>>); 551 ASSERT_TRUE(valOrErr.isOk()); 552 ASSERT_EQ(true, valOrErr.unwrap()); 553 } 554 555 TEST(ResultExtensions_ToResultInvokeMember, 556 RawPtr_AbstractClass_WithInput_Macro) 557 { 558 nsCOMPtr<nsIFile> file = MakeAndAddRef<nsLocalFile>(); 559 auto* filePtr = file.get(); 560 561 auto valOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(filePtr, Equals, file); 562 static_assert(std::is_same_v<decltype(valOrErr), Result<bool, nsresult>>); 563 ASSERT_TRUE(valOrErr.isOk()); 564 ASSERT_EQ(true, valOrErr.unwrap()); 565 } 566 567 TEST(ResultExtensions_ToResultInvokeMember, 568 RawPtr_AbstractClass_NoInput_Macro_Typed) 569 { 570 nsCOMPtr<nsIFile> file = MakeAndAddRef<nsLocalFile>(); 571 auto* filePtr = file.get(); 572 573 auto valOrErr = 574 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsCOMPtr<nsIFile>, filePtr, Clone); 575 static_assert( 576 std::is_same_v<decltype(valOrErr), Result<nsCOMPtr<nsIFile>, nsresult>>); 577 ASSERT_TRUE(valOrErr.isOk()); 578 ASSERT_NE(nullptr, valOrErr.unwrap()); 579 }