1 //
2 //
3 // Copyright 2015 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 <grpc/impl/channel_arg_names.h>
20 #include <grpc/status.h>
21
22 #include <memory>
23
24 #include "gtest/gtest.h"
25 #include "src/core/ext/transport/chttp2/transport/internal.h"
26 #include "src/core/lib/channel/channel_args.h"
27 #include "src/core/util/time.h"
28 #include "test/core/end2end/end2end_tests.h"
29
30 namespace grpc_core {
31 namespace {
32
SimpleRequestBody(CoreEnd2endTest & test)33 void SimpleRequestBody(CoreEnd2endTest& test) {
34 auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
35 IncomingStatusOnClient server_status;
36 IncomingMetadata server_initial_metadata;
37 c.NewBatch(1)
38 .SendInitialMetadata({})
39 .SendCloseFromClient()
40 .RecvInitialMetadata(server_initial_metadata)
41 .RecvStatusOnClient(server_status);
42 auto s = test.RequestCall(101);
43 test.Expect(101, true);
44 test.Step();
45 IncomingCloseOnServer client_close;
46 s.NewBatch(102)
47 .SendInitialMetadata({})
48 .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {})
49 .RecvCloseOnServer(client_close);
50 test.Expect(102, true);
51 test.Expect(1, true);
52 test.Step();
53 EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED);
54 EXPECT_EQ(server_status.message(), "xyz");
55 EXPECT_EQ(s.method(), "/foo");
56 EXPECT_FALSE(client_close.was_cancelled());
57 }
58
CORE_END2END_TEST(Http2SingleHopTest,MaxConcurrentStreams)59 CORE_END2END_TEST(Http2SingleHopTest, MaxConcurrentStreams) {
60 SKIP_IF_MINSTACK();
61 InitServer(
62 ChannelArgs()
63 .Set(GRPC_ARG_MAX_CONCURRENT_STREAMS, 1)
64 .Set(GRPC_ARG_MAX_CONCURRENT_STREAMS_OVERLOAD_PROTECTION, false));
65 InitClient(ChannelArgs());
66 // perform a ping-pong to ensure that settings have had a chance to round
67 // trip
68 SimpleRequestBody(*this);
69 // perform another one to make sure that the one stream case still works
70 SimpleRequestBody(*this);
71 // start two requests - ensuring that the second is not accepted until
72 // the first completes
73 auto c1 = NewClientCall("/alpha").Timeout(Duration::Seconds(1000)).Create();
74 auto c2 = NewClientCall("/beta").Timeout(Duration::Seconds(1000)).Create();
75 auto s1 = RequestCall(101);
76 c1.NewBatch(301).SendInitialMetadata({}).SendCloseFromClient();
77 IncomingMetadata server_initial_metadata1;
78 IncomingStatusOnClient server_status1;
79 c1.NewBatch(302)
80 .RecvStatusOnClient(server_status1)
81 .RecvInitialMetadata(server_initial_metadata1);
82 c2.NewBatch(401).SendInitialMetadata({}).SendCloseFromClient();
83 IncomingMetadata server_initial_metadata2;
84 IncomingStatusOnClient server_status2;
85 c2.NewBatch(402)
86 .RecvStatusOnClient(server_status2)
87 .RecvInitialMetadata(server_initial_metadata2);
88 bool got_client_start = false;
89 bool got_server_start = false;
90 int live_call;
91 Expect(101, MaybePerformAction{[&got_server_start](bool ok) {
92 EXPECT_TRUE(ok);
93 got_server_start = ok;
94 }});
95 Expect(301, MaybePerformAction{[&got_client_start, &live_call](bool ok) {
96 EXPECT_FALSE(got_client_start);
97 EXPECT_TRUE(ok);
98 got_client_start = ok;
99 live_call = 300;
100 }});
101 Expect(401, MaybePerformAction{[&got_client_start, &live_call](bool ok) {
102 EXPECT_FALSE(got_client_start);
103 EXPECT_TRUE(ok);
104 got_client_start = ok;
105 live_call = 400;
106 }});
107 Step();
108 if (got_client_start && !got_server_start) {
109 Expect(101, true);
110 Step();
111 got_server_start = true;
112 } else if (got_server_start && !got_client_start) {
113 Expect(301, MaybePerformAction{[&got_client_start, &live_call](bool ok) {
114 EXPECT_FALSE(got_client_start);
115 EXPECT_TRUE(ok);
116 got_client_start = ok;
117 live_call = 300;
118 }});
119 Expect(401, MaybePerformAction{[&got_client_start, &live_call](bool ok) {
120 EXPECT_FALSE(got_client_start);
121 EXPECT_TRUE(ok);
122 got_client_start = ok;
123 live_call = 400;
124 }});
125 Step();
126 EXPECT_TRUE(got_client_start);
127 }
128 IncomingCloseOnServer client_close;
129 s1.NewBatch(102)
130 .SendInitialMetadata({})
131 .RecvCloseOnServer(client_close)
132 .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {});
133 Expect(102, true);
134 Expect(live_call + 2, true);
135 // first request is finished, we should be able to start the second
136 live_call = (live_call == 300) ? 400 : 300;
137 Expect(live_call + 1, true);
138 Step();
139 // Spin for a little: we expect to see no events now - and this time allows
140 // any overload protection machinery in the transport to settle (chttp2 tries
141 // to ensure calls are finished deleting before allowing more requests
142 // through).
143 Step();
144 auto s2 = RequestCall(201);
145 Expect(201, true);
146 Step();
147 s2.NewBatch(202)
148 .SendInitialMetadata({})
149 .RecvCloseOnServer(client_close)
150 .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {});
151 Expect(live_call + 2, true);
152 Expect(202, true);
153 Step();
154 }
155
CORE_END2END_TEST(Http2SingleHopTest,MaxConcurrentStreamsTimeoutOnFirst)156 CORE_END2END_TEST(Http2SingleHopTest, MaxConcurrentStreamsTimeoutOnFirst) {
157 SKIP_IF_MINSTACK();
158 InitServer(
159 ChannelArgs()
160 .Set(GRPC_ARG_MAX_CONCURRENT_STREAMS, 1)
161 .Set(GRPC_ARG_MAX_CONCURRENT_STREAMS_OVERLOAD_PROTECTION, false));
162 InitClient(ChannelArgs());
163 // perform a ping-pong to ensure that settings have had a chance to round
164 // trip
165 SimpleRequestBody(*this);
166 // perform another one to make sure that the one stream case still works
167 SimpleRequestBody(*this);
168 // start two requests - ensuring that the second is not accepted until
169 // the first completes
170 auto c1 = NewClientCall("/alpha").Timeout(Duration::Seconds(3)).Create();
171 auto c2 = NewClientCall("/beta").Timeout(Duration::Seconds(1000)).Create();
172 auto s1 = RequestCall(101);
173 c1.NewBatch(301).SendInitialMetadata({}).SendCloseFromClient();
174 IncomingMetadata server_initial_metadata1;
175 IncomingStatusOnClient server_status1;
176 c1.NewBatch(302)
177 .RecvStatusOnClient(server_status1)
178 .RecvInitialMetadata(server_initial_metadata1);
179 Expect(101, true);
180 Expect(301, true);
181 Step();
182 c2.NewBatch(401).SendInitialMetadata({}).SendCloseFromClient();
183 IncomingMetadata server_initial_metadata2;
184 IncomingStatusOnClient server_status2;
185 c2.NewBatch(402)
186 .RecvStatusOnClient(server_status2)
187 .RecvInitialMetadata(server_initial_metadata2);
188 auto s2 = RequestCall(201);
189 Expect(302, true);
190 // first request is finished, we should be able to start the second
191 Expect(401, true);
192 Expect(201, true);
193 Step();
194 IncomingCloseOnServer client_close2;
195 s2.NewBatch(202)
196 .SendInitialMetadata({})
197 .RecvCloseOnServer(client_close2)
198 .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {});
199 Expect(402, true);
200 Expect(202, true);
201 Step();
202 }
203
CORE_END2END_TEST(Http2SingleHopTest,MaxConcurrentStreamsTimeoutOnSecond)204 CORE_END2END_TEST(Http2SingleHopTest, MaxConcurrentStreamsTimeoutOnSecond) {
205 SKIP_IF_MINSTACK();
206 InitServer(
207 ChannelArgs()
208 .Set(GRPC_ARG_MAX_CONCURRENT_STREAMS, 1)
209 .Set(GRPC_ARG_MAX_CONCURRENT_STREAMS_OVERLOAD_PROTECTION, false));
210 InitClient(ChannelArgs());
211 // perform a ping-pong to ensure that settings have had a chance to round
212 // trip
213 SimpleRequestBody(*this);
214 // perform another one to make sure that the one stream case still works
215 SimpleRequestBody(*this);
216 // start two requests - ensuring that the second is not accepted until
217 // the first completes , and the second request will timeout in the
218 // concurrent_list
219 auto c1 = NewClientCall("/alpha").Timeout(Duration::Seconds(1000)).Create();
220 auto c2 = NewClientCall("/beta").Timeout(Duration::Seconds(3)).Create();
221 auto s1 = RequestCall(101);
222 c1.NewBatch(301).SendInitialMetadata({}).SendCloseFromClient();
223 IncomingMetadata server_initial_metadata1;
224 IncomingStatusOnClient server_status1;
225 c1.NewBatch(302)
226 .RecvStatusOnClient(server_status1)
227 .RecvInitialMetadata(server_initial_metadata1);
228 Expect(101, true);
229 Expect(301, true);
230 Step();
231 c2.NewBatch(401).SendInitialMetadata({}).SendCloseFromClient();
232 IncomingMetadata server_initial_metadata2;
233 IncomingStatusOnClient server_status2;
234 c2.NewBatch(402)
235 .RecvStatusOnClient(server_status2)
236 .RecvInitialMetadata(server_initial_metadata2);
237 // the second request is time out
238 Expect(401, false);
239 Expect(402, true);
240 Step();
241 // now reply the first call
242 IncomingCloseOnServer client_close1;
243 s1.NewBatch(102)
244 .SendInitialMetadata({})
245 .RecvCloseOnServer(client_close1)
246 .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {});
247 Expect(302, true);
248 Expect(102, true);
249 Step();
250 EXPECT_EQ(server_status2.status(), GRPC_STATUS_DEADLINE_EXCEEDED);
251 }
252
CORE_END2END_TEST(Http2SingleHopTest,MaxConcurrentStreamsRejectOnClient)253 CORE_END2END_TEST(Http2SingleHopTest, MaxConcurrentStreamsRejectOnClient) {
254 SKIP_IF_MINSTACK();
255 InitServer(
256 ChannelArgs()
257 .Set(GRPC_ARG_MAX_CONCURRENT_STREAMS, 1)
258 .Set(GRPC_ARG_MAX_CONCURRENT_STREAMS_OVERLOAD_PROTECTION, false));
259 InitClient(ChannelArgs()
260 .Set(GRPC_ARG_MAX_CONCURRENT_STREAMS_REJECT_ON_CLIENT, true)
261 .Set(GRPC_ARG_ENABLE_RETRIES, false));
262 // perform a ping-pong to ensure that settings have had a chance to round
263 // trip
264 SimpleRequestBody(*this);
265 auto c1 = NewClientCall("/alpha").Timeout(Duration::Seconds(1000)).Create();
266 auto c2 = NewClientCall("/beta").Timeout(Duration::Seconds(3)).Create();
267 auto s1 = RequestCall(101);
268 c1.NewBatch(301).SendInitialMetadata({}).SendCloseFromClient();
269 IncomingMetadata server_initial_metadata1;
270 IncomingStatusOnClient server_status1;
271 c1.NewBatch(302)
272 .RecvStatusOnClient(server_status1)
273 .RecvInitialMetadata(server_initial_metadata1);
274 Expect(101, true);
275 Expect(301, true);
276 Step();
277 c2.NewBatch(401).SendInitialMetadata({}).SendCloseFromClient();
278 IncomingMetadata server_initial_metadata2;
279 IncomingStatusOnClient server_status2;
280 c2.NewBatch(402)
281 .RecvStatusOnClient(server_status2)
282 .RecvInitialMetadata(server_initial_metadata2);
283 // the second request fails
284 Expect(401, false);
285 Expect(402, true);
286 Step();
287 // now reply the first call
288 IncomingCloseOnServer client_close1;
289 s1.NewBatch(102)
290 .SendInitialMetadata({})
291 .RecvCloseOnServer(client_close1)
292 .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {});
293 Expect(302, true);
294 Expect(102, true);
295 Step();
296 EXPECT_EQ(server_status2.status(), GRPC_STATUS_RESOURCE_EXHAUSTED);
297 }
298
299 } // namespace
300 } // namespace grpc_core
301