blob: 0b7d212f58883319d7a754cf8d67f4e55b74191a [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;
61 gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
62 f = config.create_fixture(client_args, server_args);
63 config.init_server(&f, server_args);
Mark D. Rothec393342016-10-03 13:14:56 -070064 config.init_client(&f, client_args, NULL);
Mark D. Roth5d11e432016-06-23 13:14:05 -070065 return f;
66}
67
68static gpr_timespec n_seconds_time(int n) {
69 return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
70}
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;
83 grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
84 GPR_ASSERT(grpc_completion_queue_pluck(
85 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
86 .type == GRPC_OP_COMPLETE);
87 grpc_server_destroy(f->server);
88 f->server = NULL;
89}
90
91static void shutdown_client(grpc_end2end_test_fixture *f) {
92 if (!f->client) return;
93 grpc_channel_destroy(f->client);
94 f->client = NULL;
95}
96
97static void end_test(grpc_end2end_test_fixture *f) {
98 shutdown_server(f);
99 shutdown_client(f);
100
101 grpc_completion_queue_shutdown(f->cq);
102 drain_cq(f->cq);
103 grpc_completion_queue_destroy(f->cq);
104}
105
106// Simple request via a server filter that always fails to initialize
107// the call.
108static void test_request(grpc_end2end_test_config config) {
109 grpc_call *c;
110 grpc_call *s;
111 gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
112 grpc_byte_buffer *request_payload =
113 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
114 gpr_timespec deadline = five_seconds_time();
115 grpc_end2end_test_fixture f =
116 begin_test(config, "filter_call_init_fails", NULL, NULL);
117 cq_verifier *cqv = cq_verifier_create(f.cq);
118 grpc_op ops[6];
119 grpc_op *op;
120 grpc_metadata_array initial_metadata_recv;
121 grpc_metadata_array trailing_metadata_recv;
122 grpc_metadata_array request_metadata_recv;
123 grpc_byte_buffer *request_payload_recv = NULL;
124 grpc_call_details call_details;
125 grpc_status_code status;
126 grpc_call_error error;
127 char *details = NULL;
128 size_t details_capacity = 0;
129
Muxi Yan5ebd3272016-10-31 07:27:07 -0700130 c = grpc_channel_create_call(
131 f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
132 get_host_override_string("foo.test.google.fr:1234", config), deadline,
133 NULL);
Mark D. Roth5d11e432016-06-23 13:14:05 -0700134 GPR_ASSERT(c);
135
136 grpc_metadata_array_init(&initial_metadata_recv);
137 grpc_metadata_array_init(&trailing_metadata_recv);
138 grpc_metadata_array_init(&request_metadata_recv);
139 grpc_call_details_init(&call_details);
140
141 memset(ops, 0, sizeof(ops));
142 op = ops;
143 op->op = GRPC_OP_SEND_INITIAL_METADATA;
144 op->data.send_initial_metadata.count = 0;
145 op->data.send_initial_metadata.metadata = NULL;
146 op->flags = 0;
147 op->reserved = NULL;
148 op++;
149 op->op = GRPC_OP_SEND_MESSAGE;
150 op->data.send_message = request_payload;
151 op->flags = 0;
152 op->reserved = NULL;
153 op++;
154 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
155 op->flags = 0;
156 op->reserved = NULL;
157 op++;
158 op->op = GRPC_OP_RECV_INITIAL_METADATA;
159 op->data.recv_initial_metadata = &initial_metadata_recv;
160 op->flags = 0;
161 op->reserved = NULL;
162 op++;
163 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
164 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
165 op->data.recv_status_on_client.status = &status;
166 op->data.recv_status_on_client.status_details = &details;
167 op->data.recv_status_on_client.status_details_capacity = &details_capacity;
168 op->flags = 0;
169 op->reserved = NULL;
170 op++;
171 error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
172 GPR_ASSERT(GRPC_CALL_OK == error);
173
174 error =
175 grpc_server_request_call(f.server, &s, &call_details,
176 &request_metadata_recv, f.cq, f.cq, tag(101));
177 GPR_ASSERT(GRPC_CALL_OK == error);
178
Mark D. Roth7f9bba82016-08-25 08:35:42 -0700179 CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
Mark D. Roth5d11e432016-06-23 13:14:05 -0700180 cq_verify(cqv);
181
182 GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
183 GPR_ASSERT(0 == strcmp(details, "access denied"));
184
185 gpr_free(details);
186 grpc_metadata_array_destroy(&initial_metadata_recv);
187 grpc_metadata_array_destroy(&trailing_metadata_recv);
188 grpc_metadata_array_destroy(&request_metadata_recv);
189 grpc_call_details_destroy(&call_details);
190
191 grpc_call_destroy(c);
192
193 cq_verifier_destroy(cqv);
194
195 grpc_byte_buffer_destroy(request_payload);
196 grpc_byte_buffer_destroy(request_payload_recv);
197
198 end_test(&f);
199 config.tear_down_data(&f);
200}
201
202/*******************************************************************************
203 * Test filter - always fails to initialize a call
204 */
205
Mark D. Roth76d24422016-06-23 13:22:10 -0700206static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5d11e432016-06-23 13:14:05 -0700207 grpc_call_element *elem,
208 grpc_call_element_args *args) {
209 return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"),
210 GRPC_ERROR_INT_GRPC_STATUS,
211 GRPC_STATUS_PERMISSION_DENIED);
212}
213
214static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
Mark D. Rothcca4a192016-08-02 10:36:53 -0700215 const grpc_call_final_info *final_info,
Mark D. Roth5d11e432016-06-23 13:14:05 -0700216 void *and_free_memory) {}
217
218static void init_channel_elem(grpc_exec_ctx *exec_ctx,
219 grpc_channel_element *elem,
220 grpc_channel_element_args *args) {}
221
222static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
223 grpc_channel_element *elem) {}
224
225static const grpc_channel_filter test_filter = {
226 grpc_call_next_op,
227 grpc_channel_next_op,
228 0,
229 init_call_elem,
230 grpc_call_stack_ignore_set_pollset_or_pollset_set,
231 destroy_call_elem,
232 0,
233 init_channel_elem,
234 destroy_channel_elem,
235 grpc_call_next_get_peer,
236 "filter_call_init_fails"};
237
238/*******************************************************************************
239 * Registration
240 */
241
242static bool maybe_add_filter(grpc_channel_stack_builder *builder, void *arg) {
243 if (g_enable_filter) {
Mark D. Rothb5f32f02016-07-19 08:36:52 -0700244 // Want to add the filter as close to the end as possible, to make
245 // sure that all of the filters work well together. However, we
246 // can't add it at the very end, because the connected channel filter
247 // must be the last one. So we add it right before the last one.
248 grpc_channel_stack_builder_iterator *it =
249 grpc_channel_stack_builder_create_iterator_at_last(builder);
250 GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
Mark D. Roth05d73af2016-07-27 15:52:46 +0000251 const bool retval = grpc_channel_stack_builder_add_filter_before(
252 it, &test_filter, NULL, NULL);
253 grpc_channel_stack_builder_iterator_destroy(it);
254 return retval;
Mark D. Roth5d11e432016-06-23 13:14:05 -0700255 } else {
256 return true;
257 }
258}
259
260static void init_plugin(void) {
Mark D. Roth44a2f252016-07-18 14:13:31 -0700261 grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
Mark D. Roth51d00222016-07-15 09:12:26 -0700262 maybe_add_filter, NULL);
Mark D. Roth5d11e432016-06-23 13:14:05 -0700263}
264
265static void destroy_plugin(void) {}
266
267void filter_call_init_fails(grpc_end2end_test_config config) {
Mark D. Roth5d11e432016-06-23 13:14:05 -0700268 g_enable_filter = true;
269 test_request(config);
270 g_enable_filter = false;
271}
272
273void filter_call_init_fails_pre_init(void) {
274 grpc_register_plugin(init_plugin, destroy_plugin);
275}