• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/core/lib/promise/try_seq.h"
16 
17 #include <stdlib.h>
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "gtest/gtest.h"
24 #include "test/core/promise/poll_matcher.h"
25 
26 namespace grpc_core {
27 
28 struct AbslStatusTraits {
29   template <typename T>
30   using Promise = std::function<Poll<absl::StatusOr<T>>()>;
31 
32   template <typename T>
instant_okgrpc_core::AbslStatusTraits33   static Promise<T> instant_ok(T x) {
34     return [x] { return absl::StatusOr<T>(x); };
35   }
36 
instant_ok_statusgrpc_core::AbslStatusTraits37   static auto instant_ok_status() {
38     return [] { return absl::OkStatus(); };
39   }
40 
41   template <typename T>
instant_failgrpc_core::AbslStatusTraits42   static Promise<T> instant_fail() {
43     return [] { return absl::StatusOr<T>(); };
44   }
45 
46   template <typename T>
instant_crashgrpc_core::AbslStatusTraits47   static Poll<absl::StatusOr<T>> instant_crash() {
48     abort();
49   }
50 
51   template <typename T>
okgrpc_core::AbslStatusTraits52   static Poll<absl::StatusOr<T>> ok(T x) {
53     return absl::StatusOr<T>(x);
54   }
55 
ok_statusgrpc_core::AbslStatusTraits56   static Poll<absl::Status> ok_status() { return absl::OkStatus(); }
57 
58   template <typename T>
failgrpc_core::AbslStatusTraits59   static Poll<absl::StatusOr<T>> fail() {
60     return absl::StatusOr<T>();
61   }
62 
63   template <typename T>
pendinggrpc_core::AbslStatusTraits64   static Promise<T> pending() {
65     return []() -> Poll<absl::StatusOr<T>> { return Pending(); };
66   }
67 };
68 
69 struct ValueOrFailureTraits {
70   template <typename T>
71   using Promise = std::function<Poll<ValueOrFailure<T>>()>;
72 
73   template <typename T>
instant_okgrpc_core::ValueOrFailureTraits74   static Promise<T> instant_ok(T x) {
75     return [x] { return ValueOrFailure<T>(x); };
76   }
77 
instant_ok_statusgrpc_core::ValueOrFailureTraits78   static auto instant_ok_status() {
79     return [] { return StatusFlag(true); };
80   }
81 
82   template <typename T>
instant_failgrpc_core::ValueOrFailureTraits83   static Promise<T> instant_fail() {
84     return [] { return Failure{}; };
85   }
86 
87   template <typename T>
instant_crashgrpc_core::ValueOrFailureTraits88   static Poll<ValueOrFailure<T>> instant_crash() {
89     abort();
90   }
91 
92   template <typename T>
okgrpc_core::ValueOrFailureTraits93   static Poll<ValueOrFailure<T>> ok(T x) {
94     return ValueOrFailure<T>(x);
95   }
96 
ok_statusgrpc_core::ValueOrFailureTraits97   static Poll<StatusFlag> ok_status() { return Success{}; }
98 
99   template <typename T>
failgrpc_core::ValueOrFailureTraits100   static Poll<ValueOrFailure<T>> fail() {
101     return Failure{};
102   }
103 
104   template <typename T>
pendinggrpc_core::ValueOrFailureTraits105   static Promise<T> pending() {
106     return []() -> Poll<ValueOrFailure<T>> { return Pending(); };
107   }
108 };
109 
110 template <typename T>
111 class TrySeqTest : public ::testing::Test {};
112 
113 using Traits = ::testing::Types<AbslStatusTraits, ValueOrFailureTraits>;
114 TYPED_TEST_SUITE(TrySeqTest, Traits);
115 
TYPED_TEST(TrySeqTest,SucceedAndThen)116 TYPED_TEST(TrySeqTest, SucceedAndThen) {
117   EXPECT_EQ(TrySeq(TypeParam::instant_ok(1),
118                    [](int i) { return TypeParam::instant_ok(i + 1); })(),
119             TypeParam::ok(2));
120 }
121 
TYPED_TEST(TrySeqTest,SucceedDirectlyAndThenDirectly)122 TYPED_TEST(TrySeqTest, SucceedDirectlyAndThenDirectly) {
123   EXPECT_EQ(
124       TrySeq([] { return 1; }, [](int i) { return [i]() { return i + 1; }; })(),
125       Poll<absl::StatusOr<int>>(2));
126 }
127 
TYPED_TEST(TrySeqTest,SucceedAndThenChangeType)128 TYPED_TEST(TrySeqTest, SucceedAndThenChangeType) {
129   EXPECT_EQ(
130       TrySeq(TypeParam::instant_ok(42),
131              [](int i) { return TypeParam::instant_ok(std::to_string(i)); })(),
132       TypeParam::ok(std::string("42")));
133 }
134 
TYPED_TEST(TrySeqTest,FailAndThen)135 TYPED_TEST(TrySeqTest, FailAndThen) {
136   EXPECT_EQ(
137       TrySeq(TypeParam::template instant_fail<int>(),
138              [](int) { return TypeParam::template instant_crash<double>(); })(),
139       TypeParam::template fail<double>());
140 }
141 
TYPED_TEST(TrySeqTest,RawSucceedAndThen)142 TYPED_TEST(TrySeqTest, RawSucceedAndThen) {
143   EXPECT_EQ(TrySeq(TypeParam::instant_ok_status(),
144                    [] { return TypeParam::instant_ok_status(); })(),
145             TypeParam::ok_status());
146 }
147 
TYPED_TEST(TrySeqTest,RawFailAndThen)148 TYPED_TEST(TrySeqTest, RawFailAndThen) {
149   EXPECT_EQ(TrySeq([] { return absl::CancelledError(); },
150                    []() { return []() -> Poll<absl::Status> { abort(); }; })(),
151             Poll<absl::Status>(absl::CancelledError()));
152 }
153 
TYPED_TEST(TrySeqTest,RawSucceedAndThenValue)154 TYPED_TEST(TrySeqTest, RawSucceedAndThenValue) {
155   EXPECT_EQ(TrySeq([] { return absl::OkStatus(); },
156                    [] { return []() { return absl::StatusOr<int>(42); }; })(),
157             Poll<absl::StatusOr<int>>(absl::StatusOr<int>(42)));
158 }
159 
TEST(TrySeqIterTest,Ok)160 TEST(TrySeqIterTest, Ok) {
161   std::vector<int> v{1, 2, 3, 4, 5};
162   EXPECT_EQ(TrySeqIter(v.begin(), v.end(), 0,
163                        [](int elem, int accum) {
164                          return [elem, accum]() -> absl::StatusOr<int> {
165                            return elem + accum;
166                          };
167                        })(),
168             Poll<absl::StatusOr<int>>(15));
169 }
170 
TEST(TrySeqIterTest,ErrorAt3)171 TEST(TrySeqIterTest, ErrorAt3) {
172   std::vector<int> v{1, 2, 3, 4, 5};
173   EXPECT_EQ(TrySeqIter(v.begin(), v.end(), 0,
174                        [](int elem, int accum) {
175                          return [elem, accum]() -> absl::StatusOr<int> {
176                            if (elem < 3) {
177                              return elem + accum;
178                            }
179                            if (elem == 3) {
180                              return absl::CancelledError();
181                            }
182                            abort();  // unreachable
183                          };
184                        })(),
185             Poll<absl::StatusOr<int>>(absl::CancelledError()));
186 }
187 
TEST(TrySeqContainer,Ok)188 TEST(TrySeqContainer, Ok) {
189   std::vector<std::unique_ptr<int>> v;
190   v.emplace_back(std::make_unique<int>(1));
191   v.emplace_back(std::make_unique<int>(2));
192   v.emplace_back(std::make_unique<int>(3));
193   int expect = 1;
194   auto p = TrySeqContainer(std::move(v), Empty{},
195                            [&expect](const std::unique_ptr<int>& i, Empty) {
196                              EXPECT_EQ(*i, expect);
197                              ++expect;
198                            });
199   EXPECT_THAT(p(), IsReady());
200   EXPECT_EQ(expect, 4);
201 }
202 
203 }  // namespace grpc_core
204 
main(int argc,char ** argv)205 int main(int argc, char** argv) {
206   ::testing::InitGoogleTest(&argc, argv);
207   return RUN_ALL_TESTS();
208 }
209