Merge pull request #381 from ctiller/async-api-new

New Core API
pull/432/head
Yang Gao 10 years ago
commit ee8f51fc8b
  1. 9224
      Makefile
  2. 2
      build.json
  3. 83
      include/grpc/grpc.h
  4. 42
      src/core/channel/client_channel.c
  5. 16
      src/core/channel/http_client_filter.c
  6. 1
      src/core/surface/byte_buffer.c
  7. 7
      src/core/surface/byte_buffer_queue.c
  8. 1
      src/core/surface/byte_buffer_queue.h
  9. 231
      src/core/surface/call.c
  10. 27
      src/core/surface/call.h
  11. 13
      src/core/surface/call_details.c
  12. 16
      src/core/surface/channel.c
  13. 21
      src/core/surface/completion_queue.c
  14. 10
      src/core/surface/completion_queue.h
  15. 6
      src/core/surface/event_string.c
  16. 12
      src/core/surface/metadata_array.c
  17. 98
      src/core/surface/server.c
  18. 38
      test/core/end2end/cq_verifier.c
  19. 4
      test/core/end2end/cq_verifier.h
  20. 28
      test/core/end2end/gen_build_json.py
  21. 103
      test/core/end2end/tests/cancel_after_accept.c
  22. 167
      test/core/end2end/tests/cancel_after_accept_and_writes_closed_legacy.c
  23. 159
      test/core/end2end/tests/cancel_after_accept_legacy.c
  24. 72
      test/core/end2end/tests/cancel_after_invoke.c
  25. 141
      test/core/end2end/tests/cancel_after_invoke_legacy.c
  26. 69
      test/core/end2end/tests/cancel_before_invoke.c
  27. 134
      test/core/end2end/tests/cancel_before_invoke_legacy.c
  28. 2
      test/core/end2end/tests/cancel_in_a_vacuum.c
  29. 131
      test/core/end2end/tests/cancel_in_a_vacuum_legacy.c
  30. 2
      test/core/end2end/tests/cancel_test_helpers.h
  31. 178
      test/core/end2end/tests/census_simple_request_legacy.c
  32. 168
      test/core/end2end/tests/disappearing_server_legacy.c
  33. 159
      test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls_legacy.c
  34. 127
      test/core/end2end/tests/early_server_shutdown_finishes_tags_legacy.c
  35. 160
      test/core/end2end/tests/graceful_server_shutdown_legacy.c
  36. 183
      test/core/end2end/tests/invoke_large_request_legacy.c
  37. 274
      test/core/end2end/tests/max_concurrent_streams_legacy.c
  38. 109
      test/core/end2end/tests/no_op_legacy.c
  39. 203
      test/core/end2end/tests/ping_pong_streaming_legacy.c
  40. 198
      test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c
  41. 222
      test/core/end2end/tests/request_response_with_binary_metadata_and_payload_legacy.c
  42. 169
      test/core/end2end/tests/request_response_with_metadata_and_payload.c
  43. 208
      test/core/end2end/tests/request_response_with_metadata_and_payload_legacy.c
  44. 143
      test/core/end2end/tests/request_response_with_payload.c
  45. 208
      test/core/end2end/tests/request_response_with_payload_legacy.c
  46. 178
      test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c
  47. 213
      test/core/end2end/tests/request_response_with_trailing_metadata_and_payload_legacy.c
  48. 121
      test/core/end2end/tests/request_with_large_metadata.c
  49. 172
      test/core/end2end/tests/request_with_large_metadata_legacy.c
  50. 123
      test/core/end2end/tests/request_with_payload.c
  51. 172
      test/core/end2end/tests/request_with_payload_legacy.c
  52. 91
      test/core/end2end/tests/simple_delayed_request.c
  53. 175
      test/core/end2end/tests/simple_delayed_request_legacy.c
  54. 155
      test/core/end2end/tests/simple_request.c
  55. 232
      test/core/end2end/tests/simple_request_legacy.c
  56. 324
      test/core/end2end/tests/thread_stress_legacy.c
  57. 199
      test/core/end2end/tests/writes_done_hangs_with_pending_read_legacy.c
  58. 612
      tools/run_tests/tests.json
  59. 4
      vsprojects/vs2013/grpc.vcxproj
  60. 6
      vsprojects/vs2013/grpc.vcxproj.filters
  61. 4
      vsprojects/vs2013/grpc_unsecure.vcxproj
  62. 6
      vsprojects/vs2013/grpc_unsecure.vcxproj.filters

9224
Makefile

File diff suppressed because one or more lines are too long

@ -163,6 +163,7 @@
"src/core/surface/byte_buffer_queue.c",
"src/core/surface/byte_buffer_reader.c",
"src/core/surface/call.c",
"src/core/surface/call_details.c",
"src/core/surface/channel.c",
"src/core/surface/channel_create.c",
"src/core/surface/client.c",
@ -170,6 +171,7 @@
"src/core/surface/event_string.c",
"src/core/surface/init.c",
"src/core/surface/lame_client.c",
"src/core/surface/metadata_array.c",
"src/core/surface/secure_channel_create.c",
"src/core/surface/secure_server_create.c",
"src/core/surface/server.c",

