diff options
-rw-r--r-- | src/core/surface/byte_buffer.c | 1 | ||||
-rw-r--r-- | test/core/end2end/tests/cancel_after_invoke.c | 72 | ||||
-rw-r--r-- | test/core/end2end/tests/cancel_before_invoke.c | 69 | ||||
-rw-r--r-- | test/core/end2end/tests/cancel_in_a_vacuum.c | 2 | ||||
-rw-r--r-- | test/core/end2end/tests/cancel_test_helpers.h | 2 | ||||
-rwxr-xr-x | test/core/end2end/tests/generate.py | 191 |
6 files changed, 315 insertions, 22 deletions
diff --git a/src/core/surface/byte_buffer.c b/src/core/surface/byte_buffer.c index d1be41074d..09e2aa5b87 100644 --- a/src/core/surface/byte_buffer.c +++ b/src/core/surface/byte_buffer.c @@ -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); diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c index 8b28223040..ace10f172d 100644 --- a/test/core/end2end/tests/cancel_after_invoke.c +++ b/test/core/end2end/tests/cancel_after_invoke.c @@ -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 = 1; j < 6; j++) { + for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { + test_cancel_after_invoke(config, cancellation_modes[i], j); + } } } diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c index 5851277d20..63e7f09dd5 100644 --- a/test/core/end2end/tests/cancel_before_invoke.c +++ b/test/core/end2end/tests/cancel_before_invoke.c @@ -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); + } } diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c index 6b5194fb07..e493941f0a 100644 --- a/test/core/end2end/tests/cancel_in_a_vacuum.c +++ b/test/core/end2end/tests/cancel_in_a_vacuum.c @@ -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); diff --git a/test/core/end2end/tests/cancel_test_helpers.h b/test/core/end2end/tests/cancel_test_helpers.h index 35c81fa792..52ebc9052f 100644 --- a/test/core/end2end/tests/cancel_test_helpers.h +++ b/test/core/end2end/tests/cancel_test_helpers.h @@ -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 diff --git a/test/core/end2end/tests/generate.py b/test/core/end2end/tests/generate.py new file mode 100755 index 0000000000..c7cb1f8f9e --- /dev/null +++ b/test/core/end2end/tests/generate.py @@ -0,0 +1,191 @@ +#!/usr/bin/python2.7 + +from copy import deepcopy + +def create(state, name): + me = getattr(state, name) + if not me.created: + new = me.copy() + new.created = True + cg = state.codegen.copy() + cg.lines.extend([ + 'config.init_%s(f, %s_args)' % (name, name)]) + s = State(state.client, state.server, cg) + setattr(s, name, new) + yield s + +def start_client(state): + if state.client.created and not state.client.started: + cg = state.codegen.copy() + cg.lines.extend([ + 'client_call = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com", deadline);' + ]) + client = state.client.copy() + client.started = True + yield State(client, state.server, cg) + +def request_server(state): + if state.server.created and not state.server.requested: + cg = state.codegen.copy() + tag = cg.make_tag('request_server') + cg.lines.extend([ + 'GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &server_call, &call_details, &request_metadata_recv, f.server_cq, tag(%d)))' % tag]) + server = state.server.copy() + server.requested = True + yield State(state.client, server, cg) + +def start_op(state, l, r): + local = getattr(state, l) + remote = getattr(state, r) + if not local.started: + return + for send_initial_metadata in [True, False]: + for send_message in [True, False]: + for send_close in [True, False]: + for receive_initial_metadata in [True, False]: + for receive_message in [True, False]: + for receive_close in [True, False]: + if ((not send_initial_metadata) and (not send_message) and (not send_close) and + (not receive_initial_metadata) and (not receive_message) and (not receive_close)): + continue + if local.sending_initial_metadata and send_initial_metadata: continue + if local.sending_message and send_message: continue + if local.sending_close and send_close: continue + if l == 'server' and receive_initial_metadata: continue + if local.receiving_initial_metadata and receive_initial_metadata: continue + if local.receiving_message and receive_message: continue + if local.receiving_close and receive_close: continue + local2 = local.copy() + cg = state.codegen.copy() + cg.lines.extend(['op = ops']); + tag = cg.make_tag('start_op_%s' % l) + if send_initial_metadata: + cg.lines.extend([ + 'op->type = GRPC_OP_SEND_INITIAL_METADATA;', + 'op->data.send_initial_metadata.count = 0;', + 'op++;']) + local2.sending_initial_metadata = tag + if send_message: + cg.lines.extend([ + 'op->type = GRPC_OP_SEND_MESSAGE;', + 'op->data.send_message = %s_payload;' % l, + 'op++;']) + local2.sending_message = tag + if send_close: + if l == 'client': + cg.lines.extend([ + 'op->type = GRPC_OP_SEND_CLOSE_FROM_CLIENT;', + 'op++']) + else: + cg.lines.extend([ + 'op->type = GRPC_OP_SEND_STATUS_FROM_SERVER;', + 'op++']) + local2.sending_close = tag + if receive_initial_metadata: + cg.lines.extend([ + 'op->type = GRPC_OP_RECV_INITIAL_METADATA;', + 'op++']) + local2.receiving_initial_metadata = tag + if receive_message: + cg.lines.extend([ + 'op->type = GRPC_OP_RECV_MESSAGE;', + 'op++']) + local2.receiving_message = tag + if receive_close: + if l == 'client': + cg.lines.extend([ + 'op->type = GRPC_OP_RECV_STATUS_ON_CLIENT;', + 'op++']) + else: + cg.lines.extend([ + 'op->type = GRPC_OP_RECV_CLOSE_ON_SERVER;', + 'op++']) + local2.receiving_close = tag + cg.lines.extend([ + 'GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(%s_call, ops, op - ops, tag(%d)));' % (l, tag)]) + s = State(state.client, state.server, cg) + setattr(s, l, local2) + yield s + +def wrap(f, *a): + def g(state): + for x in f(state, *a): + yield x + return g + +MUTATORS = [ + wrap(create, 'client'), + wrap(create, 'server'), + wrap(start_op, 'client', 'server'), + wrap(start_op, 'server', 'client'), + start_client, + request_server, + ] + +class Codegen(object): + lines = [] + next_tag = 1 + last_tag_creator = 'nobody' + def generate(self): + print '{' + print '\n'.join(self.lines) + print '}' + def copy(self): + cg = deepcopy(self) + cg.lines = self.lines[:] + return cg + def make_tag(self, name): + self.last_tag_creator = name + tag = self.next_tag + self.next_tag += 1 + return tag + +class Endpoint(object): + created = False + started = False + requested = False + sent_initial_metadata = False + sent_messages = 0 + sent_close = False + sending_initial_metadata = False + sending_message = False + sending_close = False + received_initial_metadata = False + received_messages = 0 + received_close = False + receiving_initial_metadata = False + receiving_message = False + receiving_close = False + + def copy(self): + return deepcopy(self) + +class State(object): + def __init__(self, client, server, codegen): + self.client = client + self.server = server + self.codegen = codegen + + def as_dict(self): + return {'client': self.client.as_dict(), 'server': self.server.as_dict()} + + def mutations(self): + for mutator in MUTATORS: + for new_state in mutator(self): + yield new_state + +count = 0 +def generate(state, depth): + global count + n = 0 + #print ' '*depth, state.as_dict() + for state2 in state.mutations(): + n += 1 + generate(state2, depth+1) + if n == 0: + count += 1 + #state.codegen.generate() + +generate(State(Endpoint(), Endpoint(), Codegen()), 0) +print count + |