aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/build/c-ares.c43
-rw-r--r--test/core/bad_client/bad_client.c10
-rw-r--r--test/core/channel/channel_stack_test.c16
-rw-r--r--test/core/client_channel/BUILD7
-rw-r--r--test/core/client_channel/resolvers/dns_resolver_connectivity_test.c16
-rw-r--r--test/core/client_channel/set_initial_connect_string_test.c268
-rw-r--r--test/core/end2end/bad_server_response_test.c2
-rw-r--r--test/core/end2end/connection_refused_test.c2
-rw-r--r--test/core/end2end/end2end_tests.h7
-rw-r--r--test/core/end2end/fixtures/http_proxy_fixture.c2
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer.c12
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6723650944237568bin0 -> 669 bytes
-rw-r--r--test/core/end2end/goaway_server_test.c30
-rw-r--r--test/core/end2end/tests/filter_call_init_fails.c8
-rw-r--r--test/core/end2end/tests/filter_causes_close.c4
-rw-r--r--test/core/end2end/tests/filter_latency.c4
-rw-r--r--test/core/end2end/tests/network_status_change.c4
-rw-r--r--test/core/end2end/tests/resource_quota_server.c4
-rw-r--r--test/core/http/httpcli_test.c4
-rw-r--r--test/core/http/httpscli_test.c4
-rw-r--r--test/core/iomgr/endpoint_tests.c14
-rw-r--r--test/core/iomgr/error_test.c123
-rw-r--r--test/core/iomgr/ev_epoll_linux_test.c2
-rw-r--r--test/core/iomgr/fd_posix_test.c2
-rw-r--r--test/core/iomgr/pollset_set_test.c3
-rw-r--r--test/core/iomgr/tcp_client_posix_test.c5
-rw-r--r--test/core/iomgr/tcp_client_uv_test.c5
-rw-r--r--test/core/iomgr/tcp_server_posix_test.c5
-rw-r--r--test/core/iomgr/tcp_server_uv_test.c3
-rw-r--r--test/core/iomgr/udp_server_test.c89
-rw-r--r--test/core/memory_usage/client.c5
-rw-r--r--test/core/security/secure_endpoint_test.c10
-rw-r--r--test/core/security/ssl_server_fuzzer.c5
-rw-r--r--test/core/support/cpu_test.c7
-rw-r--r--test/core/surface/concurrent_connectivity_test.c3
-rw-r--r--test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112bin0 -> 172032 bytes
-rw-r--r--test/core/util/mock_endpoint.c5
-rw-r--r--test/core/util/passthru_endpoint.c15
-rw-r--r--test/core/util/reconnect_server.c3
-rw-r--r--test/cpp/common/channel_arguments_test.cc23
-rw-r--r--test/cpp/microbenchmarks/bm_call_create.cc234
-rw-r--r--test/cpp/microbenchmarks/bm_chttp2_transport.cc587
-rw-r--r--test/cpp/microbenchmarks/bm_error.cc72
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc225
-rw-r--r--test/http2_test/http2_base_server.py35
-rw-r--r--test/http2_test/http2_server_health_check.py49
-rw-r--r--test/http2_test/http2_test_server.py31
-rw-r--r--test/http2_test/test_data_frame_padding.py94
48 files changed, 1554 insertions, 547 deletions
diff --git a/test/build/c-ares.c b/test/build/c-ares.c
new file mode 100644
index 0000000000..c954e9397f
--- /dev/null
+++ b/test/build/c-ares.c
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright 2016, 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 <ares.h>
+
+int main(void) {
+ ares_channel channelptr;
+
+ ares_init(&channelptr);
+ ares_destroy(channelptr);
+
+ return 0;
+}
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index fdedfe284e..4870dc1a53 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -163,8 +163,9 @@ void grpc_run_bad_client_test(
gpr_event_wait(&a.done_write, grpc_timeout_seconds_to_deadline(5)));
if (flags & GRPC_BAD_CLIENT_DISCONNECT) {
- grpc_endpoint_shutdown(&exec_ctx, sfd.client,
- GRPC_ERROR_CREATE("Forced Disconnect"));
+ grpc_endpoint_shutdown(
+ &exec_ctx, sfd.client,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Disconnect"));
grpc_endpoint_destroy(&exec_ctx, sfd.client);
grpc_exec_ctx_finish(&exec_ctx);
sfd.client = NULL;
@@ -190,8 +191,9 @@ void grpc_run_bad_client_test(
grpc_slice_buffer_destroy_internal(&exec_ctx, &args.incoming);
}
// Shutdown.
- grpc_endpoint_shutdown(&exec_ctx, sfd.client,
- GRPC_ERROR_CREATE("Test Shutdown"));
+ grpc_endpoint_shutdown(
+ &exec_ctx, sfd.client,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
grpc_endpoint_destroy(&exec_ctx, sfd.client);
grpc_exec_ctx_finish(&exec_ctx);
}
diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c
index 76bb57346c..af551c4928 100644
--- a/test/core/channel/channel_stack_test.c
+++ b/test/core/channel/channel_stack_test.c
@@ -68,7 +68,7 @@ static void channel_destroy_func(grpc_exec_ctx *exec_ctx,
static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *ignored) {
+ grpc_closure *ignored) {
++*(int *)(elem->channel_data);
}
@@ -139,10 +139,16 @@ static void test_create_channel_stack(void) {
GPR_ASSERT(*channel_data == 0);
call_stack = gpr_malloc(channel_stack->call_stack_size);
- grpc_error *error =
- grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack,
- NULL, NULL, path, gpr_now(GPR_CLOCK_MONOTONIC),
- gpr_inf_future(GPR_CLOCK_MONOTONIC), call_stack);
+ const grpc_call_element_args args = {
+ .call_stack = call_stack,
+ .server_transport_data = NULL,
+ .context = NULL,
+ .path = path,
+ .start_time = gpr_now(GPR_CLOCK_MONOTONIC),
+ .deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC),
+ .arena = NULL};
+ grpc_error *error = grpc_call_stack_init(&exec_ctx, channel_stack, 1,
+ free_call, call_stack, &args);
GPR_ASSERT(error == GRPC_ERROR_NONE);
GPR_ASSERT(call_stack->count == 1);
call_elem = grpc_call_stack_element(call_stack, 0);
diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD
index a29e9aca4e..55a74c6d01 100644
--- a/test/core/client_channel/BUILD
+++ b/test/core/client_channel/BUILD
@@ -45,10 +45,3 @@ cc_test(
deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:cq_verifier"],
copts = ['-std=c99']
)
-
-cc_test(
- name = "set_initial_connect_string_test",
- srcs = ["set_initial_connect_string_test.c"],
- deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
- copts = ['-std=c99']
-)
diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
index 187757d5b3..8449afcbbe 100644
--- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
+++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
@@ -48,22 +48,26 @@ static gpr_mu g_mu;
static bool g_fail_resolution = true;
static grpc_combiner *g_combiner;
-static grpc_error *my_resolve_address(const char *name, const char *addr,
- grpc_resolved_addresses **addrs) {
+static void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr,
+ const char *default_port,
+ grpc_pollset_set *interested_parties,
+ grpc_closure *on_done,
+ grpc_resolved_addresses **addrs) {
gpr_mu_lock(&g_mu);
- GPR_ASSERT(0 == strcmp("test", name));
+ GPR_ASSERT(0 == strcmp("test", addr));
+ grpc_error *error = GRPC_ERROR_NONE;
if (g_fail_resolution) {
g_fail_resolution = false;
gpr_mu_unlock(&g_mu);
- return GRPC_ERROR_CREATE("Forced Failure");
+ error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure");
} else {
gpr_mu_unlock(&g_mu);
*addrs = gpr_malloc(sizeof(**addrs));
(*addrs)->naddrs = 1;
(*addrs)->addrs = gpr_malloc(sizeof(*(*addrs)->addrs));
(*addrs)->addrs[0].len = 123;
- return GRPC_ERROR_NONE;
}
+ grpc_closure_sched(exec_ctx, on_done, error);
}
static grpc_resolver *create_resolver(grpc_exec_ctx *exec_ctx,
@@ -135,7 +139,7 @@ int main(int argc, char **argv) {
grpc_init();
gpr_mu_init(&g_mu);
g_combiner = grpc_combiner_create(NULL);
- grpc_blocking_resolve_address = my_resolve_address;
+ grpc_resolve_address = my_resolve_address;
grpc_channel_args *result = (grpc_channel_args *)1;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
diff --git a/test/core/client_channel/set_initial_connect_string_test.c b/test/core/client_channel/set_initial_connect_string_test.c
deleted file mode 100644
index a0a33667cc..0000000000
--- a/test/core/client_channel/set_initial_connect_string_test.c
+++ /dev/null
@@ -1,268 +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.
- *
- */
-
-/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when
- using that endpoint. Because of various transitive includes in uv.h,
- including windows.h on Windows, uv.h must be included before other system
- headers. Therefore, sockaddr.h must always be included first */
-#include "src/core/lib/iomgr/sockaddr.h"
-
-#include <string.h>
-
-#include <grpc/grpc.h>
-#include <grpc/slice.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/thd.h>
-
-#include "src/core/ext/client_channel/initial_connect_string.h"
-#include "src/core/lib/iomgr/sockaddr.h"
-#include "src/core/lib/security/credentials/fake/fake_credentials.h"
-#include "src/core/lib/slice/slice_string_helpers.h"
-#include "src/core/lib/support/string.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-#include "test/core/util/test_tcp_server.h"
-
-struct rpc_state {
- char *target;
- grpc_channel_credentials *creds;
- grpc_completion_queue *cq;
- grpc_channel *channel;
- grpc_call *call;
- grpc_op op;
- grpc_slice_buffer incoming_buffer;
- grpc_slice_buffer temp_incoming_buffer;
- grpc_endpoint *tcp;
- gpr_atm done_atm;
-};
-
-static const char *magic_connect_string = "magic initial string";
-static int server_port;
-static struct rpc_state state;
-static grpc_closure on_read;
-
-static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
- GPR_ASSERT(error == GRPC_ERROR_NONE);
- grpc_slice_buffer_move_into(&state.temp_incoming_buffer,
- &state.incoming_buffer);
- gpr_log(GPR_DEBUG, "got %" PRIuPTR " bytes, magic is %" PRIuPTR " bytes",
- state.incoming_buffer.length, strlen(magic_connect_string));
- if (state.incoming_buffer.length > strlen(magic_connect_string)) {
- gpr_atm_rel_store(&state.done_atm, 1);
- grpc_endpoint_shutdown(
- exec_ctx, state.tcp,
- GRPC_ERROR_CREATE("Incoming buffer longer than magic_connect_string"));
- grpc_endpoint_destroy(exec_ctx, state.tcp);
- } else {
- grpc_endpoint_read(exec_ctx, state.tcp, &state.temp_incoming_buffer,
- &on_read);
- }
-}
-
-static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
- grpc_pollset *accepting_pollset,
- grpc_tcp_server_acceptor *acceptor) {
- gpr_free(acceptor);
- test_tcp_server *server = arg;
- grpc_closure_init(&on_read, handle_read, NULL, grpc_schedule_on_exec_ctx);
- grpc_slice_buffer_init(&state.incoming_buffer);
- grpc_slice_buffer_init(&state.temp_incoming_buffer);
- state.tcp = tcp;
- grpc_endpoint_add_to_pollset(exec_ctx, tcp, server->pollset);
- grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read);
-}
-
-static void set_magic_initial_string(grpc_resolved_address **addr,
- grpc_slice *connect_string) {
- GPR_ASSERT(addr);
- GPR_ASSERT((*addr)->len);
- *connect_string = grpc_slice_from_copied_string(magic_connect_string);
-}
-
-static void reset_addr_and_set_magic_string(grpc_resolved_address **addr,
- grpc_slice *connect_string) {
- struct sockaddr_in target;
- *connect_string = grpc_slice_from_copied_string(magic_connect_string);
- gpr_free(*addr);
- target.sin_family = AF_INET;
- target.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- target.sin_port = htons((uint16_t)server_port);
- *addr = (grpc_resolved_address *)gpr_malloc(sizeof(grpc_resolved_address));
- (*addr)->len = sizeof(target);
- memcpy((*addr)->addr, &target, sizeof(target));
-}
-
-static gpr_timespec n_sec_deadline(int seconds) {
- return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
- gpr_time_from_seconds(seconds, GPR_TIMESPAN));
-}
-
-static void start_rpc(int use_creds, int target_port) {
- state.cq = grpc_completion_queue_create(NULL);
- if (use_creds) {
- state.creds = grpc_fake_transport_security_credentials_create();
- } else {
- state.creds = NULL;
- }
- gpr_join_host_port(&state.target, "127.0.0.1", target_port);
- if (use_creds) {
- state.channel =
- grpc_secure_channel_create(state.creds, state.target, NULL, NULL);
- } else {
- state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
- }
- grpc_slice host = grpc_slice_from_static_string("localhost");
- state.call = grpc_channel_create_call(
- state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq,
- grpc_slice_from_static_string("/Service/Method"), &host,
- gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
- memset(&state.op, 0, sizeof(state.op));
- state.op.op = GRPC_OP_SEND_INITIAL_METADATA;
- state.op.data.send_initial_metadata.count = 0;
- state.op.flags = 0;
- state.op.reserved = NULL;
- GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(state.call, &state.op,
- (size_t)(1), NULL, NULL));
- grpc_completion_queue_next(state.cq, n_sec_deadline(5), NULL);
-}
-
-static void cleanup_rpc(void) {
- grpc_event ev;
- grpc_slice_buffer_destroy(&state.incoming_buffer);
- grpc_slice_buffer_destroy(&state.temp_incoming_buffer);
- grpc_channel_credentials_release(state.creds);
- grpc_call_destroy(state.call);
- grpc_completion_queue_shutdown(state.cq);
- do {
- ev = grpc_completion_queue_next(state.cq, n_sec_deadline(1), NULL);
- } while (ev.type != GRPC_QUEUE_SHUTDOWN);
- grpc_completion_queue_destroy(state.cq);
- grpc_channel_destroy(state.channel);
- gpr_free(state.target);
-}
-
-typedef struct {
- test_tcp_server *server;
- gpr_event *signal_when_done;
-} poll_args;
-
-static void actually_poll_server(void *arg) {
- poll_args *pa = arg;
- gpr_timespec deadline = n_sec_deadline(10);
- while (true) {
- bool done = gpr_atm_acq_load(&state.done_atm) != 0;
- gpr_timespec time_left =
- gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME));
- gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRId64 ".%09" PRId32, done,
- time_left.tv_sec, time_left.tv_nsec);
- if (done || gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) < 0) {
- break;
- }
- test_tcp_server_poll(pa->server, 1);
- }
- gpr_event_set(pa->signal_when_done, (void *)1);
- gpr_free(pa);
-}
-
-static void poll_server_until_read_done(test_tcp_server *server,
- gpr_event *signal_when_done) {
- gpr_atm_rel_store(&state.done_atm, 0);
- gpr_thd_id id;
- poll_args *pa = gpr_malloc(sizeof(*pa));
- pa->server = server;
- pa->signal_when_done = signal_when_done;
- gpr_thd_new(&id, actually_poll_server, pa, NULL);
-}
-
-static void match_initial_magic_string(grpc_slice_buffer *buffer) {
- size_t i, j, cmp_length;
- size_t magic_length = strlen(magic_connect_string);
- GPR_ASSERT(buffer->length >= magic_length);
- for (i = 0, j = 0; i < state.incoming_buffer.count && j < magic_length; i++) {
- char *dump = grpc_slice_to_c_string(state.incoming_buffer.slices[i]);
- cmp_length = GPR_MIN(strlen(dump), magic_length - j);
- GPR_ASSERT(strncmp(dump, magic_connect_string + j, cmp_length) == 0);
- j += cmp_length;
- gpr_free(dump);
- }
-}
-
-static void test_initial_string(test_tcp_server *server, int secure) {
- gpr_event ev;
- gpr_event_init(&ev);
- grpc_test_set_initial_connect_string_function(set_magic_initial_string);
- poll_server_until_read_done(server, &ev);
- start_rpc(secure, server_port);
- gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
- match_initial_magic_string(&state.incoming_buffer);
- cleanup_rpc();
-}
-
-static void test_initial_string_with_redirect(test_tcp_server *server,
- int secure) {
- gpr_event ev;
- gpr_event_init(&ev);
- int another_port = grpc_pick_unused_port_or_die();
- grpc_test_set_initial_connect_string_function(
- reset_addr_and_set_magic_string);
- poll_server_until_read_done(server, &ev);
- start_rpc(secure, another_port);
- gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
- match_initial_magic_string(&state.incoming_buffer);
- cleanup_rpc();
-}
-
-static void run_test(void (*test)(test_tcp_server *server, int secure),
- int secure) {
- test_tcp_server test_server;
- 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);
- test(&test_server, secure);
- test_tcp_server_destroy(&test_server);
-}
-
-int main(int argc, char **argv) {
- grpc_test_init(argc, argv);
- grpc_init();
-
- run_test(test_initial_string, 0);
- run_test(test_initial_string, 1);
- run_test(test_initial_string_with_redirect, 0);
- run_test(test_initial_string_with_redirect, 1);
-
- grpc_shutdown();
- return 0;
-}
diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c
index 39a98e84ca..c37a292af9 100644
--- a/test/core/end2end/bad_server_response_test.c
+++ b/test/core/end2end/bad_server_response_test.c
@@ -303,7 +303,7 @@ static void run_test(const char *response_payload,
/* clean up */
grpc_endpoint_shutdown(&exec_ctx, state.tcp,
- GRPC_ERROR_CREATE("Test Shutdown"));
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
grpc_endpoint_destroy(&exec_ctx, state.tcp);
cleanup_rpc(&exec_ctx);
grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/end2end/connection_refused_test.c b/test/core/end2end/connection_refused_test.c
index 16a3005539..6ded12ad48 100644
--- a/test/core/end2end/connection_refused_test.c
+++ b/test/core/end2end/connection_refused_test.c
@@ -53,7 +53,6 @@ static void *tag(intptr_t i) { return (void *)i; }
static void run_test(bool wait_for_ready, bool use_service_config) {
grpc_channel *chan;
grpc_call *call;
- gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2);
grpc_completion_queue *cq;
cq_verifier *cqv;
grpc_op ops[6];
@@ -98,6 +97,7 @@ static void run_test(bool wait_for_ready, bool use_service_config) {
gpr_log(GPR_INFO, "server: %s", addr);
chan = grpc_insecure_channel_create(addr, args, NULL);
grpc_slice host = grpc_slice_from_static_string("nonexistant");
+ gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2);
call = grpc_channel_create_call(
chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
grpc_slice_from_static_string("/service/method"), &host, deadline, NULL);
diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h
index cb0afd9cd9..cdb26a67e9 100644
--- a/test/core/end2end/end2end_tests.h
+++ b/test/core/end2end/end2end_tests.h
@@ -39,12 +39,15 @@
typedef struct grpc_end2end_test_fixture grpc_end2end_test_fixture;
typedef struct grpc_end2end_test_config grpc_end2end_test_config;
+/* Test feature flags. */
#define FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION 1
#define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION 2
#define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS 4
#define FEATURE_MASK_SUPPORTS_REQUEST_PROXYING 8
#define FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL 16
#define FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER 32
+#define FEATURE_MASK_DOES_NOT_SUPPORT_RESOURCE_QUOTA_SERVER 64
+#define FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE 128
#define FAIL_AUTH_CHECK_SERVER_ARG_NAME "fail_auth_check"
@@ -56,8 +59,12 @@ struct grpc_end2end_test_fixture {
};
struct grpc_end2end_test_config {
+ /* A descriptive name for this test fixture. */
const char *name;
+
+ /* Which features are supported by this fixture. See feature flags above. */
uint32_t feature_mask;
+
grpc_end2end_test_fixture (*create_fixture)(grpc_channel_args *client_args,
grpc_channel_args *server_args);
void (*init_client)(grpc_end2end_test_fixture *f,
diff --git a/test/core/end2end/fixtures/http_proxy_fixture.c b/test/core/end2end/fixtures/http_proxy_fixture.c
index bcd1c9914b..451ed268d3 100644
--- a/test/core/end2end/fixtures/http_proxy_fixture.c
+++ b/test/core/end2end/fixtures/http_proxy_fixture.c
@@ -342,7 +342,7 @@ static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg,
char* msg;
gpr_asprintf(&msg, "HTTP proxy got request method %s",
conn->http_request.method);
- error = GRPC_ERROR_CREATE(msg);
+ error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(msg);
proxy_connection_failed(exec_ctx, conn, true /* is_client */,
"HTTP proxy read request", error);
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index 0de8b9459a..a0acf5bf60 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -390,9 +390,9 @@ static void finish_resolve(grpc_exec_ctx *exec_ctx, void *arg,
*r->addrs = addrs;
grpc_closure_sched(exec_ctx, r->on_done, GRPC_ERROR_NONE);
} else {
- grpc_closure_sched(
- exec_ctx, r->on_done,
- GRPC_ERROR_CREATE_REFERENCING("Resolution failed", &error, 1));
+ grpc_closure_sched(exec_ctx, r->on_done,
+ GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+ "Resolution failed", &error, 1));
}
gpr_free(r->addr);
@@ -461,8 +461,8 @@ static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_endpoint **ep, gpr_timespec deadline) {
if (gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) < 0) {
*ep = NULL;
- grpc_closure_sched(exec_ctx, closure,
- GRPC_ERROR_CREATE("Connect deadline exceeded"));
+ grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Connect deadline exceeded"));
return;
}
@@ -719,10 +719,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
grpc_test_only_set_slice_hash_seed(0);
if (squelch) gpr_set_log_function(dont_log);
input_stream inp = {data, data + size};
- grpc_resolve_address = my_resolve_address;
grpc_tcp_client_connect_impl = my_tcp_client_connect;
gpr_now_impl = now_impl;
grpc_init();
+ grpc_resolve_address = my_resolve_address;
GPR_ASSERT(g_channel == NULL);
GPR_ASSERT(g_server == NULL);
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6723650944237568 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6723650944237568
new file mode 100644
index 0000000000..e140fdc705
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6723650944237568
Binary files differ
diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c
index a9634bfbae..22d93b321a 100644
--- a/test/core/end2end/goaway_server_test.c
+++ b/test/core/end2end/goaway_server_test.c
@@ -52,9 +52,11 @@ static void *tag(intptr_t i) { return (void *)i; }
static gpr_mu g_mu;
static int g_resolve_port = -1;
-static grpc_error *(*iomgr_resolve_address)(const char *name,
- const char *default_port,
- grpc_resolved_addresses **addrs);
+static void (*iomgr_resolve_address)(grpc_exec_ctx *exec_ctx, const char *addr,
+ const char *default_port,
+ grpc_pollset_set *interested_parties,
+ grpc_closure *on_done,
+ grpc_resolved_addresses **addresses);
static void set_resolve_port(int port) {
gpr_mu_lock(&g_mu);
@@ -62,16 +64,22 @@ static void set_resolve_port(int port) {
gpr_mu_unlock(&g_mu);
}
-static grpc_error *my_resolve_address(const char *name, const char *addr,
- grpc_resolved_addresses **addrs) {
- if (0 != strcmp(name, "test")) {
- return iomgr_resolve_address(name, addr, addrs);
+static void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr,
+ const char *default_port,
+ grpc_pollset_set *interested_parties,
+ grpc_closure *on_done,
+ grpc_resolved_addresses **addrs) {
+ if (0 != strcmp(addr, "test")) {
+ iomgr_resolve_address(exec_ctx, addr, default_port, interested_parties,
+ on_done, addrs);
+ return;
}
+ grpc_error *error = GRPC_ERROR_NONE;
gpr_mu_lock(&g_mu);
if (g_resolve_port < 0) {
gpr_mu_unlock(&g_mu);
- return GRPC_ERROR_CREATE("Forced Failure");
+ error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure");
} else {
*addrs = gpr_malloc(sizeof(**addrs));
(*addrs)->naddrs = 1;
@@ -83,8 +91,8 @@ static grpc_error *my_resolve_address(const char *name, const char *addr,
sa->sin_port = htons((uint16_t)g_resolve_port);
(*addrs)->addrs[0].len = sizeof(*sa);
gpr_mu_unlock(&g_mu);
- return GRPC_ERROR_NONE;
}
+ grpc_closure_sched(exec_ctx, on_done, error);
}
int main(int argc, char **argv) {
@@ -96,9 +104,9 @@ int main(int argc, char **argv) {
grpc_test_init(argc, argv);
gpr_mu_init(&g_mu);
- iomgr_resolve_address = grpc_blocking_resolve_address;
- grpc_blocking_resolve_address = my_resolve_address;
grpc_init();
+ iomgr_resolve_address = grpc_resolve_address;
+ grpc_resolve_address = my_resolve_address;
int was_cancelled1;
int was_cancelled2;
diff --git a/test/core/end2end/tests/filter_call_init_fails.c b/test/core/end2end/tests/filter_call_init_fails.c
index d2d6e82d57..ebfe3b03dc 100644
--- a/test/core/end2end/tests/filter_call_init_fails.c
+++ b/test/core/end2end/tests/filter_call_init_fails.c
@@ -206,14 +206,14 @@ static void test_request(grpc_end2end_test_config config) {
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_element_args *args) {
- return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"),
- GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_PERMISSION_DENIED);
+ return grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("access denied"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_PERMISSION_DENIED);
}
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {}
+ grpc_closure *ignored) {}
static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
index 25e606556d..e6b02eaeee 100644
--- a/test/core/end2end/tests/filter_causes_close.c
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -210,7 +210,7 @@ static void recv_im_ready(grpc_exec_ctx *exec_ctx, void *arg,
call_data *calld = elem->call_data;
grpc_closure_sched(
exec_ctx, calld->recv_im_ready,
- grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING(
+ grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Failure that's not preventable.", &error, 1),
GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_PERMISSION_DENIED));
@@ -236,7 +236,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {}
+ grpc_closure *ignored) {}
static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
diff --git a/test/core/end2end/tests/filter_latency.c b/test/core/end2end/tests/filter_latency.c
index d05e9e79a1..2428c92a42 100644
--- a/test/core/end2end/tests/filter_latency.c
+++ b/test/core/end2end/tests/filter_latency.c
@@ -267,7 +267,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {
+ grpc_closure *ignored) {
gpr_mu_lock(&g_mu);
g_client_latency = final_info->stats.latency;
gpr_mu_unlock(&g_mu);
@@ -276,7 +276,7 @@ static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {
+ grpc_closure *ignored) {
gpr_mu_lock(&g_mu);
g_server_latency = final_info->stats.latency;
gpr_mu_unlock(&g_mu);
diff --git a/test/core/end2end/tests/network_status_change.c b/test/core/end2end/tests/network_status_change.c
index 7540ce93a1..d7a4106459 100644
--- a/test/core/end2end/tests/network_status_change.c
+++ b/test/core/end2end/tests/network_status_change.c
@@ -240,6 +240,10 @@ static void test_invoke_network_status_change(grpc_end2end_test_config config) {
}
void network_status_change(grpc_end2end_test_config config) {
+ if (config.feature_mask &
+ FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE) {
+ return;
+ }
test_invoke_network_status_change(config);
}
diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c
index 4f9ed7a3a1..db26b4480e 100644
--- a/test/core/end2end/tests/resource_quota_server.c
+++ b/test/core/end2end/tests/resource_quota_server.c
@@ -113,6 +113,10 @@ static grpc_slice generate_random_slice() {
}
void resource_quota_server(grpc_end2end_test_config config) {
+ if (config.feature_mask &
+ FEATURE_MASK_DOES_NOT_SUPPORT_RESOURCE_QUOTA_SERVER) {
+ return;
+ }
grpc_resource_quota *resource_quota =
grpc_resource_quota_create("test_server");
grpc_resource_quota_resize(resource_quota, 5 * 1024 * 1024);
diff --git a/test/core/http/httpcli_test.c b/test/core/http/httpcli_test.c
index f690dbaffb..d3b45c4505 100644
--- a/test/core/http/httpcli_test.c
+++ b/test/core/http/httpcli_test.c
@@ -102,7 +102,7 @@ static void test_get(int port) {
"pollset_work",
grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
&worker, gpr_now(GPR_CLOCK_MONOTONIC),
- n_seconds_time(20))));
+ n_seconds_time(1))));
gpr_mu_unlock(g_mu);
grpc_exec_ctx_finish(&exec_ctx);
gpr_mu_lock(g_mu);
@@ -144,7 +144,7 @@ static void test_post(int port) {
"pollset_work",
grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
&worker, gpr_now(GPR_CLOCK_MONOTONIC),
- n_seconds_time(20))));
+ n_seconds_time(1))));
gpr_mu_unlock(g_mu);
grpc_exec_ctx_finish(&exec_ctx);
gpr_mu_lock(g_mu);
diff --git a/test/core/http/httpscli_test.c b/test/core/http/httpscli_test.c
index 549411037e..acc94091f4 100644
--- a/test/core/http/httpscli_test.c
+++ b/test/core/http/httpscli_test.c
@@ -103,7 +103,7 @@ static void test_get(int port) {
"pollset_work",
grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
&worker, gpr_now(GPR_CLOCK_MONOTONIC),
- n_seconds_time(20))));
+ n_seconds_time(1))));
gpr_mu_unlock(g_mu);
grpc_exec_ctx_finish(&exec_ctx);
gpr_mu_lock(g_mu);
@@ -146,7 +146,7 @@ static void test_post(int port) {
"pollset_work",
grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
&worker, gpr_now(GPR_CLOCK_MONOTONIC),
- n_seconds_time(20))));
+ n_seconds_time(1))));
gpr_mu_unlock(g_mu);
grpc_exec_ctx_finish(&exec_ctx);
gpr_mu_lock(g_mu);
diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c
index 94067a8ca4..e274796e23 100644
--- a/test/core/iomgr/endpoint_tests.c
+++ b/test/core/iomgr/endpoint_tests.c
@@ -233,11 +233,13 @@ static void read_and_write_test(grpc_endpoint_test_config config,
if (shutdown) {
gpr_log(GPR_DEBUG, "shutdown read");
- grpc_endpoint_shutdown(&exec_ctx, state.read_ep,
- GRPC_ERROR_CREATE("Test Shutdown"));
+ grpc_endpoint_shutdown(
+ &exec_ctx, state.read_ep,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
gpr_log(GPR_DEBUG, "shutdown write");
- grpc_endpoint_shutdown(&exec_ctx, state.write_ep,
- GRPC_ERROR_CREATE("Test Shutdown"));
+ grpc_endpoint_shutdown(
+ &exec_ctx, state.write_ep,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
}
grpc_exec_ctx_flush(&exec_ctx);
@@ -299,7 +301,7 @@ static void multiple_shutdown_test(grpc_endpoint_test_config config) {
grpc_schedule_on_exec_ctx));
wait_for_fail_count(&exec_ctx, &fail_count, 0);
grpc_endpoint_shutdown(&exec_ctx, f.client_ep,
- GRPC_ERROR_CREATE("Test Shutdown"));
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
wait_for_fail_count(&exec_ctx, &fail_count, 1);
grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer,
grpc_closure_create(inc_on_failure, &fail_count,
@@ -311,7 +313,7 @@ static void multiple_shutdown_test(grpc_endpoint_test_config config) {
grpc_schedule_on_exec_ctx));
wait_for_fail_count(&exec_ctx, &fail_count, 3);
grpc_endpoint_shutdown(&exec_ctx, f.client_ep,
- GRPC_ERROR_CREATE("Test Shutdown"));
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
wait_for_fail_count(&exec_ctx, &fail_count, 3);
grpc_slice_buffer_destroy_internal(&exec_ctx, &slice_buffer);
diff --git a/test/core/iomgr/error_test.c b/test/core/iomgr/error_test.c
index 2a6b1b17fd..5c60a4ddb8 100644
--- a/test/core/iomgr/error_test.c
+++ b/test/core/iomgr/error_test.c
@@ -44,7 +44,7 @@
#include "test/core/util/test_config.h"
static void test_set_get_int() {
- grpc_error* error = GRPC_ERROR_CREATE("Test");
+ grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test");
GPR_ASSERT(error);
intptr_t i = 0;
GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_FILE_LINE, &i));
@@ -66,26 +66,27 @@ static void test_set_get_int() {
}
static void test_set_get_str() {
- grpc_error* error = GRPC_ERROR_CREATE("Test");
+ grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test");
- GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL));
- GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_TSI_ERROR));
+ grpc_slice str;
+ GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str));
+ GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_TSI_ERROR, &str));
- const char* c = grpc_error_get_str(error, GRPC_ERROR_STR_FILE);
- GPR_ASSERT(c);
- GPR_ASSERT(strstr(c, "error_test.c")); // __FILE__ expands differently on
- // Windows. All should at least
- // contain error_test.c
+ GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_FILE, &str));
+ GPR_ASSERT(strstr((char*)GRPC_SLICE_START_PTR(str),
+ "error_test.c")); // __FILE__ expands differently on
+ // Windows. All should at least
+ // contain error_test.c
- c = grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION);
- GPR_ASSERT(c);
- GPR_ASSERT(!strcmp(c, "Test"));
+ GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str));
+ GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "Test",
+ GRPC_SLICE_LENGTH(str)));
- error =
- grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, "longer message");
- c = grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
- GPR_ASSERT(c);
- GPR_ASSERT(!strcmp(c, "longer message"));
+ error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
+ grpc_slice_from_static_string("longer message"));
+ GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
+ GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "longer message",
+ GRPC_SLICE_LENGTH(str)));
GRPC_ERROR_UNREF(error);
}
@@ -93,26 +94,28 @@ static void test_set_get_str() {
static void test_copy_and_unref() {
// error1 has one ref
grpc_error* error1 = grpc_error_set_str(
- GRPC_ERROR_CREATE("Test"), GRPC_ERROR_STR_GRPC_MESSAGE, "message");
- const char* c = grpc_error_get_str(error1, GRPC_ERROR_STR_GRPC_MESSAGE);
- GPR_ASSERT(c);
- GPR_ASSERT(!strcmp(c, "message"));
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"), GRPC_ERROR_STR_GRPC_MESSAGE,
+ grpc_slice_from_static_string("message"));
+ grpc_slice str;
+ GPR_ASSERT(grpc_error_get_str(error1, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
+ GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message",
+ GRPC_SLICE_LENGTH(str)));
// error 1 has two refs
GRPC_ERROR_REF(error1);
// this gives error3 a ref to the new error, and decrements error1 to one ref
- grpc_error* error3 =
- grpc_error_set_str(error1, GRPC_ERROR_STR_SYSCALL, "syscall");
+ grpc_error* error3 = grpc_error_set_str(
+ error1, GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string("syscall"));
GPR_ASSERT(error3 != error1); // should not be the same because of extra ref
- c = grpc_error_get_str(error3, GRPC_ERROR_STR_GRPC_MESSAGE);
- GPR_ASSERT(c);
- GPR_ASSERT(!strcmp(c, "message"));
+ GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
+ GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message",
+ GRPC_SLICE_LENGTH(str)));
// error 1 should not have a syscall but 3 should
- GPR_ASSERT(!grpc_error_get_str(error1, GRPC_ERROR_STR_SYSCALL));
- c = grpc_error_get_str(error3, GRPC_ERROR_STR_SYSCALL);
- GPR_ASSERT(c);
- GPR_ASSERT(!strcmp(c, "syscall"));
+ GPR_ASSERT(!grpc_error_get_str(error1, GRPC_ERROR_STR_SYSCALL, &str));
+ GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_SYSCALL, &str));
+ GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "syscall",
+ GRPC_SLICE_LENGTH(str)));
GRPC_ERROR_UNREF(error1);
GRPC_ERROR_UNREF(error3);
@@ -120,8 +123,10 @@ static void test_copy_and_unref() {
static void test_create_referencing() {
grpc_error* child = grpc_error_set_str(
- GRPC_ERROR_CREATE("Child"), GRPC_ERROR_STR_GRPC_MESSAGE, "message");
- grpc_error* parent = GRPC_ERROR_CREATE_REFERENCING("Parent", &child, 1);
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child"),
+ GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message"));
+ grpc_error* parent =
+ GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", &child, 1);
GPR_ASSERT(parent);
GRPC_ERROR_UNREF(child);
@@ -130,14 +135,18 @@ static void test_create_referencing() {
static void test_create_referencing_many() {
grpc_error* children[3];
- children[0] = grpc_error_set_str(GRPC_ERROR_CREATE("Child1"),
- GRPC_ERROR_STR_GRPC_MESSAGE, "message");
- children[1] = grpc_error_set_int(GRPC_ERROR_CREATE("Child2"),
- GRPC_ERROR_INT_HTTP2_ERROR, 5);
- children[2] = grpc_error_set_str(GRPC_ERROR_CREATE("Child3"),
- GRPC_ERROR_STR_GRPC_MESSAGE, "message 3");
-
- grpc_error* parent = GRPC_ERROR_CREATE_REFERENCING("Parent", children, 3);
+ children[0] = grpc_error_set_str(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child1"),
+ GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message"));
+ children[1] =
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child2"),
+ GRPC_ERROR_INT_HTTP2_ERROR, 5);
+ children[2] = grpc_error_set_str(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child3"),
+ GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message 3"));
+
+ grpc_error* parent =
+ GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 3);
GPR_ASSERT(parent);
for (size_t i = 0; i < 3; ++i) {
@@ -148,10 +157,11 @@ static void test_create_referencing_many() {
static void print_error_string() {
grpc_error* error =
- grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_UNIMPLEMENTED);
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED);
error = grpc_error_set_int(error, GRPC_ERROR_INT_SIZE, 666);
- error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, "message");
+ error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
+ grpc_slice_from_static_string("message"));
// gpr_log(GPR_DEBUG, "%s", grpc_error_string(error));
GRPC_ERROR_UNREF(error);
}
@@ -159,15 +169,18 @@ static void print_error_string() {
static void print_error_string_reference() {
grpc_error* children[2];
children[0] = grpc_error_set_str(
- grpc_error_set_int(GRPC_ERROR_CREATE("1"), GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_UNIMPLEMENTED),
- GRPC_ERROR_STR_GRPC_MESSAGE, "message for child 1");
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("1"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED),
+ GRPC_ERROR_STR_GRPC_MESSAGE,
+ grpc_slice_from_static_string("message for child 1"));
children[1] = grpc_error_set_str(
- grpc_error_set_int(GRPC_ERROR_CREATE("2sd"), GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_INTERNAL),
- GRPC_ERROR_STR_GRPC_MESSAGE, "message for child 2");
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("2sd"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL),
+ GRPC_ERROR_STR_GRPC_MESSAGE,
+ grpc_slice_from_static_string("message for child 2"));
- grpc_error* parent = GRPC_ERROR_CREATE_REFERENCING("Parent", children, 2);
+ grpc_error* parent =
+ GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 2);
gpr_log(GPR_DEBUG, "%s", grpc_error_string(parent));
@@ -186,15 +199,17 @@ static void test_os_error() {
GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
GPR_ASSERT(i == fake_errno);
- const char* c = grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL);
- GPR_ASSERT(c);
- GPR_ASSERT(!strcmp(c, syscall));
+ grpc_slice str;
+ GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str));
+ GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), syscall,
+ GRPC_SLICE_LENGTH(str)));
GRPC_ERROR_UNREF(error);
}
static void test_special() {
grpc_error* error = GRPC_ERROR_NONE;
- error = grpc_error_add_child(error, GRPC_ERROR_CREATE("test child"));
+ error = grpc_error_add_child(
+ error, GRPC_ERROR_CREATE_FROM_STATIC_STRING("test child"));
intptr_t i;
GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i));
GPR_ASSERT(i == GRPC_STATUS_OK);
diff --git a/test/core/iomgr/ev_epoll_linux_test.c b/test/core/iomgr/ev_epoll_linux_test.c
index 4ec959995b..d69f9a9d15 100644
--- a/test/core/iomgr/ev_epoll_linux_test.c
+++ b/test/core/iomgr/ev_epoll_linux_test.c
@@ -90,7 +90,7 @@ static void test_fd_cleanup(grpc_exec_ctx *exec_ctx, test_fd *tfds,
for (i = 0; i < num_fds; i++) {
grpc_fd_shutdown(exec_ctx, tfds[i].fd,
- GRPC_ERROR_CREATE("test_fd_cleanup"));
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_fd_cleanup"));
grpc_exec_ctx_flush(exec_ctx);
grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, "test_fd_cleanup");
diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c
index c1a0ef54d3..81d2692a08 100644
--- a/test/core/iomgr/fd_posix_test.c
+++ b/test/core/iomgr/fd_posix_test.c
@@ -133,7 +133,7 @@ static void session_shutdown_cb(grpc_exec_ctx *exec_ctx, void *arg, /*session */
gpr_free(se);
/* Start to shutdown listen fd. */
grpc_fd_shutdown(exec_ctx, sv->em_fd,
- GRPC_ERROR_CREATE("session_shutdown_cb"));
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("session_shutdown_cb"));
}
/* Called when data become readable in a session. */
diff --git a/test/core/iomgr/pollset_set_test.c b/test/core/iomgr/pollset_set_test.c
index f27e9db8c9..3a9d459579 100644
--- a/test/core/iomgr/pollset_set_test.c
+++ b/test/core/iomgr/pollset_set_test.c
@@ -143,7 +143,8 @@ static void cleanup_test_fds(grpc_exec_ctx *exec_ctx, test_fd *tfds,
int release_fd;
for (int i = 0; i < num_fds; i++) {
- grpc_fd_shutdown(exec_ctx, tfds[i].fd, GRPC_ERROR_CREATE("fd cleanup"));
+ grpc_fd_shutdown(exec_ctx, tfds[i].fd,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("fd cleanup"));
grpc_exec_ctx_flush(exec_ctx);
/* grpc_fd_orphan frees the memory allocated for grpc_fd. Normally it also
diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c
index b324b5a65e..2fae6774e8 100644
--- a/test/core/iomgr/tcp_client_posix_test.c
+++ b/test/core/iomgr/tcp_client_posix_test.c
@@ -77,8 +77,9 @@ static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
GPR_ASSERT(g_connecting != NULL);
GPR_ASSERT(error == GRPC_ERROR_NONE);
- grpc_endpoint_shutdown(exec_ctx, g_connecting,
- GRPC_ERROR_CREATE("must_succeed called"));
+ grpc_endpoint_shutdown(
+ exec_ctx, g_connecting,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called"));
grpc_endpoint_destroy(exec_ctx, g_connecting);
g_connecting = NULL;
finish_connection();
diff --git a/test/core/iomgr/tcp_client_uv_test.c b/test/core/iomgr/tcp_client_uv_test.c
index 064119f11b..92fc393422 100644
--- a/test/core/iomgr/tcp_client_uv_test.c
+++ b/test/core/iomgr/tcp_client_uv_test.c
@@ -73,8 +73,9 @@ static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
GPR_ASSERT(g_connecting != NULL);
GPR_ASSERT(error == GRPC_ERROR_NONE);
- grpc_endpoint_shutdown(exec_ctx, g_connecting,
- GRPC_ERROR_CREATE("must_succeed called"));
+ grpc_endpoint_shutdown(
+ exec_ctx, g_connecting,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called"));
grpc_endpoint_destroy(exec_ctx, g_connecting);
g_connecting = NULL;
finish_connection();
diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c
index 6e514324a5..112743b95b 100644
--- a/test/core/iomgr/tcp_server_posix_test.c
+++ b/test/core/iomgr/tcp_server_posix_test.c
@@ -163,7 +163,8 @@ static void test_addr_init_str(test_addr *addr) {
static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
grpc_pollset *pollset,
grpc_tcp_server_acceptor *acceptor) {
- grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_CREATE("Connected"));
+ grpc_endpoint_shutdown(exec_ctx, tcp,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected"));
grpc_endpoint_destroy(exec_ctx, tcp);
on_connect_result temp_result;
@@ -285,7 +286,7 @@ static grpc_error *tcp_connect(grpc_exec_ctx *exec_ctx, const test_addr *remote,
if (g_nconnects != nconnects_before + 1) {
gpr_mu_unlock(g_mu);
close(clifd);
- return GRPC_ERROR_CREATE("Didn't connect");
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Didn't connect");
}
close(clifd);
*result = g_result;
diff --git a/test/core/iomgr/tcp_server_uv_test.c b/test/core/iomgr/tcp_server_uv_test.c
index 0fc74599ea..1e039585c1 100644
--- a/test/core/iomgr/tcp_server_uv_test.c
+++ b/test/core/iomgr/tcp_server_uv_test.c
@@ -115,7 +115,8 @@ static void server_weak_ref_set(server_weak_ref *weak_ref,
static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
grpc_pollset *pollset,
grpc_tcp_server_acceptor *acceptor) {
- grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_CREATE("Connected"));
+ grpc_endpoint_shutdown(exec_ctx, tcp,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected"));
grpc_endpoint_destroy(exec_ctx, tcp);
on_connect_result temp_result;
diff --git a/test/core/iomgr/udp_server_test.c b/test/core/iomgr/udp_server_test.c
index 396ec959cd..12d8406323 100644
--- a/test/core/iomgr/udp_server_test.c
+++ b/test/core/iomgr/udp_server_test.c
@@ -48,9 +48,12 @@
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/socket_factory_posix.h"
#include "test/core/util/test_config.h"
#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x)
@@ -94,16 +97,59 @@ static void on_fd_orphaned(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
g_number_of_orphan_calls++;
}
+struct test_socket_factory {
+ grpc_socket_factory base;
+ int number_of_socket_calls;
+ int number_of_bind_calls;
+};
+typedef struct test_socket_factory test_socket_factory;
+
+static int test_socket_factory_socket(grpc_socket_factory *factory, int domain,
+ int type, int protocol) {
+ test_socket_factory *f = (test_socket_factory *)factory;
+ f->number_of_socket_calls++;
+ return socket(domain, type, protocol);
+}
+
+static int test_socket_factory_bind(grpc_socket_factory *factory, int sockfd,
+ const grpc_resolved_address *addr) {
+ test_socket_factory *f = (test_socket_factory *)factory;
+ f->number_of_bind_calls++;
+ return bind(sockfd, (struct sockaddr *)addr->addr, (socklen_t)addr->len);
+}
+
+static int test_socket_factory_compare(grpc_socket_factory *a,
+ grpc_socket_factory *b) {
+ return GPR_ICMP(a, b);
+}
+
+static void test_socket_factory_destroy(grpc_socket_factory *factory) {
+ test_socket_factory *f = (test_socket_factory *)factory;
+ gpr_free(f);
+}
+
+static const grpc_socket_factory_vtable test_socket_factory_vtable = {
+ test_socket_factory_socket, test_socket_factory_bind,
+ test_socket_factory_compare, test_socket_factory_destroy};
+
+static test_socket_factory *test_socket_factory_create(void) {
+ test_socket_factory *factory = gpr_malloc(sizeof(test_socket_factory));
+ grpc_socket_factory_init(&factory->base, &test_socket_factory_vtable);
+ factory->number_of_socket_calls = 0;
+ factory->number_of_bind_calls = 0;
+ return factory;
+}
+
static void test_no_op(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_udp_server *s = grpc_udp_server_create();
+ grpc_udp_server *s = grpc_udp_server_create(NULL);
grpc_udp_server_destroy(&exec_ctx, s, NULL);
grpc_exec_ctx_finish(&exec_ctx);
}
static void test_no_op_with_start(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_udp_server *s = grpc_udp_server_create();
+ grpc_udp_server *s = grpc_udp_server_create(NULL);
LOG_TEST("test_no_op_with_start");
grpc_udp_server_start(&exec_ctx, s, NULL, 0, NULL);
grpc_udp_server_destroy(&exec_ctx, s, NULL);
@@ -115,7 +161,7 @@ static void test_no_op_with_port(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_resolved_address resolved_addr;
struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr;
- grpc_udp_server *s = grpc_udp_server_create();
+ grpc_udp_server *s = grpc_udp_server_create(NULL);
LOG_TEST("test_no_op_with_port");
memset(&resolved_addr, 0, sizeof(resolved_addr));
@@ -131,12 +177,44 @@ static void test_no_op_with_port(void) {
GPR_ASSERT(g_number_of_orphan_calls == 1);
}
+static void test_no_op_with_port_and_socket_factory(void) {
+ g_number_of_orphan_calls = 0;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_resolved_address resolved_addr;
+ struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr;
+
+ test_socket_factory *socket_factory = test_socket_factory_create();
+ grpc_arg socket_factory_arg =
+ grpc_socket_factory_to_arg(&socket_factory->base);
+ grpc_channel_args *channel_args =
+ grpc_channel_args_copy_and_add(NULL, &socket_factory_arg, 1);
+ grpc_udp_server *s = grpc_udp_server_create(channel_args);
+ grpc_channel_args_destroy(&exec_ctx, channel_args);
+
+ LOG_TEST("test_no_op_with_port_and_socket_factory");
+
+ memset(&resolved_addr, 0, sizeof(resolved_addr));
+ resolved_addr.len = sizeof(struct sockaddr_in);
+ addr->sin_family = AF_INET;
+ GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write,
+ on_fd_orphaned));
+ GPR_ASSERT(socket_factory->number_of_socket_calls == 1);
+ GPR_ASSERT(socket_factory->number_of_bind_calls == 1);
+
+ grpc_udp_server_destroy(&exec_ctx, s, NULL);
+ grpc_exec_ctx_finish(&exec_ctx);
+ grpc_socket_factory_unref(&socket_factory->base);
+
+ /* The server had a single FD, which should have been orphaned. */
+ GPR_ASSERT(g_number_of_orphan_calls == 1);
+}
+
static void test_no_op_with_port_and_start(void) {
g_number_of_orphan_calls = 0;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_resolved_address resolved_addr;
struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr;
- grpc_udp_server *s = grpc_udp_server_create();
+ grpc_udp_server *s = grpc_udp_server_create(NULL);
LOG_TEST("test_no_op_with_port_and_start");
memset(&resolved_addr, 0, sizeof(resolved_addr));
@@ -160,7 +238,7 @@ static void test_receive(int number_of_clients) {
grpc_resolved_address resolved_addr;
struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr;
int clifd, svrfd;
- grpc_udp_server *s = grpc_udp_server_create();
+ grpc_udp_server *s = grpc_udp_server_create(NULL);
int i;
int number_of_reads_before;
gpr_timespec deadline;
@@ -243,6 +321,7 @@ int main(int argc, char **argv) {
test_no_op();
test_no_op_with_start();
test_no_op_with_port();
+ test_no_op_with_port_and_socket_factory();
test_no_op_with_port_and_start();
test_receive(1);
test_receive(10);
diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c
index 107abbc1b3..51ea51bc12 100644
--- a/test/core/memory_usage/client.c
+++ b/test/core/memory_usage/client.c
@@ -237,6 +237,11 @@ int main(int argc, char **argv) {
0, grpc_slice_from_static_string("Reflector/GetAfterSvrCreation"));
// warmup period
+ for (int i = 0; i < warmup_iterations; i++) {
+ send_snapshot_request(
+ 0, grpc_slice_from_static_string("Reflector/SimpleSnapshot"));
+ }
+
for (call_idx = 0; call_idx < warmup_iterations; ++call_idx) {
init_ping_pong_request(call_idx + 1);
}
diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c
index d2b76bae39..b3775e91a7 100644
--- a/test/core/security/secure_endpoint_test.c
+++ b/test/core/security/secure_endpoint_test.c
@@ -166,10 +166,12 @@ static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) {
GPR_ASSERT(incoming.count == 1);
GPR_ASSERT(grpc_slice_eq(s, incoming.slices[0]));
- grpc_endpoint_shutdown(&exec_ctx, f.client_ep,
- GRPC_ERROR_CREATE("test_leftover end"));
- grpc_endpoint_shutdown(&exec_ctx, f.server_ep,
- GRPC_ERROR_CREATE("test_leftover end"));
+ grpc_endpoint_shutdown(
+ &exec_ctx, f.client_ep,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_leftover end"));
+ grpc_endpoint_shutdown(
+ &exec_ctx, f.server_ep,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_leftover end"));
grpc_endpoint_destroy(&exec_ctx, f.client_ep);
grpc_endpoint_destroy(&exec_ctx, f.server_ep);
grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/security/ssl_server_fuzzer.c b/test/core/security/ssl_server_fuzzer.c
index 7a3612c419..cbbaf9f298 100644
--- a/test/core/security/ssl_server_fuzzer.c
+++ b/test/core/security/ssl_server_fuzzer.c
@@ -115,8 +115,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// server will wait for more data. Explicitly fail the server by shutting down
// the endpoint.
if (!state.done_callback_called) {
- grpc_endpoint_shutdown(&exec_ctx, mock_endpoint,
- GRPC_ERROR_CREATE("Explicit close"));
+ grpc_endpoint_shutdown(
+ &exec_ctx, mock_endpoint,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Explicit close"));
grpc_exec_ctx_flush(&exec_ctx);
}
diff --git a/test/core/support/cpu_test.c b/test/core/support/cpu_test.c
index ca0fe0ccb5..7b9bf6c5e1 100644
--- a/test/core/support/cpu_test.c
+++ b/test/core/support/cpu_test.c
@@ -81,9 +81,12 @@ static void worker_thread(void *arg) {
uint32_t cpu;
unsigned r = 12345678;
unsigned i, j;
- for (i = 0; i < 1000 / grpc_test_slowdown_factor(); i++) {
+ /* Avoid repetitive division calculations */
+ int64_t max_i = 1000 / grpc_test_slowdown_factor();
+ int64_t max_j = 1000000 / grpc_test_slowdown_factor();
+ for (i = 0; i < max_i; i++) {
/* run for a bit - just calculate something random. */
- for (j = 0; j < 1000000 / grpc_test_slowdown_factor(); j++) {
+ for (j = 0; j < max_j; j++) {
r = (r * 17) & ((r - i) | (r * i));
}
cpu = gpr_cpu_current_cpu();
diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c
index ff927385d4..2f7c3dfb85 100644
--- a/test/core/surface/concurrent_connectivity_test.c
+++ b/test/core/surface/concurrent_connectivity_test.c
@@ -109,7 +109,8 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *vargs, grpc_endpoint *tcp,
grpc_tcp_server_acceptor *acceptor) {
gpr_free(acceptor);
struct server_thread_args *args = (struct server_thread_args *)vargs;
- grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_CREATE("Connected"));
+ grpc_endpoint_shutdown(exec_ctx, tcp,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected"));
grpc_endpoint_destroy(exec_ctx, tcp);
GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL));
}
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112 b/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112
new file mode 100644
index 0000000000..04d48d6d76
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112
Binary files differ
diff --git a/test/core/util/mock_endpoint.c b/test/core/util/mock_endpoint.c
index b8fed7e14b..c747297984 100644
--- a/test/core/util/mock_endpoint.c
+++ b/test/core/util/mock_endpoint.c
@@ -89,8 +89,9 @@ static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep;
gpr_mu_lock(&m->mu);
if (m->on_read) {
- grpc_closure_sched(exec_ctx, m->on_read, GRPC_ERROR_CREATE_REFERENCING(
- "Endpoint Shutdown", &why, 1));
+ grpc_closure_sched(exec_ctx, m->on_read,
+ GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+ "Endpoint Shutdown", &why, 1));
m->on_read = NULL;
}
gpr_mu_unlock(&m->mu);
diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c
index 5f27f9ae73..121567fc0d 100644
--- a/test/core/util/passthru_endpoint.c
+++ b/test/core/util/passthru_endpoint.c
@@ -75,7 +75,8 @@ static void me_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
half *m = (half *)ep;
gpr_mu_lock(&m->parent->mu);
if (m->parent->shutdown) {
- grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_CREATE("Already shutdown"));
+ grpc_closure_sched(
+ exec_ctx, cb, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already shutdown"));
} else if (m->read_buffer.count > 0) {
grpc_slice_buffer_swap(&m->read_buffer, slices);
grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_NONE);
@@ -98,7 +99,7 @@ static void me_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_error *error = GRPC_ERROR_NONE;
m->parent->stats->num_writes++;
if (m->parent->shutdown) {
- error = GRPC_ERROR_CREATE("Endpoint already shutdown");
+ error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Endpoint already shutdown");
} else if (m->on_read != NULL) {
for (size_t i = 0; i < slices->count; i++) {
grpc_slice_buffer_add(m->on_read_out, grpc_slice_ref(slices->slices[i]));
@@ -126,14 +127,16 @@ static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_mu_lock(&m->parent->mu);
m->parent->shutdown = true;
if (m->on_read) {
- grpc_closure_sched(exec_ctx, m->on_read,
- GRPC_ERROR_CREATE_REFERENCING("Shutdown", &why, 1));
+ grpc_closure_sched(
+ exec_ctx, m->on_read,
+ GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Shutdown", &why, 1));
m->on_read = NULL;
}
m = other_half(m);
if (m->on_read) {
- grpc_closure_sched(exec_ctx, m->on_read,
- GRPC_ERROR_CREATE_REFERENCING("Shutdown", &why, 1));
+ grpc_closure_sched(
+ exec_ctx, m->on_read,
+ GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Shutdown", &why, 1));
m->on_read = NULL;
}
gpr_mu_unlock(&m->parent->mu);
diff --git a/test/core/util/reconnect_server.c b/test/core/util/reconnect_server.c
index 7fbd0ca6aa..90af1c107b 100644
--- a/test/core/util/reconnect_server.c
+++ b/test/core/util/reconnect_server.c
@@ -80,7 +80,8 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
timestamp_list *new_tail;
peer = grpc_endpoint_get_peer(tcp);
- grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_CREATE("Connected"));
+ grpc_endpoint_shutdown(exec_ctx, tcp,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected"));
grpc_endpoint_destroy(exec_ctx, tcp);
if (peer) {
last_colon = strrchr(peer, ':');
diff --git a/test/cpp/common/channel_arguments_test.cc b/test/cpp/common/channel_arguments_test.cc
index 190d32ce06..8e7b56cbd6 100644
--- a/test/cpp/common/channel_arguments_test.cc
+++ b/test/cpp/common/channel_arguments_test.cc
@@ -230,13 +230,6 @@ TEST_F(ChannelArgumentsTest, SetSocketMutator) {
EXPECT_TRUE(HasArg(arg1));
// arg0 is replaced by arg1
EXPECT_FALSE(HasArg(arg0));
-
- // arg0 is destroyed by grpc_socket_mutator_to_arg(mutator1)
- {
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- arg1.value.pointer.vtable->destroy(&exec_ctx, arg1.value.pointer.p);
- grpc_exec_ctx_finish(&exec_ctx);
- }
}
TEST_F(ChannelArgumentsTest, SetUserAgentPrefix) {
@@ -250,6 +243,22 @@ TEST_F(ChannelArgumentsTest, SetUserAgentPrefix) {
channel_args_.SetUserAgentPrefix(prefix);
EXPECT_TRUE(HasArg(arg0));
+
+ // Test if the user agent string is copied correctly
+ ChannelArguments new_channel_args(channel_args_);
+ grpc_channel_args args;
+ SetChannelArgs(new_channel_args, &args);
+ bool found = false;
+ for (size_t i = 0; i < args.num_args; i++) {
+ const grpc_arg& arg = args.args[i];
+ if (arg.type == GRPC_ARG_STRING &&
+ grpc::string(arg.key) == GRPC_ARG_PRIMARY_USER_AGENT_STRING) {
+ EXPECT_FALSE(found);
+ EXPECT_EQ(0, strcmp(arg.value.string, arg0.value.string));
+ found = true;
+ }
+ }
+ EXPECT_TRUE(found);
}
} // namespace testing
diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc
index 014e2b96b5..1ef8caa690 100644
--- a/test/cpp/microbenchmarks/bm_call_create.cc
+++ b/test/cpp/microbenchmarks/bm_call_create.cc
@@ -53,6 +53,7 @@ extern "C" {
#include "src/core/lib/channel/http_client_filter.h"
#include "src/core/lib/channel/http_server_filter.h"
#include "src/core/lib/channel/message_size_filter.h"
+#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/transport_impl.h"
}
@@ -85,6 +86,9 @@ BENCHMARK(BM_Zalloc)
->Arg(6144)
->Arg(7168);
+////////////////////////////////////////////////////////////////////////////////
+// Benchmarks creating full stacks
+
class BaseChannelFixture {
public:
BaseChannelFixture(grpc_channel *channel) : channel_(channel) {}
@@ -130,6 +134,9 @@ static void BM_CallCreateDestroy(benchmark::State &state) {
BENCHMARK_TEMPLATE(BM_CallCreateDestroy, InsecureChannel);
BENCHMARK_TEMPLATE(BM_CallCreateDestroy, LameChannel);
+////////////////////////////////////////////////////////////////////////////////
+// Benchmarks isolating individual filters
+
static void *tag(int i) {
return reinterpret_cast<void *>(static_cast<intptr_t>(i));
}
@@ -232,7 +239,7 @@ static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
static void DestroyCallElem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {}
+ grpc_closure *then_sched_closure) {}
grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_channel_element_args *args) {
@@ -275,7 +282,7 @@ const char *name;
/* implementation of grpc_transport_init_stream */
int InitStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, grpc_stream_refcount *refcount,
- const void *server_data) {
+ const void *server_data, gpr_arena *arena) {
return 0;
}
@@ -299,7 +306,7 @@ void PerformOp(grpc_exec_ctx *exec_ctx, grpc_transport *self,
/* implementation of grpc_transport_destroy_stream */
void DestroyStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
- grpc_stream *stream, void *and_free_memory) {}
+ grpc_stream *stream, grpc_closure *then_sched_closure) {}
/* implementation of grpc_transport_destroy */
void Destroy(grpc_exec_ctx *exec_ctx, grpc_transport *self) {}
@@ -394,7 +401,7 @@ static void BM_IsolatedFilter(benchmark::State &state) {
grpc_channel_stack *channel_stack =
static_cast<grpc_channel_stack *>(gpr_zalloc(channel_size));
GPR_ASSERT(GRPC_LOG_IF_ERROR(
- "call_stack_init",
+ "channel_stack_init",
grpc_channel_stack_init(&exec_ctx, 1, FilterDestroy, channel_stack,
&filters[0], filters.size(), &channel_args,
fixture.flags & REQUIRES_TRANSPORT
@@ -409,15 +416,29 @@ static void BM_IsolatedFilter(benchmark::State &state) {
grpc_slice method = grpc_slice_from_static_string("/foo/bar");
grpc_call_final_info final_info;
TestOp test_op_data;
+ grpc_call_element_args call_args;
+ call_args.call_stack = call_stack;
+ call_args.server_transport_data = NULL;
+ call_args.context = NULL;
+ call_args.path = method;
+ call_args.start_time = start_time;
+ call_args.deadline = deadline;
+ const int kArenaSize = 4096;
+ call_args.arena = gpr_arena_create(kArenaSize);
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(grpc_call_stack_init(&exec_ctx, channel_stack, 1,
- DoNothing, NULL, NULL, NULL, method,
- start_time, deadline, call_stack));
+ DoNothing, NULL, &call_args));
typename TestOp::Op op(&exec_ctx, &test_op_data, call_stack);
grpc_call_stack_destroy(&exec_ctx, call_stack, &final_info, NULL);
op.Finish(&exec_ctx);
grpc_exec_ctx_flush(&exec_ctx);
+ // recreate arena every 64k iterations to avoid oom
+ if (0 == (state.iterations() & 0xffff)) {
+ gpr_arena_destroy(call_args.arena);
+ call_args.arena = gpr_arena_create(kArenaSize);
+ }
}
+ gpr_arena_destroy(call_args.arena);
grpc_channel_stack_destroy(&exec_ctx, channel_stack);
grpc_exec_ctx_finish(&exec_ctx);
gpr_free(channel_stack);
@@ -460,4 +481,205 @@ typedef Fixture<&grpc_load_reporting_filter, CHECKS_NOT_LAST>
BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, SendEmptyMetadata);
+////////////////////////////////////////////////////////////////////////////////
+// Benchmarks isolating grpc_call
+
+namespace isolated_call_filter {
+
+static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_transport_stream_op *op) {
+ if (op->recv_initial_metadata) {
+ grpc_closure_sched(exec_ctx, op->recv_initial_metadata_ready,
+ GRPC_ERROR_NONE);
+ }
+ if (op->recv_message) {
+ grpc_closure_sched(exec_ctx, op->recv_message_ready, GRPC_ERROR_NONE);
+ }
+ grpc_closure_sched(exec_ctx, op->on_complete, GRPC_ERROR_NONE);
+}
+
+static void StartTransportOp(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ grpc_transport_op *op) {
+ if (op->disconnect_with_error != GRPC_ERROR_NONE) {
+ GRPC_ERROR_UNREF(op->disconnect_with_error);
+ }
+ grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
+}
+
+static grpc_error *InitCallElem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ const grpc_call_element_args *args) {
+ return GRPC_ERROR_NONE;
+}
+
+static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_polling_entity *pollent) {}
+
+static void DestroyCallElem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+ const grpc_call_final_info *final_info,
+ grpc_closure *then_sched_closure) {
+ grpc_closure_sched(exec_ctx, then_sched_closure, GRPC_ERROR_NONE);
+}
+
+grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
+ grpc_channel_element_args *args) {
+ return GRPC_ERROR_NONE;
+}
+
+void DestroyChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {}
+
+char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+ return gpr_strdup("peer");
+}
+
+void GetChannelInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
+ const grpc_channel_info *channel_info) {}
+
+static const grpc_channel_filter isolated_call_filter = {
+ StartTransportStreamOp,
+ StartTransportOp,
+ 0,
+ InitCallElem,
+ SetPollsetOrPollsetSet,
+ DestroyCallElem,
+ 0,
+ InitChannelElem,
+ DestroyChannelElem,
+ GetPeer,
+ GetChannelInfo,
+ "isolated_call_filter"};
+}
+
+class IsolatedCallFixture : public TrackCounters {
+ public:
+ IsolatedCallFixture() {
+ grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create();
+ grpc_channel_stack_builder_set_name(builder, "dummy");
+ grpc_channel_stack_builder_set_target(builder, "dummy_target");
+ GPR_ASSERT(grpc_channel_stack_builder_append_filter(
+ builder, &isolated_call_filter::isolated_call_filter, NULL, NULL));
+ {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ channel_ = grpc_channel_create_with_builder(&exec_ctx, builder,
+ GRPC_CLIENT_CHANNEL);
+ grpc_exec_ctx_finish(&exec_ctx);
+ }
+ cq_ = grpc_completion_queue_create(NULL);
+ }
+
+ void Finish(benchmark::State &state) {
+ grpc_completion_queue_destroy(cq_);
+ grpc_channel_destroy(channel_);
+ TrackCounters::Finish(state);
+ }
+
+ grpc_channel *channel() const { return channel_; }
+ grpc_completion_queue *cq() const { return cq_; }
+
+ private:
+ grpc_completion_queue *cq_;
+ grpc_channel *channel_;
+};
+
+static void BM_IsolatedCall_NoOp(benchmark::State &state) {
+ IsolatedCallFixture fixture;
+ gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+ void *method_hdl =
+ grpc_channel_register_call(fixture.channel(), "/foo/bar", NULL, NULL);
+ while (state.KeepRunning()) {
+ grpc_call_destroy(grpc_channel_create_registered_call(
+ fixture.channel(), nullptr, GRPC_PROPAGATE_DEFAULTS, fixture.cq(),
+ method_hdl, deadline, NULL));
+ }
+ fixture.Finish(state);
+}
+BENCHMARK(BM_IsolatedCall_NoOp);
+
+static void BM_IsolatedCall_Unary(benchmark::State &state) {
+ IsolatedCallFixture fixture;
+ gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+ void *method_hdl =
+ grpc_channel_register_call(fixture.channel(), "/foo/bar", NULL, NULL);
+ grpc_slice slice = grpc_slice_from_static_string("hello world");
+ grpc_byte_buffer *send_message = grpc_raw_byte_buffer_create(&slice, 1);
+ grpc_byte_buffer *recv_message = NULL;
+ grpc_status_code status_code;
+ grpc_slice status_details = grpc_empty_slice();
+ grpc_metadata_array recv_initial_metadata;
+ grpc_metadata_array_init(&recv_initial_metadata);
+ grpc_metadata_array recv_trailing_metadata;
+ grpc_metadata_array_init(&recv_trailing_metadata);
+ grpc_op ops[6];
+ memset(ops, 0, sizeof(ops));
+ ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
+ ops[1].op = GRPC_OP_SEND_MESSAGE;
+ ops[1].data.send_message.send_message = send_message;
+ ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+ ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
+ ops[3].data.recv_initial_metadata.recv_initial_metadata =
+ &recv_initial_metadata;
+ ops[4].op = GRPC_OP_RECV_MESSAGE;
+ ops[4].data.recv_message.recv_message = &recv_message;
+ ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+ ops[5].data.recv_status_on_client.status = &status_code;
+ ops[5].data.recv_status_on_client.status_details = &status_details;
+ ops[5].data.recv_status_on_client.trailing_metadata = &recv_trailing_metadata;
+ while (state.KeepRunning()) {
+ grpc_call *call = grpc_channel_create_registered_call(
+ fixture.channel(), nullptr, GRPC_PROPAGATE_DEFAULTS, fixture.cq(),
+ method_hdl, deadline, NULL);
+ grpc_call_start_batch(call, ops, 6, tag(1), NULL);
+ grpc_completion_queue_next(fixture.cq(),
+ gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL);
+ grpc_call_destroy(call);
+ }
+ fixture.Finish(state);
+ grpc_metadata_array_destroy(&recv_initial_metadata);
+ grpc_metadata_array_destroy(&recv_trailing_metadata);
+ grpc_byte_buffer_destroy(send_message);
+}
+BENCHMARK(BM_IsolatedCall_Unary);
+
+static void BM_IsolatedCall_StreamingSend(benchmark::State &state) {
+ IsolatedCallFixture fixture;
+ gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+ void *method_hdl =
+ grpc_channel_register_call(fixture.channel(), "/foo/bar", NULL, NULL);
+ grpc_slice slice = grpc_slice_from_static_string("hello world");
+ grpc_byte_buffer *send_message = grpc_raw_byte_buffer_create(&slice, 1);
+ grpc_metadata_array recv_initial_metadata;
+ grpc_metadata_array_init(&recv_initial_metadata);
+ grpc_metadata_array recv_trailing_metadata;
+ grpc_metadata_array_init(&recv_trailing_metadata);
+ grpc_op ops[2];
+ memset(ops, 0, sizeof(ops));
+ ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
+ ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
+ ops[1].data.recv_initial_metadata.recv_initial_metadata =
+ &recv_initial_metadata;
+ grpc_call *call = grpc_channel_create_registered_call(
+ fixture.channel(), nullptr, GRPC_PROPAGATE_DEFAULTS, fixture.cq(),
+ method_hdl, deadline, NULL);
+ grpc_call_start_batch(call, ops, 2, tag(1), NULL);
+ grpc_completion_queue_next(fixture.cq(), gpr_inf_future(GPR_CLOCK_MONOTONIC),
+ NULL);
+ memset(ops, 0, sizeof(ops));
+ ops[0].op = GRPC_OP_SEND_MESSAGE;
+ ops[0].data.send_message.send_message = send_message;
+ while (state.KeepRunning()) {
+ grpc_call_start_batch(call, ops, 1, tag(2), NULL);
+ grpc_completion_queue_next(fixture.cq(),
+ gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL);
+ }
+ grpc_call_destroy(call);
+ fixture.Finish(state);
+ grpc_metadata_array_destroy(&recv_initial_metadata);
+ grpc_metadata_array_destroy(&recv_trailing_metadata);
+ grpc_byte_buffer_destroy(send_message);
+}
+BENCHMARK(BM_IsolatedCall_StreamingSend);
+
BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
new file mode 100644
index 0000000000..254d57de20
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
@@ -0,0 +1,587 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Microbenchmarks around CHTTP2 transport operations */
+
+#include <grpc++/support/channel_arguments.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <string.h>
+#include <memory>
+#include <queue>
+#include <sstream>
+extern "C" {
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+#include "src/core/lib/iomgr/resource_quota.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/transport/static_metadata.h"
+}
+#include "test/cpp/microbenchmarks/helpers.h"
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+auto &force_library_initialization = Library::get();
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper classes
+//
+
+class DummyEndpoint : public grpc_endpoint {
+ public:
+ DummyEndpoint() {
+ static const grpc_endpoint_vtable my_vtable = {read,
+ write,
+ get_workqueue,
+ add_to_pollset,
+ add_to_pollset_set,
+ shutdown,
+ destroy,
+ get_resource_user,
+ get_peer,
+ get_fd};
+ grpc_endpoint::vtable = &my_vtable;
+ ru_ = grpc_resource_user_create(Library::get().rq(), "dummy_endpoint");
+ }
+
+ void PushInput(grpc_exec_ctx *exec_ctx, grpc_slice slice) {
+ if (read_cb_ == nullptr) {
+ GPR_ASSERT(!have_slice_);
+ buffered_slice_ = slice;
+ have_slice_ = true;
+ return;
+ }
+ grpc_slice_buffer_add(slices_, slice);
+ grpc_closure_sched(exec_ctx, read_cb_, GRPC_ERROR_NONE);
+ read_cb_ = nullptr;
+ }
+
+ private:
+ grpc_resource_user *ru_;
+ grpc_closure *read_cb_ = nullptr;
+ grpc_slice_buffer *slices_ = nullptr;
+ bool have_slice_ = false;
+ grpc_slice buffered_slice_;
+
+ void QueueRead(grpc_exec_ctx *exec_ctx, grpc_slice_buffer *slices,
+ grpc_closure *cb) {
+ GPR_ASSERT(read_cb_ == nullptr);
+ if (have_slice_) {
+ have_slice_ = false;
+ grpc_slice_buffer_add(slices, buffered_slice_);
+ grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_NONE);
+ return;
+ }
+ read_cb_ = cb;
+ slices_ = slices;
+ }
+
+ static void read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+ grpc_slice_buffer *slices, grpc_closure *cb) {
+ static_cast<DummyEndpoint *>(ep)->QueueRead(exec_ctx, slices, cb);
+ }
+
+ static void write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+ grpc_slice_buffer *slices, grpc_closure *cb) {
+ grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_NONE);
+ }
+
+ static grpc_workqueue *get_workqueue(grpc_endpoint *ep) { return NULL; }
+
+ static void add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+ grpc_pollset *pollset) {}
+
+ static void add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+ grpc_pollset_set *pollset) {}
+
+ static void shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+ grpc_error *why) {
+ grpc_resource_user_shutdown(exec_ctx,
+ static_cast<DummyEndpoint *>(ep)->ru_);
+ grpc_closure_sched(exec_ctx, static_cast<DummyEndpoint *>(ep)->read_cb_,
+ why);
+ }
+
+ static void destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+ grpc_resource_user_unref(exec_ctx, static_cast<DummyEndpoint *>(ep)->ru_);
+ delete static_cast<DummyEndpoint *>(ep);
+ }
+
+ static grpc_resource_user *get_resource_user(grpc_endpoint *ep) {
+ return static_cast<DummyEndpoint *>(ep)->ru_;
+ }
+ static char *get_peer(grpc_endpoint *ep) { return gpr_strdup("test"); }
+ static int get_fd(grpc_endpoint *ep) { return 0; }
+};
+
+class Fixture {
+ public:
+ Fixture(const grpc::ChannelArguments &args, bool client) {
+ grpc_channel_args c_args = args.c_channel_args();
+ ep_ = new DummyEndpoint;
+ t_ = grpc_create_chttp2_transport(exec_ctx(), &c_args, ep_, client);
+ grpc_chttp2_transport_start_reading(exec_ctx(), t_, NULL);
+ FlushExecCtx();
+ }
+
+ void FlushExecCtx() { grpc_exec_ctx_flush(&exec_ctx_); }
+
+ ~Fixture() {
+ grpc_transport_destroy(&exec_ctx_, t_);
+ grpc_exec_ctx_finish(&exec_ctx_);
+ }
+
+ grpc_chttp2_transport *chttp2_transport() {
+ return reinterpret_cast<grpc_chttp2_transport *>(t_);
+ }
+ grpc_transport *transport() { return t_; }
+ grpc_exec_ctx *exec_ctx() { return &exec_ctx_; }
+
+ void PushInput(grpc_slice slice) { ep_->PushInput(exec_ctx(), slice); }
+
+ private:
+ DummyEndpoint *ep_;
+ grpc_exec_ctx exec_ctx_ = GRPC_EXEC_CTX_INIT;
+ grpc_transport *t_;
+};
+
+static void DoNothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
+
+class Stream {
+ public:
+ Stream(Fixture *f) : f_(f) {
+ GRPC_STREAM_REF_INIT(&refcount_, 1, DoNothing, nullptr, "test_stream");
+ stream_size_ = grpc_transport_stream_size(f->transport());
+ stream_ = gpr_malloc(stream_size_);
+ arena_ = gpr_arena_create(4096);
+ }
+
+ ~Stream() {
+ gpr_free(stream_);
+ gpr_arena_destroy(arena_);
+ }
+
+ void Init(benchmark::State &state) {
+ memset(stream_, 0, stream_size_);
+ if ((state.iterations() & 0xffff) == 0) {
+ gpr_arena_destroy(arena_);
+ arena_ = gpr_arena_create(4096);
+ }
+ grpc_transport_init_stream(f_->exec_ctx(), f_->transport(),
+ static_cast<grpc_stream *>(stream_), &refcount_,
+ NULL, arena_);
+ }
+
+ void DestroyThen(grpc_closure *closure) {
+ grpc_transport_destroy_stream(f_->exec_ctx(), f_->transport(),
+ static_cast<grpc_stream *>(stream_), closure);
+ }
+
+ void Op(grpc_transport_stream_op *op) {
+ grpc_transport_perform_stream_op(f_->exec_ctx(), f_->transport(),
+ static_cast<grpc_stream *>(stream_), op);
+ }
+
+ grpc_chttp2_stream *chttp2_stream() {
+ return static_cast<grpc_chttp2_stream *>(stream_);
+ }
+
+ private:
+ Fixture *f_;
+ grpc_stream_refcount refcount_;
+ gpr_arena *arena_;
+ size_t stream_size_;
+ void *stream_;
+};
+
+class Closure : public grpc_closure {
+ public:
+ virtual ~Closure() {}
+};
+
+template <class F>
+std::unique_ptr<Closure> MakeClosure(
+ F f, grpc_closure_scheduler *sched = grpc_schedule_on_exec_ctx) {
+ struct C : public Closure {
+ C(const F &f, grpc_closure_scheduler *sched) : f_(f) {
+ grpc_closure_init(this, Execute, this, sched);
+ }
+ F f_;
+ static void Execute(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+ static_cast<C *>(arg)->f_(exec_ctx, error);
+ }
+ };
+ return std::unique_ptr<Closure>(new C(f, sched));
+}
+
+template <class F>
+grpc_closure *MakeOnceClosure(
+ F f, grpc_closure_scheduler *sched = grpc_schedule_on_exec_ctx) {
+ struct C : public grpc_closure {
+ C(const F &f) : f_(f) {}
+ F f_;
+ static void Execute(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+ static_cast<C *>(arg)->f_(exec_ctx, error);
+ delete static_cast<C *>(arg);
+ }
+ };
+ auto *c = new C{f};
+ return grpc_closure_init(c, C::Execute, c, sched);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Benchmarks
+//
+
+static void BM_StreamCreateDestroy(benchmark::State &state) {
+ TrackCounters track_counters;
+ Fixture f(grpc::ChannelArguments(), true);
+ Stream s(&f);
+ std::unique_ptr<Closure> next =
+ MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+ if (!state.KeepRunning()) return;
+ s.Init(state);
+ s.DestroyThen(next.get());
+ });
+ grpc_closure_run(f.exec_ctx(), next.get(), GRPC_ERROR_NONE);
+ f.FlushExecCtx();
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_StreamCreateDestroy);
+
+class RepresentativeClientInitialMetadata {
+ public:
+ static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
+ return {
+ GRPC_MDELEM_SCHEME_HTTP, GRPC_MDELEM_METHOD_POST,
+ grpc_mdelem_from_slices(
+ exec_ctx, GRPC_MDSTR_PATH,
+ grpc_slice_intern(grpc_slice_from_static_string("/foo/bar"))),
+ grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY,
+ grpc_slice_intern(grpc_slice_from_static_string(
+ "foo.test.google.fr:1234"))),
+ GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP,
+ GRPC_MDELEM_TE_TRAILERS,
+ GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
+ grpc_mdelem_from_slices(
+ exec_ctx, GRPC_MDSTR_USER_AGENT,
+ grpc_slice_intern(grpc_slice_from_static_string(
+ "grpc-c/3.0.0-dev (linux; chttp2; green)")))};
+ }
+};
+
+template <class Metadata>
+static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State &state) {
+ TrackCounters track_counters;
+ Fixture f(grpc::ChannelArguments(), true);
+ Stream s(&f);
+ grpc_transport_stream_op op;
+ std::unique_ptr<Closure> start;
+ std::unique_ptr<Closure> done;
+
+ grpc_metadata_batch b;
+ grpc_metadata_batch_init(&b);
+ b.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+ std::vector<grpc_mdelem> elems = Metadata::GetElems(f.exec_ctx());
+ std::vector<grpc_linked_mdelem> storage(elems.size());
+ for (size_t i = 0; i < elems.size(); i++) {
+ GPR_ASSERT(GRPC_LOG_IF_ERROR(
+ "addmd",
+ grpc_metadata_batch_add_tail(f.exec_ctx(), &b, &storage[i], elems[i])));
+ }
+
+ f.FlushExecCtx();
+ start = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+ if (!state.KeepRunning()) return;
+ s.Init(state);
+ memset(&op, 0, sizeof(op));
+ op.on_complete = done.get();
+ op.send_initial_metadata = &b;
+ s.Op(&op);
+ });
+ done = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+ memset(&op, 0, sizeof(op));
+ op.cancel_error = GRPC_ERROR_CANCELLED;
+ s.Op(&op);
+ s.DestroyThen(start.get());
+ });
+ grpc_closure_sched(f.exec_ctx(), start.get(), GRPC_ERROR_NONE);
+ f.FlushExecCtx();
+ grpc_metadata_batch_destroy(f.exec_ctx(), &b);
+ track_counters.Finish(state);
+}
+BENCHMARK_TEMPLATE(BM_StreamCreateSendInitialMetadataDestroy,
+ RepresentativeClientInitialMetadata);
+
+static void BM_TransportEmptyOp(benchmark::State &state) {
+ TrackCounters track_counters;
+ Fixture f(grpc::ChannelArguments(), true);
+ Stream s(&f);
+ s.Init(state);
+ grpc_transport_stream_op op;
+ std::unique_ptr<Closure> c =
+ MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+ if (!state.KeepRunning()) return;
+ memset(&op, 0, sizeof(op));
+ op.on_complete = c.get();
+ s.Op(&op);
+ });
+ grpc_closure_sched(f.exec_ctx(), c.get(), GRPC_ERROR_NONE);
+ f.FlushExecCtx();
+ s.DestroyThen(
+ MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {}));
+ f.FlushExecCtx();
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_TransportEmptyOp);
+
+static void BM_TransportStreamSend(benchmark::State &state) {
+ TrackCounters track_counters;
+ Fixture f(grpc::ChannelArguments(), true);
+ Stream s(&f);
+ s.Init(state);
+ grpc_transport_stream_op op;
+ grpc_slice_buffer_stream send_stream;
+ grpc_slice_buffer send_buffer;
+ grpc_slice_buffer_init(&send_buffer);
+ grpc_slice_buffer_add(&send_buffer, gpr_slice_malloc(state.range(0)));
+ memset(GRPC_SLICE_START_PTR(send_buffer.slices[0]), 0,
+ GRPC_SLICE_LENGTH(send_buffer.slices[0]));
+
+ grpc_metadata_batch b;
+ grpc_metadata_batch_init(&b);
+ b.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+ std::vector<grpc_mdelem> elems =
+ RepresentativeClientInitialMetadata::GetElems(f.exec_ctx());
+ std::vector<grpc_linked_mdelem> storage(elems.size());
+ for (size_t i = 0; i < elems.size(); i++) {
+ GPR_ASSERT(GRPC_LOG_IF_ERROR(
+ "addmd",
+ grpc_metadata_batch_add_tail(f.exec_ctx(), &b, &storage[i], elems[i])));
+ }
+
+ std::unique_ptr<Closure> c =
+ MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+ if (!state.KeepRunning()) return;
+ // force outgoing window to be yuge
+ s.chttp2_stream()->outgoing_window_delta = 1024 * 1024 * 1024;
+ f.chttp2_transport()->outgoing_window = 1024 * 1024 * 1024;
+ grpc_slice_buffer_stream_init(&send_stream, &send_buffer, 0);
+ memset(&op, 0, sizeof(op));
+ op.on_complete = c.get();
+ op.send_message = &send_stream.base;
+ s.Op(&op);
+ });
+
+ memset(&op, 0, sizeof(op));
+ op.send_initial_metadata = &b;
+ op.on_complete = c.get();
+ s.Op(&op);
+
+ f.FlushExecCtx();
+ memset(&op, 0, sizeof(op));
+ op.cancel_error = GRPC_ERROR_CANCELLED;
+ s.Op(&op);
+ s.DestroyThen(
+ MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {}));
+ f.FlushExecCtx();
+ track_counters.Finish(state);
+ grpc_metadata_batch_destroy(f.exec_ctx(), &b);
+ grpc_slice_buffer_destroy(&send_buffer);
+}
+BENCHMARK(BM_TransportStreamSend)->Range(0, 128 * 1024 * 1024);
+
+#define SLICE_FROM_BUFFER(s) grpc_slice_from_static_buffer(s, sizeof(s) - 1)
+
+static grpc_slice CreateIncomingDataSlice(size_t length, size_t frame_size) {
+ std::queue<char> unframed;
+
+ unframed.push(static_cast<uint8_t>(0));
+ unframed.push(static_cast<uint8_t>(length >> 24));
+ unframed.push(static_cast<uint8_t>(length >> 16));
+ unframed.push(static_cast<uint8_t>(length >> 8));
+ unframed.push(static_cast<uint8_t>(length));
+ for (size_t i = 0; i < length; i++) {
+ unframed.push('a');
+ }
+
+ std::vector<char> framed;
+ while (unframed.size() > frame_size) {
+ // frame size
+ framed.push_back(static_cast<uint8_t>(frame_size >> 16));
+ framed.push_back(static_cast<uint8_t>(frame_size >> 8));
+ framed.push_back(static_cast<uint8_t>(frame_size));
+ // data frame
+ framed.push_back(0);
+ // no flags
+ framed.push_back(0);
+ // stream id
+ framed.push_back(0);
+ framed.push_back(0);
+ framed.push_back(0);
+ framed.push_back(1);
+ // frame data
+ for (size_t i = 0; i < frame_size; i++) {
+ framed.push_back(unframed.front());
+ unframed.pop();
+ }
+ }
+
+ // frame size
+ framed.push_back(static_cast<uint8_t>(unframed.size() >> 16));
+ framed.push_back(static_cast<uint8_t>(unframed.size() >> 8));
+ framed.push_back(static_cast<uint8_t>(unframed.size()));
+ // data frame
+ framed.push_back(0);
+ // no flags
+ framed.push_back(0);
+ // stream id
+ framed.push_back(0);
+ framed.push_back(0);
+ framed.push_back(0);
+ framed.push_back(1);
+ while (!unframed.empty()) {
+ framed.push_back(unframed.front());
+ unframed.pop();
+ }
+
+ return grpc_slice_from_copied_buffer(framed.data(), framed.size());
+}
+
+static void BM_TransportStreamRecv(benchmark::State &state) {
+ TrackCounters track_counters;
+ Fixture f(grpc::ChannelArguments(), true);
+ Stream s(&f);
+ s.Init(state);
+ grpc_transport_stream_op op;
+ grpc_byte_stream *recv_stream;
+ grpc_slice incoming_data = CreateIncomingDataSlice(state.range(0), 16384);
+
+ grpc_metadata_batch b;
+ grpc_metadata_batch_init(&b);
+ grpc_metadata_batch b_recv;
+ grpc_metadata_batch_init(&b_recv);
+ b.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+ std::vector<grpc_mdelem> elems =
+ RepresentativeClientInitialMetadata::GetElems(f.exec_ctx());
+ std::vector<grpc_linked_mdelem> storage(elems.size());
+ for (size_t i = 0; i < elems.size(); i++) {
+ GPR_ASSERT(GRPC_LOG_IF_ERROR(
+ "addmd",
+ grpc_metadata_batch_add_tail(f.exec_ctx(), &b, &storage[i], elems[i])));
+ }
+
+ std::unique_ptr<Closure> do_nothing =
+ MakeClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {});
+
+ uint32_t received;
+
+ std::unique_ptr<Closure> drain_start;
+ std::unique_ptr<Closure> drain;
+ std::unique_ptr<Closure> drain_continue;
+ grpc_slice recv_slice;
+
+ std::unique_ptr<Closure> c =
+ MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+ if (!state.KeepRunning()) return;
+ // force outgoing window to be yuge
+ s.chttp2_stream()->incoming_window_delta = 1024 * 1024 * 1024;
+ f.chttp2_transport()->incoming_window = 1024 * 1024 * 1024;
+ received = 0;
+ memset(&op, 0, sizeof(op));
+ op.on_complete = do_nothing.get();
+ op.recv_message = &recv_stream;
+ op.recv_message_ready = drain_start.get();
+ s.Op(&op);
+ f.PushInput(grpc_slice_ref(incoming_data));
+ });
+
+ drain_start = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+ if (recv_stream == NULL) {
+ GPR_ASSERT(!state.KeepRunning());
+ return;
+ }
+ grpc_closure_run(exec_ctx, drain.get(), GRPC_ERROR_NONE);
+ });
+
+ drain = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+ do {
+ if (received == recv_stream->length) {
+ grpc_byte_stream_destroy(exec_ctx, recv_stream);
+ grpc_closure_sched(exec_ctx, c.get(), GRPC_ERROR_NONE);
+ return;
+ }
+ } while (grpc_byte_stream_next(exec_ctx, recv_stream, &recv_slice,
+ recv_stream->length - received,
+ drain_continue.get()));
+ });
+
+ drain_continue = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+ received += GRPC_SLICE_LENGTH(recv_slice);
+ grpc_slice_unref_internal(exec_ctx, recv_slice);
+ grpc_closure_run(exec_ctx, drain.get(), GRPC_ERROR_NONE);
+ });
+
+ memset(&op, 0, sizeof(op));
+ op.send_initial_metadata = &b;
+ op.recv_initial_metadata = &b_recv;
+ op.on_complete = c.get();
+ s.Op(&op);
+ f.PushInput(SLICE_FROM_BUFFER(
+ "\x00\x00\x00\x04\x00\x00\x00\x00\x00"
+ // Generated using:
+ // tools/codegen/core/gen_header_frame.py <
+ // test/cpp/microbenchmarks/representative_server_initial_metadata.headers
+ "\x00\x00X\x01\x04\x00\x00\x00\x01"
+ "\x10\x07:status\x03"
+ "200"
+ "\x10\x0c"
+ "content-type\x10"
+ "application/grpc"
+ "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip"));
+
+ f.FlushExecCtx();
+ memset(&op, 0, sizeof(op));
+ op.cancel_error = GRPC_ERROR_CANCELLED;
+ s.Op(&op);
+ s.DestroyThen(
+ MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {}));
+ f.FlushExecCtx();
+ track_counters.Finish(state);
+ grpc_metadata_batch_destroy(f.exec_ctx(), &b);
+ grpc_metadata_batch_destroy(f.exec_ctx(), &b_recv);
+ grpc_slice_unref(incoming_data);
+}
+BENCHMARK(BM_TransportStreamRecv)->Range(0, 128 * 1024 * 1024);
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_error.cc b/test/cpp/microbenchmarks/bm_error.cc
index c4f6aa19d5..00e1a08cab 100644
--- a/test/cpp/microbenchmarks/bm_error.cc
+++ b/test/cpp/microbenchmarks/bm_error.cc
@@ -51,21 +51,30 @@ class ErrorDeleter {
};
typedef std::unique_ptr<grpc_error, ErrorDeleter> ErrorPtr;
-static void BM_ErrorCreate(benchmark::State& state) {
+static void BM_ErrorCreateFromStatic(benchmark::State& state) {
TrackCounters track_counters;
while (state.KeepRunning()) {
- GRPC_ERROR_UNREF(GRPC_ERROR_CREATE("Error"));
+ GRPC_ERROR_UNREF(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"));
}
track_counters.Finish(state);
}
-BENCHMARK(BM_ErrorCreate);
+BENCHMARK(BM_ErrorCreateFromStatic);
+
+static void BM_ErrorCreateFromCopied(benchmark::State& state) {
+ TrackCounters track_counters;
+ while (state.KeepRunning()) {
+ GRPC_ERROR_UNREF(GRPC_ERROR_CREATE_FROM_COPIED_STRING("Error not inline"));
+ }
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_ErrorCreateFromCopied);
static void BM_ErrorCreateAndSetStatus(benchmark::State& state) {
TrackCounters track_counters;
while (state.KeepRunning()) {
- GRPC_ERROR_UNREF(grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
- GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_ABORTED));
+ GRPC_ERROR_UNREF(
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_ABORTED));
}
track_counters.Finish(state);
}
@@ -75,9 +84,10 @@ static void BM_ErrorCreateAndSetIntAndStr(benchmark::State& state) {
TrackCounters track_counters;
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(grpc_error_set_str(
- grpc_error_set_int(GRPC_ERROR_CREATE("GOAWAY received"),
- GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)0),
- GRPC_ERROR_STR_RAW_BYTES, "raw bytes"));
+ grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("GOAWAY received"),
+ GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)0),
+ GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_static_string("raw bytes")));
}
track_counters.Finish(state);
}
@@ -85,7 +95,7 @@ BENCHMARK(BM_ErrorCreateAndSetIntAndStr);
static void BM_ErrorCreateAndSetIntLoop(benchmark::State& state) {
TrackCounters track_counters;
- grpc_error* error = GRPC_ERROR_CREATE("Error");
+ grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error");
int n = 0;
while (state.KeepRunning()) {
error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, n++);
@@ -97,10 +107,11 @@ BENCHMARK(BM_ErrorCreateAndSetIntLoop);
static void BM_ErrorCreateAndSetStrLoop(benchmark::State& state) {
TrackCounters track_counters;
- grpc_error* error = GRPC_ERROR_CREATE("Error");
+ grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error");
const char* str = "hello";
while (state.KeepRunning()) {
- error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, str);
+ error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
+ grpc_slice_from_static_string(str));
}
GRPC_ERROR_UNREF(error);
track_counters.Finish(state);
@@ -109,7 +120,7 @@ BENCHMARK(BM_ErrorCreateAndSetStrLoop);
static void BM_ErrorRefUnref(benchmark::State& state) {
TrackCounters track_counters;
- grpc_error* error = GRPC_ERROR_CREATE("Error");
+ grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error");
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(GRPC_ERROR_REF(error));
}
@@ -138,8 +149,8 @@ BENCHMARK(BM_ErrorGetIntFromNoError);
static void BM_ErrorGetMissingInt(benchmark::State& state) {
TrackCounters track_counters;
- ErrorPtr error(
- grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_INDEX, 1));
+ ErrorPtr error(grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_INDEX, 1));
while (state.KeepRunning()) {
intptr_t value;
grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
@@ -150,8 +161,8 @@ BENCHMARK(BM_ErrorGetMissingInt);
static void BM_ErrorGetPresentInt(benchmark::State& state) {
TrackCounters track_counters;
- ErrorPtr error(
- grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_OFFSET, 1));
+ ErrorPtr error(grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_OFFSET, 1));
while (state.KeepRunning()) {
intptr_t value;
grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
@@ -186,7 +197,7 @@ class SimpleError {
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
- ErrorPtr error_{GRPC_ERROR_CREATE("Error")};
+ ErrorPtr error_{GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error")};
};
class ErrorWithGrpcStatus {
@@ -196,9 +207,9 @@ class ErrorWithGrpcStatus {
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
- ErrorPtr error_{grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
- GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_UNIMPLEMENTED)};
+ ErrorPtr error_{grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_UNIMPLEMENTED)};
};
class ErrorWithHttpError {
@@ -208,9 +219,9 @@ class ErrorWithHttpError {
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
- ErrorPtr error_{grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
- GRPC_ERROR_INT_HTTP2_ERROR,
- GRPC_HTTP2_COMPRESSION_ERROR)};
+ ErrorPtr error_{grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_HTTP2_ERROR,
+ GRPC_HTTP2_COMPRESSION_ERROR)};
};
class ErrorWithNestedGrpcStatus {
@@ -220,11 +231,12 @@ class ErrorWithNestedGrpcStatus {
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
- ErrorPtr nested_error_{grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
- GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_UNIMPLEMENTED)};
+ ErrorPtr nested_error_{grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_UNIMPLEMENTED)};
grpc_error* nested_errors_[1] = {nested_error_.get()};
- ErrorPtr error_{GRPC_ERROR_CREATE_REFERENCING("Error", nested_errors_, 1)};
+ ErrorPtr error_{GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+ "Error", nested_errors_, 1)};
};
template <class Fixture>
@@ -253,8 +265,8 @@ static void BM_ErrorGetStatus(benchmark::State& state) {
Fixture fixture;
while (state.KeepRunning()) {
grpc_status_code status;
- const char* msg;
- grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &msg,
+ grpc_slice slice;
+ grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &slice,
NULL);
}
track_counters.Finish(state);
diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
index dc0e7d769a..00e37f7912 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
@@ -54,86 +54,141 @@ auto& force_library_initialization = Library::get();
static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
-template <class Fixture>
-static void BM_PumpStreamClientToServer(benchmark::State& state) {
+// Repeatedly makes Streaming Bidi calls (exchanging a configurable number of
+// messages in each call) in a loop on a single channel
+//
+// First parmeter (i.e state.range(0)): Message size (in bytes) to use
+// Second parameter (i.e state.range(1)): Number of ping pong messages.
+// Note: One ping-pong means two messages (one from client to server and
+// the other from server to client):
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_StreamingPingPong(benchmark::State& state) {
+ const int msg_size = state.range(0);
+ const int max_ping_pongs = state.range(1);
+
EchoTestService::AsyncService service;
std::unique_ptr<Fixture> fixture(new Fixture(&service));
{
+ EchoResponse send_response;
+ EchoResponse recv_response;
EchoRequest send_request;
EchoRequest recv_request;
- if (state.range(0) > 0) {
- send_request.set_message(std::string(state.range(0), 'a'));
+
+ if (msg_size > 0) {
+ send_request.set_message(std::string(msg_size, 'a'));
+ send_response.set_message(std::string(msg_size, 'b'));
}
- Status recv_status;
- ServerContext svr_ctx;
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
+
std::unique_ptr<EchoTestService::Stub> stub(
EchoTestService::NewStub(fixture->channel()));
- ClientContext cli_ctx;
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
- int need_tags = (1 << 0) | (1 << 1);
- void* t;
- bool ok;
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- response_rw.Read(&recv_request, tag(0));
+
while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- request_rw->Write(send_request, tag(1));
- while (true) {
+ ServerContext svr_ctx;
+ ServerContextMutator svr_ctx_mut(&svr_ctx);
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+
+ ClientContext cli_ctx;
+ ClientContextMutator cli_ctx_mut(&cli_ctx);
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+
+ // Establish async stream between client side and server side
+ void* t;
+ bool ok;
+ int need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- if (t == tag(0)) {
- response_rw.Read(&recv_request, tag(0));
- } else if (t == tag(1)) {
- break;
- } else {
- GPR_ASSERT(false);
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ // Send 'max_ping_pongs' number of ping pong messages
+ int ping_pong_cnt = 0;
+ while (ping_pong_cnt < max_ping_pongs) {
+ request_rw->Write(send_request, tag(0)); // Start client send
+ response_rw.Read(&recv_request, tag(1)); // Start server recv
+ request_rw->Read(&recv_response, tag(2)); // Start client recv
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+
+ // If server recv is complete, start the server send operation
+ if (i == 1) {
+ response_rw.Write(send_response, tag(3));
+ }
+
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
}
+
+ ping_pong_cnt++;
}
- }
- request_rw->WritesDone(tag(1));
- need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
+
+ request_rw->WritesDone(tag(0));
+ response_rw.Finish(Status::OK, tag(1));
+
+ Status recv_status;
+ request_rw->Finish(&recv_status, tag(2));
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ GPR_ASSERT(recv_status.ok());
}
}
+
fixture->Finish(state);
fixture.reset();
- state.SetBytesProcessed(state.range(0) * state.iterations());
+ state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
}
-template <class Fixture>
-static void BM_PumpStreamServerToClient(benchmark::State& state) {
+// Repeatedly sends ping pong messages in a single streaming Bidi call in a loop
+// First parmeter (i.e state.range(0)): Message size (in bytes) to use
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_StreamingPingPongMsgs(benchmark::State& state) {
+ const int msg_size = state.range(0);
+
EchoTestService::AsyncService service;
std::unique_ptr<Fixture> fixture(new Fixture(&service));
{
EchoResponse send_response;
EchoResponse recv_response;
- if (state.range(0) > 0) {
- send_response.set_message(std::string(state.range(0), 'a'));
+ EchoRequest send_request;
+ EchoRequest recv_request;
+
+ if (msg_size > 0) {
+ send_request.set_message(std::string(msg_size, 'a'));
+ send_response.set_message(std::string(msg_size, 'b'));
}
- Status recv_status;
+
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+
ServerContext svr_ctx;
+ ServerContextMutator svr_ctx_mut(&svr_ctx);
ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
fixture->cq(), tag(0));
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
+
ClientContext cli_ctx;
+ ClientContextMutator cli_ctx_mut(&cli_ctx);
auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
- int need_tags = (1 << 0) | (1 << 1);
+
+ // Establish async stream between client side and server side
void* t;
bool ok;
+ int need_tags = (1 << 0) | (1 << 1);
while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok));
GPR_ASSERT(ok);
@@ -141,54 +196,78 @@ static void BM_PumpStreamServerToClient(benchmark::State& state) {
GPR_ASSERT(need_tags & (1 << i));
need_tags &= ~(1 << i);
}
- request_rw->Read(&recv_response, tag(0));
+
while (state.KeepRunning()) {
GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- response_rw.Write(send_response, tag(1));
- while (true) {
+ request_rw->Write(send_request, tag(0)); // Start client send
+ response_rw.Read(&recv_request, tag(1)); // Start server recv
+ request_rw->Read(&recv_response, tag(2)); // Start client recv
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
+ while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- if (t == tag(0)) {
- request_rw->Read(&recv_response, tag(0));
- } else if (t == tag(1)) {
- break;
- } else {
- GPR_ASSERT(false);
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+
+ // If server recv is complete, start the server send operation
+ if (i == 1) {
+ response_rw.Write(send_response, tag(3));
}
+
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
}
}
+
+ request_rw->WritesDone(tag(0));
response_rw.Finish(Status::OK, tag(1));
- need_tags = (1 << 0) | (1 << 1);
+ Status recv_status;
+ request_rw->Finish(&recv_status, tag(2));
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2);
while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok));
int i = (int)(intptr_t)t;
GPR_ASSERT(need_tags & (1 << i));
need_tags &= ~(1 << i);
}
+
+ GPR_ASSERT(recv_status.ok());
}
+
fixture->Finish(state);
fixture.reset();
- state.SetBytesProcessed(state.range(0) * state.iterations());
+ state.SetBytesProcessed(msg_size * state.iterations() * 2);
}
/*******************************************************************************
* CONFIGURATIONS
*/
-BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, TCP)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, UDS)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, SockPair)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcessCHTTP2)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, TCP)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, UDS)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, SockPair)
+// Generate Args for StreamingPingPong benchmarks. Currently generates args for
+// only "small streams" (i.e streams with 0, 1 or 2 messages)
+static void StreamingPingPongArgs(benchmark::internal::Benchmark* b) {
+ int msg_size = 0;
+
+ b->Args({0, 0}); // spl case: 0 ping-pong msgs (msg_size doesn't matter here)
+
+ for (msg_size = 0; msg_size <= 128 * 1024 * 1024;
+ msg_size == 0 ? msg_size++ : msg_size *= 8) {
+ b->Args({msg_size, 1});
+ b->Args({msg_size, 2});
+ }
+}
+
+BENCHMARK_TEMPLATE(BM_StreamingPingPong, InProcessCHTTP2, NoOpMutator,
+ NoOpMutator)
+ ->Apply(StreamingPingPongArgs);
+BENCHMARK_TEMPLATE(BM_StreamingPingPong, TCP, NoOpMutator, NoOpMutator)
+ ->Apply(StreamingPingPongArgs);
+
+BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcessCHTTP2, NoOpMutator,
+ NoOpMutator)
->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcessCHTTP2)
+BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, TCP, NoOpMutator, NoOpMutator)
->Range(0, 128 * 1024 * 1024);
} // namespace testing
diff --git a/test/http2_test/http2_base_server.py b/test/http2_test/http2_base_server.py
index 8de028ceb1..e158e9b703 100644
--- a/test/http2_test/http2_base_server.py
+++ b/test/http2_test/http2_base_server.py
@@ -39,6 +39,7 @@ import twisted.internet.protocol
_READ_CHUNK_SIZE = 16384
_GRPC_HEADER_SIZE = 5
+_MIN_SETTINGS_MAX_FRAME_SIZE = 16384
class H2ProtocolBaseServer(twisted.internet.protocol.Protocol):
def __init__(self):
@@ -121,38 +122,46 @@ class H2ProtocolBaseServer(twisted.internet.protocol.Protocol):
)
self.transport.write(self._conn.data_to_send())
- def on_window_update_default(self, event):
- # send pending data, if any
- self.default_send(event.stream_id)
+ def on_window_update_default(self, _, pad_length=None, read_chunk_size=_READ_CHUNK_SIZE):
+ # try to resume sending on all active streams (update might be for connection)
+ for stream_id in self._send_remaining:
+ self.default_send(stream_id, pad_length=pad_length, read_chunk_size=read_chunk_size)
def send_reset_stream(self):
self._conn.reset_stream(self._stream_id)
self.transport.write(self._conn.data_to_send())
- def setup_send(self, data_to_send, stream_id):
+ def setup_send(self, data_to_send, stream_id, pad_length=None, read_chunk_size=_READ_CHUNK_SIZE):
logging.info('Setting up data to send for stream_id: %d' % stream_id)
self._send_remaining[stream_id] = len(data_to_send)
self._send_offset = 0
self._data_to_send = data_to_send
- self.default_send(stream_id)
+ self.default_send(stream_id, pad_length=pad_length, read_chunk_size=read_chunk_size)
- def default_send(self, stream_id):
+ def default_send(self, stream_id, pad_length=None, read_chunk_size=_READ_CHUNK_SIZE):
if not self._send_remaining.has_key(stream_id):
# not setup to send data yet
return
while self._send_remaining[stream_id] > 0:
lfcw = self._conn.local_flow_control_window(stream_id)
- if lfcw == 0:
+ padding_bytes = pad_length + 1 if pad_length is not None else 0
+ if lfcw - padding_bytes <= 0:
+ logging.info('Stream %d. lfcw: %d. padding bytes: %d. not enough quota yet' % (stream_id, lfcw, padding_bytes))
break
- chunk_size = min(lfcw, _READ_CHUNK_SIZE)
+ chunk_size = min(lfcw - padding_bytes, read_chunk_size)
bytes_to_send = min(chunk_size, self._send_remaining[stream_id])
- logging.info('flow_control_window = %d. sending [%d:%d] stream_id %d' %
- (lfcw, self._send_offset, self._send_offset + bytes_to_send,
- stream_id))
+ logging.info('flow_control_window = %d. sending [%d:%d] stream_id %d. includes %d total padding bytes' %
+ (lfcw, self._send_offset, self._send_offset + bytes_to_send + padding_bytes,
+ stream_id, padding_bytes))
+ # The receiver might allow sending frames larger than the http2 minimum
+ # max frame size (16384), but this test should never send more than 16384
+ # for simplicity (which is always legal).
+ if bytes_to_send + padding_bytes > _MIN_SETTINGS_MAX_FRAME_SIZE:
+ raise ValueError("overload: sending %d" % (bytes_to_send + padding_bytes))
data = self._data_to_send[self._send_offset : self._send_offset + bytes_to_send]
try:
- self._conn.send_data(stream_id, data, False)
+ self._conn.send_data(stream_id, data, end_stream=False, pad_length=pad_length)
except h2.exceptions.ProtocolError:
logging.info('Stream %d is closed' % stream_id)
break
@@ -200,5 +209,5 @@ class H2ProtocolBaseServer(twisted.internet.protocol.Protocol):
req_proto_str = recv_buffer[5:5+grpc_msg_size]
sr = messages_pb2.SimpleRequest()
sr.ParseFromString(req_proto_str)
- logging.info('Parsed request for stream %d: response_size=%s' % (stream_id, sr.response_size))
+ logging.info('Parsed simple request for stream %d' % stream_id)
return sr
diff --git a/test/http2_test/http2_server_health_check.py b/test/http2_test/http2_server_health_check.py
new file mode 100644
index 0000000000..dd9402b855
--- /dev/null
+++ b/test/http2_test/http2_server_health_check.py
@@ -0,0 +1,49 @@
+# Copyright 2017, 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.
+
+import argparse
+import hyper
+import sys
+
+# Utility to healthcheck the http2 server. Used when starting the server to
+# verify that the server is live before tests begin.
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--server_host', type=str, default='localhost')
+ parser.add_argument('--server_port', type=int, default=8080)
+ args = parser.parse_args()
+ server_host = args.server_host
+ server_port = args.server_port
+ conn = hyper.HTTP20Connection('%s:%d' % (server_host, server_port))
+ conn.request('POST', '/grpc.testing.TestService/UnaryCall')
+ resp = conn.get_response()
+ if resp.headers.get('grpc-encoding') is None:
+ sys.exit(1)
+ else:
+ sys.exit(0)
diff --git a/test/http2_test/http2_test_server.py b/test/http2_test/http2_test_server.py
index abde3433ad..6a7849b94a 100644
--- a/test/http2_test/http2_test_server.py
+++ b/test/http2_test/http2_test_server.py
@@ -31,6 +31,7 @@
import argparse
import logging
+import sys
import twisted
import twisted.internet
import twisted.internet.endpoints
@@ -43,6 +44,7 @@ import test_ping
import test_rst_after_data
import test_rst_after_header
import test_rst_during_data
+import test_data_frame_padding
_TEST_CASE_MAPPING = {
'rst_after_header': test_rst_after_header.TestcaseRstStreamAfterHeader,
@@ -51,11 +53,17 @@ _TEST_CASE_MAPPING = {
'goaway': test_goaway.TestcaseGoaway,
'ping': test_ping.TestcasePing,
'max_streams': test_max_streams.TestcaseSettingsMaxStreams,
+
+ # Positive tests below:
+ 'data_frame_padding': test_data_frame_padding.TestDataFramePadding,
+ 'no_df_padding_sanity_test': test_data_frame_padding.TestDataFramePadding,
}
+_exit_code = 0
+
class H2Factory(twisted.internet.protocol.Factory):
def __init__(self, testcase):
- logging.info('Creating H2Factory for new connection.')
+ logging.info('Creating H2Factory for new connection (%s)', testcase)
self._num_streams = 0
self._testcase = testcase
@@ -70,6 +78,8 @@ class H2Factory(twisted.internet.protocol.Factory):
if self._testcase == 'goaway':
return t(self._num_streams).get_base_server()
+ elif self._testcase == 'no_df_padding_sanity_test':
+ return t(use_padding=False).get_base_server()
else:
return t().get_base_server()
@@ -78,11 +88,23 @@ def parse_arguments():
parser.add_argument('--base_port', type=int, default=8080,
help='base port to run the servers (default: 8080). One test server is '
'started on each incrementing port, beginning with base_port, in the '
- 'following order: goaway,max_streams,ping,rst_after_data,rst_after_header,'
+ 'following order: data_frame_padding,goaway,max_streams,'
+ 'no_df_padding_sanity_test,ping,rst_after_data,rst_after_header,'
'rst_during_data'
)
return parser.parse_args()
+def listen(endpoint, test_case):
+ deferred = endpoint.listen(H2Factory(test_case))
+ def listen_error(reason):
+ # If listening fails, we stop the reactor and exit the program
+ # with exit code 1.
+ global _exit_code
+ _exit_code = 1
+ logging.error('Listening failed: %s' % reason.value)
+ twisted.internet.reactor.stop()
+ deferred.addErrback(listen_error)
+
def start_test_servers(base_port):
""" Start one server per test case on incrementing port numbers
beginning with base_port """
@@ -92,7 +114,9 @@ def start_test_servers(base_port):
logging.warning('serving on port %d : %s'%(portnum, test_case))
endpoint = twisted.internet.endpoints.TCP4ServerEndpoint(
twisted.internet.reactor, portnum, backlog=128)
- endpoint.listen(H2Factory(test_case))
+ # Wait until the reactor is running before calling endpoint.listen().
+ twisted.internet.reactor.callWhenRunning(listen, endpoint, test_case)
+
index += 1
if __name__ == '__main__':
@@ -102,3 +126,4 @@ if __name__ == '__main__':
args = parse_arguments()
start_test_servers(args.base_port)
twisted.internet.reactor.run()
+ sys.exit(_exit_code)
diff --git a/test/http2_test/test_data_frame_padding.py b/test/http2_test/test_data_frame_padding.py
new file mode 100644
index 0000000000..e1db28faed
--- /dev/null
+++ b/test/http2_test/test_data_frame_padding.py
@@ -0,0 +1,94 @@
+# Copyright 2016, 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.
+
+import http2_base_server
+import logging
+import messages_pb2
+
+# Set the number of padding bytes per data frame to be very large
+# relative to the number of data bytes for each data frame sent.
+_LARGE_PADDING_LENGTH = 255
+_SMALL_READ_CHUNK_SIZE = 5
+
+class TestDataFramePadding(object):
+ """
+ In response to an incoming request, this test sends headers, followed by
+ data, followed by a reset stream frame. Client asserts that the RPC failed.
+ Client needs to deliver the complete message to the application layer.
+ """
+ def __init__(self, use_padding=True):
+ self._base_server = http2_base_server.H2ProtocolBaseServer()
+ self._base_server._handlers['DataReceived'] = self.on_data_received
+ self._base_server._handlers['WindowUpdated'] = self.on_window_update
+ self._base_server._handlers['RequestReceived'] = self.on_request_received
+
+ # _total_updates maps stream ids to total flow control updates received
+ self._total_updates = {}
+ # zero window updates so far for connection window (stream id '0')
+ self._total_updates[0] = 0
+ self._read_chunk_size = _SMALL_READ_CHUNK_SIZE
+
+ if use_padding:
+ self._pad_length = _LARGE_PADDING_LENGTH
+ else:
+ self._pad_length = None
+
+ def get_base_server(self):
+ return self._base_server
+
+ def on_data_received(self, event):
+ logging.info('on data received. Stream id: %d. Data length: %d' % (event.stream_id, len(event.data)))
+ self._base_server.on_data_received_default(event)
+ if len(event.data) == 0:
+ return
+ sr = self._base_server.parse_received_data(event.stream_id)
+ stream_bytes = ''
+ # Check if full grpc msg has been read into the recv buffer yet
+ if sr:
+ response_data = self._base_server.default_response_data(sr.response_size)
+ logging.info('Stream id: %d. total resp size: %d' % (event.stream_id, len(response_data)))
+ # Begin sending the response. Add ``self._pad_length`` padding to each
+ # data frame and split the whole message into data frames each carrying
+ # only self._read_chunk_size of data.
+ # The purpose is to have the majority of the data frame response bytes
+ # be padding bytes, since ``self._pad_length`` >> ``self._read_chunk_size``.
+ self._base_server.setup_send(response_data , event.stream_id, pad_length=self._pad_length, read_chunk_size=self._read_chunk_size)
+
+ def on_request_received(self, event):
+ self._base_server.on_request_received_default(event)
+ logging.info('on request received. Stream id: %s.' % event.stream_id)
+ self._total_updates[event.stream_id] = 0
+
+ # Log debug info and try to resume sending on all currently active streams.
+ def on_window_update(self, event):
+ logging.info('on window update. Stream id: %s. Delta: %s' % (event.stream_id, event.delta))
+ self._total_updates[event.stream_id] += event.delta
+ total = self._total_updates[event.stream_id]
+ logging.info('... - total updates for stream %d : %d' % (event.stream_id, total))
+ self._base_server.on_window_update_default(event, pad_length=self._pad_length, read_chunk_size=self._read_chunk_size)