@ -177,14 +177,14 @@ void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader);
/* A single metadata element */
typedef struct grpc_metadata {
char *key;
char *value;
const char *key;
const char *value;
size_t value_length;
} grpc_metadata;
typedef enum grpc_completion_type {
GRPC_QUEUE_SHUTDOWN, /* Shutting down */
GRPC_IOREQ, /* grpc_call_ioreq completion */
GRPC_OP_COMPLETE, /* operation completion */
GRPC_READ, /* A read has completed */
GRPC_WRITE_ACCEPTED, /* A write has been accepted by
flow control */
@ -212,7 +212,7 @@ typedef struct grpc_event {
grpc_op_error write_accepted;
grpc_op_error finish_accepted;
grpc_op_error invoke_accepted;
grpc_op_error ioreq;
grpc_op_error op_complete;
struct {
size_t count;
grpc_metadata *elements;
@ -239,23 +239,45 @@ typedef struct {
grpc_metadata *metadata;
} grpc_metadata_array;
void grpc_metadata_array_init(grpc_metadata_array *array);
void grpc_metadata_array_destroy(grpc_metadata_array *array);
typedef struct {
const char *method;
const char *host;
char *method;
size_t method_capacity;
char *host;
size_t host_capacity;
gpr_timespec deadline;
} grpc_call_details;
void grpc_call_details_init(grpc_call_details *details);
void grpc_call_details_destroy(grpc_call_details *details);
typedef enum {
/* Send initial metadata: one and only one instance MUST be sent for each call,
unless the call was cancelled - in which case this can be skipped */
GRPC_OP_SEND_INITIAL_METADATA = 0,
/* Send a message: 0 or more of these operations can occur for each call */
GRPC_OP_SEND_MESSAGE,
/* Send a close from the server: one and only one instance MUST be sent from the client,
unless the call was cancelled - in which case this can be skipped */
GRPC_OP_SEND_CLOSE_FROM_CLIENT,
/* Send status from the server: one and only one instance MUST be sent from the server
unless the call was cancelled - in which case this can be skipped */
GRPC_OP_SEND_STATUS_FROM_SERVER,
/* Receive initial metadata: one and only one MUST be made on the client, must
not be made on the server */
GRPC_OP_RECV_INITIAL_METADATA,
GRPC_OP_RECV_MESSAGES,
/* Receive a message: 0 or more of these operations can occur for each call */
GRPC_OP_RECV_MESSAGE,
/* Receive status on the client: one and only one must be made on the client */
GRPC_OP_RECV_STATUS_ON_CLIENT,
/* Receive status on the server: one and only one must be made on the server */
GRPC_OP_RECV_CLOSE_ON_SERVER
} grpc_op_type;
/* Operation data: one field for each op type (except SEND_CLOSE_FROM_CLIENT which has
no arguments) */
typedef struct grpc_op {
grpc_op_type op;
union {
@ -270,11 +292,40 @@ typedef struct grpc_op {
grpc_status_code status;
const char *status_details;
} send_status_from_server;
/* ownership of the array is with the caller, but ownership of the elements
stays with the call object (ie key, value members are owned by the call
object, recv_initial_metadata->array is owned by the caller).
After the operation completes, call grpc_metadata_array_destroy on this
value, or reuse it in a future op. */
grpc_metadata_array *recv_initial_metadata;
grpc_byte_buffer **recv_message;
struct {
/* ownership of the array is with the caller, but ownership of the elements
stays with the call object (ie key, value members are owned by the call
object, trailing_metadata->array is owned by the caller).
After the operation completes, call grpc_metadata_array_destroy on this
value, or reuse it in a future op. */
grpc_metadata_array *trailing_metadata;
grpc_status_code *status;
/* status_details is a buffer owned by the application before the op completes
and after the op has completed. During the operation status_details may be
reallocated to a size larger than *status_details_capacity, in which case
*status_details_capacity will be updated with the new array capacity.
Pre-allocating space:
size_t my_capacity = 8;
char *my_details = gpr_malloc(my_capacity);
x.status_details = &my_details;
x.status_details_capacity = &my_capacity;
Not pre-allocating space:
size_t my_capacity = 0;
char *my_details = NULL;
x.status_details = &my_details;
x.status_details_capacity = &my_capacity;
After the call:
gpr_free(my_details); */
char **status_details;
size_t *status_details_capacity;
} recv_status_on_client;
@ -330,6 +381,19 @@ grpc_call *grpc_channel_create_call_old(grpc_channel *channel,
const char *method, const char *host,
gpr_timespec deadline);
/* Create a call given a grpc_channel, in order to call 'method'. The request
is not sent until grpc_call_invoke is called. All completions are sent to
'completion_queue'. */
grpc_call *grpc_channel_create_call(grpc_channel *channel,
grpc_completion_queue *completion_queue,
const char *method, const char *host,
gpr_timespec deadline);
/* Start a batch of operations defined in the array ops; when complete, post a
completion of type 'tag' to the completion queue bound to the call.
The order of ops specified in the batch has no significance.
Only one operation of each type can be active at once in any given
batch. */
grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
size_t nops, void *tag);
@ -473,6 +537,11 @@ void grpc_call_destroy(grpc_call *call);
grpc_call_error grpc_server_request_call_old(grpc_server *server,
void *tag_new);
grpc_call_error grpc_server_request_call(
grpc_server *server, grpc_call **call, grpc_call_details *details,
grpc_metadata_array *request_metadata,
grpc_completion_queue *completion_queue, void *tag_new);
/* Create a server */
grpc_server *grpc_server_create(grpc_completion_queue *cq,
const grpc_channel_args *args);

@ -210,11 +210,30 @@ static void remove_waiting_child(channel_data *chand, call_data *calld) {
chand->waiting_child_count = new_count;
}
static void send_up_cancelled_ops(grpc_call_element *elem) {
grpc_call_op finish_op;
channel_data *chand = elem->channel_data;
/* send up a synthesized status */
finish_op.type = GRPC_RECV_METADATA;
finish_op.dir = GRPC_CALL_UP;
finish_op.flags = 0;
finish_op.data.metadata = grpc_mdelem_ref(chand->cancel_status);
finish_op.done_cb = do_nothing;
finish_op.user_data = NULL;
grpc_call_next_op(elem, &finish_op);
/* send up a finish */
finish_op.type = GRPC_RECV_FINISH;
finish_op.dir = GRPC_CALL_UP;
finish_op.flags = 0;
finish_op.done_cb = do_nothing;
finish_op.user_data = NULL;
grpc_call_next_op(elem, &finish_op);
}
static void cancel_rpc(grpc_call_element *elem, grpc_call_op *op) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_call_element *child_elem;
grpc_call_op finish_op;
gpr_mu_lock(&chand->mu);
switch (calld->state) {
@ -225,27 +244,16 @@ static void cancel_rpc(grpc_call_element *elem, grpc_call_op *op) {
return; /* early out */
case CALL_WAITING:
remove_waiting_child(chand, calld);
calld->state = CALL_CANCELLED;
gpr_mu_unlock(&chand->mu);
send_up_cancelled_ops(elem);
calld->s.waiting.on_complete(calld->s.waiting.on_complete_user_data,
GRPC_OP_ERROR);
/* fallthrough intended */
return; /* early out */
case CALL_CREATED:
calld->state = CALL_CANCELLED;
gpr_mu_unlock(&chand->mu);
/* send up a synthesized status */
finish_op.type = GRPC_RECV_METADATA;
finish_op.dir = GRPC_CALL_UP;
finish_op.flags = 0;
finish_op.data.metadata = grpc_mdelem_ref(chand->cancel_status);
finish_op.done_cb = do_nothing;
finish_op.user_data = NULL;
grpc_call_next_op(elem, &finish_op);
/* send up a finish */
finish_op.type = GRPC_RECV_FINISH;
finish_op.dir = GRPC_CALL_UP;
finish_op.flags = 0;
finish_op.done_cb = do_nothing;
finish_op.user_data = NULL;
grpc_call_next_op(elem, &finish_op);
send_up_cancelled_ops(elem);
return; /* early out */
case CALL_CANCELLED:
gpr_mu_unlock(&chand->mu);

@ -1,5 +1,4 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
@ -44,6 +43,7 @@ typedef struct channel_data {
grpc_mdelem *method;
grpc_mdelem *scheme;
grpc_mdelem *content_type;
grpc_mdelem *status;
} channel_data;
/* used to silence 'variable not used' warnings */
@ -86,6 +86,18 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
grpc_call_element_send_metadata(elem, grpc_mdelem_ref(channeld->content_type));
grpc_call_next_op(elem, op);
break;
case GRPC_RECV_METADATA:
if (op->data.metadata == channeld->status) {
grpc_mdelem_unref(op->data.metadata);
op->done_cb(op->user_data, GRPC_OP_OK);
} else if (op->data.metadata->key == channeld->status->key) {
grpc_mdelem_unref(op->data.metadata);
op->done_cb(op->user_data, GRPC_OP_OK);
grpc_call_element_send_cancel(elem);
} else {
grpc_call_next_op(elem, op);
}
break;
default:
/* pass control up or down the stack depending on op->dir */
grpc_call_next_op(elem, op);
@ -166,6 +178,7 @@ static void init_channel_elem(grpc_channel_element *elem,
grpc_mdelem_from_strings(mdctx, ":scheme", scheme_from_args(args));
channeld->content_type =
grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
channeld->status = grpc_mdelem_from_strings(mdctx, ":status", "200");
}
/* Destructor for channel data */
@ -177,6 +190,7 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
grpc_mdelem_unref(channeld->method);
grpc_mdelem_unref(channeld->scheme);
grpc_mdelem_unref(channeld->content_type);
grpc_mdelem_unref(channeld->status);
}
const grpc_channel_filter grpc_http_client_filter = {

@ -61,6 +61,7 @@ grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb) {
}
void grpc_byte_buffer_destroy(grpc_byte_buffer *bb) {
if (!bb) return;
switch (bb->type) {
case GRPC_BB_SLICE_BUFFER:
gpr_slice_buffer_destroy(&bb->data.slice_buffer);

@ -65,6 +65,13 @@ void grpc_bbq_push(grpc_byte_buffer_queue *q, grpc_byte_buffer *buffer) {
bba_push(&q->filling, buffer);
}
void grpc_bbq_flush(grpc_byte_buffer_queue *q) {
grpc_byte_buffer *bb;
while ((bb = grpc_bbq_pop(q))) {
grpc_byte_buffer_destroy(bb);
}
}
grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q) {
grpc_bbq_array temp_array;

@ -53,6 +53,7 @@ typedef struct {
void grpc_bbq_destroy(grpc_byte_buffer_queue *q);
grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q);
void grpc_bbq_flush(grpc_byte_buffer_queue *q);
int grpc_bbq_empty(grpc_byte_buffer_queue *q);
void grpc_bbq_push(grpc_byte_buffer_queue *q, grpc_byte_buffer *bb);

@ -225,7 +225,7 @@ static void do_nothing(void *ignored, grpc_op_error also_ignored) {}
static send_action choose_send_action(grpc_call *call);
static void enact_send_action(grpc_call *call, send_action sa);
grpc_call *grpc_call_create(grpc_channel *channel,
grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
const void *server_transport_data) {
size_t i;
grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel);
@ -234,6 +234,7 @@ grpc_call *grpc_call_create(grpc_channel *channel,
memset(call, 0, sizeof(grpc_call));
gpr_mu_init(&call->mu);
call->channel = channel;
call->cq = cq;
call->is_client = server_transport_data == NULL;
for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) {
call->request_set[i] = REQSET_EMPTY;
@ -252,6 +253,11 @@ grpc_call *grpc_call_create(grpc_channel *channel,
return call;
}
void grpc_call_set_completion_queue(grpc_call *call,
grpc_completion_queue *cq) {
call->cq = cq;
}
void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); }
static void destroy_call(void *call, int ignored_success) {
@ -291,8 +297,21 @@ void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) {
static void set_status_code(grpc_call *call, status_source source,
gpr_uint32 status) {
int flush;
call->status[source].is_set = 1;
call->status[source].code = status;
if (call->is_client) {
flush = status == GRPC_STATUS_CANCELLED;
} else {
flush = status != GRPC_STATUS_OK;
}
if (flush && !grpc_bbq_empty(&call->incoming_queue)) {
gpr_log(GPR_ERROR, "Flushing unread messages due to error status %d", status);
grpc_bbq_flush(&call->incoming_queue);
}
}
static void set_status_details(grpc_call *call, status_source source,
@ -376,37 +395,49 @@ static void unlock(grpc_call *call) {
}
}
static void get_final_status(grpc_call *call, grpc_recv_status_args args) {
static void get_final_status(grpc_call *call, grpc_ioreq_data out) {
int i;
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (call->status[i].is_set) {
out.recv_status.set_value(call->status[i].code,
out.recv_status.user_data);
return;
}
}
out.recv_status.set_value(GRPC_STATUS_UNKNOWN, out.recv_status.user_data);
}
static void get_final_details(grpc_call *call, grpc_ioreq_data out) {
int i;
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (call->status[i].is_set) {
*args.code = call->status[i].code;
if (!args.details) return;
if (call->status[i].details) {
gpr_slice details = call->status[i].details->slice;
size_t len = GPR_SLICE_LENGTH(details);
if (len + 1 > *args.details_capacity) {
*args.details_capacity =
GPR_MAX(len + 1, *args.details_capacity * 3 / 2);
*args.details = gpr_realloc(*args.details, *args.details_capacity);
if (len + 1 > *out.recv_status_details.details_capacity) {
*out.recv_status_details.details_capacity = GPR_MAX(
len + 1, *out.recv_status_details.details_capacity * 3 / 2);
*out.recv_status_details.details =
gpr_realloc(*out.recv_status_details.details,
*out.recv_status_details.details_capacity);
}
memcpy(*args.details, GPR_SLICE_START_PTR(details), len);
(*args.details)[len] = 0;
memcpy(*out.recv_status_details.details, GPR_SLICE_START_PTR(details),
len);
(*out.recv_status_details.details)[len] = 0;
} else {
goto no_details;
}
return;
}
}
*args.code = GRPC_STATUS_UNKNOWN;
if (!args.details) return;
no_details:
if (0 == *args.details_capacity) {
*args.details_capacity = 8;
*args.details = gpr_malloc(*args.details_capacity);
if (0 == *out.recv_status_details.details_capacity) {
*out.recv_status_details.details_capacity = 8;
*out.recv_status_details.details =
gpr_malloc(*out.recv_status_details.details_capacity);
}
**args.details = 0;
**out.recv_status_details.details = 0;
}
static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
@ -444,8 +475,11 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
case GRPC_IOREQ_SEND_CLOSE:
break;
case GRPC_IOREQ_RECV_STATUS:
get_final_status(
call, call->request_data[GRPC_IOREQ_RECV_STATUS].recv_status);
get_final_status(call, call->request_data[GRPC_IOREQ_RECV_STATUS]);
break;
case GRPC_IOREQ_RECV_STATUS_DETAILS:
get_final_details(call,
call->request_data[GRPC_IOREQ_RECV_STATUS_DETAILS]);
break;
case GRPC_IOREQ_RECV_INITIAL_METADATA:
SWAP(grpc_metadata_array, call->buffered_metadata[0],
@ -669,6 +703,7 @@ static void finish_read_ops(grpc_call *call) {
finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK);
}
finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK);
finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS_DETAILS, GRPC_OP_OK);
finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK);
/* fallthrough */
case READ_STATE_GOT_INITIAL_METADATA:
@ -746,20 +781,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
return GRPC_CALL_OK;
}
static void call_start_ioreq_done(grpc_call *call, grpc_op_error status,
void *user_data) {
grpc_cq_end_ioreq(call->cq, user_data, call, do_nothing, NULL, status);
}
grpc_call_error grpc_call_start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
size_t nreqs, void *tag) {
grpc_call_error err;
lock(call);
err = start_ioreq(call, reqs, nreqs, call_start_ioreq_done, tag);
unlock(call);
return err;
}
grpc_call_error grpc_call_start_ioreq_and_call_back(
grpc_call *call, const grpc_ioreq *reqs, size_t nreqs,
grpc_ioreq_completion_func on_complete, void *user_data) {
@ -919,8 +940,8 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) {
gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
}
mdusr = &dest->metadata[dest->count++];
mdusr->key = (char *)grpc_mdstr_as_c_string(md->key);
mdusr->value = (char *)grpc_mdstr_as_c_string(md->value);
mdusr->key = grpc_mdstr_as_c_string(md->key);
mdusr->value = grpc_mdstr_as_c_string(md->value);
mdusr->value_length = GPR_SLICE_LENGTH(md->value->slice);
if (call->owned_metadata_count == call->owned_metadata_capacity) {
call->owned_metadata_capacity = GPR_MAX(
@ -943,6 +964,123 @@ void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) {
set_read_state(call, READ_STATE_GOT_INITIAL_METADATA);
}
/*
* BATCH API IMPLEMENTATION
*/
static void set_status_value_directly(grpc_status_code status, void *dest) {
*(grpc_status_code *)dest = status;
}
static void set_cancelled_value(grpc_status_code status, void *dest) {
*(grpc_status_code *)dest = (status != GRPC_STATUS_OK);
}
static void finish_batch(grpc_call *call, grpc_op_error result, void *tag) {
grpc_cq_end_op_complete(call->cq, tag, call, do_nothing, NULL, GRPC_OP_OK);
}
grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
size_t nops, void *tag) {
grpc_ioreq reqs[GRPC_IOREQ_OP_COUNT];
size_t in;
size_t out;
const grpc_op *op;
grpc_ioreq *req;
/* rewrite batch ops into ioreq ops */
for (in = 0, out = 0; in < nops; in++) {
op = &ops[in];
switch (op->op) {
case GRPC_OP_SEND_INITIAL_METADATA:
req = &reqs[out++];
req->op = GRPC_IOREQ_SEND_INITIAL_METADATA;
req->data.send_metadata.count = op->data.send_initial_metadata.count;
req->data.send_metadata.metadata =
op->data.send_initial_metadata.metadata;
break;
case GRPC_OP_SEND_MESSAGE:
req = &reqs[out++];
req->op = GRPC_IOREQ_SEND_MESSAGE;
req->data.send_message = op->data.send_message;
break;
case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
if (!call->is_client) {
return GRPC_CALL_ERROR_NOT_ON_SERVER;
}
req = &reqs[out++];
req->op = GRPC_IOREQ_SEND_CLOSE;
break;
case GRPC_OP_SEND_STATUS_FROM_SERVER:
if (call->is_client) {
return GRPC_CALL_ERROR_NOT_ON_CLIENT;
}
req = &reqs[out++];
req->op = GRPC_IOREQ_SEND_TRAILING_METADATA;
req->data.send_metadata.count =
op->data.send_status_from_server.trailing_metadata_count;
req->data.send_metadata.metadata =
op->data.send_status_from_server.trailing_metadata;
req = &reqs[out++];
req->op = GRPC_IOREQ_SEND_STATUS;
req->data.send_status.code = op->data.send_status_from_server.status;
req->data.send_status.details =
op->data.send_status_from_server.status_details;
req = &reqs[out++];
req->op = GRPC_IOREQ_SEND_CLOSE;
break;
case GRPC_OP_RECV_INITIAL_METADATA:
if (!call->is_client) {
return GRPC_CALL_ERROR_NOT_ON_SERVER;
}
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
req->data.recv_metadata = op->data.recv_initial_metadata;
break;
case GRPC_OP_RECV_MESSAGE:
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_MESSAGE;
req->data.recv_message = op->data.recv_message;
break;
case GRPC_OP_RECV_STATUS_ON_CLIENT:
if (!call->is_client) {
return GRPC_CALL_ERROR_NOT_ON_SERVER;
}
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_STATUS;
req->data.recv_status.set_value = set_status_value_directly;
req->data.recv_status.user_data = op->data.recv_status_on_client.status;
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_STATUS_DETAILS;
req->data.recv_status_details.details =
op->data.recv_status_on_client.status_details;
req->data.recv_status_details.details_capacity =
op->data.recv_status_on_client.status_details_capacity;
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_TRAILING_METADATA;
req->data.recv_metadata =
op->data.recv_status_on_client.trailing_metadata;
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_CLOSE;
break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_STATUS;
req->data.recv_status.set_value = set_cancelled_value;
req->data.recv_status.user_data =
op->data.recv_close_on_server.cancelled;
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_CLOSE;
break;
}
}
grpc_cq_begin_op(call->cq, call, GRPC_OP_COMPLETE);
return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_batch,
tag);
}
/*
* LEGACY API IMPLEMENTATION
* All this code will disappear as soon as wrappings are updated
@ -983,8 +1121,8 @@ static void destroy_legacy_state(legacy_state *ls) {
size_t i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < ls->md_out_count[i]; j++) {
gpr_free(ls->md_out[i][j].key);
gpr_free(ls->md_out[i][j].value);
gpr_free((char *)ls->md_out[i][j].key);
gpr_free((char *)ls->md_out[i][j].value);
}
gpr_free(ls->md_out[i]);
}
@ -1017,7 +1155,7 @@ grpc_call_error grpc_call_add_metadata_old(grpc_call *call,
mdout->key = gpr_strdup(metadata->key);
mdout->value = gpr_malloc(metadata->value_length);
mdout->value_length = metadata->value_length;
memcpy(mdout->value, metadata->value, metadata->value_length);
memcpy((char *)mdout->value, metadata->value, metadata->value_length);
unlock(call);
@ -1060,7 +1198,7 @@ static void finish_send_metadata(grpc_call *call, grpc_op_error status,
grpc_call_error grpc_call_invoke_old(grpc_call *call, grpc_completion_queue *cq,
void *metadata_read_tag,
void *finished_tag, gpr_uint32 flags) {
grpc_ioreq reqs[3];
grpc_ioreq reqs[4];
legacy_state *ls;
grpc_call_error err;
@ -1089,11 +1227,13 @@ grpc_call_error grpc_call_invoke_old(grpc_call *call, grpc_completion_queue *cq,
reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA;
reqs[0].data.recv_metadata = &ls->trailing_md_in;
reqs[1].op = GRPC_IOREQ_RECV_STATUS;
reqs[1].data.recv_status.details = &ls->details;
reqs[1].data.recv_status.details_capacity = &ls->details_capacity;
reqs[1].data.recv_status.code = &ls->status;
reqs[2].op = GRPC_IOREQ_RECV_CLOSE;
err = start_ioreq(call, reqs, 3, finish_status, NULL);
reqs[1].data.recv_status.user_data = &ls->status;
reqs[1].data.recv_status.set_value = set_status_value_directly;
reqs[2].op = GRPC_IOREQ_RECV_STATUS_DETAILS;
reqs[2].data.recv_status_details.details = &ls->details;
reqs[2].data.recv_status_details.details_capacity = &ls->details_capacity;
reqs[3].op = GRPC_IOREQ_RECV_CLOSE;
err = start_ioreq(call, reqs, 4, finish_status, NULL);
if (err != GRPC_CALL_OK) goto done;
done:
@ -1121,9 +1261,8 @@ grpc_call_error grpc_call_server_accept_old(grpc_call *call,
ls->finished_tag = finished_tag;
reqs[0].op = GRPC_IOREQ_RECV_STATUS;
reqs[0].data.recv_status.details = NULL;
reqs[0].data.recv_status.details_capacity = 0;
reqs[0].data.recv_status.code = &ls->status;
reqs[0].data.recv_status.user_data = &ls->status;
reqs[0].data.recv_status.set_value = set_status_value_directly;
reqs[1].op = GRPC_IOREQ_RECV_CLOSE;
err = start_ioreq(call, reqs, 2, finish_status, NULL);
unlock(call);

@ -44,6 +44,7 @@ typedef enum {
GRPC_IOREQ_RECV_MESSAGE,
GRPC_IOREQ_RECV_TRAILING_METADATA,
GRPC_IOREQ_RECV_STATUS,
GRPC_IOREQ_RECV_STATUS_DETAILS,
GRPC_IOREQ_RECV_CLOSE,
GRPC_IOREQ_SEND_INITIAL_METADATA,
GRPC_IOREQ_SEND_MESSAGE,
@ -53,24 +54,25 @@ typedef enum {
GRPC_IOREQ_OP_COUNT
} grpc_ioreq_op;
typedef struct {
grpc_status_code *code;
char **details;
size_t *details_capacity;
} grpc_recv_status_args;
typedef union {
grpc_metadata_array *recv_metadata;
grpc_byte_buffer **recv_message;
grpc_recv_status_args recv_status;
struct {
void (*set_value)(grpc_status_code status, void *user_data);
void *user_data;
} recv_status;
struct {
char **details;
size_t *details_capacity;
} recv_status_details;
struct {
size_t count;
grpc_metadata *metadata;
const grpc_metadata *metadata;
} send_metadata;
grpc_byte_buffer *send_message;
struct {
grpc_status_code code;
char *details;
const char *details;
} send_status;
} grpc_ioreq_data;
@ -83,9 +85,11 @@ typedef void (*grpc_ioreq_completion_func)(grpc_call *call,
grpc_op_error status,
void *user_data);
grpc_call *grpc_call_create(grpc_channel *channel,
grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
const void *server_transport_data);
void grpc_call_set_completion_queue(grpc_call *call, grpc_completion_queue *cq);
void grpc_call_internal_ref(grpc_call *call);
void grpc_call_internal_unref(grpc_call *call, int allow_immediate_deletion);
@ -104,8 +108,7 @@ grpc_call_error grpc_call_start_ioreq_and_call_back(
grpc_ioreq_completion_func on_complete, void *user_data);
/* Called when it's known that the initial batch of metadata is complete */
void grpc_call_initial_metadata_complete(
grpc_call_element *surface_element);
void grpc_call_initial_metadata_complete(grpc_call_element *surface_element);
void grpc_call_set_deadline(grpc_call_element *surface_element,
gpr_timespec deadline);

@ -0,0 +1,13 @@
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <string.h>
void grpc_call_details_init(grpc_call_details *cd) {
memset(cd, 0, sizeof(*cd));
}
void grpc_call_details_destroy(grpc_call_details *cd) {
gpr_free(cd->method);
gpr_free(cd->host);
}

@ -77,9 +77,10 @@ grpc_channel *grpc_channel_create_from_filters(
static void do_nothing(void *ignored, grpc_op_error error) {}
grpc_call *grpc_channel_create_call_old(grpc_channel *channel,
const char *method, const char *host,
gpr_timespec absolute_deadline) {
grpc_call *grpc_channel_create_call(grpc_channel *channel,
grpc_completion_queue *cq,
const char *method, const char *host,
gpr_timespec absolute_deadline) {
grpc_call *call;
grpc_mdelem *path_mdelem;
grpc_mdelem *authority_mdelem;
@ -90,7 +91,7 @@ grpc_call *grpc_channel_create_call_old(grpc_channel *channel,
return NULL;
}
call = grpc_call_create(channel, NULL);
call = grpc_call_create(channel, cq, NULL);
/* Add :path and :authority headers. */
/* TODO(klempner): Consider optimizing this by stashing mdelems for common
@ -126,6 +127,13 @@ grpc_call *grpc_channel_create_call_old(grpc_channel *channel,
return call;
}
grpc_call *grpc_channel_create_call_old(grpc_channel *channel,
const char *method, const char *host,
gpr_timespec absolute_deadline) {
return grpc_channel_create_call(channel, NULL, method, host,
absolute_deadline);
}
void grpc_channel_internal_ref(grpc_channel *channel) {
gpr_ref(&channel->refs);
}

@ -185,14 +185,25 @@ void grpc_cq_end_write_accepted(grpc_completion_queue *cc, void *tag,
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
}
void grpc_cq_end_ioreq(grpc_completion_queue *cc, void *tag, grpc_call *call,
grpc_event_finish_func on_finish, void *user_data,
grpc_op_error error) {
void grpc_cq_end_op_complete(grpc_completion_queue *cc, void *tag,
grpc_call *call, grpc_event_finish_func on_finish,
void *user_data, grpc_op_error error) {
event *ev;
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
ev = add_locked(cc, GRPC_IOREQ, tag, call, on_finish, user_data);
ev = add_locked(cc, GRPC_OP_COMPLETE, tag, call, on_finish, user_data);
ev->base.data.write_accepted = error;
end_op_locked(cc, GRPC_IOREQ);
end_op_locked(cc, GRPC_OP_COMPLETE);
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
}
void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, grpc_call *call,
grpc_event_finish_func on_finish, void *user_data,
grpc_op_error error) {
event *ev;
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
ev = add_locked(cc, GRPC_OP_COMPLETE, tag, call, on_finish, user_data);
ev->base.data.write_accepted = error;
end_op_locked(cc, GRPC_OP_COMPLETE);
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
}

@ -78,6 +78,10 @@ void grpc_cq_end_finish_accepted(grpc_completion_queue *cc, void *tag,
grpc_call *call,
grpc_event_finish_func on_finish,
void *user_data, grpc_op_error error);
/* Queue a GRPC_OP_COMPLETED operation */
void grpc_cq_end_op_complete(grpc_completion_queue *cc, void *tag,
grpc_call *call, grpc_event_finish_func on_finish,
void *user_data, grpc_op_error error);
/* Queue a GRPC_CLIENT_METADATA_READ operation */
void grpc_cq_end_client_metadata_read(grpc_completion_queue *cc, void *tag,
grpc_call *call,
@ -97,9 +101,9 @@ void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call,
gpr_timespec deadline, size_t metadata_count,
grpc_metadata *metadata_elements);
void grpc_cq_end_ioreq(grpc_completion_queue *cc, void *tag, grpc_call *call,
grpc_event_finish_func on_finish, void *user_data,
grpc_op_error error);
void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, grpc_call *call,
grpc_event_finish_func on_finish, void *user_data,
grpc_op_error error);
void grpc_cq_end_server_shutdown(grpc_completion_queue *cc, void *tag);

@ -87,10 +87,10 @@ char *grpc_event_string(grpc_event *ev) {
gpr_strvec_add(&buf, gpr_strdup(" end-of-stream"));
}
break;
case GRPC_IOREQ:
gpr_strvec_add(&buf, gpr_strdup("IOREQ: "));
case GRPC_OP_COMPLETE:
gpr_strvec_add(&buf, gpr_strdup("OP_COMPLETE: "));
addhdr(&buf, ev);
adderr(&buf, ev->data.ioreq);
adderr(&buf, ev->data.op_complete);
break;
case GRPC_WRITE_ACCEPTED:
gpr_strvec_add(&buf, gpr_strdup("WRITE_ACCEPTED: "));

@ -0,0 +1,12 @@
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <string.h>
void grpc_metadata_array_init(grpc_metadata_array *array) {
memset(array, 0, sizeof(*array));
}
void grpc_metadata_array_destroy(grpc_metadata_array *array) {
gpr_free(array->metadata);
}

@ -72,12 +72,15 @@ struct channel_data {
};
typedef void (*new_call_cb)(grpc_server *server, grpc_completion_queue *cq,
grpc_call **call, grpc_call_details *details,
grpc_metadata_array *initial_metadata,
call_data *calld, void *user_data);
typedef struct {
void *user_data;
grpc_completion_queue *cq;
grpc_call **call;
grpc_call_details *details;
grpc_metadata_array *initial_metadata;
new_call_cb cb;
} requested_call;
@ -121,7 +124,9 @@ typedef enum {
ZOMBIED
} call_state;
typedef struct legacy_data { grpc_metadata_array *initial_metadata; } legacy_data;
typedef struct legacy_data {
grpc_metadata_array *initial_metadata;
} legacy_data;
struct call_data {
grpc_call *call;
@ -132,6 +137,7 @@ struct call_data {
grpc_mdstr *host;
legacy_data *legacy;
grpc_call_details *details;
gpr_uint8 included[CALL_LIST_COUNT];
call_link links[CALL_LIST_COUNT];
@ -240,7 +246,8 @@ static void start_new_rpc(grpc_call_element *elem) {
requested_call rc = server->requested_calls[--server->requested_call_count];
calld->state = ACTIVATED;
gpr_mu_unlock(&server->mu);
rc.cb(server, rc.cq, rc.initial_metadata, calld, rc.user_data);
rc.cb(server, rc.cq, rc.call, rc.details, rc.initial_metadata, calld,
rc.user_data);
} else {
calld->state = PENDING;
call_list_join(server, calld, PENDING_START);
@ -339,21 +346,22 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elemn,
static void channel_op(grpc_channel_element *elem,
grpc_channel_element *from_elem, grpc_channel_op *op) {
channel_data *chand = elem->channel_data;
grpc_server *server = chand->server;
switch (op->type) {
case GRPC_ACCEPT_CALL:
/* create a call */
grpc_call_create(chand->channel,
grpc_call_create(chand->channel, NULL,
op->data.accept_call.transport_server_data);
break;
case GRPC_TRANSPORT_CLOSED:
/* if the transport is closed for a server channel, we destroy the
channel */
gpr_mu_lock(&chand->server->mu);
server_ref(chand->server);
gpr_mu_lock(&server->mu);
server_ref(server);
destroy_channel(chand);
gpr_mu_unlock(&chand->server->mu);
server_unref(chand->server);
gpr_mu_unlock(&server->mu);
server_unref(server);
break;
case GRPC_TRANSPORT_GOAWAY:
gpr_slice_unref(op->data.goaway.message);
@ -617,6 +625,7 @@ void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
/* terminate all the requested calls */
for (i = 0; i < requested_call_count; i++) {
requested_calls[i].cb(server, requested_calls[i].cq,
requested_calls[i].call, requested_calls[i].details,
requested_calls[i].initial_metadata, NULL,
requested_calls[i].user_data);
}
@ -667,6 +676,8 @@ void grpc_server_add_listener(grpc_server *server, void *arg,
static grpc_call_error queue_call_request(grpc_server *server,
grpc_completion_queue *cq,
grpc_call **call,
grpc_call_details *details,
grpc_metadata_array *initial_metadata,
new_call_cb cb, void *user_data) {
call_data *calld;
@ -674,7 +685,7 @@ static grpc_call_error queue_call_request(grpc_server *server,
gpr_mu_lock(&server->mu);
if (server->shutdown) {
gpr_mu_unlock(&server->mu);
cb(server, cq, initial_metadata, NULL, user_data);
cb(server, cq, call, details, initial_metadata, NULL, user_data);
return GRPC_CALL_OK;
}
calld = call_list_remove_head(server, PENDING_START);
@ -682,7 +693,7 @@ static grpc_call_error queue_call_request(grpc_server *server,
GPR_ASSERT(calld->state == PENDING);
calld->state = ACTIVATED;
gpr_mu_unlock(&server->mu);
cb(server, cq, initial_metadata, calld, user_data);
cb(server, cq, call, details, initial_metadata, calld, user_data);
return GRPC_CALL_OK;
} else {
if (server->requested_call_count == server->requested_call_capacity) {
@ -696,6 +707,8 @@ static grpc_call_error queue_call_request(grpc_server *server,
rc = &server->requested_calls[server->requested_call_count++];
rc->cb = cb;
rc->cq = cq;
rc->call = call;
rc->details = details;
rc->user_data = user_data;
rc->initial_metadata = initial_metadata;
gpr_mu_unlock(&server->mu);
@ -703,18 +716,64 @@ static grpc_call_error queue_call_request(grpc_server *server,
}
}
static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
gpr_slice slice = value->slice;
size_t len = GPR_SLICE_LENGTH(slice);
if (len + 1 > *capacity) {
*capacity = GPR_MAX(len + 1, *capacity * 2);
*dest = gpr_realloc(*dest, *capacity);
}
memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
}
static void publish_request(grpc_call *call, grpc_op_error status, void *tag) {
grpc_call_element *elem =
grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_server *server = chand->server;
if (status == GRPC_OP_OK) {
cpstr(&calld->details->host, &calld->details->host_capacity, calld->host);
cpstr(&calld->details->method, &calld->details->method_capacity,
calld->path);
calld->details->deadline = calld->deadline;
grpc_cq_end_op_complete(server->cq, tag, call, do_nothing, NULL,
GRPC_OP_OK);
} else {
abort();
}
}
static void begin_request(grpc_server *server, grpc_completion_queue *cq,
grpc_call **call, grpc_call_details *details,
grpc_metadata_array *initial_metadata,
call_data *call_data, void *tag) {
abort();
call_data *calld, void *tag) {
grpc_ioreq req;
if (!calld) {
*call = NULL;
initial_metadata->count = 0;
grpc_cq_end_op_complete(cq, tag, NULL, do_nothing, NULL, GRPC_OP_ERROR);
return;
}
calld->details = details;
grpc_call_set_completion_queue(calld->call, cq);
*call = calld->call;
req.op = GRPC_IOREQ_RECV_INITIAL_METADATA;
req.data.recv_metadata = initial_metadata;
grpc_call_internal_ref(calld->call);
grpc_call_start_ioreq_and_call_back(calld->call, &req, 1, publish_request,
tag);
}
grpc_call_error grpc_server_request_call(
grpc_server *server, grpc_call_details *details,
grpc_metadata_array *initial_metadata, grpc_completion_queue *cq,
void *tag) {
grpc_cq_begin_op(cq, NULL, GRPC_IOREQ);
return queue_call_request(server, cq, initial_metadata, begin_request, tag);
grpc_call_error grpc_server_request_call(grpc_server *server, grpc_call **call,
grpc_call_details *details,
grpc_metadata_array *initial_metadata,
grpc_completion_queue *cq, void *tag) {
grpc_cq_begin_op(cq, NULL, GRPC_OP_COMPLETE);
return queue_call_request(server, cq, call, details, initial_metadata,
begin_request, tag);
}
static void publish_legacy_request(grpc_call *call, grpc_op_error status,
@ -737,9 +796,12 @@ static void publish_legacy_request(grpc_call *call, grpc_op_error status,
}
static void begin_legacy_request(grpc_server *server, grpc_completion_queue *cq,
grpc_call **call, grpc_call_details *details,
grpc_metadata_array *initial_metadata,
call_data *calld, void *tag) {
grpc_ioreq req;
GPR_ASSERT(call == NULL);
GPR_ASSERT(details == NULL);
if (!calld) {
gpr_free(initial_metadata);
grpc_cq_end_new_rpc(cq, tag, NULL, do_nothing, NULL, NULL, NULL,
@ -762,7 +824,7 @@ grpc_call_error grpc_server_request_call_old(grpc_server *server,
gpr_malloc(sizeof(grpc_metadata_array));
memset(client_metadata, 0, sizeof(*client_metadata));
grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_RPC_NEW);
return queue_call_request(server, server->cq, client_metadata,
return queue_call_request(server, server->cq, NULL, NULL, client_metadata,
begin_legacy_request, tag_new);
}

@ -70,7 +70,7 @@ typedef struct expectation {
union {
grpc_op_error finish_accepted;
grpc_op_error write_accepted;
grpc_op_error ioreq;
grpc_op_error op_complete;
struct {
const char *method;
const char *host;
@ -123,6 +123,10 @@ static int has_metadata(const grpc_metadata *md, size_t count, const char *key,
return 0;
}
int contains_metadata(grpc_metadata_array *array, const char *key, const char *value) {
return has_metadata(array->metadata, array->count, key, value);
}
static void verify_and_destroy_metadata(metadata *md, grpc_metadata *elems,
size_t count) {
size_t i;
@ -166,6 +170,10 @@ static int byte_buffer_eq_slice(grpc_byte_buffer *bb, gpr_slice b) {
return ok;
}
int byte_buffer_eq_string(grpc_byte_buffer *bb, const char *str) {
return byte_buffer_eq_slice(bb, gpr_slice_from_copied_string(str));
}
static int string_equivalent(const char *a, const char *b) {
if (a == NULL) return b == NULL || b[0] == 0;
if (b == NULL) return a[0] == 0;
@ -220,8 +228,8 @@ static void verify_matches(expectation *e, grpc_event *ev) {
GPR_ASSERT(ev->data.read == NULL);
}
break;
case GRPC_IOREQ:
GPR_ASSERT(e->data.ioreq == ev->data.ioreq);
case GRPC_OP_COMPLETE:
GPR_ASSERT(e->data.op_complete == ev->data.op_complete);
break;
case GRPC_SERVER_SHUTDOWN:
break;
@ -256,23 +264,23 @@ static void expectation_to_strvec(gpr_strvec *buf, expectation *e) {
switch (e->type) {
case GRPC_FINISH_ACCEPTED:
gpr_asprintf(&tmp, "GRPC_FINISH_ACCEPTED result=%d",
e->data.finish_accepted);
e->data.finish_accepted);
gpr_strvec_add(buf, tmp);
break;
case GRPC_WRITE_ACCEPTED:
gpr_asprintf(&tmp, "GRPC_WRITE_ACCEPTED result=%d",
e->data.write_accepted);
e->data.write_accepted);
gpr_strvec_add(buf, tmp);
break;
case GRPC_IOREQ:
gpr_asprintf(&tmp, "GRPC_IOREQ result=%d", e->data.ioreq);
case GRPC_OP_COMPLETE:
gpr_asprintf(&tmp, "GRPC_OP_COMPLETE result=%d", e->data.op_complete);
gpr_strvec_add(buf, tmp);
break;
case GRPC_SERVER_RPC_NEW:
timeout = gpr_time_sub(e->data.server_rpc_new.deadline, gpr_now());
gpr_asprintf(&tmp, "GRPC_SERVER_RPC_NEW method=%s host=%s timeout=%fsec",
e->data.server_rpc_new.method, e->data.server_rpc_new.host,
timeout.tv_sec + 1e-9 * timeout.tv_nsec);
e->data.server_rpc_new.method, e->data.server_rpc_new.host,
timeout.tv_sec + 1e-9 * timeout.tv_nsec);
gpr_strvec_add(buf, tmp);
break;
case GRPC_CLIENT_METADATA_READ:
@ -281,14 +289,16 @@ static void expectation_to_strvec(gpr_strvec *buf, expectation *e) {
break;
case GRPC_FINISHED:
gpr_asprintf(&tmp, "GRPC_FINISHED status=%d details=%s ",
e->data.finished.status, e->data.finished.details);
e->data.finished.status, e->data.finished.details);
gpr_strvec_add(buf, tmp);
metadata_expectation(buf, e->data.finished.metadata);
break;
case GRPC_READ:
gpr_strvec_add(buf, gpr_strdup("GRPC_READ data="));
gpr_strvec_add(buf, gpr_hexdump((char *)GPR_SLICE_START_PTR(*e->data.read),
GPR_SLICE_LENGTH(*e->data.read), GPR_HEXDUMP_PLAINTEXT));
gpr_strvec_add(
buf,
gpr_hexdump((char *)GPR_SLICE_START_PTR(*e->data.read),
GPR_SLICE_LENGTH(*e->data.read), GPR_HEXDUMP_PLAINTEXT));
break;
case GRPC_SERVER_SHUTDOWN:
gpr_strvec_add(buf, gpr_strdup("GRPC_SERVER_SHUTDOWN"));
@ -422,6 +432,10 @@ void cq_expect_write_accepted(cq_verifier *v, void *tag, grpc_op_error result) {
add(v, GRPC_WRITE_ACCEPTED, tag)->data.write_accepted = result;
}
void cq_expect_completion(cq_verifier *v, void *tag, grpc_op_error result) {
add(v, GRPC_OP_COMPLETE, tag)->data.op_complete = result;
}
void cq_expect_finish_accepted(cq_verifier *v, void *tag,
grpc_op_error result) {
add(v, GRPC_FINISH_ACCEPTED, tag)->data.finish_accepted = result;

@ -60,6 +60,7 @@ void cq_expect_write_accepted(cq_verifier *v, void *tag, grpc_op_error result);
void cq_expect_finish_accepted(cq_verifier *v, void *tag, grpc_op_error result);
void cq_expect_read(cq_verifier *v, void *tag, gpr_slice bytes);
void cq_expect_empty_read(cq_verifier *v, void *tag);
void cq_expect_completion(cq_verifier *v, void *tag, grpc_op_error result);
/* *output_call is set the the server call instance */
void cq_expect_server_rpc_new(cq_verifier *v, grpc_call **output_call,
void *tag, const char *method, const char *host,
@ -71,4 +72,7 @@ void cq_expect_finished_with_status(cq_verifier *v, void *tag,
void cq_expect_finished(cq_verifier *v, void *tag, ...);
void cq_expect_server_shutdown(cq_verifier *v, void *tag);
int byte_buffer_eq_string(grpc_byte_buffer *byte_buffer, const char *string);
int contains_metadata(grpc_metadata_array *array, const char *key, const char *value);
#endif /* __GRPC_TEST_END2END_CQ_VERIFIER_H__ */

@ -33,11 +33,37 @@ END2END_TESTS = [
'request_response_with_binary_metadata_and_payload',
'request_response_with_metadata_and_payload',
'request_response_with_payload',
'request_response_with_trailing_metadata_and_payload',
'request_with_large_metadata',
'request_with_payload',
'simple_delayed_request',
'simple_request',
'thread_stress',
'writes_done_hangs_with_pending_read',
'cancel_after_accept_legacy',
'cancel_after_accept_and_writes_closed_legacy',
'cancel_after_invoke_legacy',
'cancel_before_invoke_legacy',
'cancel_in_a_vacuum_legacy',
'census_simple_request_legacy',
'disappearing_server_legacy',
'early_server_shutdown_finishes_inflight_calls_legacy',
'early_server_shutdown_finishes_tags_legacy',
'graceful_server_shutdown_legacy',
'invoke_large_request_legacy',
'max_concurrent_streams_legacy',
'no_op_legacy',
'ping_pong_streaming_legacy',
'request_response_with_binary_metadata_and_payload_legacy',
'request_response_with_metadata_and_payload_legacy',
'request_response_with_payload_legacy',
'request_response_with_trailing_metadata_and_payload_legacy',
'request_with_large_metadata_legacy',
'request_with_payload_legacy',
'simple_delayed_request_legacy',
'simple_request_legacy',
'thread_stress_legacy',
'writes_done_hangs_with_pending_read_legacy',
]

@ -106,40 +106,107 @@ static void end_test(grpc_end2end_test_fixture *f) {
/* Cancel after accept, no payload */
static void test_cancel_after_accept(grpc_end2end_test_config config,
cancellation_mode mode) {
grpc_op ops[6];
grpc_op *op;
grpc_call *c;
grpc_call *s;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv;
grpc_call_details call_details;
grpc_status_code status;
char *details = NULL;
size_t details_capacity = 0;
grpc_byte_buffer *request_payload_recv = NULL;
grpc_byte_buffer *response_payload_recv = NULL;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
gpr_slice response_payload_slice = gpr_slice_from_copied_string("hello you");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *response_payload =
grpc_byte_buffer_create(&response_payload_slice, 1);
int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
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);
op = ops;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &response_payload_recv;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s,
&call_details,
&request_metadata_recv,
f.server_cq, tag(2)));
cq_expect_completion(v_server, tag(2), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
op = ops;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &request_payload_recv;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op++;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = response_payload;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(3)));
GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c));
cq_expect_finished_with_status(v_client, tag(3), mode.expect_status,
mode.expect_details, NULL);
cq_expect_completion(v_server, tag(3), GRPC_OP_OK);
cq_verify(v_server);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_finished_with_status(v_server, tag(102), GRPC_STATUS_CANCELLED,
NULL, NULL);
cq_verify(v_server);
GPR_ASSERT(status == mode.expect_status);
GPR_ASSERT(0 == strcmp(details, mode.expect_details));
GPR_ASSERT(was_cancelled == 1);
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_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
gpr_free(details);
grpc_call_destroy(c);
grpc_call_destroy(s);

@ -0,0 +1,167 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/tests/cancel_test_helpers.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Cancel after accept with a writes closed, no payload */
static void test_cancel_after_accept_and_writes_closed(
grpc_end2end_test_config config, cancellation_mode mode) {
grpc_call *c;
grpc_call *s;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(101)));
cq_expect_empty_read(v_server, tag(101));
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c));
cq_expect_finished_with_status(v_client, tag(3), mode.expect_status,
mode.expect_details, NULL);
cq_verify(v_client);
cq_expect_finished_with_status(v_server, tag(102), GRPC_STATUS_CANCELLED,
NULL, NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
unsigned i;
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
test_cancel_after_accept_and_writes_closed(config, cancellation_modes[i]);
}
}

@ -0,0 +1,159 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/tests/cancel_test_helpers.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Cancel after accept, no payload */
static void test_cancel_after_accept(grpc_end2end_test_config config,
cancellation_mode mode) {
grpc_call *c;
grpc_call *s;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c));
cq_expect_finished_with_status(v_client, tag(3), mode.expect_status,
mode.expect_details, NULL);
cq_verify(v_client);
cq_expect_finished_with_status(v_server, tag(102), GRPC_STATUS_CANCELLED,
NULL, NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
unsigned i;
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
test_cancel_after_accept(config, cancellation_modes[i]);
}
}

@ -105,26 +105,74 @@ static void end_test(grpc_end2end_test_fixture *f) {
/* Cancel after invoke, no payload */
static void test_cancel_after_invoke(grpc_end2end_test_config config,
cancellation_mode mode) {
cancellation_mode mode, int test_ops) {
grpc_op ops[6];
grpc_op *op;
grpc_call *c;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv;
grpc_call_details call_details;
grpc_status_code status;
char *details = NULL;
size_t details_capacity = 0;
grpc_byte_buffer *response_payload_recv = NULL;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
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);
op = ops;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &response_payload_recv;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, test_ops, tag(1)));
GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_expect_finished_with_status(v_client, tag(3), mode.expect_status,
mode.expect_details, NULL);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(status == mode.expect_status);
GPR_ASSERT(0 == strcmp(details, mode.expect_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_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload_recv);
gpr_free(details);
grpc_call_destroy(c);
cq_verifier_destroy(v_client);
@ -133,9 +181,11 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config,
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
unsigned i;
unsigned i, j;
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
test_cancel_after_invoke(config, cancellation_modes[i]);
for (j = 2; j < 6; j++) {
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
test_cancel_after_invoke(config, cancellation_modes[i], j);
}
}
}

@ -0,0 +1,141 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/tests/cancel_test_helpers.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Cancel after invoke, no payload */
static void test_cancel_after_invoke(grpc_end2end_test_config config,
cancellation_mode mode) {
grpc_call *c;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_expect_finished_with_status(v_client, tag(3), mode.expect_status,
mode.expect_details, NULL);
cq_verify(v_client);
grpc_call_destroy(c);
cq_verifier_destroy(v_client);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
unsigned i;
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
test_cancel_after_invoke(config, cancellation_modes[i]);
}
}

@ -103,25 +103,73 @@ static void end_test(grpc_end2end_test_fixture *f) {
}
/* Cancel before invoke */
static void test_cancel_before_invoke(grpc_end2end_test_config config) {
static void test_cancel_before_invoke(grpc_end2end_test_config config, int test_ops) {
grpc_op ops[6];
grpc_op *op;
grpc_call *c;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv;
grpc_call_details call_details;
grpc_status_code status;
char *details = NULL;
size_t details_capacity = 0;
grpc_byte_buffer *response_payload_recv = NULL;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_CANCELLED, NULL,
NULL);
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);
op = ops;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &response_payload_recv;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, test_ops, tag(1)));
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(status == GRPC_STATUS_CANCELLED);
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_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload_recv);
gpr_free(details);
grpc_call_destroy(c);
cq_verifier_destroy(v_client);
@ -130,5 +178,8 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config) {
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_cancel_before_invoke(config);
int i;
for (i = 1; i <= 6; i++) {
test_cancel_before_invoke(config, i);
}
}

@ -0,0 +1,134 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Cancel before invoke */
static void test_cancel_before_invoke(grpc_end2end_test_config config) {
grpc_call *c;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_CANCELLED, NULL,
NULL);
cq_verify(v_client);
grpc_call_destroy(c);
cq_verifier_destroy(v_client);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_cancel_before_invoke(config);
}

@ -109,7 +109,7 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config,
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);

@ -0,0 +1,131 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/tests/cancel_test_helpers.h"
enum { TIMEOUT = 200000 };
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Cancel and do nothing */
static void test_cancel_in_a_vacuum(grpc_end2end_test_config config,
cancellation_mode mode) {
grpc_call *c;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c));
grpc_call_destroy(c);
cq_verifier_destroy(v_client);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
unsigned i;
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
test_cancel_in_a_vacuum(config, cancellation_modes[i]);
}
}

@ -45,7 +45,7 @@ static grpc_call_error wait_for_deadline(grpc_call *call) {
}
static const cancellation_mode cancellation_modes[] = {
{grpc_call_cancel, GRPC_STATUS_CANCELLED, NULL},
{grpc_call_cancel, GRPC_STATUS_CANCELLED, ""},
{wait_for_deadline, GRPC_STATUS_DEADLINE_EXCEEDED, "Deadline Exceeded"}, };
#endif

@ -0,0 +1,178 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "src/core/support/string.h"
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, n_seconds_time(5));
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void *tag(gpr_intptr t) { return (void *)t; }
static void test_body(grpc_end2end_test_fixture f) {
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = n_seconds_time(10);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
tag(1);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5)));
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
static void test_invoke_request_with_census(
grpc_end2end_test_config config, const char *name,
void (*body)(grpc_end2end_test_fixture f)) {
char *fullname;
grpc_end2end_test_fixture f;
grpc_arg client_arg, server_arg;
grpc_channel_args client_args, server_args;
client_arg.type = GRPC_ARG_INTEGER;
client_arg.key = GRPC_ARG_ENABLE_CENSUS;
client_arg.value.integer = 1;
client_args.num_args = 1;
client_args.args = &client_arg;
server_arg.type = GRPC_ARG_INTEGER;
server_arg.key = GRPC_ARG_ENABLE_CENSUS;
server_arg.value.integer = 1;
server_args.num_args = 1;
server_args.args = &server_arg;
gpr_asprintf(&fullname, "%s/%s", __FUNCTION__, name);
f = begin_test(config, fullname, &client_args, &server_args);
body(f);
end_test(&f);
config.tear_down_data(&f);
gpr_free(fullname);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_invoke_request_with_census(config, "census_simple_request", test_body);
}

@ -0,0 +1,168 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f,
cq_verifier *v_client,
cq_verifier *v_server) {
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
c = grpc_channel_create_call_old(f->client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f->client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f->server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
/* should be able to shut down the server early
- and still complete the request */
grpc_server_shutdown(f->server);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5)));
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
}
static void disappearing_server_test(grpc_end2end_test_config config) {
grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
gpr_log(GPR_INFO, "%s/%s", __FUNCTION__, config.name);
config.init_client(&f, NULL);
config.init_server(&f, NULL);
do_request_and_shutdown_server(&f, v_client, v_server);
/* now destroy and recreate the server */
config.init_server(&f, NULL);
do_request_and_shutdown_server(&f, v_client, v_server);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
if (config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION) {
disappearing_server_test(config);
}
}

