int main(int argc, char **argv) { int four[4]; int five[5]; uint32_t bitset = 0; grpc_test_init(argc, argv); GPR_ASSERT(GPR_MIN(1, 2) == 1); GPR_ASSERT(GPR_MAX(1, 2) == 2); GPR_ASSERT(GPR_MIN(2, 1) == 1); GPR_ASSERT(GPR_MAX(2, 1) == 2); GPR_ASSERT(GPR_CLAMP(1, 0, 2) == 1); GPR_ASSERT(GPR_CLAMP(0, 0, 2) == 0); GPR_ASSERT(GPR_CLAMP(2, 0, 2) == 2); GPR_ASSERT(GPR_CLAMP(-1, 0, 2) == 0); GPR_ASSERT(GPR_CLAMP(3, 0, 2) == 2); GPR_ASSERT(GPR_ROTL((uint32_t)0x80000001, 1) == 3); GPR_ASSERT(GPR_ROTR((uint32_t)0x80000001, 1) == 0xc0000000); GPR_ASSERT(GPR_ARRAY_SIZE(four) == 4); GPR_ASSERT(GPR_ARRAY_SIZE(five) == 5); GPR_ASSERT(GPR_BITCOUNT((1u << 31) - 1) == 31); GPR_ASSERT(GPR_BITCOUNT(1u << 3) == 1); GPR_ASSERT(GPR_BITCOUNT(0) == 0); GPR_ASSERT(GPR_BITSET(&bitset, 3) == 8); GPR_ASSERT(GPR_BITCOUNT(bitset) == 1); GPR_ASSERT(GPR_BITGET(bitset, 3) == 1); GPR_ASSERT(GPR_BITSET(&bitset, 1) == 10); GPR_ASSERT(GPR_BITCOUNT(bitset) == 2); GPR_ASSERT(GPR_BITCLEAR(&bitset, 3) == 2); GPR_ASSERT(GPR_BITCOUNT(bitset) == 1); GPR_ASSERT(GPR_BITGET(bitset, 3) == 0); return 0; }
/* Constructor for channel_data */ static void init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { channel_data *channeld = elem->channel_data; channeld->enabled_algorithms_bitset = grpc_channel_args_compression_algorithm_get_states(args->channel_args); channeld->default_compression_algorithm = grpc_channel_args_get_compression_algorithm(args->channel_args); /* Make sure the default isn't disabled. */ if (!GPR_BITGET(channeld->enabled_algorithms_bitset, channeld->default_compression_algorithm)) { gpr_log(GPR_DEBUG, "compression algorithm %d not enabled: switching to none", channeld->default_compression_algorithm); channeld->default_compression_algorithm = GRPC_COMPRESS_NONE; } channeld->supported_compression_algorithms = 1; /* always support identity */ for (grpc_compression_algorithm algo_idx = 1; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) { /* skip disabled algorithms */ if (!GPR_BITGET(channeld->enabled_algorithms_bitset, algo_idx)) { continue; } channeld->supported_compression_algorithms |= 1u << algo_idx; } GPR_ASSERT(!args->is_last); }
static void test_compression_algorithm_states(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_args *ch_args, *ch_args_wo_gzip, *ch_args_wo_gzip_deflate; unsigned states_bitset; size_t i; ch_args = grpc_channel_args_copy_and_add(NULL, NULL, 0); /* by default, all enabled */ states_bitset = (unsigned)grpc_channel_args_compression_algorithm_get_states(ch_args); for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { GPR_ASSERT(GPR_BITGET(states_bitset, i)); } /* disable gzip and deflate */ ch_args_wo_gzip = grpc_channel_args_compression_algorithm_set_state( &exec_ctx, &ch_args, GRPC_COMPRESS_GZIP, 0); GPR_ASSERT(ch_args == ch_args_wo_gzip); ch_args_wo_gzip_deflate = grpc_channel_args_compression_algorithm_set_state( &exec_ctx, &ch_args_wo_gzip, GRPC_COMPRESS_DEFLATE, 0); GPR_ASSERT(ch_args_wo_gzip == ch_args_wo_gzip_deflate); states_bitset = (unsigned)grpc_channel_args_compression_algorithm_get_states( ch_args_wo_gzip_deflate); for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { if (i == GRPC_COMPRESS_GZIP || i == GRPC_COMPRESS_DEFLATE) { GPR_ASSERT(GPR_BITGET(states_bitset, i) == 0); } else { GPR_ASSERT(GPR_BITGET(states_bitset, i) != 0); } } /* re-enabled gzip only */ ch_args_wo_gzip = grpc_channel_args_compression_algorithm_set_state( &exec_ctx, &ch_args_wo_gzip_deflate, GRPC_COMPRESS_GZIP, 1); GPR_ASSERT(ch_args_wo_gzip == ch_args_wo_gzip_deflate); states_bitset = (unsigned)grpc_channel_args_compression_algorithm_get_states( ch_args_wo_gzip); for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { if (i == GRPC_COMPRESS_DEFLATE) { GPR_ASSERT(GPR_BITGET(states_bitset, i) == 0); } else { GPR_ASSERT(GPR_BITGET(states_bitset, i) != 0); } } grpc_channel_args_destroy(&exec_ctx, ch_args); grpc_exec_ctx_finish(&exec_ctx); }
/** For each \a md element from the incoming metadata, filter out the entry for * "grpc-encoding", using its value to populate the call data's * compression_algorithm field. */ static grpc_mdelem *compression_md_filter(void *user_data, grpc_mdelem *md) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) { const char *md_c_str = grpc_mdstr_as_c_string(md->value); if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str), &calld->compression_algorithm)) { gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s' (unknown). Ignoring.", md_c_str); calld->compression_algorithm = GRPC_COMPRESS_NONE; } if (!GPR_BITGET(channeld->enabled_algorithms_bitset, calld->compression_algorithm)) { gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s' (previously disabled). " "Ignoring.", md_c_str); calld->compression_algorithm = GRPC_COMPRESS_NONE; } calld->has_compression_algorithm = 1; return NULL; } return md; }
GRPCAPI grpc_stream_compression_algorithm grpc_stream_compression_algorithm_for_level( grpc_stream_compression_level level, uint32_t accepted_stream_encodings) { GRPC_API_TRACE("grpc_stream_compression_algorithm_for_level(level=%d)", 1, ((int)level)); if (level > GRPC_STREAM_COMPRESS_LEVEL_HIGH) { gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level); abort(); } switch (level) { case GRPC_STREAM_COMPRESS_LEVEL_NONE: return GRPC_STREAM_COMPRESS_NONE; case GRPC_STREAM_COMPRESS_LEVEL_LOW: case GRPC_STREAM_COMPRESS_LEVEL_MED: case GRPC_STREAM_COMPRESS_LEVEL_HIGH: if (GPR_BITGET(accepted_stream_encodings, GRPC_STREAM_COMPRESS_GZIP) == 1) { return GRPC_STREAM_COMPRESS_GZIP; } else { return GRPC_STREAM_COMPRESS_NONE; } default: abort(); } }
static grpc_error *process_send_initial_metadata( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *initial_metadata, bool *has_compression_algorithm) { call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; *has_compression_algorithm = false; /* Parse incoming request for compression. If any, it'll be available * at calld->compression_algorithm */ if (initial_metadata->idx.named.grpc_internal_encoding_request != NULL) { grpc_mdelem md = initial_metadata->idx.named.grpc_internal_encoding_request->md; if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md), &calld->compression_algorithm)) { char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s' (unknown). Ignoring.", val); gpr_free(val); calld->compression_algorithm = GRPC_COMPRESS_NONE; } if (!GPR_BITGET(channeld->enabled_algorithms_bitset, calld->compression_algorithm)) { char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s' (previously disabled). " "Ignoring.", val); gpr_free(val); calld->compression_algorithm = GRPC_COMPRESS_NONE; } *has_compression_algorithm = true; grpc_metadata_batch_remove( exec_ctx, initial_metadata, initial_metadata->idx.named.grpc_internal_encoding_request); } else { /* If no algorithm was found in the metadata and we aren't * exceptionally skipping compression, fall back to the channel * default */ calld->compression_algorithm = channeld->default_compression_algorithm; *has_compression_algorithm = true; } grpc_error *error = GRPC_ERROR_NONE; /* hint compression algorithm */ if (calld->compression_algorithm != GRPC_COMPRESS_NONE) { error = grpc_metadata_batch_add_tail( exec_ctx, initial_metadata, &calld->compression_algorithm_storage, grpc_compression_encoding_mdelem(calld->compression_algorithm)); } if (error != GRPC_ERROR_NONE) return error; /* convey supported compression algorithms */ error = grpc_metadata_batch_add_tail( exec_ctx, initial_metadata, &calld->accept_encoding_storage, GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS( channeld->supported_compression_algorithms)); return error; }
/* TODO(dgq): Add the ability to specify parameters to the individual * compression algorithms */ grpc_compression_algorithm grpc_compression_algorithm_for_level( grpc_compression_level level, uint32_t accepted_encodings) { GRPC_API_TRACE("grpc_compression_algorithm_for_level(level=%d)", 1, ((int)level)); if (level > GRPC_COMPRESS_LEVEL_HIGH) { gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level); abort(); } const size_t num_supported = GPR_BITCOUNT(accepted_encodings) - 1; /* discard NONE */ if (level == GRPC_COMPRESS_LEVEL_NONE || num_supported == 0) { return GRPC_COMPRESS_NONE; } GPR_ASSERT(level > 0); /* Establish a "ranking" or compression algorithms in increasing order of * compression. * This is simplistic and we will probably want to introduce other dimensions * in the future (cpu/memory cost, etc). */ const grpc_compression_algorithm algos_ranking[] = {GRPC_COMPRESS_GZIP, GRPC_COMPRESS_DEFLATE }; /* intersect algos_ranking with the supported ones keeping the ranked order */ grpc_compression_algorithm sorted_supported_algos[GRPC_COMPRESS_ALGORITHMS_COUNT]; size_t algos_supported_idx = 0; for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) { const grpc_compression_algorithm alg = algos_ranking[i]; for (size_t j = 0; j < num_supported; j++) { if (GPR_BITGET(accepted_encodings, alg) == 1) { /* if \a alg in supported */ sorted_supported_algos[algos_supported_idx++] = alg; break; } } if (algos_supported_idx == num_supported) break; } switch (level) { case GRPC_COMPRESS_LEVEL_NONE: abort(); /* should have been handled already */ case GRPC_COMPRESS_LEVEL_LOW: return sorted_supported_algos[0]; case GRPC_COMPRESS_LEVEL_MED: return sorted_supported_algos[num_supported / 2]; case GRPC_COMPRESS_LEVEL_HIGH: return sorted_supported_algos[num_supported - 1]; default: abort(); }; }
static void request_with_payload_template( grpc_end2end_test_config config, const char *test_name, gpr_uint32 send_flags_bitmask, grpc_compression_algorithm requested_compression_algorithm, grpc_compression_algorithm expected_compression_algorithm, grpc_metadata *client_metadata) { grpc_call *c; grpc_call *s; gpr_slice request_payload_slice; grpc_byte_buffer *request_payload; gpr_timespec deadline = five_seconds_time(); grpc_channel_args *client_args; grpc_channel_args *server_args; grpc_end2end_test_fixture f; 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; grpc_call_error error; char *details = NULL; size_t details_capacity = 0; int was_cancelled = 2; cq_verifier *cqv; char str[1024]; memset(str, 'x', 1023); str[1023] = '\0'; request_payload_slice = gpr_slice_from_copied_string(str); request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); client_args = grpc_channel_args_set_compression_algorithm( NULL, requested_compression_algorithm); server_args = grpc_channel_args_set_compression_algorithm( NULL, requested_compression_algorithm); f = begin_test(config, test_name, client_args, server_args); cqv = cq_verifier_create(f.cq); c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", "foo.test.google.fr", 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); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; if (client_metadata != NULL) { op->data.send_initial_metadata.count = 1; op->data.send_initial_metadata.metadata = client_metadata; } else { op->data.send_initial_metadata.count = 0; } op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = request_payload; op->flags = send_flags_bitmask; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &initial_metadata_recv; op->flags = 0; op->reserved = NULL; 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->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, 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); GPR_ASSERT(GPR_BITCOUNT(grpc_call_get_encodings_accepted_by_peer(s)) == 3); GPR_ASSERT(GPR_BITGET(grpc_call_get_encodings_accepted_by_peer(s), GRPC_COMPRESS_NONE) != 0); GPR_ASSERT(GPR_BITGET(grpc_call_get_encodings_accepted_by_peer(s), GRPC_COMPRESS_DEFLATE) != 0); GPR_ASSERT(GPR_BITGET(grpc_call_get_encodings_accepted_by_peer(s), GRPC_COMPRESS_GZIP) != 0); 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_RECV_MESSAGE; op->data.recv_message = &request_payload_recv; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(s, ops, op - ops, tag(102), NULL); GPR_ASSERT(GRPC_CALL_OK == error); cq_expect_completion(cqv, tag(102), 1); cq_verify(cqv); 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_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.status = GRPC_STATUS_OK; op->data.send_status_from_server.status_details = "xyz"; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(s, ops, op - ops, tag(103), NULL); GPR_ASSERT(GRPC_CALL_OK == error); cq_expect_completion(cqv, tag(103), 1); cq_expect_completion(cqv, tag(1), 1); cq_verify(cqv); GPR_ASSERT(status == GRPC_STATUS_OK); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); GPR_ASSERT(request_payload_recv->data.raw.compression == expected_compression_algorithm); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, str)); 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(cqv); gpr_slice_unref(request_payload_slice); grpc_byte_buffer_destroy(request_payload); grpc_byte_buffer_destroy(request_payload_recv); grpc_channel_args_destroy(client_args); grpc_channel_args_destroy(server_args); end_test(&f); config.tear_down_data(&f); }
int grpc_compression_options_is_stream_compression_algorithm_enabled( const grpc_compression_options *opts, grpc_stream_compression_algorithm algorithm) { return GPR_BITGET(opts->enabled_stream_compression_algorithms_bitset, algorithm); }
int grpc_compression_options_is_algorithm_enabled( const grpc_compression_options *opts, grpc_compression_algorithm algorithm) { if (algorithm >= GRPC_COMPRESS_ALGORITHMS_COUNT) return 0; return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm); }
static void request_with_payload_template( grpc_end2end_test_config config, const char *test_name, uint32_t client_send_flags_bitmask, grpc_compression_algorithm default_client_channel_compression_algorithm, grpc_compression_algorithm default_server_channel_compression_algorithm, grpc_compression_algorithm expected_algorithm_from_client, grpc_compression_algorithm expected_algorithm_from_server, grpc_metadata *client_init_metadata, bool set_server_level, grpc_compression_level server_compression_level, bool send_message_before_initial_metadata) { grpc_call *c; grpc_call *s; grpc_slice request_payload_slice; grpc_byte_buffer *request_payload = NULL; grpc_channel_args *client_args; grpc_channel_args *server_args; grpc_end2end_test_fixture f; 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; grpc_byte_buffer *response_payload_recv; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details; int was_cancelled = 2; cq_verifier *cqv; char request_str[1024]; char response_str[1024]; memset(request_str, 'x', 1023); request_str[1023] = '\0'; memset(response_str, 'y', 1023); response_str[1023] = '\0'; request_payload_slice = grpc_slice_from_copied_string(request_str); grpc_slice response_payload_slice = grpc_slice_from_copied_string(response_str); client_args = grpc_channel_args_set_compression_algorithm( NULL, default_client_channel_compression_algorithm); server_args = grpc_channel_args_set_compression_algorithm( NULL, default_server_channel_compression_algorithm); f = begin_test(config, test_name, client_args, server_args); cqv = cq_verifier_create(f.cq); gpr_timespec deadline = five_seconds_from_now(); c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, grpc_slice_from_static_string("/foo"), 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); if (send_message_before_initial_metadata) { request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; op->flags = client_send_flags_bitmask; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(2), true); } memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; if (client_init_metadata != NULL) { op->data.send_initial_metadata.count = 1; op->data.send_initial_metadata.metadata = client_init_metadata; } else { op->data.send_initial_metadata.count = 0; } 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_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++; 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(100)); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(100), true); cq_verify(cqv); GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer( s)) == GRPC_COMPRESS_ALGORITHMS_COUNT); GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), GRPC_COMPRESS_NONE) != 0); GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), GRPC_COMPRESS_DEFLATE) != 0); GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), GRPC_COMPRESS_GZIP) != 0); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; if (set_server_level) { op->data.send_initial_metadata.maybe_compression_level.is_set = true; op->data.send_initial_metadata.maybe_compression_level.level = server_compression_level; } op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(101), NULL); GPR_ASSERT(GRPC_CALL_OK == error); for (int i = 0; i < 2; i++) { response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); if (i > 0 || !send_message_before_initial_metadata) { request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; op->flags = client_send_flags_bitmask; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(2), 1); } 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++; 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_verify(cqv); GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); GPR_ASSERT(request_payload_recv->data.raw.compression == expected_algorithm_from_client); memset(ops, 0, sizeof(ops)); op = ops; 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); memset(ops, 0, sizeof(ops)); op = ops; 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(3), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(103), 1); CQ_EXPECT_COMPLETION(cqv, tag(3), 1); cq_verify(cqv); GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); if (server_compression_level > GRPC_COMPRESS_LEVEL_NONE) { const grpc_compression_algorithm algo_for_server_level = grpc_call_compression_for_level(s, server_compression_level); GPR_ASSERT(response_payload_recv->data.raw.compression == algo_for_server_level); } else { GPR_ASSERT(response_payload_recv->data.raw.compression == expected_algorithm_from_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); } grpc_slice_unref(request_payload_slice); grpc_slice_unref(response_payload_slice); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); GPR_ASSERT(GRPC_CALL_OK == error); memset(ops, 0, sizeof(ops)); op = ops; 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_OK; grpc_slice status_details = grpc_slice_from_static_string("xyz"); op->data.send_status_from_server.status_details = &status_details; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(1), 1); CQ_EXPECT_COMPLETION(cqv, tag(4), 1); CQ_EXPECT_COMPLETION(cqv, tag(101), 1); CQ_EXPECT_COMPLETION(cqv, tag(104), 1); cq_verify(cqv); GPR_ASSERT(status == GRPC_STATUS_OK); GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, config); GPR_ASSERT(was_cancelled == 0); grpc_slice_unref(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_unref(c); grpc_call_unref(s); cq_verifier_destroy(cqv); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_args_destroy(&exec_ctx, client_args); grpc_channel_args_destroy(&exec_ctx, server_args); grpc_exec_ctx_finish(&exec_ctx); } end_test(&f); config.tear_down_data(&f); }