stream_op cleanup: test fixes and updates

reviewable/pr3993/r1
Craig Tiller 9 years ago
parent c7e1a2a38d
commit 93b944785c
  1. 30
      test/core/channel/channel_stack_test.c
  2. 27
      test/core/client_config/lb_policies_test.c
  3. 6
      test/core/end2end/fixtures/proxy.c
  4. 7
      test/core/end2end/tests/max_message_length.c
  5. 2
      test/core/end2end/tests/request_with_flags.c
  6. 59
      test/core/network_benchmarks/low_level_ping_pong.c
  7. 200
      test/core/transport/chttp2/hpack_encoder_test.c
  8. 359
      test/core/transport/chttp2/stream_encoder_test.c
  9. 116
      test/core/transport/stream_op_test.c
  10. 10
      test/cpp/end2end/end2end_test.cc
  11. 2
      test/cpp/interop/interop_client.cc

@ -42,22 +42,19 @@
#include "test/core/util/test_config.h"
static void channel_init_func(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args,
grpc_mdctx *metadata_context, int is_first,
int is_last) {
GPR_ASSERT(args->num_args == 1);
GPR_ASSERT(args->args[0].type == GRPC_ARG_INTEGER);
GPR_ASSERT(0 == strcmp(args->args[0].key, "test_key"));
GPR_ASSERT(args->args[0].value.integer == 42);
GPR_ASSERT(is_first);
GPR_ASSERT(is_last);
grpc_channel_element *elem,
grpc_channel_element_args *args) {
GPR_ASSERT(args->channel_args->num_args == 1);
GPR_ASSERT(args->channel_args->args[0].type == GRPC_ARG_INTEGER);
GPR_ASSERT(0 == strcmp(args->channel_args->args[0].key, "test_key"));
GPR_ASSERT(args->channel_args->args[0].value.integer == 42);
GPR_ASSERT(args->is_first);
GPR_ASSERT(args->is_last);
*(int *)(elem->channel_data) = 0;
}
static void call_init_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_call_element_args *args) {
++*(int *)(elem->channel_data);
*(int *)(elem->call_data) = 0;
}
@ -86,9 +83,9 @@ static char *get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
static void test_create_channel_stack(void) {
const grpc_channel_filter filter = {
call_func, channel_func, sizeof(int), call_init_func, call_destroy_func,
sizeof(int), channel_init_func, channel_destroy_func, get_peer,
"some_test_filter"};
call_func, channel_func, sizeof(int), call_init_func,
grpc_call_stack_ignore_set_pollset, call_destroy_func, sizeof(int),
channel_init_func, channel_destroy_func, get_peer, "some_test_filter"};
const grpc_channel_filter *filters = &filter;
grpc_channel_stack *channel_stack;
grpc_call_stack *call_stack;
@ -119,7 +116,8 @@ static void test_create_channel_stack(void) {
GPR_ASSERT(*channel_data == 0);
call_stack = gpr_malloc(channel_stack->call_stack_size);
grpc_call_stack_init(&exec_ctx, channel_stack, NULL, NULL, call_stack);
grpc_call_stack_init(&exec_ctx, channel_stack, 0, NULL, NULL, NULL, NULL,
call_stack);
GPR_ASSERT(call_stack->count == 1);
call_elem = grpc_call_stack_element(call_stack, 0);
GPR_ASSERT(call_elem->filter == channel_elem->filter);

@ -234,13 +234,13 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
grpc_event ev;
int read_tag;
int *connection_sequence;
int completed_client;
s_valid = gpr_malloc(sizeof(int) * f->num_servers);
rdata->call_details = gpr_malloc(sizeof(grpc_call_details) * f->num_servers);
connection_sequence = gpr_malloc(sizeof(int) * spec->num_iters);
/* Send a trivial request. */
deadline = n_seconds_time(60);
for (iter_num = 0; iter_num < spec->num_iters; iter_num++) {
cq_verifier *cqv = cq_verifier_create(f->cq);
@ -266,9 +266,11 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
}
memset(s_valid, 0, f->num_servers * sizeof(int));
deadline = n_seconds_time(1);
c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
"/foo", "foo.test.google.fr", deadline, NULL);
GPR_ASSERT(c);
completed_client = 0;
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
@ -286,10 +288,12 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
op->data.recv_status_on_client.trailing_metadata = &rdata->trailing_metadata_recv;
op->data.recv_status_on_client.trailing_metadata =
&rdata->trailing_metadata_recv;
op->data.recv_status_on_client.status = &rdata->status;
op->data.recv_status_on_client.status_details = &rdata->details;
op->data.recv_status_on_client.status_details_capacity = &rdata->details_capacity;
op->data.recv_status_on_client.status_details_capacity =
&rdata->details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
@ -310,8 +314,9 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
s_idx = -1;
while ((ev = grpc_completion_queue_next(
f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL)).type !=
f->cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(300), NULL)).type !=
GRPC_QUEUE_TIMEOUT) {
GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
read_tag = ((int)(gpr_intptr)ev.tag);
gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%d",
ev.success, ev.type, read_tag, iter_num);
@ -321,6 +326,9 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
s_idx = read_tag - 1000;
s_valid[s_idx] = 1;
connection_sequence[iter_num] = s_idx;
} else if (read_tag == 1) {
GPR_ASSERT(ev.success);
completed_client = 1;
}
}
@ -348,15 +356,22 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
tag(102), NULL));
cq_expect_completion(cqv, tag(102), 1);
cq_expect_completion(cqv, tag(1), 1);
if (!completed_client) {
cq_expect_completion(cqv, tag(1), 1);
}
cq_verify(cqv);
GPR_ASSERT(rdata->status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(rdata->details, "xyz"));
GPR_ASSERT(0 == strcmp(rdata->call_details[s_idx].method, "/foo"));
GPR_ASSERT(0 == strcmp(rdata->call_details[s_idx].host, "foo.test.google.fr"));
GPR_ASSERT(0 ==
strcmp(rdata->call_details[s_idx].host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 1);
} else {
if (!completed_client) {
cq_expect_completion(cqv, tag(1), 1);
cq_verify(cqv);
}
}
for (i = 0; i < f->num_servers; i++) {

@ -146,6 +146,7 @@ void grpc_end2end_proxy_destroy(grpc_end2end_proxy *proxy) {
}
static void unrefpc(proxy_call *pc, const char *reason) {
gpr_log(GPR_DEBUG, "PROXY UNREF %s", reason);
if (gpr_unref(&pc->refs)) {
grpc_call_destroy(pc->c2p);
grpc_call_destroy(pc->p2s);
@ -157,7 +158,10 @@ static void unrefpc(proxy_call *pc, const char *reason) {
}
}
static void refpc(proxy_call *pc, const char *reason) { gpr_ref(&pc->refs); }
static void refpc(proxy_call *pc, const char *reason) {
gpr_log(GPR_DEBUG, "PROXY REF %s", reason);
gpr_ref(&pc->refs);
}
static void on_c2p_sent_initial_metadata(void *arg, int success) {
proxy_call *pc = arg;

@ -109,6 +109,7 @@ static void test_max_message_length(grpc_end2end_test_config config) {
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
grpc_byte_buffer *request_payload =
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *recv_payload;
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv;
@ -183,6 +184,11 @@ static void test_max_message_length(grpc_end2end_test_config config) {
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &recv_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);
@ -194,6 +200,7 @@ static void test_max_message_length(grpc_end2end_test_config config) {
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234"));
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(recv_payload == NULL);
gpr_free(details);
grpc_metadata_array_destroy(&initial_metadata_recv);

@ -41,7 +41,7 @@
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "src/core/transport/stream_op.h"
#include "src/core/transport/byte_stream.h"
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };

@ -84,7 +84,7 @@ static int read_bytes(int fd, char *buf, size_t read_size, int spin) {
size_t bytes_read = 0;
int err;
do {
err = read(fd, buf + bytes_read, read_size - bytes_read);
err = (int)read(fd, buf + bytes_read, read_size - bytes_read);
if (err < 0) {
if (errno == EINTR) {
continue;
@ -96,7 +96,7 @@ static int read_bytes(int fd, char *buf, size_t read_size, int spin) {
return -1;
}
} else {
bytes_read += err;
bytes_read += (size_t)err;
}
} while (bytes_read < read_size);
return 0;
@ -132,13 +132,13 @@ static int poll_read_bytes(int fd, char *buf, size_t read_size, int spin) {
GPR_ASSERT(err == 1);
GPR_ASSERT(pfd.revents == POLLIN);
do {
err = read(fd, buf + bytes_read, read_size - bytes_read);
err = (int)read(fd, buf + bytes_read, read_size - bytes_read);
} while (err < 0 && errno == EINTR);
if (err < 0 && errno != EAGAIN) {
gpr_log(GPR_ERROR, "Read failed: %s", strerror(errno));
return -1;
}
bytes_read += err;
bytes_read += (size_t)err;
} while (bytes_read < read_size);
return 0;
}
@ -172,10 +172,11 @@ static int epoll_read_bytes(struct thread_args *args, char *buf, int spin) {
GPR_ASSERT(ev.data.fd == args->fds.read_fd);
do {
do {
err = read(args->fds.read_fd, buf + bytes_read, read_size - bytes_read);
err = (int)read(args->fds.read_fd, buf + bytes_read,
read_size - bytes_read);
} while (err < 0 && errno == EINTR);
if (errno == EAGAIN) break;
bytes_read += err;
bytes_read += (size_t)err;
/* TODO(klempner): This should really be doing an extra call after we are
done to ensure we see an EAGAIN */
} while (bytes_read < read_size);
@ -202,8 +203,8 @@ static int blocking_write_bytes(struct thread_args *args, char *buf) {
int err;
size_t write_size = args->msg_size;
do {
err = write(args->fds.write_fd, buf + bytes_written,
write_size - bytes_written);
err = (int)write(args->fds.write_fd, buf + bytes_written,
write_size - bytes_written);
if (err < 0) {
if (errno == EINTR) {
continue;
@ -212,7 +213,7 @@ static int blocking_write_bytes(struct thread_args *args, char *buf) {
return -1;
}
} else {
bytes_written += err;
bytes_written += (size_t)err;
}
} while (bytes_written < write_size);
return 0;
@ -297,7 +298,7 @@ static void print_histogram(gpr_histogram *histogram) {
static double now(void) {
gpr_timespec tv = gpr_now(GPR_CLOCK_REALTIME);
return 1e9 * tv.tv_sec + tv.tv_nsec;
return 1e9 * (double)tv.tv_sec + tv.tv_nsec;
}
static void client_thread(thread_args *args) {
@ -387,7 +388,7 @@ static int connect_client(struct sockaddr *addr, int len) {
}
do {
err = connect(fd, addr, len);
err = (int)connect(fd, addr, (socklen_t)len);
} while (err < 0 && errno == EINTR);
if (err < 0) {
@ -590,23 +591,23 @@ static int run_all_benchmarks(int msg_size) {
int error = 0;
size_t i;
for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) {
test_strategy *test_strategy = &test_strategies[i];
test_strategy *ts = &test_strategies[i];
size_t j;
for (j = 0; j < GPR_ARRAY_SIZE(socket_types); ++j) {
thread_args *client_args = malloc(sizeof(thread_args));
thread_args *server_args = malloc(sizeof(thread_args));
char *socket_type = socket_types[j];
client_args->read_bytes = test_strategy->read_strategy;
client_args->read_bytes = ts->read_strategy;
client_args->write_bytes = blocking_write_bytes;
client_args->setup = test_strategy->setup;
client_args->msg_size = msg_size;
client_args->strategy_name = test_strategy->name;
server_args->read_bytes = test_strategy->read_strategy;
client_args->setup = ts->setup;
client_args->msg_size = (size_t)msg_size;
client_args->strategy_name = ts->name;
server_args->read_bytes = ts->read_strategy;
server_args->write_bytes = blocking_write_bytes;
server_args->setup = test_strategy->setup;
server_args->msg_size = msg_size;
server_args->strategy_name = test_strategy->name;
server_args->setup = ts->setup;
server_args->msg_size = (size_t)msg_size;
server_args->strategy_name = ts->name;
error = run_benchmark(socket_type, client_args, server_args);
if (error < 0) {
return error;
@ -623,7 +624,7 @@ int main(int argc, char **argv) {
char *read_strategy = NULL;
char *socket_type = NULL;
size_t i;
const test_strategy *test_strategy = NULL;
const test_strategy *ts = NULL;
int error = 0;
gpr_cmdline *cmdline =
@ -657,23 +658,23 @@ int main(int argc, char **argv) {
for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) {
if (strcmp(test_strategies[i].name, read_strategy) == 0) {
test_strategy = &test_strategies[i];
ts = &test_strategies[i];
}
}
if (test_strategy == NULL) {
if (ts == NULL) {
fprintf(stderr, "Invalid read strategy %s\n", read_strategy);
return -1;
}
client_args->read_bytes = test_strategy->read_strategy;
client_args->read_bytes = ts->read_strategy;
client_args->write_bytes = blocking_write_bytes;
client_args->setup = test_strategy->setup;
client_args->msg_size = msg_size;
client_args->setup = ts->setup;
client_args->msg_size = (size_t)msg_size;
client_args->strategy_name = read_strategy;
server_args->read_bytes = test_strategy->read_strategy;
server_args->read_bytes = ts->read_strategy;
server_args->write_bytes = blocking_write_bytes;
server_args->setup = test_strategy->setup;
server_args->msg_size = msg_size;
server_args->setup = ts->setup;
server_args->msg_size = (size_t)msg_size;
server_args->strategy_name = read_strategy;
error = run_benchmark(socket_type, client_args, server_args);

@ -0,0 +1,200 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/transport/chttp2/hpack_encoder.h"
#include <stdio.h>
#include "src/core/support/string.h"
#include "src/core/transport/chttp2/hpack_parser.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "test/core/util/parse_hexstring.h"
#include "test/core/util/slice_splitter.h"
#include "test/core/util/test_config.h"
#define TEST(x) run_test(x, #x)
grpc_mdctx *g_mdctx;
grpc_chttp2_hpack_compressor g_compressor;
int g_failure = 0;
void **to_delete = NULL;
size_t num_to_delete = 0;
size_t cap_to_delete = 0;
/* verify that the output generated by encoding the stream matches the
hexstring passed in */
static void verify(size_t window_available, int eof, size_t expect_window_used,
const char *expected, size_t nheaders, ...) {
gpr_slice_buffer output;
gpr_slice merged;
gpr_slice expect = parse_hexstring(expected);
size_t i;
va_list l;
grpc_linked_mdelem *e = gpr_malloc(sizeof(*e) * nheaders);
grpc_metadata_batch b;
grpc_metadata_batch_init(&b);
va_start(l, nheaders);
for (i = 0; i < nheaders; i++) {
char *key = va_arg(l, char *);
char *value = va_arg(l, char *);
if (i) {
e[i - 1].next = &e[i];
e[i].prev = &e[i - 1];
}
e[i].md = grpc_mdelem_from_strings(g_mdctx, key, value);
}
e[0].prev = NULL;
e[nheaders - 1].next = NULL;
va_end(l);
b.list.head = &e[0];
b.list.tail = &e[nheaders - 1];
if (cap_to_delete == num_to_delete) {
cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000);
to_delete = gpr_realloc(to_delete, sizeof(*to_delete) * cap_to_delete);
}
to_delete[num_to_delete++] = e;
gpr_slice_buffer_init(&output);
grpc_chttp2_encode_header(&g_compressor, 0xdeadbeef, &b, eof, &output);
merged = grpc_slice_merge(output.slices, output.count);
gpr_slice_buffer_destroy(&output);
grpc_metadata_batch_destroy(&b);
if (0 != gpr_slice_cmp(merged, expect)) {
char *expect_str = gpr_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
char *got_str = gpr_dump_slice(merged, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_ERROR, "mismatched output for %s", expected);
gpr_log(GPR_ERROR, "EXPECT: %s", expect_str);
gpr_log(GPR_ERROR, "GOT: %s", got_str);
gpr_free(expect_str);
gpr_free(got_str);
g_failure = 1;
}
gpr_slice_unref(merged);
gpr_slice_unref(expect);
}
static void test_basic_headers(void) {
int i;
verify(0, 0, 0, "000005 0104 deadbeef 40 0161 0161", 1, "a", "a");
verify(0, 0, 0, "000001 0104 deadbeef be", 1, "a", "a");
verify(0, 0, 0, "000001 0104 deadbeef be", 1, "a", "a");
verify(0, 0, 0, "000006 0104 deadbeef be 40 0162 0163", 2, "a", "a", "b",
"c");
verify(0, 0, 0, "000002 0104 deadbeef bf be", 2, "a", "a", "b", "c");
verify(0, 0, 0, "000004 0104 deadbeef 7f 00 0164", 1, "a", "d");
/* flush out what's there to make a few values look very popular */
for (i = 0; i < 350; i++) {
verify(0, 0, 0, "000003 0104 deadbeef c0 bf be", 3, "a", "a", "b", "c", "a",
"d");
}
verify(0, 0, 0, "000006 0104 deadbeef c0 00 016b 0176", 2, "a", "a", "k",
"v");
/* this could be 000004 0104 deadbeef 0f 30 0176 also */
verify(0, 0, 0, "000004 0104 deadbeef 0f 2f 0176", 1, "a", "v");
}
static void encode_int_to_str(int i, char *p) {
p[0] = (char)('a' + i % 26);
i /= 26;
GPR_ASSERT(i < 26);
p[1] = (char)('a' + i);
p[2] = 0;
}
static void test_decode_table_overflow(void) {
int i;
char key[3], value[3];
char *expect;
for (i = 0; i < 114; i++) {
encode_int_to_str(i, key);
encode_int_to_str(i + 1, value);
if (i + 61 >= 127) {
gpr_asprintf(&expect,
"000009 0104 deadbeef ff%02x 40 02%02x%02x 02%02x%02x",
i + 61 - 127, key[0], key[1], value[0], value[1]);
} else if (i > 0) {
gpr_asprintf(&expect,
"000008 0104 deadbeef %02x 40 02%02x%02x 02%02x%02x",
0x80 + 61 + i, key[0], key[1], value[0], value[1]);
} else {
gpr_asprintf(&expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x",
key[0], key[1], value[0], value[1]);
}
if (i > 0) {
verify(0, 0, 0, expect, 2, "aa", "ba", key, value);
} else {
verify(0, 0, 0, expect, 1, key, value);
}
gpr_free(expect);
}
/* if the above passes, then we must have just knocked this pair out of the
decoder stack, and so we'll be forced to re-encode it */
verify(0, 0, 0, "000007 0104 deadbeef 40 026161 026261", 1, "aa", "ba");
}
static void run_test(void (*test)(), const char *name) {
gpr_log(GPR_INFO, "RUN TEST: %s", name);
g_mdctx = grpc_mdctx_create_with_seed(0);
grpc_chttp2_hpack_compressor_init(&g_compressor, g_mdctx);
test();
grpc_chttp2_hpack_compressor_destroy(&g_compressor);
grpc_mdctx_unref(g_mdctx);
}
int main(int argc, char **argv) {
size_t i;
grpc_test_init(argc, argv);
TEST(test_basic_headers);
TEST(test_decode_table_overflow);
for (i = 0; i < num_to_delete; i++) {
gpr_free(to_delete[i]);
}
return g_failure;
}

@ -1,359 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/transport/chttp2/stream_encoder.h"
#include <stdio.h>
#include "src/core/support/string.h"
#include "src/core/transport/chttp2/hpack_parser.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "test/core/util/parse_hexstring.h"
#include "test/core/util/slice_splitter.h"
#include "test/core/util/test_config.h"
#define TEST(x) run_test(x, #x)
grpc_mdctx *g_mdctx;
grpc_chttp2_hpack_compressor g_compressor;
int g_failure = 0;
grpc_stream_op_buffer g_sopb;
void **to_delete = NULL;
size_t num_to_delete = 0;
size_t cap_to_delete = 0;
static gpr_slice create_test_slice(size_t length) {
gpr_slice slice = gpr_slice_malloc(length);
size_t i;
for (i = 0; i < length; i++) {
GPR_SLICE_START_PTR(slice)[i] = (gpr_uint8)i;
}
return slice;
}
/* verify that the output generated by encoding the stream matches the
hexstring passed in */
static void verify_sopb(size_t window_available, int eof,
size_t expect_window_used, const char *expected) {
gpr_slice_buffer output;
grpc_stream_op_buffer encops;
gpr_slice merged;
gpr_slice expect = parse_hexstring(expected);
gpr_slice_buffer_init(&output);
grpc_sopb_init(&encops);
GPR_ASSERT(expect_window_used ==
grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops,
(gpr_uint32)window_available, &encops));
grpc_chttp2_encode(encops.ops, encops.nops, eof, 0xdeadbeef, &g_compressor,
&output);
encops.nops = 0;
merged = grpc_slice_merge(output.slices, output.count);
gpr_slice_buffer_destroy(&output);
grpc_sopb_destroy(&encops);
if (0 != gpr_slice_cmp(merged, expect)) {
char *expect_str = gpr_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
char *got_str = gpr_dump_slice(merged, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_ERROR, "mismatched output for %s", expected);
gpr_log(GPR_ERROR, "EXPECT: %s", expect_str);
gpr_log(GPR_ERROR, "GOT: %s", got_str);
gpr_free(expect_str);
gpr_free(got_str);
g_failure = 1;
}
gpr_slice_unref(merged);
gpr_slice_unref(expect);
}
static void test_small_data_framing(void) {
grpc_sopb_add_no_op(&g_sopb);
verify_sopb(10, 0, 0, "");
grpc_sopb_add_slice(&g_sopb, create_test_slice(3));
verify_sopb(10, 0, 3, "000003 0000 deadbeef 000102");
grpc_sopb_add_slice(&g_sopb, create_test_slice(4));
verify_sopb(10, 0, 4, "000004 0000 deadbeef 00010203");
grpc_sopb_add_slice(&g_sopb, create_test_slice(3));
grpc_sopb_add_slice(&g_sopb, create_test_slice(4));
verify_sopb(10, 0, 7, "000007 0000 deadbeef 000102 00010203");
grpc_sopb_add_slice(&g_sopb, create_test_slice(0));
grpc_sopb_add_slice(&g_sopb, create_test_slice(0));
grpc_sopb_add_slice(&g_sopb, create_test_slice(0));
grpc_sopb_add_slice(&g_sopb, create_test_slice(0));
grpc_sopb_add_slice(&g_sopb, create_test_slice(3));
verify_sopb(10, 0, 3, "000003 0000 deadbeef 000102");
verify_sopb(10, 1, 0, "000000 0001 deadbeef");
grpc_sopb_add_begin_message(&g_sopb, 255, 0);
verify_sopb(10, 0, 5, "000005 0000 deadbeef 00000000ff");
}
static void add_sopb_headers(size_t n, ...) {
size_t i;
grpc_metadata_batch b;
va_list l;
grpc_linked_mdelem *e = gpr_malloc(sizeof(*e) * n);
grpc_metadata_batch_init(&b);
va_start(l, n);
for (i = 0; i < n; i++) {
char *key = va_arg(l, char *);
char *value = va_arg(l, char *);
if (i) {
e[i - 1].next = &e[i];
e[i].prev = &e[i - 1];
}
e[i].md = grpc_mdelem_from_strings(g_mdctx, key, value);
}
e[0].prev = NULL;
e[n - 1].next = NULL;
va_end(l);
b.list.head = &e[0];
b.list.tail = &e[n - 1];
if (cap_to_delete == num_to_delete) {
cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000);
to_delete = gpr_realloc(to_delete, sizeof(*to_delete) * cap_to_delete);
}
to_delete[num_to_delete++] = e;
grpc_sopb_add_metadata(&g_sopb, b);
}
static void test_basic_headers(void) {
int i;
add_sopb_headers(1, "a", "a");
verify_sopb(0, 0, 0, "000005 0104 deadbeef 40 0161 0161");
add_sopb_headers(1, "a", "a");
verify_sopb(0, 0, 0, "000001 0104 deadbeef be");
add_sopb_headers(1, "a", "a");
verify_sopb(0, 0, 0, "000001 0104 deadbeef be");
add_sopb_headers(2, "a", "a", "b", "c");
verify_sopb(0, 0, 0, "000006 0104 deadbeef be 40 0162 0163");
add_sopb_headers(2, "a", "a", "b", "c");
verify_sopb(0, 0, 0, "000002 0104 deadbeef bf be");
add_sopb_headers(1, "a", "d");
verify_sopb(0, 0, 0, "000004 0104 deadbeef 7f 00 0164");
/* flush out what's there to make a few values look very popular */
for (i = 0; i < 350; i++) {
add_sopb_headers(3, "a", "a", "b", "c", "a", "d");
verify_sopb(0, 0, 0, "000003 0104 deadbeef c0 bf be");
}
add_sopb_headers(2, "a", "a", "k", "v");
verify_sopb(0, 0, 0, "000006 0104 deadbeef c0 00 016b 0176");
add_sopb_headers(1, "a", "v");
/* this could be 000004 0104 deadbeef 0f 30 0176 also */
verify_sopb(0, 0, 0, "000004 0104 deadbeef 0f 2f 0176");
}
static void encode_int_to_str(int i, char *p) {
p[0] = (char)('a' + i % 26);
i /= 26;
GPR_ASSERT(i < 26);
p[1] = (char)('a' + i);
p[2] = 0;
}
static void test_decode_table_overflow(void) {
int i;
char key[3], value[3];
char *expect;
for (i = 0; i < 114; i++) {
if (i > 0) {
add_sopb_headers(1, "aa", "ba");
}
encode_int_to_str(i, key);
encode_int_to_str(i + 1, value);
if (i + 61 >= 127) {
gpr_asprintf(&expect,
"000002 0104 deadbeef ff%02x 000007 0104 deadbeef 40 "
"02%02x%02x 02%02x%02x",
i + 61 - 127, key[0], key[1], value[0], value[1]);
} else if (i > 0) {
gpr_asprintf(&expect,
"000001 0104 deadbeef %02x 000007 0104 deadbeef 40 "
"02%02x%02x 02%02x%02x",
0x80 + 61 + i, key[0], key[1], value[0], value[1]);
} else {
gpr_asprintf(&expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x",
key[0], key[1], value[0], value[1]);
}
add_sopb_headers(1, key, value);
verify_sopb(0, 0, 0, expect);
gpr_free(expect);
}
/* if the above passes, then we must have just knocked this pair out of the
decoder stack, and so we'll be forced to re-encode it */
add_sopb_headers(1, "aa", "ba");
verify_sopb(0, 0, 0, "000007 0104 deadbeef 40 026161 026261");
}
static void randstr(char *p, int bufsz) {
int i;
int len = 1 + rand() % bufsz;
for (i = 0; i < len; i++) {
p[i] = (char)('a' + rand() % 26);
}
p[len] = 0;
}
typedef struct {
char key[300];
char value[300];
int got_hdr;
} test_decode_random_header_state;
static void chk_hdr(void *p, grpc_mdelem *el) {
test_decode_random_header_state *st = p;
GPR_ASSERT(0 == gpr_slice_str_cmp(el->key->slice, st->key));
GPR_ASSERT(0 == gpr_slice_str_cmp(el->value->slice, st->value));
st->got_hdr = 1;
GRPC_MDELEM_UNREF(el);
}
static void test_decode_random_headers_inner(int max_len) {
int i;
test_decode_random_header_state st;
gpr_slice_buffer output;
gpr_slice merged;
grpc_stream_op_buffer encops;
grpc_chttp2_hpack_parser parser;
grpc_chttp2_hpack_parser_init(&parser, g_mdctx);
grpc_sopb_init(&encops);
gpr_log(GPR_INFO, "max_len = %d", max_len);
for (i = 0; i < 10000; i++) {
randstr(st.key, max_len);
randstr(st.value, max_len);
add_sopb_headers(1, st.key, st.value);
gpr_slice_buffer_init(&output);
GPR_ASSERT(0 ==
grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops, 0, &encops));
grpc_chttp2_encode(encops.ops, encops.nops, 0, 0xdeadbeef, &g_compressor,
&output);
encops.nops = 0;
merged = grpc_slice_merge(output.slices, output.count);
gpr_slice_buffer_destroy(&output);
st.got_hdr = 0;
parser.on_header = chk_hdr;
parser.on_header_user_data = &st;
grpc_chttp2_hpack_parser_parse(&parser, GPR_SLICE_START_PTR(merged) + 9,
GPR_SLICE_END_PTR(merged));
GPR_ASSERT(st.got_hdr);
gpr_slice_unref(merged);
}
grpc_chttp2_hpack_parser_destroy(&parser);
grpc_sopb_destroy(&encops);
}
#define DECL_TEST_DECODE_RANDOM_HEADERS(n) \
static void test_decode_random_headers_##n(void) { \
test_decode_random_headers_inner(n); \
} \
int keeps_formatting_correct_##n
DECL_TEST_DECODE_RANDOM_HEADERS(1);
DECL_TEST_DECODE_RANDOM_HEADERS(2);
DECL_TEST_DECODE_RANDOM_HEADERS(3);
DECL_TEST_DECODE_RANDOM_HEADERS(5);
DECL_TEST_DECODE_RANDOM_HEADERS(8);
DECL_TEST_DECODE_RANDOM_HEADERS(13);
DECL_TEST_DECODE_RANDOM_HEADERS(21);
DECL_TEST_DECODE_RANDOM_HEADERS(34);
DECL_TEST_DECODE_RANDOM_HEADERS(55);
DECL_TEST_DECODE_RANDOM_HEADERS(89);
DECL_TEST_DECODE_RANDOM_HEADERS(144);
static void run_test(void (*test)(), const char *name) {
gpr_log(GPR_INFO, "RUN TEST: %s", name);
g_mdctx = grpc_mdctx_create_with_seed(0);
grpc_chttp2_hpack_compressor_init(&g_compressor, g_mdctx);
grpc_sopb_init(&g_sopb);
test();
grpc_chttp2_hpack_compressor_destroy(&g_compressor);
grpc_mdctx_unref(g_mdctx);
grpc_sopb_destroy(&g_sopb);
}
int main(int argc, char **argv) {
size_t i;
grpc_test_init(argc, argv);
TEST(test_small_data_framing);
TEST(test_basic_headers);
TEST(test_decode_table_overflow);
TEST(test_decode_random_headers_1);
TEST(test_decode_random_headers_2);
TEST(test_decode_random_headers_3);
TEST(test_decode_random_headers_5);
TEST(test_decode_random_headers_8);
TEST(test_decode_random_headers_13);
TEST(test_decode_random_headers_21);
TEST(test_decode_random_headers_34);
TEST(test_decode_random_headers_55);
TEST(test_decode_random_headers_89);
TEST(test_decode_random_headers_144);
for (i = 0; i < num_to_delete; i++) {
gpr_free(to_delete[i]);
}
return g_failure;
}

@ -1,116 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/transport/stream_op.h"
#include <string.h>
#include <grpc/support/log.h>
#include "test/core/util/test_config.h"
static void assert_slices_equal(gpr_slice a, gpr_slice b) {
GPR_ASSERT(a.refcount == b.refcount);
if (a.refcount) {
GPR_ASSERT(a.data.refcounted.bytes == b.data.refcounted.bytes);
GPR_ASSERT(a.data.refcounted.length == b.data.refcounted.length);
} else {
GPR_ASSERT(a.data.inlined.length == b.data.inlined.length);
GPR_ASSERT(0 == memcmp(a.data.inlined.bytes, b.data.inlined.bytes,
a.data.inlined.length));
}
}
int main(int argc, char **argv) {
/* some basic test data */
gpr_slice test_slice_1 = gpr_slice_malloc(1);
gpr_slice test_slice_2 = gpr_slice_malloc(2);
gpr_slice test_slice_3 = gpr_slice_malloc(3);
gpr_slice test_slice_4 = gpr_slice_malloc(4);
unsigned i;
grpc_stream_op_buffer buf;
grpc_stream_op_buffer buf2;
grpc_test_init(argc, argv);
/* initialize one of our buffers */
grpc_sopb_init(&buf);
/* it should start out empty */
GPR_ASSERT(buf.nops == 0);
/* add some data to the buffer */
grpc_sopb_add_begin_message(&buf, 1, 2);
grpc_sopb_add_slice(&buf, test_slice_1);
grpc_sopb_add_slice(&buf, test_slice_2);
grpc_sopb_add_slice(&buf, test_slice_3);
grpc_sopb_add_slice(&buf, test_slice_4);
grpc_sopb_add_no_op(&buf);
/* verify that the data went in ok */
GPR_ASSERT(buf.nops == 6);
GPR_ASSERT(buf.ops[0].type == GRPC_OP_BEGIN_MESSAGE);
GPR_ASSERT(buf.ops[0].data.begin_message.length == 1);
GPR_ASSERT(buf.ops[0].data.begin_message.flags == 2);
GPR_ASSERT(buf.ops[1].type == GRPC_OP_SLICE);
assert_slices_equal(buf.ops[1].data.slice, test_slice_1);
GPR_ASSERT(buf.ops[2].type == GRPC_OP_SLICE);
assert_slices_equal(buf.ops[2].data.slice, test_slice_2);
GPR_ASSERT(buf.ops[3].type == GRPC_OP_SLICE);
assert_slices_equal(buf.ops[3].data.slice, test_slice_3);
GPR_ASSERT(buf.ops[4].type == GRPC_OP_SLICE);
assert_slices_equal(buf.ops[4].data.slice, test_slice_4);
GPR_ASSERT(buf.ops[5].type == GRPC_NO_OP);
/* initialize the second buffer */
grpc_sopb_init(&buf2);
/* add a no-op, and then the original buffer */
grpc_sopb_add_no_op(&buf2);
grpc_sopb_append(&buf2, buf.ops, buf.nops);
/* should be one element bigger than the original */
GPR_ASSERT(buf2.nops == buf.nops + 1);
GPR_ASSERT(buf2.ops[0].type == GRPC_NO_OP);
/* and the tail should be the same */
for (i = 0; i < buf.nops; i++) {
GPR_ASSERT(buf2.ops[i + 1].type == buf.ops[i].type);
}
/* destroy the buffers */
grpc_sopb_destroy(&buf);
grpc_sopb_destroy(&buf2);
gpr_slice_unref(test_slice_1);
gpr_slice_unref(test_slice_2);
gpr_slice_unref(test_slice_3);
gpr_slice_unref(test_slice_4);
return 0;
}

@ -1217,14 +1217,14 @@ TEST_P(SecureEnd2endTest, ClientAuthContext) {
}
INSTANTIATE_TEST_CASE_P(End2end, End2endTest,
::testing::Values(TestScenario(false, true),
TestScenario(false, false)));
::testing::Values(TestScenario(false, false),
TestScenario(false, true)));
INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest,
::testing::Values(TestScenario(true, true),
TestScenario(true, false),
::testing::Values(TestScenario(false, false),
TestScenario(false, true),
TestScenario(false, false)));
TestScenario(true, false),
TestScenario(true, true)));
INSTANTIATE_TEST_CASE_P(SecureEnd2end, SecureEnd2endTest,
::testing::Values(TestScenario(false, true)));

@ -46,7 +46,7 @@
#include <grpc++/client_context.h>
#include <grpc++/security/credentials.h>
#include "src/core/transport/stream_op.h"
#include "src/core/transport/byte_stream.h"
#include "test/cpp/interop/client_helper.h"
#include "test/proto/test.grpc.pb.h"
#include "test/proto/empty.grpc.pb.h"

Loading…
Cancel
Save