blob: ed193ea042793d147f6d69da54548ebd4cc88986 [file] [log] [blame]
Mark D. Roth5d11e432016-06-23 13:14:05 -07001/*
2 *
3 * Copyright 2016, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "test/core/end2end/end2end_tests.h"
35
Mark D. Roth44a2f252016-07-18 14:13:31 -070036#include <limits.h>
Mark D. Roth5d11e432016-06-23 13:14:05 -070037#include <stdbool.h>
38#include <stdio.h>
39#include <string.h>
40
41#include <grpc/byte_buffer.h>
42#include <grpc/support/alloc.h>
43#include <grpc/support/log.h>
44#include <grpc/support/time.h>
45#include <grpc/support/useful.h>
46#include "src/core/lib/channel/channel_stack_builder.h"
47#include "src/core/lib/surface/channel_init.h"
48#include "test/core/end2end/cq_verifier.h"
49
50enum { TIMEOUT = 200000 };
51
52static bool g_enable_filter = false;
53
54static void *tag(intptr_t t) { return (void *)t; }
55
56static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
57 const char *test_name,
58 grpc_channel_args *client_args,
59 grpc_channel_args *server_args) {
60 grpc_end2end_test_fixture f;
Robbie Shade55a046a2017-01-25 15:14:28 -050061 gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
Mark D. Roth5d11e432016-06-23 13:14:05 -070062 f = config.create_fixture(client_args, server_args);
63 config.init_server(&f, server_args);
Mark D. Rothe127a392016-10-27 08:27:15 -070064 config.init_client(&f, client_args);
Mark D. Roth5d11e432016-06-23 13:14:05 -070065 return f;
66}
67
68static gpr_timespec n_seconds_time(int n) {
Robbie Shadeca7effc2017-01-17 09:14:29 -050069 return grpc_timeout_seconds_to_deadline(n);
Mark D. Roth5d11e432016-06-23 13:14:05 -070070}
71
72static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
73
74static void drain_cq(grpc_completion_queue *cq) {
75 grpc_event ev;
76 do {
77 ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL);
78 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
79}
80
81static void shutdown_server(grpc_end2end_test_fixture *f) {
82 if (!f->server) return;
Sree Kuchibhotla321881d2017-02-27 11:25:28 -080083 grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
84 GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
85 grpc_timeout_seconds_to_deadline(5),
86 NULL)
Mark D. Roth5d11e432016-06-23 13:14:05 -070087 .type == GRPC_OP_COMPLETE);
88 grpc_server_destroy(f->server);
89 f->server = NULL;
90}
91
92static void shutdown_client(grpc_end2end_test_fixture *f) {
93 if (!f->client) return;
94 grpc_channel_destroy(f->client);
95 f->client = NULL;
96}
97
98static void end_test(grpc_end2end_test_fixture *f) {
99 shutdown_server(f);
100 shutdown_client(f);
101
102 grpc_completion_queue_shutdown(f->cq);
103 drain_cq(f->cq);
104 grpc_completion_queue_destroy(f->cq);
Sree Kuchibhotla321881d2017-02-27 11:25:28 -0800105 grpc_completion_queue_destroy(f->shutdown_cq);
Mark D. Roth5d11e432016-06-23 13:14:05 -0700106}
107
108// Simple request via a server filter that always fails to initialize
109// the call.
110static void test_request(grpc_end2end_test_config config) {
111 grpc_call *c;
112 grpc_call *s;
Craig Tiller28b72422016-10-26 21:15:29 -0700113 grpc_slice request_payload_slice =
114 grpc_slice_from_copied_string("hello world");
Mark D. Roth5d11e432016-06-23 13:14:05 -0700115 grpc_byte_buffer *request_payload =
116 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
117 gpr_timespec deadline = five_seconds_time();
118 grpc_end2end_test_fixture f =
119 begin_test(config, "filter_call_init_fails", NULL, NULL);
120 cq_verifier *cqv = cq_verifier_create(f.cq);
121 grpc_op ops[6];
122 grpc_op *op;
123 grpc_metadata_array initial_metadata_recv;
124 grpc_metadata_array trailing_metadata_recv;
125 grpc_metadata_array request_metadata_recv;
126 grpc_byte_buffer *request_payload_recv = NULL;
127 grpc_call_details call_details;
128 grpc_status_code status;
129 grpc_call_error error;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800130 grpc_slice details;
Mark D. Roth5d11e432016-06-23 13:14:05 -0700131
Muxi Yan5ebd3272016-10-31 07:27:07 -0700132 c = grpc_channel_create_call(
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800133 f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
134 grpc_slice_from_static_string("/foo"),
135 get_host_override_slice("foo.test.google.fr:1234", config), deadline,
Muxi Yan5ebd3272016-10-31 07:27:07 -0700136 NULL);
Mark D. Roth5d11e432016-06-23 13:14:05 -0700137 GPR_ASSERT(c);
138
139 grpc_metadata_array_init(&initial_metadata_recv);
140 grpc_metadata_array_init(&trailing_metadata_recv);
141 grpc_metadata_array_init(&request_metadata_recv);
142 grpc_call_details_init(&call_details);
143
144 memset(ops, 0, sizeof(ops));
145 op = ops;
146 op->op = GRPC_OP_SEND_INITIAL_METADATA;
147 op->data.send_initial_metadata.count = 0;
148 op->data.send_initial_metadata.metadata = NULL;
149 op->flags = 0;
150 op->reserved = NULL;
151 op++;
152 op->op = GRPC_OP_SEND_MESSAGE;
Mark D. Roth435f9f22017-01-25 12:53:54 -0800153 op->data.send_message.send_message = request_payload;
Mark D. Roth5d11e432016-06-23 13:14:05 -0700154 op->flags = 0;
155 op->reserved = NULL;
156 op++;
157 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
158 op->flags = 0;
159 op->reserved = NULL;
160 op++;
161 op->op = GRPC_OP_RECV_INITIAL_METADATA;
Mark D. Roth435f9f22017-01-25 12:53:54 -0800162 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
Mark D. Roth5d11e432016-06-23 13:14:05 -0700163 op->flags = 0;
164 op->reserved = NULL;
165 op++;
166 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
167 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
168 op->data.recv_status_on_client.status = &status;
169 op->data.recv_status_on_client.status_details = &details;
Mark D. Roth5d11e432016-06-23 13:14:05 -0700170 op->flags = 0;
171 op->reserved = NULL;
172 op++;
173 error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
174 GPR_ASSERT(GRPC_CALL_OK == error);
175
176 error =
177 grpc_server_request_call(f.server, &s, &call_details,
178 &request_metadata_recv, f.cq, f.cq, tag(101));
179 GPR_ASSERT(GRPC_CALL_OK == error);
180
Mark D. Roth7f9bba82016-08-25 08:35:42 -0700181 CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
Mark D. Roth5d11e432016-06-23 13:14:05 -0700182 cq_verify(cqv);
183
184 GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800185 GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied"));
Mark D. Roth5d11e432016-06-23 13:14:05 -0700186
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800187 grpc_slice_unref(details);
Mark D. Roth5d11e432016-06-23 13:14:05 -0700188 grpc_metadata_array_destroy(&initial_metadata_recv);
189 grpc_metadata_array_destroy(&trailing_metadata_recv);
190 grpc_metadata_array_destroy(&request_metadata_recv);
191 grpc_call_details_destroy(&call_details);
192
193 grpc_call_destroy(c);
194
195 cq_verifier_destroy(cqv);
196
197 grpc_byte_buffer_destroy(request_payload);
198 grpc_byte_buffer_destroy(request_payload_recv);
199
200 end_test(&f);
201 config.tear_down_data(&f);
202}
203
204/*******************************************************************************
205 * Test filter - always fails to initialize a call
206 */
207
Mark D. Roth76d24422016-06-23 13:22:10 -0700208static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5d11e432016-06-23 13:14:05 -0700209 grpc_call_element *elem,
Craig Tiller3e16f4f2017-02-17 06:58:43 -0800210 const grpc_call_element_args *args) {
Mark D. Roth5d11e432016-06-23 13:14:05 -0700211 return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"),
212 GRPC_ERROR_INT_GRPC_STATUS,
213 GRPC_STATUS_PERMISSION_DENIED);
214}
215
216static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
Mark D. Rothcca4a192016-08-02 10:36:53 -0700217 const grpc_call_final_info *final_info,
Craig Tillerd426cac2017-03-13 12:30:45 -0700218 grpc_closure *ignored) {}
Mark D. Roth5d11e432016-06-23 13:14:05 -0700219
Mark D. Rothc1087882016-11-18 10:54:45 -0800220static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800221 grpc_channel_element *elem,
222 grpc_channel_element_args *args) {
223 return GRPC_ERROR_NONE;
224}
Mark D. Roth5d11e432016-06-23 13:14:05 -0700225
226static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
227 grpc_channel_element *elem) {}
228
229static const grpc_channel_filter test_filter = {
230 grpc_call_next_op,
231 grpc_channel_next_op,
232 0,
233 init_call_elem,
234 grpc_call_stack_ignore_set_pollset_or_pollset_set,
235 destroy_call_elem,
236 0,
237 init_channel_elem,
238 destroy_channel_elem,
239 grpc_call_next_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -0700240 grpc_channel_next_get_info,
Mark D. Roth5d11e432016-06-23 13:14:05 -0700241 "filter_call_init_fails"};
242
243/*******************************************************************************
244 * Registration
245 */
246
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800247static bool maybe_add_filter(grpc_exec_ctx *exec_ctx,
248 grpc_channel_stack_builder *builder, void *arg) {
Mark D. Roth5d11e432016-06-23 13:14:05 -0700249 if (g_enable_filter) {
Mark D. Rothb5f32f02016-07-19 08:36:52 -0700250 // Want to add the filter as close to the end as possible, to make
251 // sure that all of the filters work well together. However, we
252 // can't add it at the very end, because the connected channel filter
253 // must be the last one. So we add it right before the last one.
254 grpc_channel_stack_builder_iterator *it =
255 grpc_channel_stack_builder_create_iterator_at_last(builder);
256 GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
Mark D. Roth05d73af2016-07-27 15:52:46 +0000257 const bool retval = grpc_channel_stack_builder_add_filter_before(
258 it, &test_filter, NULL, NULL);
259 grpc_channel_stack_builder_iterator_destroy(it);
260 return retval;
Mark D. Roth5d11e432016-06-23 13:14:05 -0700261 } else {
262 return true;
263 }
264}
265
266static void init_plugin(void) {
Mark D. Roth44a2f252016-07-18 14:13:31 -0700267 grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
Mark D. Roth51d00222016-07-15 09:12:26 -0700268 maybe_add_filter, NULL);
Mark D. Roth5d11e432016-06-23 13:14:05 -0700269}
270
271static void destroy_plugin(void) {}
272
273void filter_call_init_fails(grpc_end2end_test_config config) {
274 g_enable_filter = true;
275 test_request(config);
276 g_enable_filter = false;
277}
278
279void filter_call_init_fails_pre_init(void) {
280 grpc_register_plugin(init_plugin, destroy_plugin);
281}