@ -0,0 +1,159 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void test_early_server_shutdown_finishes_inflight_calls(
grpc_end2end_test_config config) {
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
/* shutdown and destroy the server */
shutdown_server(&f);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(s);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNAVAILABLE,
NULL, NULL);
cq_verify(v_client);
grpc_call_destroy(c);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_early_server_shutdown_finishes_inflight_calls(config);
}

@ -0,0 +1,127 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void test_early_server_shutdown_finishes_tags(
grpc_end2end_test_config config) {
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
grpc_call *s = (void *)1;
/* upon shutdown, the server should finish all requested calls indicating
no new call */
grpc_server_request_call_old(f.server, tag(1000));
grpc_server_shutdown(f.server);
cq_expect_server_rpc_new(v_server, &s, tag(1000), NULL, NULL, gpr_inf_past,
NULL);
cq_verify(v_server);
GPR_ASSERT(s == NULL);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_server);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_early_server_shutdown_finishes_tags(config);
}

@ -0,0 +1,160 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void test_early_server_shutdown_finishes_inflight_calls(
grpc_end2end_test_config config) {
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
/* shutdown the server */
grpc_server_shutdown_and_notify(f.server, tag(0xdead));
cq_verify_empty(v_server);
grpc_call_start_write_status_old(s, GRPC_STATUS_OK, NULL, tag(103));
grpc_call_destroy(s);
cq_expect_finish_accepted(v_server, tag(103), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_expect_server_shutdown(v_server, tag(0xdead));
cq_verify(v_server);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_OK, NULL, NULL);
cq_verify(v_client);
grpc_call_destroy(c);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_early_server_shutdown_finishes_inflight_calls(config);
}

