• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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/interceptor_list.h"
16 
17 #include <grpc/event_engine/memory_allocator.h>
18 
19 #include <memory>
20 
21 #include "gtest/gtest.h"
22 #include "src/core/lib/resource_quota/arena.h"
23 #include "src/core/lib/resource_quota/memory_quota.h"
24 #include "src/core/lib/resource_quota/resource_quota.h"
25 #include "src/core/util/ref_counted_ptr.h"
26 #include "test/core/promise/test_context.h"
27 
28 namespace grpc_core {
29 namespace {
30 
31 class InterceptorListTest : public ::testing::Test {
32  protected:
33   RefCountedPtr<Arena> arena_ = SimpleArenaAllocator()->MakeArena();
34   TestContext<Arena> arena_ctx_{arena_.get()};
35 };
36 
TEST_F(InterceptorListTest,NoOp)37 TEST_F(InterceptorListTest, NoOp) { InterceptorList<std::string>(); }
38 
TEST_F(InterceptorListTest,CanRunOne)39 TEST_F(InterceptorListTest, CanRunOne) {
40   InterceptorList<std::string> list;
41   list.AppendMap([](std::string s) { return s + "a"; }, DEBUG_LOCATION);
42   EXPECT_EQ(list.Run("hello")(), Poll<absl::optional<std::string>>("helloa"));
43 }
44 
TEST_F(InterceptorListTest,CanRunTwo)45 TEST_F(InterceptorListTest, CanRunTwo) {
46   InterceptorList<std::string> list;
47   list.AppendMap([](std::string s) { return s + "a"; }, DEBUG_LOCATION);
48   list.AppendMap([](std::string s) { return s + "b"; }, DEBUG_LOCATION);
49   EXPECT_EQ(list.Run("hello")(), Poll<absl::optional<std::string>>("helloab"));
50 }
51 
TEST_F(InterceptorListTest,CanRunTwoTwice)52 TEST_F(InterceptorListTest, CanRunTwoTwice) {
53   InterceptorList<std::string> list;
54   list.AppendMap([](std::string s) { return s + s; }, DEBUG_LOCATION);
55   list.AppendMap([](std::string s) { return s + s + s; }, DEBUG_LOCATION);
56   EXPECT_EQ(list.Run(std::string(10, 'a'))().value().value(),
57             std::string(60, 'a'));
58   EXPECT_EQ(list.Run(std::string(100, 'b'))().value().value(),
59             std::string(600, 'b'));
60 }
61 
TEST_F(InterceptorListTest,CanRunManyWithCaptures)62 TEST_F(InterceptorListTest, CanRunManyWithCaptures) {
63   InterceptorList<std::string> list;
64   for (size_t i = 0; i < 26 * 1000; i++) {
65     list.AppendMap(
66         [i = std::make_shared<size_t>(i)](std::string s) {
67           return s + static_cast<char>((*i % 26) + 'a');
68         },
69         DEBUG_LOCATION);
70   }
71   std::string expected;
72   for (size_t i = 0; i < 1000; i++) {
73     expected += "abcdefghijklmnopqrstuvwxyz";
74   }
75   EXPECT_EQ(list.Run("")().value().value(), expected);
76 }
77 
TEST_F(InterceptorListTest,CanRunOnePrepended)78 TEST_F(InterceptorListTest, CanRunOnePrepended) {
79   InterceptorList<std::string> list;
80   list.PrependMap([](std::string s) { return s + "a"; }, DEBUG_LOCATION);
81   EXPECT_EQ(list.Run("hello")(), Poll<absl::optional<std::string>>("helloa"));
82 }
83 
TEST_F(InterceptorListTest,CanRunTwoPrepended)84 TEST_F(InterceptorListTest, CanRunTwoPrepended) {
85   InterceptorList<std::string> list;
86   list.PrependMap([](std::string s) { return s + "a"; }, DEBUG_LOCATION);
87   list.PrependMap([](std::string s) { return s + "b"; }, DEBUG_LOCATION);
88   EXPECT_EQ(list.Run("hello")(), Poll<absl::optional<std::string>>("helloba"));
89 }
90 
TEST_F(InterceptorListTest,CanRunManyWithCapturesPrepended)91 TEST_F(InterceptorListTest, CanRunManyWithCapturesPrepended) {
92   InterceptorList<std::string> list;
93   for (size_t i = 0; i < 26 * 1000; i++) {
94     list.PrependMap(
95         [i = std::make_shared<size_t>(i)](std::string s) {
96           return s + static_cast<char>((*i % 26) + 'a');
97         },
98         DEBUG_LOCATION);
99   }
100   std::string expected;
101   for (size_t i = 0; i < 1000; i++) {
102     expected += "zyxwvutsrqponmlkjihgfedcba";
103   }
104   EXPECT_EQ(list.Run("")().value().value(), expected);
105 }
106 
TEST_F(InterceptorListTest,CanRunManyWithCapturesThatDelay)107 TEST_F(InterceptorListTest, CanRunManyWithCapturesThatDelay) {
108   InterceptorList<std::string> list;
109   for (size_t i = 0; i < 26 * 1000; i++) {
110     list.AppendMap(
111         [i = std::make_shared<size_t>(i)](std::string s) {
112           return
113               [x = false, i, s]() mutable -> Poll<absl::optional<std::string>> {
114                 if (!x) {
115                   x = true;
116                   return Pending{};
117                 }
118                 return s + static_cast<char>((*i % 26) + 'a');
119               };
120         },
121         DEBUG_LOCATION);
122   }
123   auto promise = list.Run("");
124   for (size_t i = 0; i < 26 * 1000; i++) {
125     EXPECT_TRUE(promise().pending()) << i;
126   }
127   std::string expected;
128   for (size_t i = 0; i < 1000; i++) {
129     expected += "abcdefghijklmnopqrstuvwxyz";
130   }
131   EXPECT_EQ(promise().value().value(), expected);
132 }
133 
134 }  // namespace
135 }  // namespace grpc_core
136 
main(int argc,char ** argv)137 int main(int argc, char** argv) {
138   ::testing::InitGoogleTest(&argc, argv);
139   return RUN_ALL_TESTS();
140 }
141