|  | @@ -16,43 +16,38 @@
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include <grpc/impl/codegen/grpc_types.h>
 | 
	
		
			
				|  |  | +#include <grpc/impl/codegen/log.h>
 | 
	
		
			
				|  |  |  #include <string.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <grpc/support/log.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include "src/core/lib/channel/channel_args.h"
 | 
	
		
			
				|  |  | +#include "src/core/lib/channel/channel_stack.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/gpr/useful.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/iomgr/exec_ctx.h"
 | 
	
		
			
				|  |  | +#include "src/core/lib/surface/channel.h"
 | 
	
		
			
				|  |  |  #include "test/core/util/test_config.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void test_create(void) {
 | 
	
		
			
				|  |  |    grpc_core::ExecCtx exec_ctx;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  grpc_arg arg_int;
 | 
	
		
			
				|  |  | -  grpc_arg arg_string;
 | 
	
		
			
				|  |  |    grpc_arg to_add[2];
 | 
	
		
			
				|  |  |    grpc_channel_args* ch_args;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  arg_int.key = const_cast<char*>("int_arg");
 | 
	
		
			
				|  |  | -  arg_int.type = GRPC_ARG_INTEGER;
 | 
	
		
			
				|  |  | -  arg_int.value.integer = 123;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  arg_string.key = const_cast<char*>("str key");
 | 
	
		
			
				|  |  | -  arg_string.type = GRPC_ARG_STRING;
 | 
	
		
			
				|  |  | -  arg_string.value.string = const_cast<char*>("str value");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  to_add[0] = arg_int;
 | 
	
		
			
				|  |  | -  to_add[1] = arg_string;
 | 
	
		
			
				|  |  | +  to_add[0] =
 | 
	
		
			
				|  |  | +      grpc_channel_arg_integer_create(const_cast<char*>("int_arg"), 123);
 | 
	
		
			
				|  |  | +  to_add[1] = grpc_channel_arg_string_create(const_cast<char*>("str key"),
 | 
	
		
			
				|  |  | +                                             const_cast<char*>("str value"));
 | 
	
		
			
				|  |  |    ch_args = grpc_channel_args_copy_and_add(nullptr, to_add, 2);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GPR_ASSERT(ch_args->num_args == 2);
 | 
	
		
			
				|  |  | -  GPR_ASSERT(strcmp(ch_args->args[0].key, arg_int.key) == 0);
 | 
	
		
			
				|  |  | -  GPR_ASSERT(ch_args->args[0].type == arg_int.type);
 | 
	
		
			
				|  |  | -  GPR_ASSERT(ch_args->args[0].value.integer == arg_int.value.integer);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(strcmp(ch_args->args[0].key, to_add[0].key) == 0);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(ch_args->args[0].type == to_add[0].type);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(ch_args->args[0].value.integer == to_add[0].value.integer);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  GPR_ASSERT(strcmp(ch_args->args[1].key, arg_string.key) == 0);
 | 
	
		
			
				|  |  | -  GPR_ASSERT(ch_args->args[1].type == arg_string.type);
 | 
	
		
			
				|  |  | -  GPR_ASSERT(strcmp(ch_args->args[1].value.string, arg_string.value.string) ==
 | 
	
		
			
				|  |  | +  GPR_ASSERT(strcmp(ch_args->args[1].key, to_add[1].key) == 0);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(ch_args->args[1].type == to_add[1].type);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(strcmp(ch_args->args[1].value.string, to_add[1].value.string) ==
 | 
	
		
			
				|  |  |               0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    grpc_channel_args_destroy(ch_args);
 | 
	
	
		
			
				|  | @@ -84,23 +79,15 @@ static const grpc_arg_pointer_vtable fake_pointer_arg_vtable = {
 | 
	
		
			
				|  |  |  static void test_channel_create_with_args(void) {
 | 
	
		
			
				|  |  |    grpc_arg client_a[3];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // adds integer arg
 | 
	
		
			
				|  |  | -  client_a[0].type = GRPC_ARG_INTEGER;
 | 
	
		
			
				|  |  | -  client_a[0].key = const_cast<char*>("arg_int");
 | 
	
		
			
				|  |  | -  client_a[0].value.integer = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // adds const str arg
 | 
	
		
			
				|  |  | -  client_a[1].type = GRPC_ARG_STRING;
 | 
	
		
			
				|  |  | -  client_a[1].key = const_cast<char*>("arg_str");
 | 
	
		
			
				|  |  | -  client_a[1].value.string = const_cast<char*>("arg_str_val");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +  client_a[0] =
 | 
	
		
			
				|  |  | +      grpc_channel_arg_integer_create(const_cast<char*>("arg_int"), 0);
 | 
	
		
			
				|  |  | +  client_a[1] = grpc_channel_arg_string_create(
 | 
	
		
			
				|  |  | +      const_cast<char*>("arg_str"), const_cast<char*>("arg_str_val"));
 | 
	
		
			
				|  |  |    // allocated and adds custom pointer arg
 | 
	
		
			
				|  |  |    fake_class* fc = static_cast<fake_class*>(gpr_malloc(sizeof(fake_class)));
 | 
	
		
			
				|  |  |    fc->foo = 42;
 | 
	
		
			
				|  |  | -  client_a[2].type = GRPC_ARG_POINTER;
 | 
	
		
			
				|  |  | -  client_a[2].key = const_cast<char*>("arg_pointer");
 | 
	
		
			
				|  |  | -  client_a[2].value.pointer.vtable = &fake_pointer_arg_vtable;
 | 
	
		
			
				|  |  | -  client_a[2].value.pointer.p = fc;
 | 
	
		
			
				|  |  | +  client_a[2] = grpc_channel_arg_pointer_create(
 | 
	
		
			
				|  |  | +      const_cast<char*>("arg_pointer"), fc, &fake_pointer_arg_vtable);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // creates channel
 | 
	
		
			
				|  |  |    grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
 | 
	
	
		
			
				|  | @@ -111,6 +98,78 @@ static void test_channel_create_with_args(void) {
 | 
	
		
			
				|  |  |    grpc_channel_destroy(c);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +grpc_channel_args* mutate_channel_args(const char* target,
 | 
	
		
			
				|  |  | +                                       grpc_channel_args* old_args,
 | 
	
		
			
				|  |  | +                                       grpc_channel_stack_type type) {
 | 
	
		
			
				|  |  | +  GPR_ASSERT(old_args != nullptr);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(grpc_channel_args_find(old_args, "arg_int")->value.integer == 0);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(strcmp(grpc_channel_args_find(old_args, "arg_str")->value.string,
 | 
	
		
			
				|  |  | +                    "arg_str_val") == 0);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(
 | 
	
		
			
				|  |  | +      grpc_channel_args_find(old_args, "arg_pointer")->value.pointer.vtable ==
 | 
	
		
			
				|  |  | +      &fake_pointer_arg_vtable);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (strcmp(target, "no_op_mutator") == 0) {
 | 
	
		
			
				|  |  | +    return old_args;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  GPR_ASSERT(strcmp(target, "minimal_stack_mutator") == 0);
 | 
	
		
			
				|  |  | +  const char* args_to_remove[] = {"arg_int", "arg_str", "arg_pointer"};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  grpc_arg no_deadline_filter_arg = grpc_channel_arg_integer_create(
 | 
	
		
			
				|  |  | +      const_cast<char*>(GRPC_ARG_MINIMAL_STACK), 1);
 | 
	
		
			
				|  |  | +  grpc_channel_args* new_args = nullptr;
 | 
	
		
			
				|  |  | +  new_args = grpc_channel_args_copy_and_add_and_remove(
 | 
	
		
			
				|  |  | +      old_args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove),
 | 
	
		
			
				|  |  | +      &no_deadline_filter_arg, 1);
 | 
	
		
			
				|  |  | +  grpc_channel_args_destroy(old_args);
 | 
	
		
			
				|  |  | +  return new_args;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Minimal stack should not have client_idle filter
 | 
	
		
			
				|  |  | +static bool channel_has_client_idle_filter(grpc_channel* c) {
 | 
	
		
			
				|  |  | +  grpc_channel_stack* stack = grpc_channel_get_channel_stack(c);
 | 
	
		
			
				|  |  | +  for (size_t i = 0; i < stack->count; i++) {
 | 
	
		
			
				|  |  | +    if (strcmp(grpc_channel_stack_element(stack, i)->filter->name,
 | 
	
		
			
				|  |  | +               "client_idle") == 0) {
 | 
	
		
			
				|  |  | +      return true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return false;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void test_channel_create_with_global_mutator(void) {
 | 
	
		
			
				|  |  | +  grpc_channel_args_set_client_channel_creation_mutator(mutate_channel_args);
 | 
	
		
			
				|  |  | +  // We also add some custom args to make sure the ownership is correct.
 | 
	
		
			
				|  |  | +  grpc_arg client_a[3];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  client_a[0] =
 | 
	
		
			
				|  |  | +      grpc_channel_arg_integer_create(const_cast<char*>("arg_int"), 0);
 | 
	
		
			
				|  |  | +  client_a[1] = grpc_channel_arg_string_create(
 | 
	
		
			
				|  |  | +      const_cast<char*>("arg_str"), const_cast<char*>("arg_str_val"));
 | 
	
		
			
				|  |  | +  // allocated and adds custom pointer arg
 | 
	
		
			
				|  |  | +  fake_class* fc = static_cast<fake_class*>(gpr_malloc(sizeof(fake_class)));
 | 
	
		
			
				|  |  | +  fc->foo = 42;
 | 
	
		
			
				|  |  | +  client_a[2] = grpc_channel_arg_pointer_create(
 | 
	
		
			
				|  |  | +      const_cast<char*>("arg_pointer"), fc, &fake_pointer_arg_vtable);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // creates channels
 | 
	
		
			
				|  |  | +  grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
 | 
	
		
			
				|  |  | +  grpc_channel* c =
 | 
	
		
			
				|  |  | +      grpc_insecure_channel_create("no_op_mutator", &client_args, nullptr);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(channel_has_client_idle_filter(c));
 | 
	
		
			
				|  |  | +  grpc_channel_destroy(c);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  c = grpc_insecure_channel_create("minimal_stack_mutator", &client_args,
 | 
	
		
			
				|  |  | +                                   nullptr);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(channel_has_client_idle_filter(c) == false);
 | 
	
		
			
				|  |  | +  grpc_channel_destroy(c);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  gpr_free(fc);
 | 
	
		
			
				|  |  | +  auto mutator = grpc_channel_args_get_client_channel_creation_mutator();
 | 
	
		
			
				|  |  | +  GPR_ASSERT(mutator == &mutate_channel_args);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void test_server_create_with_args(void) {
 | 
	
		
			
				|  |  |    grpc_arg server_a[3];
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -146,6 +205,8 @@ int main(int argc, char** argv) {
 | 
	
		
			
				|  |  |    test_create();
 | 
	
		
			
				|  |  |    test_channel_create_with_args();
 | 
	
		
			
				|  |  |    test_server_create_with_args();
 | 
	
		
			
				|  |  | +  // This has to be the last test.
 | 
	
		
			
				|  |  | +  test_channel_create_with_global_mutator();
 | 
	
		
			
				|  |  |    grpc_shutdown();
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 |