@ -0,0 +1,183 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, n_seconds_time(5));
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static gpr_slice large_slice(void) {
gpr_slice slice = gpr_slice_malloc(1000000);
memset(GPR_SLICE_START_PTR(slice), 0xab, GPR_SLICE_LENGTH(slice));
return slice;
}
static void test_invoke_large_request(grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_slice request_payload_slice = large_slice();
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
gpr_timespec deadline = n_seconds_time(30);
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
/* write should not be accepted until the server is willing to read the
request (as this request is very large) */
cq_verify_empty(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
/* now the write can be accepted */
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_read(v_server, tag(5), large_slice());
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_invoke_large_request(config);
}

@ -0,0 +1,274 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void simple_request_body(grpc_end2end_test_fixture f) {
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5)));
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
static void test_max_concurrent_streams(grpc_end2end_test_config config) {
grpc_end2end_test_fixture f;
grpc_arg server_arg;
grpc_channel_args server_args;
grpc_call *c1;
grpc_call *c2;
grpc_call *s1;
grpc_call *s2;
int live_call;
gpr_timespec deadline;
cq_verifier *v_client;
cq_verifier *v_server;
grpc_event *ev;
server_arg.key = GRPC_ARG_MAX_CONCURRENT_STREAMS;
server_arg.type = GRPC_ARG_INTEGER;
server_arg.value.integer = 1;
server_args.num_args = 1;
server_args.args = &server_arg;
f = begin_test(config, __FUNCTION__, NULL, &server_args);
v_client = cq_verifier_create(f.client_cq);
v_server = cq_verifier_create(f.server_cq);
/* perform a ping-pong to ensure that settings have had a chance to round
trip */
simple_request_body(f);
/* perform another one to make sure that the one stream case still works */
simple_request_body(f);
/* start two requests - ensuring that the second is not accepted until
the first completes */
deadline = five_seconds_time();
c1 = grpc_channel_create_call_old(f.client, "/alpha", "test.google.com",
deadline);
GPR_ASSERT(c1);
c2 = grpc_channel_create_call_old(f.client, "/beta", "test.google.com",
deadline);
GPR_ASSERT(c1);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c1, f.client_cq, tag(301), tag(302), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c2, f.client_cq, tag(401), tag(402), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c1, tag(303)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c2, tag(303)));
ev = grpc_completion_queue_next(
f.client_cq, gpr_time_add(gpr_now(), gpr_time_from_seconds(10)));
GPR_ASSERT(ev);
GPR_ASSERT(ev->type == GRPC_FINISH_ACCEPTED);
GPR_ASSERT(ev->data.invoke_accepted == GRPC_OP_OK);
/* The /alpha or /beta calls started above could be invoked (but NOT both);
* check this here */
/* We'll get tag 303 or 403, we want 300, 400 */
live_call = ((int)(gpr_intptr) ev->tag) - 3;
grpc_event_finish(ev);
cq_expect_server_rpc_new(v_server, &s1, tag(100),
live_call == 300 ? "/alpha" : "/beta",
"test.google.com", deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s1, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s1, 0));
cq_expect_client_metadata_read(v_client, tag(live_call + 1), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_status_old(s1, GRPC_STATUS_UNIMPLEMENTED,
"xyz", tag(103)));
cq_expect_finish_accepted(v_server, tag(103), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
/* first request is finished, we should be able to start the second */
cq_expect_finished_with_status(v_client, tag(live_call + 2),
GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL);
cq_expect_finish_accepted(v_client, tag(live_call + 3), GRPC_OP_OK);
live_call = (live_call == 300) ? 400 : 300;
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(200)));
cq_expect_server_rpc_new(v_server, &s2, tag(200),
live_call == 300 ? "/alpha" : "/beta",
"test.google.com", deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s2, f.server_cq, tag(202)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s2, 0));
cq_expect_client_metadata_read(v_client, tag(live_call + 1), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_status_old(s2, GRPC_STATUS_UNIMPLEMENTED,
"xyz", tag(203)));
cq_expect_finish_accepted(v_server, tag(203), GRPC_OP_OK);
cq_expect_finished(v_server, tag(202), NULL);
cq_verify(v_server);
cq_expect_finished_with_status(v_client, tag(live_call + 2),
GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL);
cq_verify(v_client);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
grpc_call_destroy(c1);
grpc_call_destroy(s1);
grpc_call_destroy(c2);
grpc_call_destroy(s2);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_max_concurrent_streams(config);
}

