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