|
|
|
@ -49,7 +49,9 @@ |
|
|
|
|
|
|
|
|
|
enum { TIMEOUT = 200000 }; |
|
|
|
|
|
|
|
|
|
static bool g_enable_filter = false; |
|
|
|
|
static bool g_enable_server_channel_filter = false; |
|
|
|
|
static bool g_enable_client_channel_filter = false; |
|
|
|
|
static bool g_enable_client_subchannel_filter = false; |
|
|
|
|
|
|
|
|
|
static void *tag(intptr_t t) { return (void *)t; } |
|
|
|
|
|
|
|
|
@ -105,9 +107,9 @@ static void end_test(grpc_end2end_test_fixture *f) { |
|
|
|
|
grpc_completion_queue_destroy(f->cq); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Simple request via a server filter that always fails to initialize
|
|
|
|
|
// the call.
|
|
|
|
|
static void test_request(grpc_end2end_test_config config) { |
|
|
|
|
// Simple request via a SERVER_CHANNEL filter that always fails to
|
|
|
|
|
// initialize the call.
|
|
|
|
|
static void test_server_channel_filter(grpc_end2end_test_config config) { |
|
|
|
|
grpc_call *c; |
|
|
|
|
grpc_call *s; |
|
|
|
|
grpc_slice request_payload_slice = |
|
|
|
@ -201,6 +203,211 @@ static void test_request(grpc_end2end_test_config config) { |
|
|
|
|
config.tear_down_data(&f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Simple request via a CLIENT_CHANNEL or CLIENT_DIRECT_CHANNEL filter
|
|
|
|
|
// that always fails to initialize the call.
|
|
|
|
|
static void test_client_channel_filter(grpc_end2end_test_config config) { |
|
|
|
|
grpc_call *c; |
|
|
|
|
grpc_slice request_payload_slice = |
|
|
|
|
grpc_slice_from_copied_string("hello world"); |
|
|
|
|
grpc_byte_buffer *request_payload = |
|
|
|
|
grpc_raw_byte_buffer_create(&request_payload_slice, 1); |
|
|
|
|
gpr_timespec deadline = five_seconds_from_now(); |
|
|
|
|
grpc_end2end_test_fixture f = |
|
|
|
|
begin_test(config, "filter_call_init_fails", NULL, NULL); |
|
|
|
|
cq_verifier *cqv = cq_verifier_create(f.cq); |
|
|
|
|
grpc_op ops[6]; |
|
|
|
|
grpc_op *op; |
|
|
|
|
grpc_metadata_array initial_metadata_recv; |
|
|
|
|
grpc_metadata_array trailing_metadata_recv; |
|
|
|
|
grpc_metadata_array request_metadata_recv; |
|
|
|
|
grpc_byte_buffer *request_payload_recv = NULL; |
|
|
|
|
grpc_call_details call_details; |
|
|
|
|
grpc_status_code status; |
|
|
|
|
grpc_call_error error; |
|
|
|
|
grpc_slice details; |
|
|
|
|
|
|
|
|
|
c = grpc_channel_create_call( |
|
|
|
|
f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, |
|
|
|
|
grpc_slice_from_static_string("/foo"), |
|
|
|
|
get_host_override_slice("foo.test.google.fr:1234", config), deadline, |
|
|
|
|
NULL); |
|
|
|
|
GPR_ASSERT(c); |
|
|
|
|
|
|
|
|
|
grpc_metadata_array_init(&initial_metadata_recv); |
|
|
|
|
grpc_metadata_array_init(&trailing_metadata_recv); |
|
|
|
|
grpc_metadata_array_init(&request_metadata_recv); |
|
|
|
|
grpc_call_details_init(&call_details); |
|
|
|
|
|
|
|
|
|
memset(ops, 0, sizeof(ops)); |
|
|
|
|
op = ops; |
|
|
|
|
op->op = GRPC_OP_SEND_INITIAL_METADATA; |
|
|
|
|
op->data.send_initial_metadata.count = 0; |
|
|
|
|
op->data.send_initial_metadata.metadata = NULL; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
op->op = GRPC_OP_SEND_MESSAGE; |
|
|
|
|
op->data.send_message.send_message = request_payload; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
op->op = GRPC_OP_RECV_INITIAL_METADATA; |
|
|
|
|
op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; |
|
|
|
|
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; |
|
|
|
|
op->data.recv_status_on_client.status = &status; |
|
|
|
|
op->data.recv_status_on_client.status_details = &details; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); |
|
|
|
|
GPR_ASSERT(GRPC_CALL_OK == error); |
|
|
|
|
|
|
|
|
|
CQ_EXPECT_COMPLETION(cqv, tag(1), 1); |
|
|
|
|
cq_verify(cqv); |
|
|
|
|
|
|
|
|
|
GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); |
|
|
|
|
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); |
|
|
|
|
|
|
|
|
|
grpc_slice_unref(details); |
|
|
|
|
grpc_metadata_array_destroy(&initial_metadata_recv); |
|
|
|
|
grpc_metadata_array_destroy(&trailing_metadata_recv); |
|
|
|
|
grpc_metadata_array_destroy(&request_metadata_recv); |
|
|
|
|
grpc_call_details_destroy(&call_details); |
|
|
|
|
|
|
|
|
|
grpc_call_destroy(c); |
|
|
|
|
|
|
|
|
|
cq_verifier_destroy(cqv); |
|
|
|
|
|
|
|
|
|
grpc_byte_buffer_destroy(request_payload); |
|
|
|
|
grpc_byte_buffer_destroy(request_payload_recv); |
|
|
|
|
|
|
|
|
|
end_test(&f); |
|
|
|
|
config.tear_down_data(&f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Simple request via a CLIENT_SUBCHANNEL filter that always fails to
|
|
|
|
|
// initialize the call.
|
|
|
|
|
static void test_client_subchannel_filter(grpc_end2end_test_config config) { |
|
|
|
|
grpc_call *c; |
|
|
|
|
grpc_slice request_payload_slice = |
|
|
|
|
grpc_slice_from_copied_string("hello world"); |
|
|
|
|
grpc_byte_buffer *request_payload = |
|
|
|
|
grpc_raw_byte_buffer_create(&request_payload_slice, 1); |
|
|
|
|
gpr_timespec deadline = five_seconds_from_now(); |
|
|
|
|
grpc_end2end_test_fixture f = |
|
|
|
|
begin_test(config, "filter_call_init_fails", NULL, NULL); |
|
|
|
|
cq_verifier *cqv = cq_verifier_create(f.cq); |
|
|
|
|
grpc_op ops[6]; |
|
|
|
|
grpc_op *op; |
|
|
|
|
grpc_metadata_array initial_metadata_recv; |
|
|
|
|
grpc_metadata_array trailing_metadata_recv; |
|
|
|
|
grpc_metadata_array request_metadata_recv; |
|
|
|
|
grpc_byte_buffer *request_payload_recv = NULL; |
|
|
|
|
grpc_call_details call_details; |
|
|
|
|
grpc_status_code status; |
|
|
|
|
grpc_call_error error; |
|
|
|
|
grpc_slice details; |
|
|
|
|
|
|
|
|
|
c = grpc_channel_create_call( |
|
|
|
|
f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, |
|
|
|
|
grpc_slice_from_static_string("/foo"), |
|
|
|
|
get_host_override_slice("foo.test.google.fr:1234", config), deadline, |
|
|
|
|
NULL); |
|
|
|
|
GPR_ASSERT(c); |
|
|
|
|
|
|
|
|
|
grpc_metadata_array_init(&initial_metadata_recv); |
|
|
|
|
grpc_metadata_array_init(&trailing_metadata_recv); |
|
|
|
|
grpc_metadata_array_init(&request_metadata_recv); |
|
|
|
|
grpc_call_details_init(&call_details); |
|
|
|
|
|
|
|
|
|
memset(ops, 0, sizeof(ops)); |
|
|
|
|
op = ops; |
|
|
|
|
op->op = GRPC_OP_SEND_INITIAL_METADATA; |
|
|
|
|
op->data.send_initial_metadata.count = 0; |
|
|
|
|
op->data.send_initial_metadata.metadata = NULL; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
op->op = GRPC_OP_SEND_MESSAGE; |
|
|
|
|
op->data.send_message.send_message = request_payload; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
op->op = GRPC_OP_RECV_INITIAL_METADATA; |
|
|
|
|
op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; |
|
|
|
|
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; |
|
|
|
|
op->data.recv_status_on_client.status = &status; |
|
|
|
|
op->data.recv_status_on_client.status_details = &details; |
|
|
|
|
op->flags = 0; |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op++; |
|
|
|
|
|
|
|
|
|
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); |
|
|
|
|
GPR_ASSERT(GRPC_CALL_OK == error); |
|
|
|
|
|
|
|
|
|
CQ_EXPECT_COMPLETION(cqv, tag(1), 1); |
|
|
|
|
cq_verify(cqv); |
|
|
|
|
|
|
|
|
|
GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); |
|
|
|
|
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); |
|
|
|
|
|
|
|
|
|
// Reset and create a new call. (The first call uses a different code
|
|
|
|
|
// path in client_channel.c than subsequent calls on the same channel,
|
|
|
|
|
// and we need to test both.)
|
|
|
|
|
grpc_call_destroy(c); |
|
|
|
|
status = GRPC_STATUS_OK; |
|
|
|
|
grpc_slice_unref(details); |
|
|
|
|
details = grpc_empty_slice(); |
|
|
|
|
|
|
|
|
|
c = grpc_channel_create_call( |
|
|
|
|
f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, |
|
|
|
|
grpc_slice_from_static_string("/foo"), |
|
|
|
|
get_host_override_slice("foo.test.google.fr:1234", config), deadline, |
|
|
|
|
NULL); |
|
|
|
|
GPR_ASSERT(c); |
|
|
|
|
|
|
|
|
|
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); |
|
|
|
|
GPR_ASSERT(GRPC_CALL_OK == error); |
|
|
|
|
|
|
|
|
|
CQ_EXPECT_COMPLETION(cqv, tag(2), 1); |
|
|
|
|
cq_verify(cqv); |
|
|
|
|
|
|
|
|
|
GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); |
|
|
|
|
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); |
|
|
|
|
|
|
|
|
|
grpc_slice_unref(details); |
|
|
|
|
grpc_metadata_array_destroy(&initial_metadata_recv); |
|
|
|
|
grpc_metadata_array_destroy(&trailing_metadata_recv); |
|
|
|
|
grpc_metadata_array_destroy(&request_metadata_recv); |
|
|
|
|
grpc_call_details_destroy(&call_details); |
|
|
|
|
|
|
|
|
|
grpc_call_destroy(c); |
|
|
|
|
|
|
|
|
|
cq_verifier_destroy(cqv); |
|
|
|
|
|
|
|
|
|
grpc_byte_buffer_destroy(request_payload); |
|
|
|
|
grpc_byte_buffer_destroy(request_payload_recv); |
|
|
|
|
|
|
|
|
|
end_test(&f); |
|
|
|
|
config.tear_down_data(&f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* Test filter - always fails to initialize a call |
|
|
|
|
*/ |
|
|
|
@ -244,9 +451,30 @@ static const grpc_channel_filter test_filter = { |
|
|
|
|
* Registration |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
static bool maybe_add_filter(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_channel_stack_builder *builder, void *arg) { |
|
|
|
|
if (g_enable_filter) { |
|
|
|
|
static bool maybe_add_server_channel_filter(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_channel_stack_builder *builder, |
|
|
|
|
void *arg) { |
|
|
|
|
if (g_enable_server_channel_filter) { |
|
|
|
|
// Want to add the filter as close to the end as possible, to make
|
|
|
|
|
// sure that all of the filters work well together. However, we
|
|
|
|
|
// can't add it at the very end, because the connected channel filter
|
|
|
|
|
// must be the last one. So we add it right before the last one.
|
|
|
|
|
grpc_channel_stack_builder_iterator *it = |
|
|
|
|
grpc_channel_stack_builder_create_iterator_at_last(builder); |
|
|
|
|
GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); |
|
|
|
|
const bool retval = grpc_channel_stack_builder_add_filter_before( |
|
|
|
|
it, &test_filter, NULL, NULL); |
|
|
|
|
grpc_channel_stack_builder_iterator_destroy(it); |
|
|
|
|
return retval; |
|
|
|
|
} else { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool maybe_add_client_channel_filter(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_channel_stack_builder *builder, |
|
|
|
|
void *arg) { |
|
|
|
|
if (g_enable_client_channel_filter) { |
|
|
|
|
// Want to add the filter as close to the end as possible, to make
|
|
|
|
|
// sure that all of the filters work well together. However, we
|
|
|
|
|
// can't add it at the very end, because the connected channel filter
|
|
|
|
@ -263,17 +491,53 @@ static bool maybe_add_filter(grpc_exec_ctx *exec_ctx, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool maybe_add_client_subchannel_filter( |
|
|
|
|
grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { |
|
|
|
|
if (g_enable_client_subchannel_filter) { |
|
|
|
|
// Want to add the filter as close to the end as possible, to make
|
|
|
|
|
// sure that all of the filters work well together. However, we
|
|
|
|
|
// can't add it at the very end, because the client channel filter
|
|
|
|
|
// must be the last one. So we add it right before the last one.
|
|
|
|
|
grpc_channel_stack_builder_iterator *it = |
|
|
|
|
grpc_channel_stack_builder_create_iterator_at_last(builder); |
|
|
|
|
GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); |
|
|
|
|
const bool retval = grpc_channel_stack_builder_add_filter_before( |
|
|
|
|
it, &test_filter, NULL, NULL); |
|
|
|
|
grpc_channel_stack_builder_iterator_destroy(it); |
|
|
|
|
return retval; |
|
|
|
|
} else { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void init_plugin(void) { |
|
|
|
|
grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, |
|
|
|
|
maybe_add_filter, NULL); |
|
|
|
|
maybe_add_server_channel_filter, NULL); |
|
|
|
|
grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, |
|
|
|
|
maybe_add_client_channel_filter, NULL); |
|
|
|
|
grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX, |
|
|
|
|
maybe_add_client_subchannel_filter, NULL); |
|
|
|
|
grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, |
|
|
|
|
maybe_add_client_channel_filter, NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void destroy_plugin(void) {} |
|
|
|
|
|
|
|
|
|
void filter_call_init_fails(grpc_end2end_test_config config) { |
|
|
|
|
g_enable_filter = true; |
|
|
|
|
test_request(config); |
|
|
|
|
g_enable_filter = false; |
|
|
|
|
gpr_log(GPR_INFO, "Testing SERVER_CHANNEL filter."); |
|
|
|
|
g_enable_server_channel_filter = true; |
|
|
|
|
test_server_channel_filter(config); |
|
|
|
|
g_enable_server_channel_filter = false; |
|
|
|
|
gpr_log(GPR_INFO, "Testing CLIENT_CHANNEL / CLIENT_DIRECT_CHANNEL filter."); |
|
|
|
|
g_enable_client_channel_filter = true; |
|
|
|
|
test_client_channel_filter(config); |
|
|
|
|
g_enable_client_channel_filter = false; |
|
|
|
|
if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) { |
|
|
|
|
gpr_log(GPR_INFO, "Testing CLIENT_SUBCHANNEL filter."); |
|
|
|
|
g_enable_client_subchannel_filter = true; |
|
|
|
|
test_client_subchannel_filter(config); |
|
|
|
|
g_enable_client_subchannel_filter = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void filter_call_init_fails_pre_init(void) { |
|
|
|
|