blob: f9129605e9bec128af8bb7605ff67b1b522da2aa [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
David Garcia Quintas243fe9d2017-08-24 14:16:37 -070062bool g_replacement_fn_called = false;
63bool g_original_fn_called = false;
64void set_arg_once_fn(grpc_channel_stack *channel_stack,
65 grpc_channel_element *elem, void *arg) {
Yash Tibrewal34a57d02017-10-23 15:33:21 -070066 bool *called = static_cast<bool *>(arg);
David Garcia Quintas243fe9d2017-08-24 14:16:37 -070067 // Make sure this function is only called once per arg.
68 GPR_ASSERT(*called == false);
69 *called = true;
70}
71
72static void test_channel_stack_builder_filter_replace(void) {
73 grpc_channel *channel =
74 grpc_insecure_channel_create("target name isn't used", NULL, NULL);
75 GPR_ASSERT(channel != NULL);
76 // Make sure the high priority filter has been created.
77 GPR_ASSERT(g_replacement_fn_called);
78 // ... and that the low priority one hasn't.
79 GPR_ASSERT(!g_original_fn_called);
80 grpc_channel_destroy(channel);
81}
82
83const grpc_channel_filter replacement_filter = {
84 call_func,
85 channel_func,
86 0,
87 call_init_func,
88 grpc_call_stack_ignore_set_pollset_or_pollset_set,
89 call_destroy_func,
90 0,
91 channel_init_func,
92 channel_destroy_func,
David Garcia Quintas243fe9d2017-08-24 14:16:37 -070093 grpc_channel_next_get_info,
94 "filter_name"};
95
96const grpc_channel_filter original_filter = {
97 call_func,
98 channel_func,
99 0,
100 call_init_func,
101 grpc_call_stack_ignore_set_pollset_or_pollset_set,
102 call_destroy_func,
103 0,
104 channel_init_func,
105 channel_destroy_func,
David Garcia Quintas243fe9d2017-08-24 14:16:37 -0700106 grpc_channel_next_get_info,
107 "filter_name"};
108
109static bool add_replacement_filter(grpc_exec_ctx *exec_ctx,
110 grpc_channel_stack_builder *builder,
111 void *arg) {
Yash Tibrewal34a57d02017-10-23 15:33:21 -0700112 const grpc_channel_filter *filter =
113 static_cast<const grpc_channel_filter *>(arg);
David Garcia Quintas243fe9d2017-08-24 14:16:37 -0700114 // Get rid of any other version of the filter, as determined by having the
115 // same name.
116 GPR_ASSERT(grpc_channel_stack_builder_remove_filter(builder, filter->name));
117 return grpc_channel_stack_builder_prepend_filter(
118 builder, filter, set_arg_once_fn, &g_replacement_fn_called);
119}
120
121static bool add_original_filter(grpc_exec_ctx *exec_ctx,
122 grpc_channel_stack_builder *builder,
123 void *arg) {
124 return grpc_channel_stack_builder_prepend_filter(
125 builder, (const grpc_channel_filter *)arg, set_arg_once_fn,
126 &g_original_fn_called);
127}
128
129static void init_plugin(void) {
130 grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
131 add_original_filter,
132 (void *)&original_filter);
133 grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
134 add_replacement_filter,
135 (void *)&replacement_filter);
136}
137
138static void destroy_plugin(void) {}
139
140int main(int argc, char **argv) {
141 grpc_test_init(argc, argv);
142 grpc_register_plugin(init_plugin, destroy_plugin);
143 grpc_init();
144 test_channel_stack_builder_filter_replace();
145 grpc_shutdown();
146 return 0;
147}