| 
					
				 | 
			
			
				@@ -0,0 +1,298 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Copyright 2017 gRPC authors. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Licensed under the Apache License, Version 2.0 (the "License"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * you may not use this file except in compliance with the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * You may obtain a copy of the License at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     http://www.apache.org/licenses/LICENSE-2.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Unless required by applicable law or agreed to in writing, software 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * distributed under the License is distributed on an "AS IS" BASIS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * See the License for the specific language governing permissions and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * limitations under the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "test/core/end2end/end2end_tests.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <stdio.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <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 "src/core/lib/channel/channel_args.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/slice/slice_internal.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/transport/metadata.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/transport/service_config.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "test/core/end2end/cq_verifier.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "test/core/end2end/tests/cancel_test_helpers.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void *tag(intptr_t 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, "Running test: %s/%s", test_name, config.name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  f = config.create_fixture(client_args, server_args); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  config.init_server(&f, server_args); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  config.init_client(&f, client_args); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static gpr_timespec n_seconds_from_now(int n) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return grpc_timeout_seconds_to_deadline(n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static gpr_timespec five_seconds_from_now(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return n_seconds_from_now(5); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void drain_cq(grpc_completion_queue *cq) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_event ev; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  do { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } while (ev.type != GRPC_QUEUE_SHUTDOWN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void shutdown_server(grpc_end2end_test_fixture *f) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!f->server) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                         grpc_timeout_seconds_to_deadline(5), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                         NULL) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 .type == GRPC_OP_COMPLETE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  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->cq); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  drain_cq(f->cq); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_completion_queue_destroy(f->cq); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_completion_queue_destroy(f->shutdown_cq); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Cancel after accept, no payload */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void test_cancel_after_round_trip(grpc_end2end_test_config config, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                         cancellation_mode mode, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                         bool use_service_config) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_op ops[6]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_op *op; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_call *c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_call *s; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_call_error error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice details; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_byte_buffer *request_payload_recv = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_byte_buffer *response_payload_recv = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice request_payload_slice = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_slice_from_copied_string("hello world"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice response_payload_slice = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_slice_from_copied_string("hello you"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_byte_buffer *request_payload = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_raw_byte_buffer_create(&request_payload_slice, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_byte_buffer *response_payload = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_raw_byte_buffer_create(&response_payload_slice, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int was_cancelled = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_channel_args *args = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (use_service_config) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_arg arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    arg.type = GRPC_ARG_STRING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    arg.key = GRPC_ARG_SERVICE_CONFIG; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    arg.value.string = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "{\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "  \"methodConfig\": [ {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "    \"name\": [\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "      { \"service\": \"service\", \"method\": \"method\" }\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "    ],\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "    \"timeout\": \"5s\"\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "  } ]\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "}"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    args = grpc_channel_args_copy_and_add(args, &arg, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_end2end_test_fixture f = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      begin_test(config, "cancel_after_round_trip", args, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cq_verifier *cqv = cq_verifier_create(f.cq); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_timespec deadline = use_service_config 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                              ? gpr_inf_future(GPR_CLOCK_MONOTONIC) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                              : five_seconds_from_now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  c = grpc_channel_create_call( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_slice_from_static_string("/service/method"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      get_host_override_slice("foo.test.google.fr:1234", config), deadline, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_metadata_array_init(&initial_metadata_recv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_metadata_array_init(&trailing_metadata_recv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_metadata_array_init(&request_metadata_recv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_call_details_init(&call_details); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  memset(ops, 0, sizeof(ops)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op = ops; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_SEND_INITIAL_METADATA; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.send_initial_metadata.count = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_SEND_MESSAGE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.send_message.send_message = request_payload; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_RECV_INITIAL_METADATA; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_RECV_MESSAGE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.recv_message.recv_message = &response_payload_recv; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(GRPC_CALL_OK == error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  error = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_server_request_call(f.server, &s, &call_details, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               &request_metadata_recv, f.cq, f.cq, tag(101)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(GRPC_CALL_OK == error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  CQ_EXPECT_COMPLETION(cqv, tag(101), 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cq_verify(cqv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  memset(ops, 0, sizeof(ops)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op = ops; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_RECV_MESSAGE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.recv_message.recv_message = &request_payload_recv; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_SEND_INITIAL_METADATA; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.send_initial_metadata.count = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_SEND_MESSAGE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.send_message.send_message = response_payload; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(GRPC_CALL_OK == error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  CQ_EXPECT_COMPLETION(cqv, tag(102), 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  CQ_EXPECT_COMPLETION(cqv, tag(1), 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cq_verify(cqv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_byte_buffer_destroy(request_payload_recv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_byte_buffer_destroy(response_payload_recv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_payload_recv = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  response_payload_recv = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  memset(ops, 0, sizeof(ops)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  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->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_RECV_MESSAGE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.recv_message.recv_message = &response_payload_recv; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(GRPC_CALL_OK == error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  memset(ops, 0, sizeof(ops)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op = ops; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.recv_close_on_server.cancelled = &was_cancelled; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->op = GRPC_OP_SEND_MESSAGE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->data.send_message.send_message = response_payload; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  op++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(GRPC_CALL_OK == error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  CQ_EXPECT_COMPLETION(cqv, tag(2), 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  CQ_EXPECT_COMPLETION(cqv, tag(103), 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cq_verify(cqv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice_unref(details); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_call_unref(c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_call_unref(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (args != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_channel_args_destroy(&exec_ctx, args); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_exec_ctx_finish(&exec_ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cq_verifier_destroy(cqv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  end_test(&f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  config.tear_down_data(&f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void cancel_after_round_trip(grpc_end2end_test_config config) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  unsigned i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    test_cancel_after_round_trip(config, cancellation_modes[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 false /* use_service_config */); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      test_cancel_after_round_trip(config, cancellation_modes[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   true /* use_service_config */); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void cancel_after_round_trip_pre_init(void) {} 
			 |