|  | @@ -31,15 +31,110 @@
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include <grpc/grpc.h>
 | 
	
		
			
				|  |  | +#include <grpc/support/alloc.h>
 | 
	
		
			
				|  |  | +#include <grpc/support/string_util.h>
 | 
	
		
			
				|  |  | +#include <string.h>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include "src/core/lib/channel/channel_stack_builder.h"
 | 
	
		
			
				|  |  | +#include "src/core/lib/support/string.h"
 | 
	
		
			
				|  |  | +#include "src/core/lib/surface/channel_init.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/surface/channel_stack_type.h"
 | 
	
		
			
				|  |  | +#include "src/core/lib/transport/transport_impl.h"
 | 
	
		
			
				|  |  | +#include "test/core/util/test_config.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int check_stack(const char *transport_name, grpc_channel_args *init_args,
 | 
	
		
			
				|  |  | +                       grpc_channel_stack_type channel_stack_type, ...) {
 | 
	
		
			
				|  |  | +  // create dummy channel stack
 | 
	
		
			
				|  |  | +  grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create();
 | 
	
		
			
				|  |  | +  grpc_transport_vtable fake_transport_vtable = {.name = transport_name};
 | 
	
		
			
				|  |  | +  grpc_transport fake_transport = {.vtable = &fake_transport_vtable};
 | 
	
		
			
				|  |  | +  grpc_arg arg = {.type = GRPC_ARG_INTEGER,
 | 
	
		
			
				|  |  | +                  .key = GRPC_ARG_MINIMAL_STACK,
 | 
	
		
			
				|  |  | +                  .value.integer = 1};
 | 
	
		
			
				|  |  | +  grpc_channel_stack_builder_set_target(builder, "foo.test.google.fr");
 | 
	
		
			
				|  |  | +  grpc_channel_args *channel_args =
 | 
	
		
			
				|  |  | +      grpc_channel_args_copy_and_add(init_args, &arg, 1);
 | 
	
		
			
				|  |  | +  if (transport_name != NULL) {
 | 
	
		
			
				|  |  | +    grpc_channel_stack_builder_set_transport(builder, &fake_transport);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 | 
	
		
			
				|  |  | +    grpc_channel_stack_builder_set_channel_arguments(&exec_ctx, builder,
 | 
	
		
			
				|  |  | +                                                     channel_args);
 | 
	
		
			
				|  |  | +    GPR_ASSERT(
 | 
	
		
			
				|  |  | +        grpc_channel_init_create_stack(&exec_ctx, builder, channel_stack_type));
 | 
	
		
			
				|  |  | +    grpc_exec_ctx_finish(&exec_ctx);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // build up our expectation list
 | 
	
		
			
				|  |  | +  gpr_strvec v;
 | 
	
		
			
				|  |  | +  gpr_strvec_init(&v);
 | 
	
		
			
				|  |  | +  va_list args;
 | 
	
		
			
				|  |  | +  va_start(args, channel_stack_type);
 | 
	
		
			
				|  |  | +  for (;;) {
 | 
	
		
			
				|  |  | +    char *a = va_arg(args, char *);
 | 
	
		
			
				|  |  | +    if (a == NULL) break;
 | 
	
		
			
				|  |  | +    if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", "));
 | 
	
		
			
				|  |  | +    gpr_strvec_add(&v, gpr_strdup(a));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  va_end(args);
 | 
	
		
			
				|  |  | +  char *expect = gpr_strvec_flatten(&v, NULL);
 | 
	
		
			
				|  |  | +  gpr_strvec_destroy(&v);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // build up our "got" list
 | 
	
		
			
				|  |  | +  gpr_strvec_init(&v);
 | 
	
		
			
				|  |  | +  grpc_channel_stack_builder_iterator *it =
 | 
	
		
			
				|  |  | +      grpc_channel_stack_builder_create_iterator_at_first(builder);
 | 
	
		
			
				|  |  | +  while (grpc_channel_stack_builder_move_next(it)) {
 | 
	
		
			
				|  |  | +    const char *name = grpc_channel_stack_builder_iterator_filter_name(it);
 | 
	
		
			
				|  |  | +    if (name == NULL) continue;
 | 
	
		
			
				|  |  | +    if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", "));
 | 
	
		
			
				|  |  | +    gpr_strvec_add(&v, gpr_strdup(name));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  char *got = gpr_strvec_flatten(&v, NULL);
 | 
	
		
			
				|  |  | +  gpr_strvec_destroy(&v);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // figure out result, log if there's an error
 | 
	
		
			
				|  |  | +  int result = 0;
 | 
	
		
			
				|  |  | +  if (0 != strcmp(got, expect)) {
 | 
	
		
			
				|  |  | +    gpr_log(GPR_ERROR,
 | 
	
		
			
				|  |  | +            "FAILED transport=%s; stack_type=%d: expected '%s'; got '%s'",
 | 
	
		
			
				|  |  | +            transport_name, channel_stack_type, expect, got);
 | 
	
		
			
				|  |  | +    result = 1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  gpr_free(got);
 | 
	
		
			
				|  |  | +  gpr_free(expect);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 | 
	
		
			
				|  |  | +    grpc_channel_stack_builder_destroy(&exec_ctx, builder);
 | 
	
		
			
				|  |  | +    grpc_exec_ctx_finish(&exec_ctx);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  return result;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  int main(int argc, char **argv) {
 | 
	
		
			
				|  |  |    grpc_test_init(argc, argv);
 | 
	
		
			
				|  |  |    grpc_init();
 | 
	
		
			
				|  |  | -  check_stack(GRPC_CLIENT_CHANNEL, "client_channel", NULL);
 | 
	
		
			
				|  |  | -  check_stack(GRPC_CLIENT_DIRECT_CHANNEL, "connected_channel", NULL);
 | 
	
		
			
				|  |  | -  check_stack(GRPC_CLIENT_SUBCHANNEL, "connected_channel", NULL);
 | 
	
		
			
				|  |  | -  check_stack(GRPC_SERVER_CHANNEL, "server", "connected_channel", NULL);
 | 
	
		
			
				|  |  | +  int errors = 0;
 | 
	
		
			
				|  |  | +  errors += check_stack("unknown", NULL, GRPC_CLIENT_DIRECT_CHANNEL,
 | 
	
		
			
				|  |  | +                        "connected", NULL);
 | 
	
		
			
				|  |  | +  errors +=
 | 
	
		
			
				|  |  | +      check_stack("unknown", NULL, GRPC_CLIENT_SUBCHANNEL, "connected", NULL);
 | 
	
		
			
				|  |  | +  errors += check_stack("unknown", NULL, GRPC_SERVER_CHANNEL, "server",
 | 
	
		
			
				|  |  | +                        "connected", NULL);
 | 
	
		
			
				|  |  | +  errors += check_stack("chttp2", NULL, GRPC_CLIENT_DIRECT_CHANNEL,
 | 
	
		
			
				|  |  | +                        "http-client", "connected", NULL);
 | 
	
		
			
				|  |  | +  errors +=
 | 
	
		
			
				|  |  | +      check_stack("chttp2", NULL, GRPC_CLIENT_SUBCHANNEL, "connected", NULL);
 | 
	
		
			
				|  |  | +  errors += check_stack("chttp2", NULL, GRPC_SERVER_CHANNEL, "server",
 | 
	
		
			
				|  |  | +                        "http-server", "connected", NULL);
 | 
	
		
			
				|  |  | +  errors +=
 | 
	
		
			
				|  |  | +      check_stack(NULL, NULL, GRPC_CLIENT_CHANNEL, "client-channel", NULL);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(errors == 0);
 | 
	
		
			
				|  |  |    grpc_shutdown();
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 |