blob: be6afb7c07e2fa000763bfcf5a04c58568fa2c75 [file] [log] [blame]
David Garcia Quintas243fe9d2017-08-24 14:16:37 -07001/*
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 "src/core/lib/channel/channel_stack_builder.h"
20
21#include <limits.h>
22#include <string.h>
23
24#include <grpc/support/alloc.h>
25#include <grpc/support/log.h>
26#include <grpc/support/string_util.h>
27
28#include "src/core/lib/slice/slice_internal.h"
29#include "src/core/lib/surface/channel_init.h"
30#include "test/core/util/test_config.h"
31
32static grpc_error *channel_init_func(grpc_exec_ctx *exec_ctx,
33 grpc_channel_element *elem,
34 grpc_channel_element_args *args) {
35 return GRPC_ERROR_NONE;
36}
37
38static grpc_error *call_init_func(grpc_exec_ctx *exec_ctx,
39 grpc_call_element *elem,
40 const grpc_call_element_args *args) {
41 return GRPC_ERROR_NONE;
42}
43
44static void channel_destroy_func(grpc_exec_ctx *exec_ctx,
45 grpc_channel_element *elem) {}
46
47static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
48 const grpc_call_final_info *final_info,
49 grpc_closure *ignored) {}
50
51static void call_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
52 grpc_transport_stream_op_batch *op) {}
53
54static void channel_func(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
55 grpc_transport_op *op) {
56 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
57 GRPC_ERROR_UNREF(op->disconnect_with_error);
58 }
59 GRPC_CLOSURE_SCHED(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
60}
61
62static char *get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
63 return gpr_strdup("peer");
64}
65
66bool g_replacement_fn_called = false;
67bool g_original_fn_called = false;
68void set_arg_once_fn(grpc_channel_stack *channel_stack,
69 grpc_channel_element *elem, void *arg) {
70 bool *called = arg;
71 // Make sure this function is only called once per arg.
72 GPR_ASSERT(*called == false);
73 *called = true;
74}
75
76static void test_channel_stack_builder_filter_replace(void) {
77 grpc_channel *channel =
78 grpc_insecure_channel_create("target name isn't used", NULL, NULL);
79 GPR_ASSERT(channel != NULL);
80 // Make sure the high priority filter has been created.
81 GPR_ASSERT(g_replacement_fn_called);
82 // ... and that the low priority one hasn't.
83 GPR_ASSERT(!g_original_fn_called);
84 grpc_channel_destroy(channel);
85}
86
87const grpc_channel_filter replacement_filter = {
88 call_func,
89 channel_func,
90 0,
91 call_init_func,
92 grpc_call_stack_ignore_set_pollset_or_pollset_set,
93 call_destroy_func,
94 0,
95 channel_init_func,
96 channel_destroy_func,
97 get_peer,
98 grpc_channel_next_get_info,
99 "filter_name"};
100
101const grpc_channel_filter original_filter = {
102 call_func,
103 channel_func,
104 0,
105 call_init_func,
106 grpc_call_stack_ignore_set_pollset_or_pollset_set,
107 call_destroy_func,
108 0,
109 channel_init_func,
110 channel_destroy_func,
111 get_peer,
112 grpc_channel_next_get_info,
113 "filter_name"};
114
115static bool add_replacement_filter(grpc_exec_ctx *exec_ctx,
116 grpc_channel_stack_builder *builder,
117 void *arg) {
118 const grpc_channel_filter *filter = arg;
119 // Get rid of any other version of the filter, as determined by having the
120 // same name.
121 GPR_ASSERT(grpc_channel_stack_builder_remove_filter(builder, filter->name));
122 return grpc_channel_stack_builder_prepend_filter(
123 builder, filter, set_arg_once_fn, &g_replacement_fn_called);
124}
125
126static bool add_original_filter(grpc_exec_ctx *exec_ctx,
127 grpc_channel_stack_builder *builder,
128 void *arg) {
129 return grpc_channel_stack_builder_prepend_filter(
130 builder, (const grpc_channel_filter *)arg, set_arg_once_fn,
131 &g_original_fn_called);
132}
133
134static void init_plugin(void) {
135 grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
136 add_original_filter,
137 (void *)&original_filter);
138 grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
139 add_replacement_filter,
140 (void *)&replacement_filter);
141}
142
143static void destroy_plugin(void) {}
144
145int main(int argc, char **argv) {
146 grpc_test_init(argc, argv);
147 grpc_register_plugin(init_plugin, destroy_plugin);
148 grpc_init();
149 test_channel_stack_builder_filter_replace();
150 grpc_shutdown();
151 return 0;
152}