@ -0,0 +1,109 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void test_no_op(grpc_end2end_test_config config) {
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) { test_no_op(config); }

@ -0,0 +1,203 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Client pings and server pongs. Repeat messages rounds before finishing. */
static void test_pingpong_streaming(grpc_end2end_test_config config,
int messages) {
int i;
grpc_call *c;
grpc_call *s = NULL;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
gpr_slice response_payload_slice = gpr_slice_from_copied_string("hello you");
grpc_byte_buffer *request_payload = NULL;
grpc_byte_buffer *response_payload = NULL;
gpr_timespec deadline = n_seconds_time(messages * 5);
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
gpr_log(GPR_INFO, "testing with %d message pairs.", messages);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
for (i = 0; i < messages; i++) {
request_payload = grpc_byte_buffer_create(&request_payload_slice, 1);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(2), 0));
/* destroy byte buffer early to ensure async code keeps track of its
contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(2), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(3)));
cq_expect_read(v_server, tag(3),
gpr_slice_from_copied_string("hello world"));
cq_verify(v_server);
response_payload = grpc_byte_buffer_create(&response_payload_slice, 1);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its
contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(4), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(5)));
cq_expect_read(v_client, tag(5), gpr_slice_from_copied_string("hello you"));
cq_verify(v_client);
}
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(6)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(7)));
cq_expect_finish_accepted(v_client, tag(6), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(7), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
int i;
for (i = 1; i < 10; i++) {
test_pingpong_streaming(config, i);
}
}

@ -114,107 +114,137 @@ static void test_request_response_with_metadata_and_payload(
grpc_byte_buffer *response_payload =
grpc_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
/* staggered lengths to ensure we hit various branches in base64 encode/decode
*/
grpc_metadata meta1 = {
"key1-bin", "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", 13};
grpc_metadata meta2 = {
"key2-bin", "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d",
14};
grpc_metadata meta3 = {
"key3-bin",
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee", 15};
grpc_metadata meta4 = {
"key4-bin",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", 16};
grpc_metadata meta_c[2] = {
{"key1-bin", "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", 13},
{"key2-bin", "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d",
14}};
grpc_metadata meta_s[2] = {
{"key3-bin",
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee", 15},
{"key4-bin",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", 16}};
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
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_byte_buffer *response_payload_recv = NULL;
grpc_call_details call_details;
grpc_status_code status;
char *details = NULL;
size_t details_capacity = 0;
int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta1, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta2, 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_server_rpc_new(
v_server, &s, tag(100), "/foo", "test.google.com", deadline, "key1-bin",
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", "key2-bin",
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d", NULL);
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);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 2;
op->data.send_initial_metadata.metadata = meta_c;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &response_payload_recv;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s,
&call_details,
&request_metadata_recv,
f.server_cq, tag(101)));
cq_expect_completion(v_server, tag(101), GRPC_OP_OK);
cq_verify(v_server);
grpc_call_server_accept_old(s, f.server_cq, tag(102));
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta3, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta4, 0));
grpc_call_server_end_initial_metadata_old(s, 0);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world"));
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 2;
op->data.send_initial_metadata.metadata = meta_s;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = response_payload;
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
op->data.send_status_from_server.status_details = "xyz";
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &request_payload_recv;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102)));
cq_expect_completion(v_server, tag(102), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(6), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK);
cq_verify(v_server);
/* fetch metadata.. */
cq_expect_client_metadata_read(
v_client, tag(2), "key3-bin",
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee",
"key4-bin",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", NULL);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7)));
cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you"));
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "test.google.com"));
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
GPR_ASSERT(contains_metadata(
&request_metadata_recv, "key1-bin",
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc"));
GPR_ASSERT(contains_metadata(
&request_metadata_recv, "key2-bin",
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"));
GPR_ASSERT(contains_metadata(
&initial_metadata_recv, "key3-bin",
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee"));
GPR_ASSERT(contains_metadata(
&initial_metadata_recv, "key4-bin",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
gpr_free(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);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {

@ -0,0 +1,222 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Request/response with metadata and payload.*/
static void test_request_response_with_metadata_and_payload(
grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
gpr_slice response_payload_slice = gpr_slice_from_copied_string("hello you");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *response_payload =
grpc_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
/* staggered lengths to ensure we hit various branches in base64 encode/decode
*/
grpc_metadata meta1 = {
"key1-bin", "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", 13};
grpc_metadata meta2 = {
"key2-bin", "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d",
14};
grpc_metadata meta3 = {
"key3-bin",
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee", 15};
grpc_metadata meta4 = {
"key4-bin",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", 16};
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta1, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta2, 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_server_rpc_new(
v_server, &s, tag(100), "/foo", "test.google.com", deadline, "key1-bin",
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", "key2-bin",
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d", NULL);
cq_verify(v_server);
grpc_call_server_accept_old(s, f.server_cq, tag(102));
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta3, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta4, 0));
grpc_call_server_end_initial_metadata_old(s, 0);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world"));
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(6), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK);
cq_verify(v_server);
/* fetch metadata.. */
cq_expect_client_metadata_read(
v_client, tag(2), "key3-bin",
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee",
"key4-bin",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7)));
cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you"));
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_request_response_with_metadata_and_payload(config);
}

@ -114,93 +114,122 @@ static void test_request_response_with_metadata_and_payload(
grpc_byte_buffer *response_payload =
grpc_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_metadata meta1 = {"key1", "val1", 4};
grpc_metadata meta2 = {"key2", "val2", 4};
grpc_metadata meta3 = {"key3", "val3", 4};
grpc_metadata meta4 = {"key4", "val4", 4};
grpc_metadata meta_c[2] = {{"key1", "val1", 4}, {"key2", "val2", 4}};
grpc_metadata meta_s[2] = {{"key3", "val3", 4}, {"key4", "val4", 4}};
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
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_byte_buffer *response_payload_recv = NULL;
grpc_call_details call_details;
grpc_status_code status;
char *details = NULL;
size_t details_capacity = 0;
int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta1, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta2, 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, "key1", "val1", "key2", "val2", NULL);
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);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 2;
op->data.send_initial_metadata.metadata = meta_c;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &response_payload_recv;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s,
&call_details,
&request_metadata_recv,
f.server_cq, tag(101)));
cq_expect_completion(v_server, tag(101), GRPC_OP_OK);
cq_verify(v_server);
grpc_call_server_accept_old(s, f.server_cq, tag(102));
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta3, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta4, 0));
grpc_call_server_end_initial_metadata_old(s, 0);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world"));
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 2;
op->data.send_initial_metadata.metadata = meta_s;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = response_payload;
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
op->data.send_status_from_server.status_details = "xyz";
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &request_payload_recv;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102)));
cq_expect_completion(v_server, tag(102), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(6), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK);
cq_verify(v_server);
/* fetch metadata.. */
cq_expect_client_metadata_read(v_client, tag(2), "key3", "val3", "key4",
"val4", NULL);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7)));
cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you"));
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "test.google.com"));
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1"));
GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2"));
GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3"));
GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4"));
gpr_free(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);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {

@ -0,0 +1,208 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Request/response with metadata and payload.*/
static void test_request_response_with_metadata_and_payload(
grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
gpr_slice response_payload_slice = gpr_slice_from_copied_string("hello you");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *response_payload =
grpc_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_metadata meta1 = {"key1", "val1", 4};
grpc_metadata meta2 = {"key2", "val2", 4};
grpc_metadata meta3 = {"key3", "val3", 4};
grpc_metadata meta4 = {"key4", "val4", 4};
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta1, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta2, 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, "key1", "val1", "key2", "val2", NULL);
cq_verify(v_server);
grpc_call_server_accept_old(s, f.server_cq, tag(102));
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta3, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta4, 0));
grpc_call_server_end_initial_metadata_old(s, 0);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world"));
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(6), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK);
cq_verify(v_server);
/* fetch metadata.. */
cq_expect_client_metadata_read(v_client, tag(2), "key3", "val3", "key4",
"val4", NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7)));
cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you"));
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_request_response_with_metadata_and_payload(config);
}

