• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 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 <grpc/impl/codegen/grpc_types.h>
20 #include <grpc/impl/codegen/log.h>
21 #include <string.h>
22 
23 #include <grpc/support/log.h>
24 
25 #include "src/core/lib/channel/channel_args.h"
26 #include "src/core/lib/channel/channel_stack.h"
27 #include "src/core/lib/gpr/useful.h"
28 #include "src/core/lib/iomgr/exec_ctx.h"
29 #include "src/core/lib/surface/channel.h"
30 #include "test/core/util/test_config.h"
31 
test_create(void)32 static void test_create(void) {
33   grpc_core::ExecCtx exec_ctx;
34   grpc_arg to_add[2];
35   grpc_channel_args* ch_args;
36 
37   to_add[0] =
38       grpc_channel_arg_integer_create(const_cast<char*>("int_arg"), 123);
39   to_add[1] = grpc_channel_arg_string_create(const_cast<char*>("str key"),
40                                              const_cast<char*>("str value"));
41   ch_args = grpc_channel_args_copy_and_add(nullptr, to_add, 2);
42 
43   GPR_ASSERT(ch_args->num_args == 2);
44   GPR_ASSERT(strcmp(ch_args->args[0].key, to_add[0].key) == 0);
45   GPR_ASSERT(ch_args->args[0].type == to_add[0].type);
46   GPR_ASSERT(ch_args->args[0].value.integer == to_add[0].value.integer);
47 
48   GPR_ASSERT(strcmp(ch_args->args[1].key, to_add[1].key) == 0);
49   GPR_ASSERT(ch_args->args[1].type == to_add[1].type);
50   GPR_ASSERT(strcmp(ch_args->args[1].value.string, to_add[1].value.string) ==
51              0);
52 
53   grpc_channel_args_destroy(ch_args);
54 }
55 
56 struct fake_class {
57   int foo;
58 };
59 
fake_pointer_arg_copy(void * arg)60 static void* fake_pointer_arg_copy(void* arg) {
61   gpr_log(GPR_DEBUG, "fake_pointer_arg_copy");
62   fake_class* fc = static_cast<fake_class*>(arg);
63   fake_class* new_fc = static_cast<fake_class*>(gpr_malloc(sizeof(fake_class)));
64   new_fc->foo = fc->foo;
65   return new_fc;
66 }
67 
fake_pointer_arg_destroy(void * arg)68 static void fake_pointer_arg_destroy(void* arg) {
69   gpr_log(GPR_DEBUG, "fake_pointer_arg_destroy");
70   fake_class* fc = static_cast<fake_class*>(arg);
71   gpr_free(fc);
72 }
73 
fake_pointer_cmp(void * a,void * b)74 static int fake_pointer_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
75 
76 static const grpc_arg_pointer_vtable fake_pointer_arg_vtable = {
77     fake_pointer_arg_copy, fake_pointer_arg_destroy, fake_pointer_cmp};
78 
test_channel_create_with_args(void)79 static void test_channel_create_with_args(void) {
80   grpc_arg client_a[3];
81 
82   client_a[0] =
83       grpc_channel_arg_integer_create(const_cast<char*>("arg_int"), 0);
84   client_a[1] = grpc_channel_arg_string_create(
85       const_cast<char*>("arg_str"), const_cast<char*>("arg_str_val"));
86   // allocated and adds custom pointer arg
87   fake_class* fc = static_cast<fake_class*>(gpr_malloc(sizeof(fake_class)));
88   fc->foo = 42;
89   client_a[2] = grpc_channel_arg_pointer_create(
90       const_cast<char*>("arg_pointer"), fc, &fake_pointer_arg_vtable);
91 
92   // creates channel
93   grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
94   grpc_channel* c =
95       grpc_insecure_channel_create("fake_target", &client_args, nullptr);
96   // user is can free the memory they allocated here
97   gpr_free(fc);
98   grpc_channel_destroy(c);
99 }
100 
mutate_channel_args(const char * target,grpc_channel_args * old_args,grpc_channel_stack_type)101 grpc_channel_args* mutate_channel_args(const char* target,
102                                        grpc_channel_args* old_args,
103                                        grpc_channel_stack_type /*type*/) {
104   GPR_ASSERT(old_args != nullptr);
105   GPR_ASSERT(grpc_channel_args_find(old_args, "arg_int")->value.integer == 0);
106   GPR_ASSERT(strcmp(grpc_channel_args_find(old_args, "arg_str")->value.string,
107                     "arg_str_val") == 0);
108   GPR_ASSERT(
109       grpc_channel_args_find(old_args, "arg_pointer")->value.pointer.vtable ==
110       &fake_pointer_arg_vtable);
111 
112   if (strcmp(target, "no_op_mutator") == 0) {
113     return old_args;
114   }
115 
116   GPR_ASSERT(strcmp(target, "minimal_stack_mutator") == 0);
117   const char* args_to_remove[] = {"arg_int", "arg_str", "arg_pointer"};
118 
119   grpc_arg no_deadline_filter_arg = grpc_channel_arg_integer_create(
120       const_cast<char*>(GRPC_ARG_MINIMAL_STACK), 1);
121   grpc_channel_args* new_args = nullptr;
122   new_args = grpc_channel_args_copy_and_add_and_remove(
123       old_args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove),
124       &no_deadline_filter_arg, 1);
125   grpc_channel_args_destroy(old_args);
126   return new_args;
127 }
128 
129 // Minimal stack should not have client_idle filter
channel_has_client_idle_filter(grpc_channel * c)130 static bool channel_has_client_idle_filter(grpc_channel* c) {
131   grpc_channel_stack* stack = grpc_channel_get_channel_stack(c);
132   for (size_t i = 0; i < stack->count; i++) {
133     if (strcmp(grpc_channel_stack_element(stack, i)->filter->name,
134                "client_idle") == 0) {
135       return true;
136     }
137   }
138   return false;
139 }
140 
test_channel_create_with_global_mutator(void)141 static void test_channel_create_with_global_mutator(void) {
142   grpc_channel_args_set_client_channel_creation_mutator(mutate_channel_args);
143   // We also add some custom args to make sure the ownership is correct.
144   grpc_arg client_a[3];
145 
146   client_a[0] =
147       grpc_channel_arg_integer_create(const_cast<char*>("arg_int"), 0);
148   client_a[1] = grpc_channel_arg_string_create(
149       const_cast<char*>("arg_str"), const_cast<char*>("arg_str_val"));
150   // allocated and adds custom pointer arg
151   fake_class* fc = static_cast<fake_class*>(gpr_malloc(sizeof(fake_class)));
152   fc->foo = 42;
153   client_a[2] = grpc_channel_arg_pointer_create(
154       const_cast<char*>("arg_pointer"), fc, &fake_pointer_arg_vtable);
155 
156   // creates channels
157   grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
158   grpc_channel* c =
159       grpc_insecure_channel_create("no_op_mutator", &client_args, nullptr);
160   GPR_ASSERT(channel_has_client_idle_filter(c));
161   grpc_channel_destroy(c);
162 
163   c = grpc_insecure_channel_create("minimal_stack_mutator", &client_args,
164                                    nullptr);
165   GPR_ASSERT(channel_has_client_idle_filter(c) == false);
166   grpc_channel_destroy(c);
167 
168   gpr_free(fc);
169   auto mutator = grpc_channel_args_get_client_channel_creation_mutator();
170   GPR_ASSERT(mutator == &mutate_channel_args);
171 }
172 
test_server_create_with_args(void)173 static void test_server_create_with_args(void) {
174   grpc_arg server_a[3];
175 
176   // adds integer arg
177   server_a[0].type = GRPC_ARG_INTEGER;
178   server_a[0].key = const_cast<char*>("arg_int");
179   server_a[0].value.integer = 0;
180 
181   // adds const str arg
182   server_a[1].type = GRPC_ARG_STRING;
183   server_a[1].key = const_cast<char*>("arg_str");
184   server_a[1].value.string = const_cast<char*>("arg_str_val");
185 
186   // allocated and adds custom pointer arg
187   fake_class* fc = static_cast<fake_class*>(gpr_malloc(sizeof(fake_class)));
188   fc->foo = 42;
189   server_a[2].type = GRPC_ARG_POINTER;
190   server_a[2].key = const_cast<char*>("arg_pointer");
191   server_a[2].value.pointer.vtable = &fake_pointer_arg_vtable;
192   server_a[2].value.pointer.p = fc;
193 
194   // creates server
195   grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a};
196   grpc_server* s = grpc_server_create(&server_args, nullptr);
197   // user is can free the memory they allocated here
198   gpr_free(fc);
199   grpc_server_destroy(s);
200 }
201 
main(int argc,char ** argv)202 int main(int argc, char** argv) {
203   grpc::testing::TestEnvironment env(argc, argv);
204   grpc_init();
205   test_create();
206   test_channel_create_with_args();
207   test_server_create_with_args();
208   // This has to be the last test.
209   // TODO(markdroth): re-enable this test once client_idle is re-enabled
210   // test_channel_create_with_global_mutator();
211   grpc_shutdown();
212   return 0;
213 }
214