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