@ -103,10 +103,10 @@ static void end_test(grpc_end2end_test_fixture *f) {
}
static void request_response_with_payload(grpc_end2end_test_fixture f) {
grpc_call *c;
grpc_call *s;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
gpr_slice response_payload_slice = gpr_slice_from_copied_string("hello you");
grpc_call *c;
grpc_call *s;
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *response_payload =
@ -114,71 +114,108 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) {
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
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_byte_buffer *response_payload_recv = NULL;
grpc_call_details call_details;
grpc_status_code status;
char *details = NULL;
size_t details_capacity = 0;
int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
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);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &response_payload_recv;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s,
&call_details,
&request_metadata_recv,
f.server_cq, tag(101)));
cq_expect_completion(v_server, tag(101), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world"));
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(6), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = response_payload;
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
op->data.send_status_from_server.status_details = "xyz";
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &request_payload_recv;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102)));
cq_expect_completion(v_server, tag(102), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7)));
cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you"));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "test.google.com"));
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
gpr_free(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);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
}
/* Client sends a request with payload, server reads then returns a response

@ -0,0 +1,208 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void request_response_with_payload(grpc_end2end_test_fixture f) {
grpc_call *c;
grpc_call *s;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
gpr_slice response_payload_slice = gpr_slice_from_copied_string("hello you");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *response_payload =
grpc_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world"));
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(6), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7)));
cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you"));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
/* Client sends a request with payload, server reads then returns a response
payload and status. */
static void test_invoke_request_response_with_payload(
grpc_end2end_test_config config) {
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
request_response_with_payload(f);
end_test(&f);
config.tear_down_data(&f);
}
static void test_invoke_10_request_response_with_payload(
grpc_end2end_test_config config) {
int i;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
for (i = 0; i < 10; i++) {
request_response_with_payload(f);
}
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_invoke_request_response_with_payload(config);
test_invoke_10_request_response_with_payload(config);
}

