• 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/seq.h"
16 
17 #include <memory>
18 #include <string>
19 #include <vector>
20 
21 #include "absl/strings/str_cat.h"
22 #include "gtest/gtest.h"
23 
24 namespace grpc_core {
25 
TEST(SeqTest,Immediate)26 TEST(SeqTest, Immediate) {
27   std::string execution_order;
28   Poll<int> result = Seq([&execution_order] {
29     absl::StrAppend(&execution_order, "1");
30     return 100;
31   })();
32   EXPECT_EQ(result, Poll<int>(100));
33   EXPECT_STREQ(execution_order.c_str(), "1");
34 }
35 
TEST(SeqTest,OneThen)36 TEST(SeqTest, OneThen) {
37   std::string execution_order;
38   auto initial = [&execution_order,
39                   test_destructor_invocation1 =
40                       std::make_unique<int>(1)]() -> Poll<std::string> {
41     absl::StrAppend(&execution_order, "1");
42     return "Hello";
43   };
44   auto then = [&execution_order,
45                test_destructor_invocation2 =
46                    std::make_unique<int>(2)](std::string initial_output) {
47     absl::StrAppend(&execution_order, "2");
48     return [test_destructor_invocation3 = std::make_unique<int>(3),
49             &execution_order, initial_output]() -> Poll<int> {
50       absl::StrAppend(&execution_order, "3");
51       return initial_output.length() + 4;
52     };
53   };
54   auto result = Seq(std::move(initial), std::move(then))();
55   EXPECT_TRUE(result.ready());
56   EXPECT_EQ(result.value(), 9);
57   EXPECT_STREQ(execution_order.c_str(), "123");
58 }
59 
TEST(SeqTest,TestPending)60 TEST(SeqTest, TestPending) {
61   std::string execution_order;
62   bool return_pending = true;
63   auto initial = [&execution_order, &return_pending,
64                   test_destructor_invocation1 =
65                       std::make_unique<int>(1)]() -> Poll<int> {
66     absl::StrAppend(&execution_order, "1");
67     if (return_pending) return Pending{};
68     return 100;
69   };
70 
71   auto then = [test_destructor_invocation2 = std::make_unique<int>(2),
72                &execution_order](int i) {
73     absl::StrAppend(&execution_order, "2");
74     return [i, test_destructor_invocation3 = std::make_unique<int>(3),
75             &execution_order]() -> Poll<int> {
76       absl::StrAppend(&execution_order, "3");
77       return i + 4;
78     };
79   };
80 
81   auto seq_combinator = Seq(std::move(initial), std::move(then));
82   auto result = seq_combinator();
83   EXPECT_EQ(result, Poll<int>(Pending{}));
84   EXPECT_STREQ(execution_order.c_str(), "1");
85 
86   execution_order.clear();
87   return_pending = false;
88   result = seq_combinator();
89   EXPECT_EQ(result, Poll<int>(104));
90   EXPECT_STREQ(execution_order.c_str(), "123");
91 }
92 
TEST(SeqTest,ThreeTypedPendingThens)93 TEST(SeqTest, ThreeTypedPendingThens) {
94   std::string execution_order;
95   bool pending_a = true;
96   bool pending_b = true;
97   bool pending_c = true;
98   bool pending_d = true;
99 
100   struct A {
101     int a_ = -1;
102   };
103   struct B {
104     int b_ = -1;
105   };
106   struct C {
107     int c_ = -1;
108   };
109   struct D {
110     int d_ = -1;
111   };
112 
113   auto initial = [&execution_order, &pending_a]() -> Poll<A> {
114     absl::StrAppend(&execution_order, "0");
115     if (pending_a) {
116       absl::StrAppend(&execution_order, "P");
117       return Pending{};
118     }
119     absl::StrAppend(&execution_order, "a");
120     return A{100};
121   };
122 
123   auto next1 = [&execution_order, &pending_b](A a) {
124     absl::StrAppend(&execution_order, "1");
125     return [&execution_order, &pending_b, a]() -> Poll<B> {
126       EXPECT_EQ(a.a_, 100);
127       if (pending_b) {
128         absl::StrAppend(&execution_order, "P");
129         return Pending{};
130       }
131       absl::StrAppend(&execution_order, "b");
132       return B{200};
133     };
134   };
135 
136   auto next2 = [&execution_order, &pending_c](B b) {
137     absl::StrAppend(&execution_order, "2");
138     return [&execution_order, &pending_c, b]() -> Poll<C> {
139       EXPECT_EQ(b.b_, 200);
140       if (pending_c) {
141         absl::StrAppend(&execution_order, "P");
142         return Pending{};
143       }
144       absl::StrAppend(&execution_order, "c");
145       return C{300};
146     };
147   };
148 
149   auto next3 = [&execution_order, &pending_d](C c) {
150     absl::StrAppend(&execution_order, "3");
151     return [&execution_order, &pending_d, c]() -> Poll<D> {
152       EXPECT_EQ(c.c_, 300);
153       if (pending_d) {
154         absl::StrAppend(&execution_order, "P");
155         return Pending{};
156       }
157       absl::StrAppend(&execution_order, "d");
158       return D{400};
159     };
160   };
161 
162   auto seq_combinator = Seq(initial, next1, next2, next3);
163 
164   auto retval = seq_combinator();
165   EXPECT_TRUE(retval.pending());
166   EXPECT_STREQ(execution_order.c_str(), "0P");
167 
168   execution_order.clear();
169   pending_a = false;
170   retval = seq_combinator();
171   EXPECT_TRUE(retval.pending());
172   EXPECT_STREQ(execution_order.c_str(), "0a1P");
173 
174   execution_order.clear();
175   pending_b = false;
176   retval = seq_combinator();
177   EXPECT_TRUE(retval.pending());
178   EXPECT_STREQ(execution_order.c_str(), "b2P");
179 
180   execution_order.clear();
181   pending_c = false;
182   retval = seq_combinator();
183   EXPECT_TRUE(retval.pending());
184   EXPECT_STREQ(execution_order.c_str(), "c3P");
185 
186   execution_order.clear();
187   pending_d = false;
188   retval = seq_combinator();
189   EXPECT_TRUE(retval.ready());
190   EXPECT_EQ(retval.value().d_, 400);
191   EXPECT_STREQ(execution_order.c_str(), "d");
192 }
193 
194 // This does not compile, but is useful for testing error messages generated
195 // TEST(SeqTest, MisTypedThen) {
196 // struct A {};
197 // struct B {};
198 // auto initial = [] { return A{}; };
199 // auto next = [](B) { return []() { return B{}; }; };
200 // Seq(initial, next)().take();
201 //}
202 //
203 
TEST(SeqTest,TwoThens)204 TEST(SeqTest, TwoThens) {
205   auto initial = [] { return std::string("a"); };
206   auto next1 = [](std::string i) { return [i]() { return i + "b"; }; };
207   auto next2 = [](std::string i) { return [i]() { return i + "c"; }; };
208   EXPECT_EQ(Seq(initial, next1, next2)(), Poll<std::string>("abc"));
209 }
210 
TEST(SeqTest,ThreeThens)211 TEST(SeqTest, ThreeThens) {
212   EXPECT_EQ(
213       Seq([test_destructor_invocation1 =
214                std::make_unique<int>(1)] { return std::string("a"); },
215           [test_destructor_invocation2 =
216                std::make_unique<int>(2)](std::string i) {
217             return [i, y = std::make_unique<int>(2)]() { return i + "b"; };
218           },
219           [test_destructor_invocation3 =
220                std::make_unique<int>(1)](std::string i) {
221             return [i, y = std::make_unique<int>(3)]() { return i + "c"; };
222           },
223           [test_destructor_invocation4 =
224                std::make_unique<int>(1)](std::string i) {
225             return [i, y = std::make_unique<int>(4)]() { return i + "d"; };
226           })(),
227       Poll<std::string>("abcd"));
228 }
229 
230 struct Big {
231   int x[256];
YesItIsUnusedgrpc_core::Big232   void YesItIsUnused() const {}
233 };
234 
TEST(SeqTest,SaneSizes)235 TEST(SeqTest, SaneSizes) {
236   auto x = Big();
237   auto p1 = Seq(
238       [x] {
239         x.YesItIsUnused();
240         return 1;
241       },
242       [](int) {
243         auto y = Big();
244         return [y]() {
245           y.YesItIsUnused();
246           return 2;
247         };
248       });
249   LOG(INFO) << "sizeof(Big): " << sizeof(Big);  // Was 1024
250   LOG(INFO) << "sizeof(p1): " << sizeof(p1);    // Was 1048
251   EXPECT_GE(sizeof(p1), sizeof(Big));
252   EXPECT_LT(sizeof(p1), 1.05 * sizeof(Big));  // Watchout for size bloat!
253 }
254 
TEST(SeqIterTest,Accumulate)255 TEST(SeqIterTest, Accumulate) {
256   std::vector<int> v{1, 2, 3, 4, 5};
257   EXPECT_EQ(SeqIter(v.begin(), v.end(), 0,
258                     [](int cur, int next) {
259                       return [cur, next]() { return cur + next; };
260                     })(),
261             Poll<int>(15));
262 }
263 
264 }  // namespace grpc_core
265 
main(int argc,char ** argv)266 int main(int argc, char** argv) {
267   ::testing::InitGoogleTest(&argc, argv);
268   return RUN_ALL_TESTS();
269 }
270