|  | @@ -29,6 +29,7 @@
 | 
	
		
			
				|  |  |  #include <grpc/support/alloc.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/log.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include "src/core/lib/channel/channel_args.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/gpr/string.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/gprpp/host_port.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/gprpp/memory.h"
 | 
	
	
		
			
				|  | @@ -47,15 +48,16 @@
 | 
	
		
			
				|  |  |    "Content-Length: 0\n"                      \
 | 
	
		
			
				|  |  |    "Date: Tue, 07 Jun 2016 17:43:20 GMT\n\n"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define HTTP2_RESP(STATUS_CODE)          \
 | 
	
		
			
				|  |  | -  "\x00\x00\x00\x04\x00\x00\x00\x00\x00" \
 | 
	
		
			
				|  |  | -  "\x00\x00>\x01\x04\x00\x00\x00\x01"    \
 | 
	
		
			
				|  |  | -  "\x10\x0e"                             \
 | 
	
		
			
				|  |  | -  "content-length\x01"                   \
 | 
	
		
			
				|  |  | -  "0"                                    \
 | 
	
		
			
				|  |  | -  "\x10\x0c"                             \
 | 
	
		
			
				|  |  | -  "content-type\x10"                     \
 | 
	
		
			
				|  |  | -  "application/grpc"                     \
 | 
	
		
			
				|  |  | +#define HTTP2_SETTINGS_FRAME "\x00\x00\x00\x04\x00\x00\x00\x00\x00"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define HTTP2_RESP(STATUS_CODE)       \
 | 
	
		
			
				|  |  | +  "\x00\x00>\x01\x04\x00\x00\x00\x01" \
 | 
	
		
			
				|  |  | +  "\x10\x0e"                          \
 | 
	
		
			
				|  |  | +  "content-length\x01"                \
 | 
	
		
			
				|  |  | +  "0"                                 \
 | 
	
		
			
				|  |  | +  "\x10\x0c"                          \
 | 
	
		
			
				|  |  | +  "content-type\x10"                  \
 | 
	
		
			
				|  |  | +  "application/grpc"                  \
 | 
	
		
			
				|  |  |    "\x10\x07:status\x03" #STATUS_CODE
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #define UNPARSEABLE_RESP "Bad Request\n"
 | 
	
	
		
			
				|  | @@ -63,8 +65,6 @@
 | 
	
		
			
				|  |  |  #define HTTP2_DETAIL_MSG(STATUS_CODE) \
 | 
	
		
			
				|  |  |    "Received http2 header with status: " #STATUS_CODE
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define HTTP1_DETAIL_MSG "Trying to connect an http1.x server"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  /* TODO(zyc) Check the content of incoming data instead of using this length */
 | 
	
		
			
				|  |  |  /* The 'bad' server will start sending responses after reading this amount of
 | 
	
		
			
				|  |  |   * data from the client. */
 | 
	
	
		
			
				|  | @@ -80,24 +80,32 @@ struct rpc_state {
 | 
	
		
			
				|  |  |    grpc_slice_buffer outgoing_buffer;
 | 
	
		
			
				|  |  |    grpc_endpoint* tcp;
 | 
	
		
			
				|  |  |    gpr_atm done_atm;
 | 
	
		
			
				|  |  | -  bool write_done;
 | 
	
		
			
				|  |  | +  bool http2_response;
 | 
	
		
			
				|  |  | +  bool send_settings;
 | 
	
		
			
				|  |  |    const char* response_payload;
 | 
	
		
			
				|  |  |    size_t response_payload_length;
 | 
	
		
			
				|  |  | +  bool connection_attempt_made;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int server_port;
 | 
	
		
			
				|  |  |  static struct rpc_state state;
 | 
	
		
			
				|  |  |  static grpc_closure on_read;
 | 
	
		
			
				|  |  | +static grpc_closure on_writing_settings_frame;
 | 
	
		
			
				|  |  |  static grpc_closure on_write;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void* tag(intptr_t t) { return (void*)t; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void done_write(void* /*arg*/, grpc_error* error) {
 | 
	
		
			
				|  |  |    GPR_ASSERT(error == GRPC_ERROR_NONE);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    gpr_atm_rel_store(&state.done_atm, 1);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static void done_writing_settings_frame(void* /* arg */, grpc_error* error) {
 | 
	
		
			
				|  |  | +  GPR_ASSERT(error == GRPC_ERROR_NONE);
 | 
	
		
			
				|  |  | +  grpc_endpoint_read(state.tcp, &state.temp_incoming_buffer, &on_read,
 | 
	
		
			
				|  |  | +                     /*urgent=*/false);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void handle_write() {
 | 
	
		
			
				|  |  |    grpc_slice slice = grpc_slice_from_copied_buffer(
 | 
	
		
			
				|  |  |        state.response_payload, state.response_payload_length);
 | 
	
	
		
			
				|  | @@ -108,7 +116,10 @@ static void handle_write() {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void handle_read(void* /*arg*/, grpc_error* error) {
 | 
	
		
			
				|  |  | -  GPR_ASSERT(error == GRPC_ERROR_NONE);
 | 
	
		
			
				|  |  | +  if (error != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | +    gpr_log(GPR_ERROR, "handle_read error: %s", grpc_error_string(error));
 | 
	
		
			
				|  |  | +    return;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    state.incoming_data_length += state.temp_incoming_buffer.length;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    size_t i;
 | 
	
	
		
			
				|  | @@ -119,11 +130,14 @@ static void handle_read(void* /*arg*/, grpc_error* error) {
 | 
	
		
			
				|  |  |      gpr_free(dump);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  gpr_log(GPR_DEBUG, "got %" PRIuPTR " bytes, expected %" PRIuPTR " bytes",
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG,
 | 
	
		
			
				|  |  | +          "got %" PRIuPTR " bytes, expected %" PRIuPTR
 | 
	
		
			
				|  |  | +          " bytes or a non-HTTP2 response to be sent",
 | 
	
		
			
				|  |  |            state.incoming_data_length,
 | 
	
		
			
				|  |  |            SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD);
 | 
	
		
			
				|  |  |    if (state.incoming_data_length >=
 | 
	
		
			
				|  |  | -      SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD) {
 | 
	
		
			
				|  |  | +          SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD ||
 | 
	
		
			
				|  |  | +      !state.http2_response) {
 | 
	
		
			
				|  |  |      handle_write();
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  |      grpc_endpoint_read(state.tcp, &state.temp_incoming_buffer, &on_read,
 | 
	
	
		
			
				|  | @@ -137,14 +151,26 @@ static void on_connect(void* arg, grpc_endpoint* tcp,
 | 
	
		
			
				|  |  |    gpr_free(acceptor);
 | 
	
		
			
				|  |  |    test_tcp_server* server = static_cast<test_tcp_server*>(arg);
 | 
	
		
			
				|  |  |    GRPC_CLOSURE_INIT(&on_read, handle_read, nullptr, grpc_schedule_on_exec_ctx);
 | 
	
		
			
				|  |  | +  GRPC_CLOSURE_INIT(&on_writing_settings_frame, done_writing_settings_frame,
 | 
	
		
			
				|  |  | +                    nullptr, grpc_schedule_on_exec_ctx);
 | 
	
		
			
				|  |  |    GRPC_CLOSURE_INIT(&on_write, done_write, nullptr, grpc_schedule_on_exec_ctx);
 | 
	
		
			
				|  |  |    grpc_slice_buffer_init(&state.temp_incoming_buffer);
 | 
	
		
			
				|  |  |    grpc_slice_buffer_init(&state.outgoing_buffer);
 | 
	
		
			
				|  |  | +  state.connection_attempt_made = true;
 | 
	
		
			
				|  |  |    state.tcp = tcp;
 | 
	
		
			
				|  |  |    state.incoming_data_length = 0;
 | 
	
		
			
				|  |  |    grpc_endpoint_add_to_pollset(tcp, server->pollset[0]);
 | 
	
		
			
				|  |  | -  grpc_endpoint_read(tcp, &state.temp_incoming_buffer, &on_read,
 | 
	
		
			
				|  |  | -                     /*urgent=*/false);
 | 
	
		
			
				|  |  | +  if (state.send_settings) {
 | 
	
		
			
				|  |  | +    // Send settings frame from server
 | 
	
		
			
				|  |  | +    grpc_slice slice = grpc_slice_from_static_buffer(
 | 
	
		
			
				|  |  | +        HTTP2_SETTINGS_FRAME, sizeof(HTTP2_SETTINGS_FRAME) - 1);
 | 
	
		
			
				|  |  | +    grpc_slice_buffer_add(&state.outgoing_buffer, slice);
 | 
	
		
			
				|  |  | +    grpc_endpoint_write(state.tcp, &state.outgoing_buffer,
 | 
	
		
			
				|  |  | +                        &on_writing_settings_frame, nullptr);
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    grpc_endpoint_read(state.tcp, &state.temp_incoming_buffer, &on_read,
 | 
	
		
			
				|  |  | +                       /*urgent=*/false);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static gpr_timespec n_sec_deadline(int seconds) {
 | 
	
	
		
			
				|  | @@ -166,13 +192,20 @@ static void start_rpc(int target_port, grpc_status_code expected_status,
 | 
	
		
			
				|  |  |    state.cq = grpc_completion_queue_create_for_next(nullptr);
 | 
	
		
			
				|  |  |    cqv = cq_verifier_create(state.cq);
 | 
	
		
			
				|  |  |    state.target = grpc_core::JoinHostPort("127.0.0.1", target_port);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    state.channel =
 | 
	
		
			
				|  |  |        grpc_insecure_channel_create(state.target.c_str(), nullptr, nullptr);
 | 
	
		
			
				|  |  |    grpc_slice host = grpc_slice_from_static_string("localhost");
 | 
	
		
			
				|  |  | +  // The default connect deadline is 20 seconds, so reduce the RPC deadline to 1
 | 
	
		
			
				|  |  | +  // second. This helps us verify - a) If the server responded with a non-HTTP2
 | 
	
		
			
				|  |  | +  // response, the connect fails immediately resulting in
 | 
	
		
			
				|  |  | +  // GRPC_STATUS_UNAVAILABLE instead of GRPC_STATUS_DEADLINE_EXCEEDED. b) If the
 | 
	
		
			
				|  |  | +  // server does not send a HTTP2 SETTINGs frame, the RPC fails with a
 | 
	
		
			
				|  |  | +  // DEADLINE_EXCEEDED.
 | 
	
		
			
				|  |  |    state.call = grpc_channel_create_call(
 | 
	
		
			
				|  |  |        state.channel, nullptr, GRPC_PROPAGATE_DEFAULTS, state.cq,
 | 
	
		
			
				|  |  |        grpc_slice_from_static_string("/Service/Method"), &host,
 | 
	
		
			
				|  |  | -      gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
 | 
	
		
			
				|  |  | +      n_sec_deadline(1), nullptr);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    grpc_metadata_array_init(&initial_metadata_recv);
 | 
	
		
			
				|  |  |    grpc_metadata_array_init(&trailing_metadata_recv);
 | 
	
	
		
			
				|  | @@ -214,6 +247,9 @@ static void start_rpc(int target_port, grpc_status_code expected_status,
 | 
	
		
			
				|  |  |                                                     expected_detail)));
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  gpr_log(GPR_ERROR, "%s",
 | 
	
		
			
				|  |  | +          grpc_dump_slice(details, GPR_DUMP_ASCII | GPR_DUMP_HEX));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    grpc_metadata_array_destroy(&initial_metadata_recv);
 | 
	
		
			
				|  |  |    grpc_metadata_array_destroy(&trailing_metadata_recv);
 | 
	
		
			
				|  |  |    grpc_slice_unref(details);
 | 
	
	
		
			
				|  | @@ -241,7 +277,7 @@ typedef struct {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void actually_poll_server(void* arg) {
 | 
	
		
			
				|  |  |    poll_args* pa = static_cast<poll_args*>(arg);
 | 
	
		
			
				|  |  | -  gpr_timespec deadline = n_sec_deadline(10);
 | 
	
		
			
				|  |  | +  gpr_timespec deadline = n_sec_deadline(1);
 | 
	
		
			
				|  |  |    while (true) {
 | 
	
		
			
				|  |  |      bool done = gpr_atm_acq_load(&state.done_atm) != 0;
 | 
	
		
			
				|  |  |      gpr_timespec time_left =
 | 
	
	
		
			
				|  | @@ -251,7 +287,7 @@ static void actually_poll_server(void* arg) {
 | 
	
		
			
				|  |  |      if (done || gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) < 0) {
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    test_tcp_server_poll(pa->server, 1000);
 | 
	
		
			
				|  |  | +    test_tcp_server_poll(pa->server, 100);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    gpr_event_set(pa->signal_when_done, (void*)1);
 | 
	
		
			
				|  |  |    gpr_free(pa);
 | 
	
	
		
			
				|  | @@ -260,7 +296,7 @@ static void actually_poll_server(void* arg) {
 | 
	
		
			
				|  |  |  static grpc_core::Thread* poll_server_until_read_done(
 | 
	
		
			
				|  |  |      test_tcp_server* server, gpr_event* signal_when_done) {
 | 
	
		
			
				|  |  |    gpr_atm_rel_store(&state.done_atm, 0);
 | 
	
		
			
				|  |  | -  state.write_done = 0;
 | 
	
		
			
				|  |  | +  state.connection_attempt_made = false;
 | 
	
		
			
				|  |  |    poll_args* pa = static_cast<poll_args*>(gpr_malloc(sizeof(*pa)));
 | 
	
		
			
				|  |  |    pa->server = server;
 | 
	
		
			
				|  |  |    pa->signal_when_done = signal_when_done;
 | 
	
	
		
			
				|  | @@ -270,7 +306,8 @@ static grpc_core::Thread* poll_server_until_read_done(
 | 
	
		
			
				|  |  |    return th;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void run_test(const char* response_payload,
 | 
	
		
			
				|  |  | +static void run_test(bool http2_response, bool send_settings,
 | 
	
		
			
				|  |  | +                     const char* response_payload,
 | 
	
		
			
				|  |  |                       size_t response_payload_length,
 | 
	
		
			
				|  |  |                       grpc_status_code expected_status,
 | 
	
		
			
				|  |  |                       const char* expected_detail) {
 | 
	
	
		
			
				|  | @@ -283,6 +320,8 @@ static void run_test(const char* response_payload,
 | 
	
		
			
				|  |  |    server_port = grpc_pick_unused_port_or_die();
 | 
	
		
			
				|  |  |    test_tcp_server_init(&test_server, on_connect, &test_server);
 | 
	
		
			
				|  |  |    test_tcp_server_start(&test_server, server_port);
 | 
	
		
			
				|  |  | +  state.http2_response = http2_response;
 | 
	
		
			
				|  |  | +  state.send_settings = send_settings;
 | 
	
		
			
				|  |  |    state.response_payload = response_payload;
 | 
	
		
			
				|  |  |    state.response_payload_length = response_payload_length;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -292,7 +331,8 @@ static void run_test(const char* response_payload,
 | 
	
		
			
				|  |  |    start_rpc(server_port, expected_status, expected_detail);
 | 
	
		
			
				|  |  |    gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
 | 
	
		
			
				|  |  |    thdptr->Join();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +  /* Proof that the server accepted the TCP connection. */
 | 
	
		
			
				|  |  | +  GPR_ASSERT(state.connection_attempt_made == true);
 | 
	
		
			
				|  |  |    /* clean up */
 | 
	
		
			
				|  |  |    grpc_endpoint_shutdown(state.tcp,
 | 
	
		
			
				|  |  |                           GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
 | 
	
	
		
			
				|  | @@ -309,43 +349,48 @@ int main(int argc, char** argv) {
 | 
	
		
			
				|  |  |    grpc_init();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* status defined in hpack static table */
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(204), sizeof(HTTP2_RESP(204)) - 1, GRPC_STATUS_UNKNOWN,
 | 
	
		
			
				|  |  | -           HTTP2_DETAIL_MSG(204));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(206), sizeof(HTTP2_RESP(206)) - 1, GRPC_STATUS_UNKNOWN,
 | 
	
		
			
				|  |  | -           HTTP2_DETAIL_MSG(206));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(304), sizeof(HTTP2_RESP(304)) - 1, GRPC_STATUS_UNKNOWN,
 | 
	
		
			
				|  |  | -           HTTP2_DETAIL_MSG(304));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(400), sizeof(HTTP2_RESP(400)) - 1, GRPC_STATUS_INTERNAL,
 | 
	
		
			
				|  |  | -           HTTP2_DETAIL_MSG(400));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1,
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(204), sizeof(HTTP2_RESP(204)) - 1,
 | 
	
		
			
				|  |  | +           GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(204));
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(206), sizeof(HTTP2_RESP(206)) - 1,
 | 
	
		
			
				|  |  | +           GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(206));
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(304), sizeof(HTTP2_RESP(304)) - 1,
 | 
	
		
			
				|  |  | +           GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(304));
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(400), sizeof(HTTP2_RESP(400)) - 1,
 | 
	
		
			
				|  |  | +           GRPC_STATUS_INTERNAL, HTTP2_DETAIL_MSG(400));
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1,
 | 
	
		
			
				|  |  |             GRPC_STATUS_UNIMPLEMENTED, HTTP2_DETAIL_MSG(404));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(500), sizeof(HTTP2_RESP(500)) - 1, GRPC_STATUS_UNKNOWN,
 | 
	
		
			
				|  |  | -           HTTP2_DETAIL_MSG(500));
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(500), sizeof(HTTP2_RESP(500)) - 1,
 | 
	
		
			
				|  |  | +           GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(500));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* status not defined in hpack static table */
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(401), sizeof(HTTP2_RESP(401)) - 1,
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(401), sizeof(HTTP2_RESP(401)) - 1,
 | 
	
		
			
				|  |  |             GRPC_STATUS_UNAUTHENTICATED, HTTP2_DETAIL_MSG(401));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(403), sizeof(HTTP2_RESP(403)) - 1,
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(403), sizeof(HTTP2_RESP(403)) - 1,
 | 
	
		
			
				|  |  |             GRPC_STATUS_PERMISSION_DENIED, HTTP2_DETAIL_MSG(403));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(429), sizeof(HTTP2_RESP(429)) - 1,
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(429), sizeof(HTTP2_RESP(429)) - 1,
 | 
	
		
			
				|  |  |             GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(429));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(499), sizeof(HTTP2_RESP(499)) - 1, GRPC_STATUS_UNKNOWN,
 | 
	
		
			
				|  |  | -           HTTP2_DETAIL_MSG(499));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(502), sizeof(HTTP2_RESP(502)) - 1,
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(499), sizeof(HTTP2_RESP(499)) - 1,
 | 
	
		
			
				|  |  | +           GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(499));
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(502), sizeof(HTTP2_RESP(502)) - 1,
 | 
	
		
			
				|  |  |             GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(502));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(503), sizeof(HTTP2_RESP(503)) - 1,
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(503), sizeof(HTTP2_RESP(503)) - 1,
 | 
	
		
			
				|  |  |             GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(503));
 | 
	
		
			
				|  |  | -  run_test(HTTP2_RESP(504), sizeof(HTTP2_RESP(504)) - 1,
 | 
	
		
			
				|  |  | +  run_test(true, true, HTTP2_RESP(504), sizeof(HTTP2_RESP(504)) - 1,
 | 
	
		
			
				|  |  |             GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(504));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* unparseable response */
 | 
	
		
			
				|  |  | -  run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1, GRPC_STATUS_UNKNOWN,
 | 
	
		
			
				|  |  | -           nullptr);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* http1 response */
 | 
	
		
			
				|  |  | -  run_test(HTTP1_RESP_400, sizeof(HTTP1_RESP_400) - 1, GRPC_STATUS_INTERNAL,
 | 
	
		
			
				|  |  | -           HTTP1_DETAIL_MSG);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +  /* unparseable response. RPC should fail immediately due to a connect failure.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  run_test(false, false, UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1,
 | 
	
		
			
				|  |  | +           GRPC_STATUS_UNAVAILABLE, nullptr);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* http1 response. RPC should fail immediately due to a connect failure. */
 | 
	
		
			
				|  |  | +  run_test(false, false, HTTP1_RESP_400, sizeof(HTTP1_RESP_400) - 1,
 | 
	
		
			
				|  |  | +           GRPC_STATUS_UNAVAILABLE, nullptr);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* http2 response without sending a SETTINGs frame. RPC should fail with
 | 
	
		
			
				|  |  | +   * DEADLINE_EXCEEDED since the RPC deadline is lower than the connection
 | 
	
		
			
				|  |  | +   * attempt deadline. */
 | 
	
		
			
				|  |  | +  run_test(true, false, HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1,
 | 
	
		
			
				|  |  | +           GRPC_STATUS_DEADLINE_EXCEEDED, nullptr);
 | 
	
		
			
				|  |  |    grpc_shutdown();
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 |