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 "test/core/end2end/end2end_tests.h"
20
21 #include <limits.h>
22 #include <stdbool.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include <grpc/byte_buffer.h>
27 #include <grpc/support/alloc.h>
28 #include <grpc/support/log.h>
29 #include <grpc/support/time.h>
30 #include "src/core/lib/channel/channel_stack_builder.h"
31 #include "src/core/lib/surface/channel_init.h"
32 #include "test/core/end2end/cq_verifier.h"
33
34 enum { TIMEOUT = 200000 };
35
36 static bool g_enable_server_channel_filter = false;
37 static bool g_enable_client_channel_filter = false;
38 static bool g_enable_client_subchannel_filter = false;
39
tag(intptr_t t)40 static void* tag(intptr_t t) { return (void*)t; }
41
begin_test(grpc_end2end_test_config config,const char * test_name,grpc_channel_args * client_args,grpc_channel_args * server_args)42 static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
43 const char* test_name,
44 grpc_channel_args* client_args,
45 grpc_channel_args* server_args) {
46 grpc_end2end_test_fixture f;
47 gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
48 f = config.create_fixture(client_args, server_args);
49 config.init_server(&f, server_args);
50 config.init_client(&f, client_args);
51 return f;
52 }
53
n_seconds_from_now(int n)54 static gpr_timespec n_seconds_from_now(int n) {
55 return grpc_timeout_seconds_to_deadline(n);
56 }
57
five_seconds_from_now(void)58 static gpr_timespec five_seconds_from_now(void) {
59 return n_seconds_from_now(5);
60 }
61
drain_cq(grpc_completion_queue * cq)62 static void drain_cq(grpc_completion_queue* cq) {
63 grpc_event ev;
64 do {
65 ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
66 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
67 }
68
shutdown_server(grpc_end2end_test_fixture * f)69 static void shutdown_server(grpc_end2end_test_fixture* f) {
70 if (!f->server) return;
71 grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
72 GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
73 grpc_timeout_seconds_to_deadline(5),
74 nullptr)
75 .type == GRPC_OP_COMPLETE);
76 grpc_server_destroy(f->server);
77 f->server = nullptr;
78 }
79
shutdown_client(grpc_end2end_test_fixture * f)80 static void shutdown_client(grpc_end2end_test_fixture* f) {
81 if (!f->client) return;
82 grpc_channel_destroy(f->client);
83 f->client = nullptr;
84 }
85
end_test(grpc_end2end_test_fixture * f)86 static void end_test(grpc_end2end_test_fixture* f) {
87 shutdown_server(f);
88 shutdown_client(f);
89
90 grpc_completion_queue_shutdown(f->cq);
91 drain_cq(f->cq);
92 grpc_completion_queue_destroy(f->cq);
93 grpc_completion_queue_destroy(f->shutdown_cq);
94 }
95
96 // Simple request via a SERVER_CHANNEL filter that always fails to
97 // initialize the call.
test_server_channel_filter(grpc_end2end_test_config config)98 static void test_server_channel_filter(grpc_end2end_test_config config) {
99 grpc_call* c;
100 grpc_call* s;
101 grpc_slice request_payload_slice =
102 grpc_slice_from_copied_string("hello world");
103 grpc_byte_buffer* request_payload =
104 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
105 grpc_end2end_test_fixture f =
106 begin_test(config, "filter_call_init_fails", nullptr, nullptr);
107 cq_verifier* cqv = cq_verifier_create(f.cq);
108 grpc_op ops[6];
109 grpc_op* op;
110 grpc_metadata_array initial_metadata_recv;
111 grpc_metadata_array trailing_metadata_recv;
112 grpc_metadata_array request_metadata_recv;
113 grpc_byte_buffer* request_payload_recv = nullptr;
114 grpc_call_details call_details;
115 grpc_status_code status;
116 grpc_call_error error;
117 grpc_slice details;
118
119 gpr_timespec deadline = five_seconds_from_now();
120 c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
121 grpc_slice_from_static_string("/foo"), nullptr,
122 deadline, nullptr);
123 GPR_ASSERT(c);
124
125 grpc_metadata_array_init(&initial_metadata_recv);
126 grpc_metadata_array_init(&trailing_metadata_recv);
127 grpc_metadata_array_init(&request_metadata_recv);
128 grpc_call_details_init(&call_details);
129
130 memset(ops, 0, sizeof(ops));
131 op = ops;
132 op->op = GRPC_OP_SEND_INITIAL_METADATA;
133 op->data.send_initial_metadata.count = 0;
134 op->data.send_initial_metadata.metadata = nullptr;
135 op->flags = 0;
136 op->reserved = nullptr;
137 op++;
138 op->op = GRPC_OP_SEND_MESSAGE;
139 op->data.send_message.send_message = request_payload;
140 op->flags = 0;
141 op->reserved = nullptr;
142 op++;
143 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
144 op->flags = 0;
145 op->reserved = nullptr;
146 op++;
147 op->op = GRPC_OP_RECV_INITIAL_METADATA;
148 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
149 op->flags = 0;
150 op->reserved = nullptr;
151 op++;
152 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
153 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
154 op->data.recv_status_on_client.status = &status;
155 op->data.recv_status_on_client.status_details = &details;
156 op->flags = 0;
157 op->reserved = nullptr;
158 op++;
159 error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
160 nullptr);
161 GPR_ASSERT(GRPC_CALL_OK == error);
162
163 error =
164 grpc_server_request_call(f.server, &s, &call_details,
165 &request_metadata_recv, f.cq, f.cq, tag(101));
166 GPR_ASSERT(GRPC_CALL_OK == error);
167
168 CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
169 cq_verify(cqv);
170
171 GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
172 GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied"));
173
174 grpc_slice_unref(details);
175 grpc_metadata_array_destroy(&initial_metadata_recv);
176 grpc_metadata_array_destroy(&trailing_metadata_recv);
177 grpc_metadata_array_destroy(&request_metadata_recv);
178 grpc_call_details_destroy(&call_details);
179
180 grpc_call_unref(c);
181
182 cq_verifier_destroy(cqv);
183
184 grpc_byte_buffer_destroy(request_payload);
185 grpc_byte_buffer_destroy(request_payload_recv);
186
187 end_test(&f);
188 config.tear_down_data(&f);
189 }
190
191 // Simple request via a CLIENT_CHANNEL or CLIENT_DIRECT_CHANNEL filter
192 // that always fails to initialize the call.
test_client_channel_filter(grpc_end2end_test_config config)193 static void test_client_channel_filter(grpc_end2end_test_config config) {
194 grpc_call* c;
195 grpc_slice request_payload_slice =
196 grpc_slice_from_copied_string("hello world");
197 grpc_byte_buffer* request_payload =
198 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
199 gpr_timespec deadline = five_seconds_from_now();
200 grpc_end2end_test_fixture f =
201 begin_test(config, "filter_call_init_fails", nullptr, nullptr);
202 cq_verifier* cqv = cq_verifier_create(f.cq);
203 grpc_op ops[6];
204 grpc_op* op;
205 grpc_metadata_array initial_metadata_recv;
206 grpc_metadata_array trailing_metadata_recv;
207 grpc_metadata_array request_metadata_recv;
208 grpc_byte_buffer* request_payload_recv = nullptr;
209 grpc_call_details call_details;
210 grpc_status_code status;
211 grpc_call_error error;
212 grpc_slice details;
213
214 c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
215 grpc_slice_from_static_string("/foo"), nullptr,
216 deadline, nullptr);
217 GPR_ASSERT(c);
218
219 grpc_metadata_array_init(&initial_metadata_recv);
220 grpc_metadata_array_init(&trailing_metadata_recv);
221 grpc_metadata_array_init(&request_metadata_recv);
222 grpc_call_details_init(&call_details);
223
224 memset(ops, 0, sizeof(ops));
225 op = ops;
226 op->op = GRPC_OP_SEND_INITIAL_METADATA;
227 op->data.send_initial_metadata.count = 0;
228 op->data.send_initial_metadata.metadata = nullptr;
229 op->flags = 0;
230 op->reserved = nullptr;
231 op++;
232 op->op = GRPC_OP_SEND_MESSAGE;
233 op->data.send_message.send_message = request_payload;
234 op->flags = 0;
235 op->reserved = nullptr;
236 op++;
237 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
238 op->flags = 0;
239 op->reserved = nullptr;
240 op++;
241 op->op = GRPC_OP_RECV_INITIAL_METADATA;
242 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
243 op->flags = 0;
244 op->reserved = nullptr;
245 op++;
246 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
247 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
248 op->data.recv_status_on_client.status = &status;
249 op->data.recv_status_on_client.status_details = &details;
250 op->flags = 0;
251 op->reserved = nullptr;
252 op++;
253 error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
254 nullptr);
255 GPR_ASSERT(GRPC_CALL_OK == error);
256
257 CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
258 cq_verify(cqv);
259
260 GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
261 GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied"));
262
263 grpc_slice_unref(details);
264 grpc_metadata_array_destroy(&initial_metadata_recv);
265 grpc_metadata_array_destroy(&trailing_metadata_recv);
266 grpc_metadata_array_destroy(&request_metadata_recv);
267 grpc_call_details_destroy(&call_details);
268
269 grpc_call_unref(c);
270
271 cq_verifier_destroy(cqv);
272
273 grpc_byte_buffer_destroy(request_payload);
274 grpc_byte_buffer_destroy(request_payload_recv);
275
276 end_test(&f);
277 config.tear_down_data(&f);
278 }
279
280 // Simple request via a CLIENT_SUBCHANNEL filter that always fails to
281 // initialize the call.
test_client_subchannel_filter(grpc_end2end_test_config config)282 static void test_client_subchannel_filter(grpc_end2end_test_config config) {
283 grpc_call* c;
284 grpc_slice request_payload_slice =
285 grpc_slice_from_copied_string("hello world");
286 grpc_byte_buffer* request_payload =
287 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
288 gpr_timespec deadline = five_seconds_from_now();
289 grpc_end2end_test_fixture f =
290 begin_test(config, "filter_call_init_fails", nullptr, nullptr);
291 cq_verifier* cqv = cq_verifier_create(f.cq);
292 grpc_op ops[6];
293 grpc_op* op;
294 grpc_metadata_array initial_metadata_recv;
295 grpc_metadata_array trailing_metadata_recv;
296 grpc_metadata_array request_metadata_recv;
297 grpc_byte_buffer* request_payload_recv = nullptr;
298 grpc_call_details call_details;
299 grpc_status_code status;
300 grpc_call_error error;
301 grpc_slice details;
302
303 c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
304 grpc_slice_from_static_string("/foo"), nullptr,
305 deadline, nullptr);
306 GPR_ASSERT(c);
307
308 grpc_metadata_array_init(&initial_metadata_recv);
309 grpc_metadata_array_init(&trailing_metadata_recv);
310 grpc_metadata_array_init(&request_metadata_recv);
311 grpc_call_details_init(&call_details);
312
313 memset(ops, 0, sizeof(ops));
314 op = ops;
315 op->op = GRPC_OP_SEND_INITIAL_METADATA;
316 op->data.send_initial_metadata.count = 0;
317 op->data.send_initial_metadata.metadata = nullptr;
318 op->flags = 0;
319 op->reserved = nullptr;
320 op++;
321 op->op = GRPC_OP_SEND_MESSAGE;
322 op->data.send_message.send_message = request_payload;
323 op->flags = 0;
324 op->reserved = nullptr;
325 op++;
326 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
327 op->flags = 0;
328 op->reserved = nullptr;
329 op++;
330 op->op = GRPC_OP_RECV_INITIAL_METADATA;
331 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
332 op->flags = 0;
333 op->reserved = nullptr;
334 op++;
335 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
336 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
337 op->data.recv_status_on_client.status = &status;
338 op->data.recv_status_on_client.status_details = &details;
339 op->flags = 0;
340 op->reserved = nullptr;
341 op++;
342
343 error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
344 nullptr);
345 GPR_ASSERT(GRPC_CALL_OK == error);
346
347 CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
348 cq_verify(cqv);
349
350 GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
351 GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied"));
352
353 // Reset and create a new call. (The first call uses a different code
354 // path in client_channel.c than subsequent calls on the same channel,
355 // and we need to test both.)
356 grpc_call_unref(c);
357 status = GRPC_STATUS_OK;
358 grpc_slice_unref(details);
359 details = grpc_empty_slice();
360
361 c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
362 grpc_slice_from_static_string("/foo"), nullptr,
363 deadline, nullptr);
364 GPR_ASSERT(c);
365
366 error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(2),
367 nullptr);
368 GPR_ASSERT(GRPC_CALL_OK == error);
369
370 CQ_EXPECT_COMPLETION(cqv, tag(2), 1);
371 cq_verify(cqv);
372
373 GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
374 GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied"));
375
376 grpc_slice_unref(details);
377 grpc_metadata_array_destroy(&initial_metadata_recv);
378 grpc_metadata_array_destroy(&trailing_metadata_recv);
379 grpc_metadata_array_destroy(&request_metadata_recv);
380 grpc_call_details_destroy(&call_details);
381
382 grpc_call_unref(c);
383
384 cq_verifier_destroy(cqv);
385
386 grpc_byte_buffer_destroy(request_payload);
387 grpc_byte_buffer_destroy(request_payload_recv);
388
389 end_test(&f);
390 config.tear_down_data(&f);
391 }
392
393 /*******************************************************************************
394 * Test filter - always fails to initialize a call
395 */
396
init_call_elem(grpc_call_element *,const grpc_call_element_args *)397 static grpc_error* init_call_elem(grpc_call_element* /*elem*/,
398 const grpc_call_element_args* /*args*/) {
399 return grpc_error_set_int(
400 GRPC_ERROR_CREATE_FROM_STATIC_STRING("access denied"),
401 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_PERMISSION_DENIED);
402 }
403
destroy_call_elem(grpc_call_element *,const grpc_call_final_info *,grpc_closure *)404 static void destroy_call_elem(grpc_call_element* /*elem*/,
405 const grpc_call_final_info* /*final_info*/,
406 grpc_closure* /*ignored*/) {}
407
init_channel_elem(grpc_channel_element *,grpc_channel_element_args *)408 static grpc_error* init_channel_elem(grpc_channel_element* /*elem*/,
409 grpc_channel_element_args* /*args*/) {
410 return GRPC_ERROR_NONE;
411 }
412
destroy_channel_elem(grpc_channel_element *)413 static void destroy_channel_elem(grpc_channel_element* /*elem*/) {}
414
415 static const grpc_channel_filter test_filter = {
416 grpc_call_next_op,
417 grpc_channel_next_op,
418 0,
419 init_call_elem,
420 grpc_call_stack_ignore_set_pollset_or_pollset_set,
421 destroy_call_elem,
422 0,
423 init_channel_elem,
424 destroy_channel_elem,
425 grpc_channel_next_get_info,
426 "filter_call_init_fails"};
427
428 /*******************************************************************************
429 * Registration
430 */
431
maybe_add_server_channel_filter(grpc_channel_stack_builder * builder,void *)432 static bool maybe_add_server_channel_filter(grpc_channel_stack_builder* builder,
433 void* /*arg*/) {
434 if (g_enable_server_channel_filter) {
435 // Want to add the filter as close to the end as possible, to make
436 // sure that all of the filters work well together. However, we
437 // can't add it at the very end, because the connected channel filter
438 // must be the last one. So we add it right before the last one.
439 grpc_channel_stack_builder_iterator* it =
440 grpc_channel_stack_builder_create_iterator_at_last(builder);
441 GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
442 const bool retval = grpc_channel_stack_builder_add_filter_before(
443 it, &test_filter, nullptr, nullptr);
444 grpc_channel_stack_builder_iterator_destroy(it);
445 return retval;
446 } else {
447 return true;
448 }
449 }
450
maybe_add_client_channel_filter(grpc_channel_stack_builder * builder,void *)451 static bool maybe_add_client_channel_filter(grpc_channel_stack_builder* builder,
452 void* /*arg*/) {
453 if (g_enable_client_channel_filter) {
454 // Want to add the filter as close to the end as possible, to make
455 // sure that all of the filters work well together. However, we
456 // can't add it at the very end, because the connected channel filter
457 // must be the last one. So we add it right before the last one.
458 grpc_channel_stack_builder_iterator* it =
459 grpc_channel_stack_builder_create_iterator_at_last(builder);
460 GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
461 const bool retval = grpc_channel_stack_builder_add_filter_before(
462 it, &test_filter, nullptr, nullptr);
463 grpc_channel_stack_builder_iterator_destroy(it);
464 return retval;
465 } else {
466 return true;
467 }
468 }
469
maybe_add_client_subchannel_filter(grpc_channel_stack_builder * builder,void *)470 static bool maybe_add_client_subchannel_filter(
471 grpc_channel_stack_builder* builder, void* /*arg*/) {
472 if (g_enable_client_subchannel_filter) {
473 // Want to add the filter as close to the end as possible, to make
474 // sure that all of the filters work well together. However, we
475 // can't add it at the very end, because the client channel filter
476 // must be the last one. So we add it right before the last one.
477 grpc_channel_stack_builder_iterator* it =
478 grpc_channel_stack_builder_create_iterator_at_last(builder);
479 GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
480 const bool retval = grpc_channel_stack_builder_add_filter_before(
481 it, &test_filter, nullptr, nullptr);
482 grpc_channel_stack_builder_iterator_destroy(it);
483 return retval;
484 } else {
485 return true;
486 }
487 }
488
init_plugin(void)489 static void init_plugin(void) {
490 grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
491 maybe_add_server_channel_filter, nullptr);
492 grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
493 maybe_add_client_channel_filter, nullptr);
494 grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
495 maybe_add_client_subchannel_filter, nullptr);
496 grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
497 maybe_add_client_channel_filter, nullptr);
498 }
499
destroy_plugin(void)500 static void destroy_plugin(void) {}
501
filter_call_init_fails(grpc_end2end_test_config config)502 void filter_call_init_fails(grpc_end2end_test_config config) {
503 gpr_log(GPR_INFO, "Testing SERVER_CHANNEL filter.");
504 g_enable_server_channel_filter = true;
505 test_server_channel_filter(config);
506 g_enable_server_channel_filter = false;
507 gpr_log(GPR_INFO, "Testing CLIENT_CHANNEL / CLIENT_DIRECT_CHANNEL filter.");
508 g_enable_client_channel_filter = true;
509 test_client_channel_filter(config);
510 g_enable_client_channel_filter = false;
511 if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) {
512 gpr_log(GPR_INFO, "Testing CLIENT_SUBCHANNEL filter.");
513 g_enable_client_subchannel_filter = true;
514 test_client_subchannel_filter(config);
515 g_enable_client_subchannel_filter = false;
516 }
517 }
518
filter_call_init_fails_pre_init(void)519 void filter_call_init_fails_pre_init(void) {
520 grpc_register_plugin(init_plugin, destroy_plugin);
521 }
522