xref: /aosp_15_r20/external/grpc-grpc/test/core/end2end/tests/resource_quota_server.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2016 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include <stddef.h>
20 
21 #include <algorithm>
22 #include <vector>
23 
24 #include "absl/strings/str_format.h"
25 #include "gtest/gtest.h"
26 
27 #include <grpc/grpc.h>
28 #include <grpc/impl/channel_arg_names.h>
29 #include <grpc/status.h>
30 #include <grpc/support/log.h>
31 
32 #include "src/core/lib/channel/channel_args.h"
33 #include "src/core/lib/experiments/experiments.h"
34 #include "src/core/lib/gprpp/crash.h"
35 #include "src/core/lib/gprpp/time.h"
36 #include "src/core/lib/slice/slice.h"
37 #include "test/core/end2end/end2end_tests.h"
38 
39 namespace grpc_core {
40 namespace {
41 
42 const int kNumCalls = 8;
43 const int kClientBaseTag = 1000;
44 const int kServerStartBaseTag = 2000;
45 const int kServerRecvBaseTag = 3000;
46 const int kServerEndBaseTag = 4000;
47 
48 template <typename F>
MakeVec(F init)49 auto MakeVec(F init) {
50   std::vector<decltype(init(0))> v;
51   v.reserve(kNumCalls);
52   for (int i = 0; i < kNumCalls; ++i) {
53     v.push_back(init(i));
54   }
55   return v;
56 }
57 
CORE_END2END_TEST(ResourceQuotaTest,ResourceQuota)58 CORE_END2END_TEST(ResourceQuotaTest, ResourceQuota) {
59   if (IsEventEngineListenerEnabled()) {
60     GTEST_SKIP() << "Not with event engine listener";
61   }
62 
63   grpc_resource_quota* resource_quota =
64       grpc_resource_quota_create("test_server");
65   grpc_resource_quota_resize(resource_quota, 1024 * 1024);
66   InitServer(ChannelArgs().Set(
67       GRPC_ARG_RESOURCE_QUOTA,
68       ChannelArgs::Pointer(resource_quota, grpc_resource_quota_arg_vtable())));
69   InitClient(ChannelArgs());
70   // Create large request and response bodies. These are big enough to require
71   // multiple round trips to deliver to the peer, and their exact contents of
72   // will be verified on completion.
73   auto requests = MakeVec([](int) { return RandomSlice(128 * 1024); });
74   auto server_calls =
75       MakeVec([this](int i) { return RequestCall(kServerRecvBaseTag + i); });
76   IncomingMetadata server_metadata[kNumCalls];
77   IncomingStatusOnClient server_status[kNumCalls];
78   IncomingMessage client_message[kNumCalls];
79   IncomingCloseOnServer client_close[kNumCalls];
80   enum class SeenServerCall {
81     kNotSeen = 0,
82     kSeenWithSuccess,
83     kSeenWithFailure
84   };
85   // Yep, this really initializes all the elements.
86   SeenServerCall seen_server_call[kNumCalls] = {SeenServerCall::kNotSeen};
87   auto client_calls =
88       MakeVec([this, &requests, &server_metadata, &server_status](int i) {
89         auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
90         c.NewBatch(kClientBaseTag + i)
91             .SendInitialMetadata({}, GRPC_INITIAL_METADATA_WAIT_FOR_READY)
92             .SendMessage(requests[i].Ref())
93             .SendCloseFromClient()
94             .RecvInitialMetadata(server_metadata[i])
95             .RecvStatusOnClient(server_status[i]);
96         return c;
97       });
98   for (int i = 0; i < kNumCalls; i++) {
99     Expect(kClientBaseTag + i, true);
100     Expect(
101         kServerRecvBaseTag + i,
102         MaybePerformAction{[this, &seen_server_call, &server_calls,
103                             &client_message, &client_close, i](bool success) {
104           seen_server_call[i] = success ? SeenServerCall::kSeenWithSuccess
105                                         : SeenServerCall::kSeenWithFailure;
106           if (!success) return;
107           server_calls[i]
108               .NewBatch(kServerStartBaseTag + i)
109               .RecvMessage(client_message[i])
110               .SendInitialMetadata({});
111           Expect(kServerStartBaseTag + i,
112                  PerformAction{[&server_calls, &client_close, i](bool) {
113                    server_calls[i]
114                        .NewBatch(kServerEndBaseTag + i)
115                        .RecvCloseOnServer(client_close[i])
116                        .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {});
117                  }});
118           Expect(kServerEndBaseTag + i, true);
119         }});
120   }
121   Step();
122 
123   int cancelled_calls_on_client = 0;
124   int cancelled_calls_on_server = 0;
125   int deadline_exceeded = 0;
126   int unavailable = 0;
127   for (int i = 0; i < kNumCalls; i++) {
128     switch (server_status[i].status()) {
129       case GRPC_STATUS_RESOURCE_EXHAUSTED:
130         cancelled_calls_on_client++;
131         break;
132       case GRPC_STATUS_DEADLINE_EXCEEDED:
133         deadline_exceeded++;
134         break;
135       case GRPC_STATUS_UNAVAILABLE:
136         unavailable++;
137         break;
138       case GRPC_STATUS_OK:
139         break;
140       default:
141         Crash(absl::StrFormat("Unexpected status code: %d",
142                               server_status[i].status()));
143     }
144     if (seen_server_call[i] == SeenServerCall::kSeenWithSuccess &&
145         client_close[i].was_cancelled()) {
146       cancelled_calls_on_server++;
147     }
148   }
149   gpr_log(GPR_INFO,
150           "Done. %d total calls: %d cancelled at server, %d cancelled at "
151           "client, %d timed out, %d unavailable.",
152           kNumCalls, cancelled_calls_on_server, cancelled_calls_on_client,
153           deadline_exceeded, unavailable);
154 
155   ShutdownServerAndNotify(0);
156   Expect(0, PerformAction{[this](bool success) {
157            EXPECT_TRUE(success);
158            DestroyServer();
159          }});
160   for (size_t i = 0; i < kNumCalls; i++) {
161     if (seen_server_call[i] == SeenServerCall::kNotSeen) {
162       Expect(kServerRecvBaseTag + i, false);
163     }
164   }
165   Step();
166 }
167 
168 }  // namespace
169 }  // namespace grpc_core
170