diff --git a/src/core/surface/byte_buffer.c b/src/core/surface/byte_buffer.c
index d1be41074d375ecbccbd8fbd6bc4f258958e5509..09e2aa5b872ab3fa5c2a681a717da16260b5d238 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 8b282230405a50077a9af7a8014eb7ad313dffd1..ace10f172d5d78f2e4f58e83ee98d2d2bb64ba5e 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 5851277d201c2d8d161a6caf70a2dadf3608b9c0..63e7f09dd5f603e07ea19199eb2e615b0c5cdb5b 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 6b5194fb07f6efadd9fff74a667e3a186267d473..e493941f0a0bdbc5fb07aafd8d390adf7da971d4 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 35c81fa7928ea52c1189259af4c090cdaf83c361..52ebc9052fc1399e32b49a836f3fbe7c2c04660e 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 0000000000000000000000000000000000000000..c7cb1f8f9ec70468deb59af184f407cf118b368d
--- /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
+