1 /*
2 *
3 * Copyright 2017 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 "test/core/end2end/end2end_tests.h"
20
21 #include <limits.h>
22 #include <string.h>
23
24 #include <grpc/support/log.h>
25 #include <grpc/support/sync.h>
26 #include <grpc/support/time.h>
27
28 #include "src/core/lib/gpr/useful.h"
29 #include "test/core/end2end/cq_verifier.h"
30
31 #define MAX_CONNECTION_AGE_MS 500
32 #define MAX_CONNECTION_AGE_GRACE_MS 1000
33 #define MAX_CONNECTION_IDLE_MS 9999
34
35 #define MAX_CONNECTION_AGE_JITTER_MULTIPLIER 1.1
36 #define CALL_DEADLINE_S 10
37 /* The amount of time we wait for the connection to time out, but after it the
38 connection should not use up its grace period. It should be a number between
39 MAX_CONNECTION_AGE_MS and MAX_CONNECTION_AGE_MS +
40 MAX_CONNECTION_AGE_GRACE_MS */
41 #define CQ_MAX_CONNECTION_AGE_WAIT_TIME_S 1
42 /* The amount of time we wait after the connection reaches its max age, it
43 should be shorter than CALL_DEADLINE_S - CQ_MAX_CONNECTION_AGE_WAIT_TIME_S */
44 #define CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S 2
45 /* The grace period for the test to observe the channel shutdown process */
46 #define IMMEDIATE_SHUTDOWN_GRACE_TIME_MS 3000
47
tag(intptr_t t)48 static void* tag(intptr_t t) { return (void*)t; }
49
drain_cq(grpc_completion_queue * cq)50 static void drain_cq(grpc_completion_queue* cq) {
51 grpc_event ev;
52 do {
53 ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5),
54 nullptr);
55 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
56 }
57
shutdown_server(grpc_end2end_test_fixture * f)58 static void shutdown_server(grpc_end2end_test_fixture* f) {
59 if (!f->server) return;
60 grpc_server_destroy(f->server);
61 f->server = nullptr;
62 }
63
shutdown_client(grpc_end2end_test_fixture * f)64 static void shutdown_client(grpc_end2end_test_fixture* f) {
65 if (!f->client) return;
66 grpc_channel_destroy(f->client);
67 f->client = nullptr;
68 }
69
end_test(grpc_end2end_test_fixture * f)70 static void end_test(grpc_end2end_test_fixture* f) {
71 shutdown_server(f);
72 shutdown_client(f);
73
74 grpc_completion_queue_shutdown(f->cq);
75 drain_cq(f->cq);
76 grpc_completion_queue_destroy(f->cq);
77 grpc_completion_queue_destroy(f->shutdown_cq);
78 }
79
test_max_age_forcibly_close(grpc_end2end_test_config config)80 static void test_max_age_forcibly_close(grpc_end2end_test_config config) {
81 grpc_end2end_test_fixture f = config.create_fixture(nullptr, nullptr);
82 cq_verifier* cqv = cq_verifier_create(f.cq);
83 grpc_arg server_a[3];
84 server_a[0].type = GRPC_ARG_INTEGER;
85 server_a[0].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_AGE_MS);
86 server_a[0].value.integer = MAX_CONNECTION_AGE_MS;
87 server_a[1].type = GRPC_ARG_INTEGER;
88 server_a[1].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS);
89 server_a[1].value.integer = MAX_CONNECTION_AGE_GRACE_MS;
90 server_a[2].type = GRPC_ARG_INTEGER;
91 server_a[2].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_IDLE_MS);
92 server_a[2].value.integer = MAX_CONNECTION_IDLE_MS;
93 grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a};
94
95 config.init_client(&f, nullptr);
96 config.init_server(&f, &server_args);
97
98 grpc_call* c;
99 grpc_call* s;
100 gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S);
101 grpc_op ops[6];
102 grpc_op* op;
103 grpc_metadata_array initial_metadata_recv;
104 grpc_metadata_array trailing_metadata_recv;
105 grpc_metadata_array request_metadata_recv;
106 grpc_call_details call_details;
107 grpc_status_code status;
108 grpc_call_error error;
109 grpc_slice details;
110 int was_cancelled = 2;
111
112 c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
113 grpc_slice_from_static_string("/foo"), nullptr,
114 deadline, nullptr);
115 GPR_ASSERT(c);
116
117 grpc_metadata_array_init(&initial_metadata_recv);
118 grpc_metadata_array_init(&trailing_metadata_recv);
119 grpc_metadata_array_init(&request_metadata_recv);
120 grpc_call_details_init(&call_details);
121
122 memset(ops, 0, sizeof(ops));
123 op = ops;
124 op->op = GRPC_OP_SEND_INITIAL_METADATA;
125 op->data.send_initial_metadata.count = 0;
126 op->data.send_initial_metadata.metadata = nullptr;
127 op->flags = 0;
128 op->reserved = nullptr;
129 op++;
130 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
131 op->flags = 0;
132 op->reserved = nullptr;
133 op++;
134 op->op = GRPC_OP_RECV_INITIAL_METADATA;
135 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
136 op->flags = 0;
137 op->reserved = nullptr;
138 op++;
139 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
140 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
141 op->data.recv_status_on_client.status = &status;
142 op->data.recv_status_on_client.status_details = &details;
143 op->flags = 0;
144 op->reserved = nullptr;
145 op++;
146 error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
147 nullptr);
148 GPR_ASSERT(GRPC_CALL_OK == error);
149
150 error =
151 grpc_server_request_call(f.server, &s, &call_details,
152 &request_metadata_recv, f.cq, f.cq, tag(101));
153 GPR_ASSERT(GRPC_CALL_OK == error);
154 CQ_EXPECT_COMPLETION(cqv, tag(101), true);
155 cq_verify(cqv);
156
157 gpr_timespec expect_shutdown_time = grpc_timeout_milliseconds_to_deadline(
158 static_cast<int>(MAX_CONNECTION_AGE_MS *
159 MAX_CONNECTION_AGE_JITTER_MULTIPLIER) +
160 MAX_CONNECTION_AGE_GRACE_MS + IMMEDIATE_SHUTDOWN_GRACE_TIME_MS);
161
162 /* Wait for the channel to reach its max age */
163 cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S);
164
165 /* After the channel reaches its max age, we still do nothing here. And wait
166 for it to use up its max age grace period. */
167 CQ_EXPECT_COMPLETION(cqv, tag(1), true);
168 cq_verify(cqv);
169
170 gpr_timespec channel_shutdown_time = gpr_now(GPR_CLOCK_MONOTONIC);
171 GPR_ASSERT(gpr_time_cmp(channel_shutdown_time, expect_shutdown_time) < 0);
172
173 memset(ops, 0, sizeof(ops));
174 op = ops;
175 op->op = GRPC_OP_SEND_INITIAL_METADATA;
176 op->data.send_initial_metadata.count = 0;
177 op->flags = 0;
178 op->reserved = nullptr;
179 op++;
180 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
181 op->data.send_status_from_server.trailing_metadata_count = 0;
182 op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
183 grpc_slice status_details = grpc_slice_from_static_string("xyz");
184 op->data.send_status_from_server.status_details = &status_details;
185 op->flags = 0;
186 op->reserved = nullptr;
187 op++;
188 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
189 op->data.recv_close_on_server.cancelled = &was_cancelled;
190 op->flags = 0;
191 op->reserved = nullptr;
192 op++;
193 error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
194 nullptr);
195 GPR_ASSERT(GRPC_CALL_OK == error);
196 CQ_EXPECT_COMPLETION(cqv, tag(102), true);
197 cq_verify(cqv);
198
199 grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead));
200 CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true);
201 cq_verify(cqv);
202
203 grpc_call_unref(s);
204
205 /* The connection should be closed immediately after the max age grace period,
206 the in-progress RPC should fail. */
207 GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
208 GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
209 GPR_ASSERT(was_cancelled == 1);
210
211 grpc_slice_unref(details);
212 grpc_metadata_array_destroy(&initial_metadata_recv);
213 grpc_metadata_array_destroy(&trailing_metadata_recv);
214 grpc_metadata_array_destroy(&request_metadata_recv);
215 grpc_call_details_destroy(&call_details);
216 grpc_call_unref(c);
217 cq_verifier_destroy(cqv);
218 end_test(&f);
219 config.tear_down_data(&f);
220 }
221
test_max_age_gracefully_close(grpc_end2end_test_config config)222 static void test_max_age_gracefully_close(grpc_end2end_test_config config) {
223 grpc_end2end_test_fixture f = config.create_fixture(nullptr, nullptr);
224 cq_verifier* cqv = cq_verifier_create(f.cq);
225 grpc_arg server_a[3];
226 server_a[0].type = GRPC_ARG_INTEGER;
227 server_a[0].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_AGE_MS);
228 server_a[0].value.integer = MAX_CONNECTION_AGE_MS;
229 server_a[1].type = GRPC_ARG_INTEGER;
230 server_a[1].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS);
231 server_a[1].value.integer = INT_MAX;
232 server_a[2].type = GRPC_ARG_INTEGER;
233 server_a[2].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_IDLE_MS);
234 server_a[2].value.integer = MAX_CONNECTION_IDLE_MS;
235 grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a};
236
237 config.init_client(&f, nullptr);
238 config.init_server(&f, &server_args);
239
240 grpc_call* c;
241 grpc_call* s;
242 gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S);
243 grpc_op ops[6];
244 grpc_op* op;
245 grpc_metadata_array initial_metadata_recv;
246 grpc_metadata_array trailing_metadata_recv;
247 grpc_metadata_array request_metadata_recv;
248 grpc_call_details call_details;
249 grpc_status_code status;
250 grpc_call_error error;
251 grpc_slice details;
252 int was_cancelled = 2;
253
254 c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
255 grpc_slice_from_static_string("/foo"), nullptr,
256 deadline, nullptr);
257 GPR_ASSERT(c);
258
259 grpc_metadata_array_init(&initial_metadata_recv);
260 grpc_metadata_array_init(&trailing_metadata_recv);
261 grpc_metadata_array_init(&request_metadata_recv);
262 grpc_call_details_init(&call_details);
263
264 memset(ops, 0, sizeof(ops));
265 op = ops;
266 op->op = GRPC_OP_SEND_INITIAL_METADATA;
267 op->data.send_initial_metadata.count = 0;
268 op->data.send_initial_metadata.metadata = nullptr;
269 op->flags = 0;
270 op->reserved = nullptr;
271 op++;
272 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
273 op->flags = 0;
274 op->reserved = nullptr;
275 op++;
276 op->op = GRPC_OP_RECV_INITIAL_METADATA;
277 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
278 op->flags = 0;
279 op->reserved = nullptr;
280 op++;
281 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
282 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
283 op->data.recv_status_on_client.status = &status;
284 op->data.recv_status_on_client.status_details = &details;
285 op->flags = 0;
286 op->reserved = nullptr;
287 op++;
288 error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
289 nullptr);
290 GPR_ASSERT(GRPC_CALL_OK == error);
291
292 error =
293 grpc_server_request_call(f.server, &s, &call_details,
294 &request_metadata_recv, f.cq, f.cq, tag(101));
295 GPR_ASSERT(GRPC_CALL_OK == error);
296 CQ_EXPECT_COMPLETION(cqv, tag(101), true);
297 cq_verify(cqv);
298
299 /* Wait for the channel to reach its max age */
300 cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S);
301
302 /* The connection is shutting down gracefully. In-progress rpc should not be
303 closed, hence the completion queue should see nothing here. */
304 cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S);
305
306 memset(ops, 0, sizeof(ops));
307 op = ops;
308 op->op = GRPC_OP_SEND_INITIAL_METADATA;
309 op->data.send_initial_metadata.count = 0;
310 op->flags = 0;
311 op->reserved = nullptr;
312 op++;
313 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
314 op->data.send_status_from_server.trailing_metadata_count = 0;
315 op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
316 grpc_slice status_details = grpc_slice_from_static_string("xyz");
317 op->data.send_status_from_server.status_details = &status_details;
318 op->flags = 0;
319 op->reserved = nullptr;
320 op++;
321 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
322 op->data.recv_close_on_server.cancelled = &was_cancelled;
323 op->flags = 0;
324 op->reserved = nullptr;
325 op++;
326 error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
327 nullptr);
328 GPR_ASSERT(GRPC_CALL_OK == error);
329
330 CQ_EXPECT_COMPLETION(cqv, tag(102), true);
331 CQ_EXPECT_COMPLETION(cqv, tag(1), true);
332 cq_verify(cqv);
333
334 grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead));
335 CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true);
336 cq_verify(cqv);
337
338 grpc_call_unref(s);
339
340 /* The connection is closed gracefully with goaway, the rpc should still be
341 completed. */
342 GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
343 GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
344 GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
345 GPR_ASSERT(was_cancelled == 1);
346
347 grpc_slice_unref(details);
348 grpc_metadata_array_destroy(&initial_metadata_recv);
349 grpc_metadata_array_destroy(&trailing_metadata_recv);
350 grpc_metadata_array_destroy(&request_metadata_recv);
351 grpc_call_details_destroy(&call_details);
352 grpc_call_unref(c);
353 cq_verifier_destroy(cqv);
354 end_test(&f);
355 config.tear_down_data(&f);
356 }
357
max_connection_age(grpc_end2end_test_config config)358 void max_connection_age(grpc_end2end_test_config config) {
359 test_max_age_forcibly_close(config);
360 test_max_age_gracefully_close(config);
361 }
362
max_connection_age_pre_init(void)363 void max_connection_age_pre_init(void) {}
364