ExpectedCoroutinesTest.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Copyright 2017-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/Expected.h>
  17. #include <folly/Portability.h>
  18. #include <folly/ScopeGuard.h>
  19. #include <folly/portability/GTest.h>
  20. using namespace folly;
  21. namespace {
  22. struct Exn {};
  23. // not default-constructible, thereby preventing Expected<T, Err> from being
  24. // default-constructible, forcing our implementation to handle such cases
  25. class Err {
  26. private:
  27. enum class Type { Bad, Badder, Baddest };
  28. Type type_;
  29. constexpr Err(Type type) : type_(type) {}
  30. public:
  31. Err(Err const&) = default;
  32. Err(Err&&) = default;
  33. Err& operator=(Err const&) = default;
  34. Err& operator=(Err&&) = default;
  35. friend bool operator==(Err a, Err b) {
  36. return a.type_ == b.type_;
  37. }
  38. friend bool operator!=(Err a, Err b) {
  39. return a.type_ != b.type_;
  40. }
  41. static constexpr Err bad() {
  42. return Type::Bad;
  43. }
  44. static constexpr Err badder() {
  45. return Type::Badder;
  46. }
  47. static constexpr Err baddest() {
  48. return Type::Baddest;
  49. }
  50. };
  51. Expected<int, Err> f1() {
  52. return 7;
  53. }
  54. Expected<double, Err> f2(int x) {
  55. return 2.0 * x;
  56. }
  57. // move-only type
  58. Expected<std::unique_ptr<int>, Err> f3(int x, double y) {
  59. return std::make_unique<int>(int(x + y));
  60. }
  61. // error result
  62. Expected<int, Err> f4(int, double, Err err) {
  63. return makeUnexpected(err);
  64. }
  65. // exception
  66. Expected<int, Err> throws() {
  67. throw Exn{};
  68. }
  69. } // namespace
  70. #if FOLLY_HAS_COROUTINES
  71. TEST(Expected, CoroutineSuccess) {
  72. auto r0 = []() -> Expected<int, Err> {
  73. auto x = co_await f1();
  74. EXPECT_EQ(7, x);
  75. auto y = co_await f2(x);
  76. EXPECT_EQ(2.0 * 7, y);
  77. auto z = co_await f3(x, y);
  78. EXPECT_EQ(int(2.0 * 7 + 7), *z);
  79. co_return* z;
  80. }();
  81. EXPECT_TRUE(r0.hasValue());
  82. EXPECT_EQ(21, *r0);
  83. }
  84. TEST(Expected, CoroutineFailure) {
  85. auto r1 = []() -> Expected<int, Err> {
  86. auto x = co_await f1();
  87. auto y = co_await f2(x);
  88. auto z = co_await f4(x, y, Err::badder());
  89. ADD_FAILURE();
  90. co_return z;
  91. }();
  92. EXPECT_TRUE(r1.hasError());
  93. EXPECT_EQ(Err::badder(), r1.error());
  94. }
  95. TEST(Expected, CoroutineException) {
  96. EXPECT_THROW(
  97. ([]() -> Expected<int, Err> {
  98. auto x = co_await throws();
  99. ADD_FAILURE();
  100. co_return x;
  101. }()),
  102. Exn);
  103. }
  104. // this test makes sure that the coroutine is destroyed properly
  105. TEST(Expected, CoroutineCleanedUp) {
  106. int count_dest = 0;
  107. auto r = [&]() -> Expected<int, Err> {
  108. SCOPE_EXIT {
  109. ++count_dest;
  110. };
  111. auto x = co_await Expected<int, Err>(makeUnexpected(Err::badder()));
  112. ADD_FAILURE() << "Should not be resuming";
  113. co_return x;
  114. }();
  115. EXPECT_FALSE(r.hasValue());
  116. EXPECT_EQ(1, count_dest);
  117. }
  118. #endif