Bug 1732219 - Add API for fetching the preview image. r=geckoview-reviewers,agi,mconley
[gecko.git] / mfbt / tests / TestResult.cpp
blobb66d3b608ed2c0f27d380833eb01149876ca8a43
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/. */
7 #include <string.h>
8 #include "mozilla/ResultVariant.h"
9 #include "mozilla/UniquePtr.h"
11 using mozilla::Err;
12 using mozilla::GenericErrorResult;
13 using mozilla::Ok;
14 using mozilla::Result;
15 using mozilla::UniquePtr;
17 #define MOZ_STATIC_AND_RELEASE_ASSERT(expr) \
18 static_assert(expr); \
19 MOZ_RELEASE_ASSERT(expr)
21 enum struct TestUnusedZeroEnum : int16_t { Ok = 0, NotOk = 1 };
23 namespace mozilla::detail {
24 template <>
25 struct UnusedZero<TestUnusedZeroEnum> : UnusedZeroEnum<TestUnusedZeroEnum> {};
26 } // namespace mozilla::detail
28 struct Failed {};
30 namespace mozilla::detail {
31 template <>
32 struct UnusedZero<Failed> {
33 using StorageType = uintptr_t;
35 static constexpr bool value = true;
36 static constexpr StorageType nullValue = 0;
37 static constexpr StorageType GetDefaultValue() { return 2; }
39 static constexpr void AssertValid(StorageType aValue) {}
40 static constexpr Failed Inspect(const StorageType& aValue) {
41 return Failed{};
43 static constexpr Failed Unwrap(StorageType aValue) { return Failed{}; }
44 static constexpr StorageType Store(Failed aValue) {
45 return GetDefaultValue();
49 } // namespace mozilla::detail
51 // V is trivially default-constructible, and E has UnusedZero<E>::value == true,
52 // for a reference type and for a non-reference type
53 static_assert(mozilla::detail::SelectResultImpl<uintptr_t, Failed>::value ==
54 mozilla::detail::PackingStrategy::NullIsOk);
55 static_assert(
56 mozilla::detail::SelectResultImpl<Ok, TestUnusedZeroEnum>::value ==
57 mozilla::detail::PackingStrategy::NullIsOk);
58 static_assert(mozilla::detail::SelectResultImpl<Ok, Failed>::value ==
59 mozilla::detail::PackingStrategy::LowBitTagIsError);
61 static_assert(std::is_trivially_destructible_v<Result<uintptr_t, Failed>>);
62 static_assert(std::is_trivially_destructible_v<Result<Ok, TestUnusedZeroEnum>>);
63 static_assert(std::is_trivially_destructible_v<Result<Ok, Failed>>);
65 static_assert(
66 sizeof(Result<bool, TestUnusedZeroEnum>) <= sizeof(uintptr_t),
67 "Result with bool value type should not be larger than pointer-sized");
68 static_assert(sizeof(Result<Ok, Failed>) == sizeof(uint8_t),
69 "Result with empty value type should be size 1");
70 static_assert(sizeof(Result<int*, Failed>) == sizeof(uintptr_t),
71 "Result with two aligned pointer types should be pointer-sized");
72 static_assert(
73 sizeof(Result<char*, Failed*>) > sizeof(char*),
74 "Result with unaligned success type `char*` must not be pointer-sized");
75 static_assert(
76 sizeof(Result<int*, char*>) > sizeof(char*),
77 "Result with unaligned error type `char*` must not be pointer-sized");
79 enum Foo8 : uint8_t {};
80 enum Foo16 : uint16_t {};
81 enum Foo32 : uint32_t {};
82 static_assert(sizeof(Result<Ok, Foo8>) <= sizeof(uintptr_t),
83 "Result with small types should be pointer-sized");
84 static_assert(sizeof(Result<Ok, Foo16>) <= sizeof(uintptr_t),
85 "Result with small types should be pointer-sized");
86 static_assert(sizeof(Foo32) >= sizeof(uintptr_t) ||
87 sizeof(Result<Ok, Foo32>) <= sizeof(uintptr_t),
88 "Result with small types should be pointer-sized");
90 static_assert(sizeof(Result<Foo16, Foo8>) <= sizeof(uintptr_t),
91 "Result with small types should be pointer-sized");
92 static_assert(sizeof(Result<Foo8, Foo16>) <= sizeof(uintptr_t),
93 "Result with small types should be pointer-sized");
94 static_assert(sizeof(Foo32) >= sizeof(uintptr_t) ||
95 sizeof(Result<Foo32, Foo16>) <= sizeof(uintptr_t),
96 "Result with small types should be pointer-sized");
97 static_assert(sizeof(Foo32) >= sizeof(uintptr_t) ||
98 sizeof(Result<Foo16, Foo32>) <= sizeof(uintptr_t),
99 "Result with small types should be pointer-sized");
101 static_assert(std::is_literal_type_v<Result<int*, Failed>>);
102 static_assert(std::is_literal_type_v<Result<Ok, Failed>>);
103 static_assert(std::is_literal_type_v<Result<Ok, Foo8>>);
104 static_assert(std::is_literal_type_v<Result<Foo8, Foo16>>);
105 static_assert(!std::is_literal_type_v<Result<Ok, UniquePtr<int>>>);
107 static constexpr GenericErrorResult<Failed> Fail() { return Err(Failed{}); }
109 static constexpr GenericErrorResult<TestUnusedZeroEnum>
110 FailTestUnusedZeroEnum() {
111 return Err(TestUnusedZeroEnum::NotOk);
114 static constexpr Result<Ok, Failed> Task1(bool pass) {
115 if (!pass) {
116 return Fail(); // implicit conversion from GenericErrorResult to Result
118 return Ok();
121 static constexpr Result<Ok, TestUnusedZeroEnum> Task1UnusedZeroEnumErr(
122 bool pass) {
123 if (!pass) {
124 return FailTestUnusedZeroEnum(); // implicit conversion from
125 // GenericErrorResult to Result
127 return Ok();
130 static constexpr Result<int, Failed> Task2(bool pass, int value) {
131 MOZ_TRY(
132 Task1(pass)); // converts one type of result to another in the error case
133 return value; // implicit conversion from T to Result<T, E>
136 static constexpr Result<int, TestUnusedZeroEnum> Task2UnusedZeroEnumErr(
137 bool pass, int value) {
138 MOZ_TRY(Task1UnusedZeroEnumErr(
139 pass)); // converts one type of result to another in the error case
140 return value; // implicit conversion from T to Result<T, E>
143 static Result<int, Failed> Task3(bool pass1, bool pass2, int value) {
144 int x, y;
145 MOZ_TRY_VAR(x, Task2(pass1, value));
146 MOZ_TRY_VAR(y, Task2(pass2, value));
147 return x + y;
150 static void BasicTests() {
151 MOZ_STATIC_AND_RELEASE_ASSERT(Task1(true).isOk());
152 MOZ_STATIC_AND_RELEASE_ASSERT(!Task1(true).isErr());
153 MOZ_STATIC_AND_RELEASE_ASSERT(!Task1(false).isOk());
154 MOZ_STATIC_AND_RELEASE_ASSERT(Task1(false).isErr());
156 MOZ_STATIC_AND_RELEASE_ASSERT(Task1UnusedZeroEnumErr(true).isOk());
157 MOZ_STATIC_AND_RELEASE_ASSERT(!Task1UnusedZeroEnumErr(true).isErr());
158 MOZ_STATIC_AND_RELEASE_ASSERT(!Task1UnusedZeroEnumErr(false).isOk());
159 MOZ_STATIC_AND_RELEASE_ASSERT(Task1UnusedZeroEnumErr(false).isErr());
160 MOZ_STATIC_AND_RELEASE_ASSERT(TestUnusedZeroEnum::NotOk ==
161 Task1UnusedZeroEnumErr(false).inspectErr());
162 MOZ_STATIC_AND_RELEASE_ASSERT(TestUnusedZeroEnum::NotOk ==
163 Task1UnusedZeroEnumErr(false).unwrapErr());
165 // MOZ_TRY works.
166 MOZ_STATIC_AND_RELEASE_ASSERT(Task2(true, 3).isOk());
167 MOZ_STATIC_AND_RELEASE_ASSERT(Task2(true, 3).unwrap() == 3);
168 MOZ_STATIC_AND_RELEASE_ASSERT(Task2(true, 3).unwrapOr(6) == 3);
169 MOZ_RELEASE_ASSERT(Task2(false, 3).isErr());
170 MOZ_RELEASE_ASSERT(Task2(false, 3).unwrapOr(6) == 6);
172 MOZ_STATIC_AND_RELEASE_ASSERT(Task2UnusedZeroEnumErr(true, 3).isOk());
173 MOZ_STATIC_AND_RELEASE_ASSERT(Task2UnusedZeroEnumErr(true, 3).unwrap() == 3);
174 MOZ_STATIC_AND_RELEASE_ASSERT(Task2UnusedZeroEnumErr(true, 3).unwrapOr(6) ==
176 MOZ_STATIC_AND_RELEASE_ASSERT(Task2UnusedZeroEnumErr(false, 3).isErr());
177 MOZ_STATIC_AND_RELEASE_ASSERT(Task2UnusedZeroEnumErr(false, 3).unwrapOr(6) ==
180 // MOZ_TRY_VAR works.
181 MOZ_RELEASE_ASSERT(Task3(true, true, 3).isOk());
182 MOZ_RELEASE_ASSERT(Task3(true, true, 3).unwrap() == 6);
183 MOZ_RELEASE_ASSERT(Task3(true, false, 3).isErr());
184 MOZ_RELEASE_ASSERT(Task3(false, true, 3).isErr());
185 MOZ_RELEASE_ASSERT(Task3(false, true, 3).unwrapOr(6) == 6);
187 // Lvalues should work too.
189 constexpr Result<Ok, Failed> res1 = Task1(true);
190 MOZ_STATIC_AND_RELEASE_ASSERT(res1.isOk());
191 MOZ_STATIC_AND_RELEASE_ASSERT(!res1.isErr());
193 constexpr Result<Ok, Failed> res2 = Task1(false);
194 MOZ_STATIC_AND_RELEASE_ASSERT(!res2.isOk());
195 MOZ_STATIC_AND_RELEASE_ASSERT(res2.isErr());
199 Result<int, Failed> res = Task2(true, 3);
200 MOZ_RELEASE_ASSERT(res.isOk());
201 MOZ_RELEASE_ASSERT(res.unwrap() == 3);
203 res = Task2(false, 4);
204 MOZ_RELEASE_ASSERT(res.isErr());
207 // Some tests for pointer tagging.
209 int i = 123;
211 Result<int*, Failed> res = &i;
212 static_assert(sizeof(res) == sizeof(uintptr_t),
213 "should use pointer tagging to fit in a word");
215 MOZ_RELEASE_ASSERT(res.isOk());
216 MOZ_RELEASE_ASSERT(*res.unwrap() == 123);
218 res = Err(Failed());
219 MOZ_RELEASE_ASSERT(res.isErr());
223 struct NonCopyableNonMovable {
224 explicit constexpr NonCopyableNonMovable(uint32_t aValue) : mValue(aValue) {}
226 NonCopyableNonMovable(const NonCopyableNonMovable&) = delete;
227 NonCopyableNonMovable(NonCopyableNonMovable&&) = delete;
228 NonCopyableNonMovable& operator=(const NonCopyableNonMovable&) = delete;
229 NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete;
231 uint32_t mValue;
234 static void InPlaceConstructionTests() {
236 // PackingStrategy == NullIsOk
237 static_assert(mozilla::detail::SelectResultImpl<NonCopyableNonMovable,
238 Failed>::value ==
239 mozilla::detail::PackingStrategy::NullIsOk);
240 constexpr Result<NonCopyableNonMovable, Failed> result{std::in_place, 42u};
241 MOZ_STATIC_AND_RELEASE_ASSERT(42 == result.inspect().mValue);
245 // PackingStrategy == Variant
246 static_assert(
247 mozilla::detail::SelectResultImpl<NonCopyableNonMovable, int>::value ==
248 mozilla::detail::PackingStrategy::Variant);
249 const Result<NonCopyableNonMovable, int> result{std::in_place, 42};
250 MOZ_RELEASE_ASSERT(42 == result.inspect().mValue);
254 /* * */
256 struct Snafu : Failed {};
258 static Result<Ok, Snafu*> Explode() {
259 static Snafu snafu;
260 return Err(&snafu);
263 static Result<Ok, Failed*> ErrorGeneralization() {
264 MOZ_TRY(Explode()); // change error type from Snafu* to more general Failed*
265 return Ok();
268 static void TypeConversionTests() {
269 MOZ_RELEASE_ASSERT(ErrorGeneralization().isErr());
272 const Result<Ok, Failed*> res = Explode();
273 MOZ_RELEASE_ASSERT(res.isErr());
277 const Result<Ok, Failed*> res = Result<Ok, Snafu*>{Ok{}};
278 MOZ_RELEASE_ASSERT(res.isOk());
282 static void EmptyValueTest() {
283 struct Fine {};
284 mozilla::Result<Fine, Failed> res((Fine()));
285 res.unwrap();
286 MOZ_RELEASE_ASSERT(res.isOk());
287 static_assert(sizeof(res) == sizeof(uint8_t),
288 "Result with empty value and error types should be size 1");
291 static void MapTest() {
292 struct MyError {
293 int x;
295 explicit MyError(int y) : x(y) {}
298 // Mapping over success values, to the same success type.
300 Result<int, MyError> res(5);
301 bool invoked = false;
302 auto res2 = res.map([&invoked](int x) {
303 MOZ_RELEASE_ASSERT(x == 5);
304 invoked = true;
305 return 6;
307 MOZ_RELEASE_ASSERT(res2.isOk());
308 MOZ_RELEASE_ASSERT(invoked);
309 MOZ_RELEASE_ASSERT(res2.unwrap() == 6);
312 // Mapping over success values, to a different success type.
314 Result<int, MyError> res(5);
315 bool invoked = false;
316 auto res2 = res.map([&invoked](int x) {
317 MOZ_RELEASE_ASSERT(x == 5);
318 invoked = true;
319 return "hello";
321 MOZ_RELEASE_ASSERT(res2.isOk());
322 MOZ_RELEASE_ASSERT(invoked);
323 MOZ_RELEASE_ASSERT(strcmp(res2.unwrap(), "hello") == 0);
326 // Mapping over success values (constexpr).
328 constexpr uint64_t kValue = 42u;
329 constexpr auto res2a = Result<int32_t, Failed>{5}.map([](int32_t x) {
330 MOZ_RELEASE_ASSERT(x == 5);
331 return kValue;
333 MOZ_STATIC_AND_RELEASE_ASSERT(res2a.isOk());
334 MOZ_STATIC_AND_RELEASE_ASSERT(kValue == res2a.inspect());
337 // Mapping over error values.
339 MyError err(1);
340 Result<char, MyError> res(err);
341 MOZ_RELEASE_ASSERT(res.isErr());
342 Result<char, MyError> res2 = res.map([](int x) {
343 MOZ_RELEASE_ASSERT(false);
344 return 'a';
346 MOZ_RELEASE_ASSERT(res2.isErr());
347 MOZ_RELEASE_ASSERT(res2.unwrapErr().x == err.x);
350 // Function pointers instead of lambdas as the mapping function.
352 Result<const char*, MyError> res("hello");
353 auto res2 = res.map(strlen);
354 MOZ_RELEASE_ASSERT(res2.isOk());
355 MOZ_RELEASE_ASSERT(res2.unwrap() == 5);
359 static void MapErrTest() {
360 struct MyError {
361 int x;
363 explicit MyError(int y) : x(y) {}
366 struct MyError2 {
367 int a;
369 explicit MyError2(int b) : a(b) {}
372 // Mapping over error values, to the same error type.
374 MyError err(1);
375 Result<char, MyError> res(err);
376 MOZ_RELEASE_ASSERT(res.isErr());
377 bool invoked = false;
378 auto res2 = res.mapErr([&invoked](const auto err) {
379 MOZ_RELEASE_ASSERT(err.x == 1);
380 invoked = true;
381 return MyError(2);
383 MOZ_RELEASE_ASSERT(res2.isErr());
384 MOZ_RELEASE_ASSERT(invoked);
385 MOZ_RELEASE_ASSERT(res2.unwrapErr().x == 2);
388 // Mapping over error values, to a different error type.
390 MyError err(1);
391 Result<char, MyError> res(err);
392 MOZ_RELEASE_ASSERT(res.isErr());
393 bool invoked = false;
394 auto res2 = res.mapErr([&invoked](const auto err) {
395 MOZ_RELEASE_ASSERT(err.x == 1);
396 invoked = true;
397 return MyError2(2);
399 MOZ_RELEASE_ASSERT(res2.isErr());
400 MOZ_RELEASE_ASSERT(invoked);
401 MOZ_RELEASE_ASSERT(res2.unwrapErr().a == 2);
404 // Mapping over success values.
406 Result<int, MyError> res(5);
407 auto res2 = res.mapErr([](const auto err) {
408 MOZ_RELEASE_ASSERT(false);
409 return MyError(1);
411 MOZ_RELEASE_ASSERT(res2.isOk());
412 MOZ_RELEASE_ASSERT(res2.unwrap() == 5);
415 // Function pointers instead of lambdas as the mapping function.
417 Result<Ok, const char*> res("hello");
418 auto res2 = res.mapErr(strlen);
419 MOZ_RELEASE_ASSERT(res2.isErr());
420 MOZ_RELEASE_ASSERT(res2.unwrapErr() == 5);
424 static Result<Ok, size_t> strlen_ResultWrapper(const char* aValue) {
425 return Err(strlen(aValue));
428 static void OrElseTest() {
429 struct MyError {
430 int x;
432 explicit constexpr MyError(int y) : x(y) {}
435 struct MyError2 {
436 int a;
438 explicit constexpr MyError2(int b) : a(b) {}
441 // `orElse`ing over error values, to Result<V, E> (the same error type) error
442 // variant.
444 MyError err(1);
445 Result<char, MyError> res(err);
446 MOZ_RELEASE_ASSERT(res.isErr());
447 bool invoked = false;
448 auto res2 = res.orElse([&invoked](const auto err) -> Result<char, MyError> {
449 MOZ_RELEASE_ASSERT(err.x == 1);
450 invoked = true;
451 if (err.x != 42) {
452 return Err(MyError(2));
454 return 'a';
456 MOZ_RELEASE_ASSERT(res2.isErr());
457 MOZ_RELEASE_ASSERT(invoked);
458 MOZ_RELEASE_ASSERT(res2.unwrapErr().x == 2);
461 // `orElse`ing over error values, to Result<V, E> (the same error type)
462 // success variant.
464 MyError err(42);
465 Result<char, MyError> res(err);
466 MOZ_RELEASE_ASSERT(res.isErr());
467 bool invoked = false;
468 auto res2 = res.orElse([&invoked](const auto err) -> Result<char, MyError> {
469 MOZ_RELEASE_ASSERT(err.x == 42);
470 invoked = true;
471 if (err.x != 42) {
472 return Err(MyError(2));
474 return 'a';
476 MOZ_RELEASE_ASSERT(res2.isOk());
477 MOZ_RELEASE_ASSERT(invoked);
478 MOZ_RELEASE_ASSERT(res2.unwrap() == 'a');
481 // `orElse`ing over error values, to Result<V, E2> (a different error type)
482 // error variant.
484 MyError err(1);
485 Result<char, MyError> res(err);
486 MOZ_RELEASE_ASSERT(res.isErr());
487 bool invoked = false;
488 auto res2 =
489 res.orElse([&invoked](const auto err) -> Result<char, MyError2> {
490 MOZ_RELEASE_ASSERT(err.x == 1);
491 invoked = true;
492 if (err.x != 42) {
493 return Err(MyError2(2));
495 return 'a';
497 MOZ_RELEASE_ASSERT(res2.isErr());
498 MOZ_RELEASE_ASSERT(invoked);
499 MOZ_RELEASE_ASSERT(res2.unwrapErr().a == 2);
502 // `orElse`ing over error values, to Result<V, E2> (a different error type)
503 // success variant.
505 MyError err(42);
506 Result<char, MyError> res(err);
507 MOZ_RELEASE_ASSERT(res.isErr());
508 bool invoked = false;
509 auto res2 =
510 res.orElse([&invoked](const auto err) -> Result<char, MyError2> {
511 MOZ_RELEASE_ASSERT(err.x == 42);
512 invoked = true;
513 if (err.x != 42) {
514 return Err(MyError2(2));
516 return 'a';
518 MOZ_RELEASE_ASSERT(res2.isOk());
519 MOZ_RELEASE_ASSERT(invoked);
520 MOZ_RELEASE_ASSERT(res2.unwrap() == 'a');
523 // `orElse`ing over success values.
525 Result<int, MyError> res(5);
526 auto res2 = res.orElse([](const auto err) -> Result<int, MyError> {
527 MOZ_RELEASE_ASSERT(false);
528 return Err(MyError(1));
530 MOZ_RELEASE_ASSERT(res2.isOk());
531 MOZ_RELEASE_ASSERT(res2.unwrap() == 5);
534 // Function pointers instead of lambdas as the `orElse`ing function.
536 Result<Ok, const char*> res("hello");
537 auto res2 = res.orElse(strlen_ResultWrapper);
538 MOZ_RELEASE_ASSERT(res2.isErr());
539 MOZ_RELEASE_ASSERT(res2.unwrapErr() == 5);
543 static void AndThenTest() {
544 // `andThen`ing over success results.
546 Result<int, const char*> r1(10);
547 Result<int, const char*> r2 =
548 r1.andThen([](int x) { return Result<int, const char*>(x + 1); });
549 MOZ_RELEASE_ASSERT(r2.isOk());
550 MOZ_RELEASE_ASSERT(r2.unwrap() == 11);
553 // `andThen`ing over success results (constexpr).
555 constexpr Result<int, Failed> r2a = Result<int, Failed>{10}.andThen(
556 [](int x) { return Result<int, Failed>(x + 1); });
557 MOZ_STATIC_AND_RELEASE_ASSERT(r2a.isOk());
558 MOZ_STATIC_AND_RELEASE_ASSERT(r2a.inspect() == 11);
561 // `andThen`ing over error results.
563 Result<int, const char*> r3("error");
564 Result<int, const char*> r4 = r3.andThen([](int x) {
565 MOZ_RELEASE_ASSERT(false);
566 return Result<int, const char*>(1);
568 MOZ_RELEASE_ASSERT(r4.isErr());
569 MOZ_RELEASE_ASSERT(r3.unwrapErr() == r4.unwrapErr());
572 // andThen with a function accepting an rvalue
574 Result<int, const char*> r1(10);
575 Result<int, const char*> r2 =
576 r1.andThen([](int&& x) { return Result<int, const char*>(x + 1); });
577 MOZ_RELEASE_ASSERT(r2.isOk());
578 MOZ_RELEASE_ASSERT(r2.unwrap() == 11);
581 // `andThen`ing over error results (constexpr).
583 constexpr Result<int, Failed> r4a =
584 Result<int, Failed>{Failed{}}.andThen([](int x) {
585 MOZ_RELEASE_ASSERT(false);
586 return Result<int, Failed>(1);
588 MOZ_STATIC_AND_RELEASE_ASSERT(r4a.isErr());
592 using UniqueResult = Result<UniquePtr<int>, const char*>;
594 static UniqueResult UniqueTask() { return mozilla::MakeUnique<int>(3); }
595 static UniqueResult UniqueTaskError() { return Err("bad"); }
597 using UniqueErrorResult = Result<int, UniquePtr<int>>;
598 static UniqueErrorResult UniqueError() {
599 return Err(mozilla::MakeUnique<int>(4));
602 static Result<Ok, UniquePtr<int>> TryUniqueErrorResult() {
603 MOZ_TRY(UniqueError());
604 return Ok();
607 static void UniquePtrTest() {
609 auto result = UniqueTask();
610 MOZ_RELEASE_ASSERT(result.isOk());
611 auto ptr = result.unwrap();
612 MOZ_RELEASE_ASSERT(ptr);
613 MOZ_RELEASE_ASSERT(*ptr == 3);
614 auto moved = result.unwrap();
615 MOZ_RELEASE_ASSERT(!moved);
619 auto err = UniqueTaskError();
620 MOZ_RELEASE_ASSERT(err.isErr());
621 auto ptr = err.unwrapOr(mozilla::MakeUnique<int>(4));
622 MOZ_RELEASE_ASSERT(ptr);
623 MOZ_RELEASE_ASSERT(*ptr == 4);
627 auto result = UniqueTaskError();
628 result = UniqueResult(mozilla::MakeUnique<int>(6));
629 MOZ_RELEASE_ASSERT(result.isOk());
630 MOZ_RELEASE_ASSERT(result.inspect() && *result.inspect() == 6);
634 auto result = UniqueError();
635 MOZ_RELEASE_ASSERT(result.isErr());
636 MOZ_RELEASE_ASSERT(result.inspectErr());
637 MOZ_RELEASE_ASSERT(*result.inspectErr() == 4);
638 auto err = result.unwrapErr();
639 MOZ_RELEASE_ASSERT(!result.inspectErr());
640 MOZ_RELEASE_ASSERT(err);
641 MOZ_RELEASE_ASSERT(*err == 4);
643 result = UniqueErrorResult(0);
644 MOZ_RELEASE_ASSERT(result.isOk() && result.unwrap() == 0);
648 auto result = TryUniqueErrorResult();
649 MOZ_RELEASE_ASSERT(result.isErr());
650 auto err = result.unwrapErr();
651 MOZ_RELEASE_ASSERT(err && *err == 4);
652 MOZ_RELEASE_ASSERT(!result.inspectErr());
656 /* * */
658 int main() {
659 BasicTests();
660 InPlaceConstructionTests();
661 TypeConversionTests();
662 EmptyValueTest();
663 MapTest();
664 MapErrTest();
665 OrElseTest();
666 AndThenTest();
667 UniquePtrTest();
668 return 0;