@ -114,98 +114,126 @@ static void test_request_response_with_metadata_and_payload(
grpc_byte_buffer *response_payload =
grpc_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_metadata meta1 = {"key1", "val1", 4};
grpc_metadata meta2 = {"key2", "val2", 4};
grpc_metadata meta3 = {"key3", "val3", 4};
grpc_metadata meta4 = {"key4", "val4", 4};
grpc_metadata meta5 = {"key5", "val5", 4};
grpc_metadata meta6 = {"key6", "val6", 4};
grpc_metadata meta_c[2] = {{"key1", "val1", 4}, {"key2", "val2", 4}};
grpc_metadata meta_s[2] = {{"key3", "val3", 4}, {"key4", "val4", 4}};
grpc_metadata meta_t[2] = {{"key5", "val5", 4}, {"key6", "val6", 4}};
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
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_byte_buffer *response_payload_recv = NULL;
grpc_call_details call_details;
grpc_status_code status;
char *details = NULL;
size_t details_capacity = 0;
int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta1, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta2, 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, "key1", "val1", "key2", "val2", NULL);
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);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 2;
op->data.send_initial_metadata.metadata = meta_c;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &response_payload_recv;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s,
&call_details,
&request_metadata_recv,
f.server_cq, tag(101)));
cq_expect_completion(v_server, tag(101), GRPC_OP_OK);
cq_verify(v_server);
grpc_call_server_accept_old(s, f.server_cq, tag(102));
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta3, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta4, 0));
grpc_call_server_end_initial_metadata_old(s, 0);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta5, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta6, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world"));
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(6), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 2;
op->data.send_initial_metadata.metadata = meta_s;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = response_payload;
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 2;
op->data.send_status_from_server.trailing_metadata = meta_t;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
op->data.send_status_from_server.status_details = "xyz";
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &request_payload_recv;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102)));
cq_expect_completion(v_server, tag(102), GRPC_OP_OK);
cq_verify(v_server);
/* fetch metadata.. */
cq_expect_client_metadata_read(v_client, tag(2), "key3", "val3", "key4",
"val4", NULL);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7)));
cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you"));
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", "key5", "val5", "key6", "val6", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "test.google.com"));
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1"));
GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2"));
GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3"));
GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4"));
GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key5", "val5"));
GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key6", "val6"));
gpr_free(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);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {

@ -0,0 +1,213 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Request/response with metadata and payload.*/
static void test_request_response_with_metadata_and_payload(
grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
gpr_slice response_payload_slice = gpr_slice_from_copied_string("hello you");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *response_payload =
grpc_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_metadata meta1 = {"key1", "val1", 4};
grpc_metadata meta2 = {"key2", "val2", 4};
grpc_metadata meta3 = {"key3", "val3", 4};
grpc_metadata meta4 = {"key4", "val4", 4};
grpc_metadata meta5 = {"key5", "val5", 4};
grpc_metadata meta6 = {"key6", "val6", 4};
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta1, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta2, 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, "key1", "val1", "key2", "val2", NULL);
cq_verify(v_server);
grpc_call_server_accept_old(s, f.server_cq, tag(102));
/* add multiple metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta3, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta4, 0));
grpc_call_server_end_initial_metadata_old(s, 0);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta5, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta6, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world"));
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(6), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK);
cq_verify(v_server);
/* fetch metadata.. */
cq_expect_client_metadata_read(v_client, tag(2), "key3", "val3", "key4",
"val4", NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7)));
cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you"));
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", "key5", "val5", "key6", "val6", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_request_response_with_metadata_and_payload(config);
}

@ -106,63 +106,120 @@ static void end_test(grpc_end2end_test_fixture *f) {
static void test_request_with_large_metadata(grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_metadata meta;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_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;
char *details = NULL;
size_t details_capacity = 0;
int was_cancelled = 2;
const int large_size = 64 * 1024;
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
meta.key = "key";
meta.value = gpr_malloc(large_size + 1);
memset(meta.value, 'a', large_size);
meta.value[large_size] = 0;
memset((char *)meta.value, 'a', large_size);
((char*)meta.value)[large_size] = 0;
meta.value_length = large_size;
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
/* add the metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta, 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, "key", meta.value, NULL);
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);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 1;
op->data.send_initial_metadata.metadata = &meta;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s,
&call_details,
&request_metadata_recv,
f.server_cq, tag(101)));
cq_expect_completion(v_server, tag(101), GRPC_OP_OK);
cq_verify(v_server);
grpc_call_accept(s, f.server_cq, tag(102), 0);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
op->data.send_status_from_server.status_details = "xyz";
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &request_payload_recv;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102)));
cq_expect_completion(v_server, tag(102), GRPC_OP_OK);
cq_verify(v_server);
/* fetch metadata.. */
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_status_old(s, GRPC_STATUS_OK, NULL, tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_OK, NULL, NULL);
cq_verify(v_client);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "test.google.com"));
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(contains_metadata(&request_metadata_recv, "key", meta.value));
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
gpr_free(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);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
gpr_free(meta.value);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(request_payload_recv);
gpr_free((char *)meta.value);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {

@ -0,0 +1,172 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Request with a large amount of metadata.*/
static void test_request_with_large_metadata(grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
grpc_metadata meta;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
const int large_size = 64 * 1024;
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
meta.key = "key";
meta.value = gpr_malloc(large_size + 1);
memset((char *)meta.value, 'a', large_size);
((char*)meta.value)[large_size] = 0;
meta.value_length = large_size;
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
/* add the metadata */
GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta, 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, "key", meta.value, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
/* fetch metadata.. */
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8)));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_status_old(s, GRPC_STATUS_OK, NULL, tag(9)));
cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_OK, NULL, NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(9), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
gpr_free((char *)meta.value);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_request_with_large_metadata(config);
}

@ -106,63 +106,108 @@ static void end_test(grpc_end2end_test_fixture *f) {
static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_slice payload_slice = gpr_slice_from_copied_string("hello world");
grpc_byte_buffer *payload = grpc_byte_buffer_create(&payload_slice, 1);
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
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;
char *details = NULL;
size_t details_capacity = 0;
int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_old(c, payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
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);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s,
&call_details,
&request_metadata_recv,
f.server_cq, tag(101)));
cq_expect_completion(v_server, tag(101), GRPC_OP_OK);
cq_verify(v_server);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
op->data.send_status_from_server.status_details = "xyz";
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &request_payload_recv;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102)));
cq_expect_completion(v_server, tag(102), GRPC_OP_OK);
cq_verify(v_server);
grpc_call_accept(s, f.server_cq, tag(102), 0);
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(4)));
cq_expect_read(v_server, tag(4), gpr_slice_from_copied_string("hello world"));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(5)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(6)));
cq_expect_finish_accepted(v_client, tag(5), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "test.google.com"));
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
cq_expect_finish_accepted(v_server, tag(6), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
gpr_free(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);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(request_payload_recv);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {

@ -0,0 +1,172 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* Client sends a request with payload, server reads then returns status. */
static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_slice payload_slice = gpr_slice_from_copied_string("hello world");
grpc_byte_buffer *payload = grpc_byte_buffer_create(&payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_old(c, payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(4)));
cq_expect_read(v_server, tag(4), gpr_slice_from_copied_string("hello world"));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(5)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(6)));
cq_expect_finish_accepted(v_client, tag(5), GRPC_OP_OK);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(6), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_invoke_request_with_payload(config);
}

@ -100,44 +100,85 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f->client_cq);
cq_verifier *v_server = cq_verifier_create(f->server_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_call_details call_details;
grpc_status_code status;
char *details = NULL;
size_t details_capacity = 0;
int was_cancelled = 2;
config.init_client(f, client_args);
c = grpc_channel_create_call_old(f->client, "/foo", "test.google.com",
deadline);
c = grpc_channel_create_call(f->client, f->client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f->client_cq, tag(2), tag(3), 0));
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);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
config.init_server(f, server_args);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f->server, &s,
&call_details,
&request_metadata_recv,
f->server_cq, tag(101)));
cq_expect_completion(v_server, tag(101), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f->server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
op->data.send_status_from_server.status_details = "xyz";
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102)));
cq_expect_completion(v_server, tag(102), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5)));
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "test.google.com"));
GPR_ASSERT(was_cancelled == 1);
gpr_free(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);
grpc_call_destroy(s);

@ -0,0 +1,175 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void simple_delayed_request_body(grpc_end2end_test_config config,
grpc_end2end_test_fixture *f,
grpc_channel_args *client_args,
grpc_channel_args *server_args,
long delay_us) {
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f->client_cq);
cq_verifier *v_server = cq_verifier_create(f->server_cq);
config.init_client(f, client_args);
c = grpc_channel_create_call_old(f->client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f->client_cq, tag(2), tag(3), 0));
config.init_server(f, server_args);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f->server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5)));
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
static void test_simple_delayed_request_short(grpc_end2end_test_config config) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", __FUNCTION__, config.name);
f = config.create_fixture(NULL, NULL);
simple_delayed_request_body(config, &f, NULL, NULL, 100000);
end_test(&f);
config.tear_down_data(&f);
}
static void test_simple_delayed_request_long(grpc_end2end_test_config config) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", __FUNCTION__, config.name);
f = config.create_fixture(NULL, NULL);
/* This timeout should be longer than a single retry */
simple_delayed_request_body(config, &f, NULL, NULL, 1500000);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
if (config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION) {
test_simple_delayed_request_short(config);
test_simple_delayed_request_long(config);
}
}

@ -39,6 +39,7 @@
#include "src/core/support/string.h"
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
@ -109,86 +110,81 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
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_call_details call_details;
grpc_status_code status;
char *details = NULL;
size_t details_capacity = 0;
int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
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);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1)));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s,
&call_details,
&request_metadata_recv,
f.server_cq, tag(101)));
cq_expect_completion(v_server, tag(101), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5)));
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
op->data.send_status_from_server.status_details = "xyz";
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op++;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102)));
cq_expect_completion(v_server, tag(102), GRPC_OP_OK);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
/* an alternative ordering of the simple request body */
static void simple_request_body2(grpc_end2end_test_fixture f) {
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_expect_completion(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5)));
cq_verify(v_server);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "test.google.com"));
GPR_ASSERT(was_cancelled == 1);
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
gpr_free(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);
grpc_call_destroy(s);
@ -197,19 +193,13 @@ static void simple_request_body2(grpc_end2end_test_fixture f) {
cq_verifier_destroy(v_server);
}
static void test_invoke_simple_request(
grpc_end2end_test_config config, const char *name,
void (*body)(grpc_end2end_test_fixture f)) {
char *fullname;
static void test_invoke_simple_request(grpc_end2end_test_config config) {
grpc_end2end_test_fixture f;
gpr_asprintf(&fullname, "%s/%s", __FUNCTION__, name);
f = begin_test(config, fullname, NULL, NULL);
body(f);
f = begin_test(config, __FUNCTION__, NULL, NULL);
simple_request_body(f);
end_test(&f);
config.tear_down_data(&f);
gpr_free(fullname);
}
static void test_invoke_10_simple_requests(grpc_end2end_test_config config) {
@ -224,9 +214,6 @@ static void test_invoke_10_simple_requests(grpc_end2end_test_config config) {
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_invoke_simple_request(config, "simple_request_body",
simple_request_body);
test_invoke_simple_request(config, "simple_request_body2",
simple_request_body2);
test_invoke_simple_request(config);
test_invoke_10_simple_requests(config);
}

@ -0,0 +1,232 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "src/core/support/string.h"
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void simple_request_body(grpc_end2end_test_fixture f) {
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5)));
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
/* an alternative ordering of the simple request body */
static void simple_request_body2(grpc_end2end_test_fixture f) {
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5)));
cq_verify(v_server);
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
static void test_invoke_simple_request(
grpc_end2end_test_config config, const char *name,
void (*body)(grpc_end2end_test_fixture f)) {
char *fullname;
grpc_end2end_test_fixture f;
gpr_asprintf(&fullname, "%s/%s", __FUNCTION__, name);
f = begin_test(config, fullname, NULL, NULL);
body(f);
end_test(&f);
config.tear_down_data(&f);
gpr_free(fullname);
}
static void test_invoke_10_simple_requests(grpc_end2end_test_config config) {
int i;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
for (i = 0; i < 10; i++) {
simple_request_body(f);
gpr_log(GPR_INFO, "Passed simple request %d", i);
}
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_invoke_simple_request(config, "simple_request_body",
simple_request_body);
test_invoke_simple_request(config, "simple_request_body2",
simple_request_body2);
test_invoke_10_simple_requests(config);
}

@ -0,0 +1,324 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <string.h>
#include "src/core/surface/event_string.h"
#include "src/core/surface/completion_queue.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/thd.h>
#define SERVER_THREADS 16
#define CLIENT_THREADS 16
static grpc_end2end_test_fixture g_fixture;
static gpr_timespec g_test_end_time;
static gpr_event g_client_done[CLIENT_THREADS];
static gpr_event g_server_done[SERVER_THREADS];
static gpr_mu g_mu;
static int g_active_requests;
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
/* Drain pending events on a completion queue until it's ready to destroy.
Does some post-processing to safely release memory on some of the events. */
static void drain_cq(int client, grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
char *evstr;
int done = 0;
char *name = client ? "client" : "server";
while (!done) {
ev = grpc_completion_queue_next(cq, five_seconds_time());
if (!ev) {
gpr_log(GPR_ERROR, "waiting for %s cq to drain", name);
grpc_cq_dump_pending_ops(cq);
continue;
}
evstr = grpc_event_string(ev);
gpr_log(GPR_INFO, "got late %s event: %s", name, evstr);
gpr_free(evstr);
type = ev->type;
switch (type) {
case GRPC_SERVER_RPC_NEW:
gpr_free(ev->tag);
if (ev->call) {
grpc_call_destroy(ev->call);
}
break;
case GRPC_FINISHED:
grpc_call_destroy(ev->call);
break;
case GRPC_QUEUE_SHUTDOWN:
done = 1;
break;
case GRPC_READ:
case GRPC_WRITE_ACCEPTED:
if (!client && gpr_unref(ev->tag)) {
gpr_free(ev->tag);
}
default:
break;
}
grpc_event_finish(ev);
}
}
/* Kick off a new request - assumes g_mu taken */
static void start_request(void) {
gpr_slice slice = gpr_slice_malloc(100);
grpc_byte_buffer *buf;
grpc_call *call = grpc_channel_create_call_old(
g_fixture.client, "/Foo", "test.google.com", g_test_end_time);
memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice));
buf = grpc_byte_buffer_create(&slice, 1);
gpr_slice_unref(slice);
g_active_requests++;
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(call, g_fixture.client_cq, NULL, NULL, 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(call, NULL));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_old(call, buf, NULL, 0));
grpc_byte_buffer_destroy(buf);
}
/* Async client: handle sending requests, reading responses, and starting
new requests when old ones finish */
static void client_thread(void *p) {
gpr_intptr id = (gpr_intptr)p;
grpc_event *ev;
char *estr;
for (;;) {
ev = grpc_completion_queue_next(g_fixture.client_cq, n_seconds_time(1));
if (ev) {
switch (ev->type) {
default:
estr = grpc_event_string(ev);
gpr_log(GPR_ERROR, "unexpected event: %s", estr);
gpr_free(estr);
break;
case GRPC_READ:
break;
case GRPC_WRITE_ACCEPTED:
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(ev->call, NULL));
break;
case GRPC_FINISH_ACCEPTED:
break;
case GRPC_CLIENT_METADATA_READ:
break;
case GRPC_FINISHED:
/* kick off a new request if the test should still be running */
gpr_mu_lock(&g_mu);
g_active_requests--;
if (gpr_time_cmp(gpr_now(), g_test_end_time) < 0) {
start_request();
}
gpr_mu_unlock(&g_mu);
grpc_call_destroy(ev->call);
break;
}
grpc_event_finish(ev);
}
gpr_mu_lock(&g_mu);
if (g_active_requests == 0) {
gpr_mu_unlock(&g_mu);
break;
}
gpr_mu_unlock(&g_mu);
}
gpr_event_set(&g_client_done[id], (void *)1);
}
/* Request a new server call. We tag them with a ref-count that starts at two,
and decrements after each of: a read completes and a write completes.
When it drops to zero, we write status */
static void request_server_call(void) {
gpr_refcount *rc = gpr_malloc(sizeof(gpr_refcount));
gpr_ref_init(rc, 2);
grpc_server_request_call_old(g_fixture.server, rc);
}
static void maybe_end_server_call(grpc_call *call, gpr_refcount *rc) {
if (gpr_unref(rc)) {
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
call, GRPC_STATUS_OK, NULL, NULL));
gpr_free(rc);
}
}
static void server_thread(void *p) {
int id = (gpr_intptr)p;
gpr_slice slice = gpr_slice_malloc(100);
grpc_byte_buffer *buf;
grpc_event *ev;
char *estr;
memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice));
buf = grpc_byte_buffer_create(&slice, 1);
gpr_slice_unref(slice);
request_server_call();
for (;;) {
ev = grpc_completion_queue_next(g_fixture.server_cq, n_seconds_time(1));
if (ev) {
switch (ev->type) {
default:
estr = grpc_event_string(ev);
gpr_log(GPR_ERROR, "unexpected event: %s", estr);
gpr_free(estr);
break;
case GRPC_SERVER_RPC_NEW:
if (ev->call) {
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(
ev->call, g_fixture.server_cq, ev->tag));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_end_initial_metadata_old(ev->call, 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_read_old(ev->call, ev->tag));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(ev->call, buf, ev->tag, 0));
} else {
gpr_free(ev->tag);
}
break;
case GRPC_READ:
if (ev->data.read) {
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_read_old(ev->call, ev->tag));
} else {
maybe_end_server_call(ev->call, ev->tag);
}
break;
case GRPC_WRITE_ACCEPTED:
maybe_end_server_call(ev->call, ev->tag);
break;
case GRPC_FINISH_ACCEPTED:
break;
case GRPC_FINISHED:
grpc_call_destroy(ev->call);
request_server_call();
break;
}
grpc_event_finish(ev);
}
gpr_mu_lock(&g_mu);
if (g_active_requests == 0) {
gpr_mu_unlock(&g_mu);
break;
}
gpr_mu_unlock(&g_mu);
}
grpc_byte_buffer_destroy(buf);
gpr_event_set(&g_server_done[id], (void *)1);
}
static void run_test(grpc_end2end_test_config config, int requests_in_flight) {
int i;
gpr_thd_id thd_id;
gpr_log(GPR_INFO, "thread_stress_test/%s @ %d requests", config.name,
requests_in_flight);
/* setup client, server */
g_fixture = config.create_fixture(NULL, NULL);
config.init_client(&g_fixture, NULL);
config.init_server(&g_fixture, NULL);
/* schedule end time */
g_test_end_time = n_seconds_time(5);
g_active_requests = 0;
gpr_mu_init(&g_mu);
/* kick off threads */
for (i = 0; i < CLIENT_THREADS; i++) {
gpr_event_init(&g_client_done[i]);
gpr_thd_new(&thd_id, client_thread, (void *)(gpr_intptr)i, NULL);
}
for (i = 0; i < SERVER_THREADS; i++) {
gpr_event_init(&g_server_done[i]);
gpr_thd_new(&thd_id, server_thread, (void *)(gpr_intptr)i, NULL);
}
/* start requests */
gpr_mu_lock(&g_mu);
for (i = 0; i < requests_in_flight; i++) {
start_request();
}
gpr_mu_unlock(&g_mu);
/* await completion */
for (i = 0; i < CLIENT_THREADS; i++) {
gpr_event_wait(&g_client_done[i], gpr_inf_future);
}
for (i = 0; i < SERVER_THREADS; i++) {
gpr_event_wait(&g_server_done[i], gpr_inf_future);
}
/* shutdown the things */
grpc_server_shutdown(g_fixture.server);
grpc_server_destroy(g_fixture.server);
grpc_channel_destroy(g_fixture.client);
grpc_completion_queue_shutdown(g_fixture.server_cq);
drain_cq(0, g_fixture.server_cq);
grpc_completion_queue_destroy(g_fixture.server_cq);
grpc_completion_queue_shutdown(g_fixture.client_cq);
drain_cq(1, g_fixture.client_cq);
grpc_completion_queue_destroy(g_fixture.client_cq);
config.tear_down_data(&g_fixture);
gpr_mu_destroy(&g_mu);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
run_test(config, 1000);
}

@ -0,0 +1,199 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown(f->server);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
/* test the case when there is a pending message at the client side,
writes_done should not return a status without a start_read.
Note: this test will last for 3s. Do not run in a loop. */
static void test_writes_done_hangs_with_pending_read(
grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
gpr_slice response_payload_slice = gpr_slice_from_copied_string("hello you");
grpc_byte_buffer *request_payload =
grpc_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *response_payload =
grpc_byte_buffer_create(&response_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
/* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com",
deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(c, request_payload, tag(4), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(request_payload);
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5)));
cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world"));
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_write_old(s, response_payload, tag(6), 0));
/* destroy byte buffer early to ensure async code keeps track of its contents
correctly */
grpc_byte_buffer_destroy(response_payload);
cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(6)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old(
s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(7)));
cq_expect_finish_accepted(v_client, tag(6), GRPC_OP_OK);
cq_verify(v_client);
/* does not return status because there is a pending message to be read */
cq_verify_empty(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(8)));
cq_expect_read(v_client, tag(8), gpr_slice_from_copied_string("hello you"));
cq_verify(v_client);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED,
"xyz", NULL);
cq_verify(v_client);
cq_expect_finish_accepted(v_server, tag(7), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_verify(v_server);
grpc_call_destroy(c);
grpc_call_destroy(s);
end_test(&f);
config.tear_down_data(&f);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_writes_done_hangs_with_pending_read(config);
}

@ -367,7 +367,11 @@
},
{
"language": "c",
"name": "chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test"
"name": "chttp2_fake_security_request_with_large_metadata_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_with_payload_test"
},
{
"language": "c",
@ -385,6 +389,102 @@
"language": "c",
"name": "chttp2_fake_security_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_after_accept_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_after_accept_and_writes_closed_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_after_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_before_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_in_a_vacuum_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_census_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_disappearing_server_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_early_server_shutdown_finishes_tags_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_graceful_server_shutdown_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_invoke_large_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_max_concurrent_streams_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_no_op_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_ping_pong_streaming_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_response_with_binary_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_response_with_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_response_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_response_with_trailing_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_with_large_metadata_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_simple_delayed_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_thread_stress_legacy_test"
},
{
"language": "c",
"name": "chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_after_accept_test"
@ -455,7 +555,11 @@
},
{
"language": "c",
"name": "chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test"
"name": "chttp2_fullstack_request_with_large_metadata_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_with_payload_test"
},
{
"language": "c",
@ -473,6 +577,102 @@
"language": "c",
"name": "chttp2_fullstack_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_after_accept_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_after_accept_and_writes_closed_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_after_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_before_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_in_a_vacuum_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_census_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_disappearing_server_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_early_server_shutdown_finishes_tags_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_graceful_server_shutdown_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_invoke_large_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_max_concurrent_streams_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_no_op_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_ping_pong_streaming_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_response_with_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_response_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_with_large_metadata_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_simple_delayed_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_thread_stress_legacy_test"
},
{
"language": "c",
"name": "chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_after_accept_test"
@ -543,7 +743,11 @@
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test"
"name": "chttp2_simple_ssl_fullstack_request_with_large_metadata_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_with_payload_test"
},
{
"language": "c",
@ -561,6 +765,102 @@
"language": "c",
"name": "chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_after_accept_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_after_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_before_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_census_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_disappearing_server_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_graceful_server_shutdown_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_invoke_large_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_max_concurrent_streams_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_no_op_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_ping_pong_streaming_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_response_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_with_large_metadata_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_simple_delayed_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_thread_stress_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test"
@ -631,7 +931,11 @@
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test"
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test"
},
{
"language": "c",
@ -649,6 +953,102 @@
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_no_op_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_after_accept_test"
@ -719,7 +1119,11 @@
},
{
"language": "c",
"name": "chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test"
"name": "chttp2_socket_pair_request_with_large_metadata_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_with_payload_test"
},
{
"language": "c",
@ -737,6 +1141,102 @@
"language": "c",
"name": "chttp2_socket_pair_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_after_accept_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_after_accept_and_writes_closed_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_after_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_before_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_in_a_vacuum_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_census_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_disappearing_server_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_early_server_shutdown_finishes_tags_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_graceful_server_shutdown_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_invoke_large_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_max_concurrent_streams_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_no_op_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_ping_pong_streaming_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_response_with_binary_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_response_with_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_response_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_with_large_metadata_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_simple_delayed_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_thread_stress_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test"
@ -807,7 +1307,11 @@
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test"
"name": "chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test"
},
{
"language": "c",
@ -824,6 +1328,102 @@
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_census_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_disappearing_server_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_no_op_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_with_payload_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_simple_request_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_thread_stress_legacy_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_legacy_test"
}
]

@ -319,6 +319,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\surface\call.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\call_details.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\channel.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\channel_create.c">
@ -333,6 +335,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\surface\lame_client.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\metadata_array.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\secure_channel_create.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\secure_server_create.c">

@ -211,6 +211,9 @@
<ClCompile Include="..\..\src\core\surface\call.c">
<Filter>src\core\surface</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\surface\call_details.c">
<Filter>src\core\surface</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\surface\channel.c">
<Filter>src\core\surface</Filter>
</ClCompile>
@ -232,6 +235,9 @@
<ClCompile Include="..\..\src\core\surface\lame_client.c">
<Filter>src\core\surface</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\surface\metadata_array.c">
<Filter>src\core\surface</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\surface\secure_channel_create.c">
<Filter>src\core\surface</Filter>
</ClCompile>

@ -319,6 +319,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\surface\call.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\call_details.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\channel.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\channel_create.c">
@ -333,6 +335,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\surface\lame_client.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\metadata_array.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\secure_channel_create.c">
</ClCompile>
<ClCompile Include="..\..\src\core\surface\secure_server_create.c">

@ -172,6 +172,9 @@
<ClCompile Include="..\..\src\core\surface\call.c">
<Filter>src\core\surface</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\surface\call_details.c">
<Filter>src\core\surface</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\surface\channel.c">
<Filter>src\core\surface</Filter>
</ClCompile>
@ -193,6 +196,9 @@
<ClCompile Include="..\..\src\core\surface\lame_client.c">
<Filter>src\core\surface</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\surface\metadata_array.c">
<Filter>src\core\surface</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\surface\secure_channel_create.c">
<Filter>src\core\surface</Filter>
</ClCompile>

Loading…
Cancel
Save