diff options
Diffstat (limited to 'test')
105 files changed, 2268 insertions, 285 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_ssl/servers/cert.c b/test/core/bad_ssl/servers/cert.c index 9aadf452e2..2b014b2343 100644 --- a/test/core/bad_ssl/servers/cert.c +++ b/test/core/bad_ssl/servers/cert.c @@ -56,11 +56,11 @@ int main(int argc, char **argv) { grpc_init(); GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file("src/core/lib/tsi/test_creds/badserver.pem", - 1, &cert_slice))); + "load_file", + grpc_load_file("src/core/tsi/test_creds/badserver.pem", 1, &cert_slice))); GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file("src/core/lib/tsi/test_creds/badserver.key", - 1, &key_slice))); + "load_file", + grpc_load_file("src/core/tsi/test_creds/badserver.key", 1, &key_slice))); pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c index af551c4928..4be89c78b5 100644 --- a/test/core/channel/channel_stack_test.c +++ b/test/core/channel/channel_stack_test.c @@ -73,7 +73,7 @@ static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, } static void call_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_transport_stream_op *op) { + grpc_transport_stream_op_batch *op) { ++*(int *)(elem->call_data); } diff --git a/test/core/client_channel/lb_policies_test.c b/test/core/client_channel/lb_policies_test.c index 057b90ec84..e03492f80e 100644 --- a/test/core/client_channel/lb_policies_test.c +++ b/test/core/client_channel/lb_policies_test.c @@ -41,8 +41,8 @@ #include <grpc/support/string_util.h> #include <grpc/support/time.h> -#include "src/core/ext/client_channel/client_channel.h" -#include "src/core/ext/client_channel/lb_policy_registry.h" +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/support/string.h" diff --git a/test/core/client_channel/parse_address_test.c b/test/core/client_channel/parse_address_test.c index 37dd0fba52..629cdb001f 100644 --- a/test/core/client_channel/parse_address_test.c +++ b/test/core/client_channel/parse_address_test.c @@ -31,7 +31,7 @@ * */ -#include "src/core/ext/client_channel/parse_address.h" +#include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include <string.h> 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 b85ca89337..8e15faa1dd 100644 --- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c +++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c @@ -36,8 +36,8 @@ #include <grpc/grpc.h> #include <grpc/support/alloc.h> -#include "src/core/ext/client_channel/resolver.h" -#include "src/core/ext/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/resolver.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/resolve_address.h" @@ -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_FROM_STATIC_STRING("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/resolvers/dns_resolver_test.c b/test/core/client_channel/resolvers/dns_resolver_test.c index 919a85d58f..fa7857d418 100644 --- a/test/core/client_channel/resolvers/dns_resolver_test.c +++ b/test/core/client_channel/resolvers/dns_resolver_test.c @@ -35,7 +35,7 @@ #include <grpc/support/log.h> -#include "src/core/ext/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/iomgr/combiner.h" #include "test/core/util/test_config.h" diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.c b/test/core/client_channel/resolvers/sockaddr_resolver_test.c index bc4f02c339..847eabae3b 100644 --- a/test/core/client_channel/resolvers/sockaddr_resolver_test.c +++ b/test/core/client_channel/resolvers/sockaddr_resolver_test.c @@ -37,7 +37,7 @@ #include <grpc/support/log.h> #include <grpc/support/string_util.h> -#include "src/core/ext/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/combiner.h" diff --git a/test/core/client_channel/uri_fuzzer_test.c b/test/core/client_channel/uri_fuzzer_test.c index baadd4fc65..51da7f9988 100644 --- a/test/core/client_channel/uri_fuzzer_test.c +++ b/test/core/client_channel/uri_fuzzer_test.c @@ -37,7 +37,7 @@ #include <grpc/support/alloc.h> -#include "src/core/ext/client_channel/uri_parser.h" +#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/iomgr/exec_ctx.h" bool squelch = true; diff --git a/test/core/client_channel/uri_parser_test.c b/test/core/client_channel/uri_parser_test.c index 8a127f72eb..9fd0dd07f0 100644 --- a/test/core/client_channel/uri_parser_test.c +++ b/test/core/client_channel/uri_parser_test.c @@ -31,7 +31,7 @@ * */ -#include "src/core/ext/client_channel/uri_parser.h" +#include "src/core/ext/filters/client_channel/uri_parser.h" #include <string.h> 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_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c index b351bdee27..64bdceb211 100644 --- a/test/core/end2end/end2end_nosec_tests.c +++ b/test/core/end2end/end2end_nosec_tests.c @@ -97,6 +97,10 @@ extern void load_reporting_hook(grpc_end2end_test_config config); extern void load_reporting_hook_pre_init(void); extern void max_concurrent_streams(grpc_end2end_test_config config); extern void max_concurrent_streams_pre_init(void); +extern void max_connection_age(grpc_end2end_test_config config); +extern void max_connection_age_pre_init(void); +extern void max_connection_idle(grpc_end2end_test_config config); +extern void max_connection_idle_pre_init(void); extern void max_message_length(grpc_end2end_test_config config); extern void max_message_length_pre_init(void); extern void negative_deadline(grpc_end2end_test_config config); @@ -174,6 +178,8 @@ void grpc_end2end_tests_pre_init(void) { large_metadata_pre_init(); load_reporting_hook_pre_init(); max_concurrent_streams_pre_init(); + max_connection_age_pre_init(); + max_connection_idle_pre_init(); max_message_length_pre_init(); negative_deadline_pre_init(); network_status_change_pre_init(); @@ -232,6 +238,8 @@ void grpc_end2end_tests(int argc, char **argv, large_metadata(config); load_reporting_hook(config); max_concurrent_streams(config); + max_connection_age(config); + max_connection_idle(config); max_message_length(config); negative_deadline(config); network_status_change(config); @@ -363,6 +371,14 @@ void grpc_end2end_tests(int argc, char **argv, max_concurrent_streams(config); continue; } + if (0 == strcmp("max_connection_age", argv[i])) { + max_connection_age(config); + continue; + } + if (0 == strcmp("max_connection_idle", argv[i])) { + max_connection_idle(config); + continue; + } if (0 == strcmp("max_message_length", argv[i])) { max_message_length(config); continue; diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c index 199c09ec96..37c1be4133 100644 --- a/test/core/end2end/end2end_tests.c +++ b/test/core/end2end/end2end_tests.c @@ -99,6 +99,10 @@ extern void load_reporting_hook(grpc_end2end_test_config config); extern void load_reporting_hook_pre_init(void); extern void max_concurrent_streams(grpc_end2end_test_config config); extern void max_concurrent_streams_pre_init(void); +extern void max_connection_age(grpc_end2end_test_config config); +extern void max_connection_age_pre_init(void); +extern void max_connection_idle(grpc_end2end_test_config config); +extern void max_connection_idle_pre_init(void); extern void max_message_length(grpc_end2end_test_config config); extern void max_message_length_pre_init(void); extern void negative_deadline(grpc_end2end_test_config config); @@ -177,6 +181,8 @@ void grpc_end2end_tests_pre_init(void) { large_metadata_pre_init(); load_reporting_hook_pre_init(); max_concurrent_streams_pre_init(); + max_connection_age_pre_init(); + max_connection_idle_pre_init(); max_message_length_pre_init(); negative_deadline_pre_init(); network_status_change_pre_init(); @@ -236,6 +242,8 @@ void grpc_end2end_tests(int argc, char **argv, large_metadata(config); load_reporting_hook(config); max_concurrent_streams(config); + max_connection_age(config); + max_connection_idle(config); max_message_length(config); negative_deadline(config); network_status_change(config); @@ -371,6 +379,14 @@ void grpc_end2end_tests(int argc, char **argv, max_concurrent_streams(config); continue; } + if (0 == strcmp("max_connection_age", argv[i])) { + max_connection_age(config); + continue; + } + if (0 == strcmp("max_connection_idle", argv[i])) { + max_connection_idle(config); + continue; + } if (0 == strcmp("max_message_length", argv[i])) { max_message_length(config); continue; diff --git a/test/core/end2end/fake_resolver.c b/test/core/end2end/fake_resolver.c index 8a37531449..1c7dd1339c 100644 --- a/test/core/end2end/fake_resolver.c +++ b/test/core/end2end/fake_resolver.c @@ -42,9 +42,9 @@ #include <grpc/support/port_platform.h> #include <grpc/support/string_util.h> -#include "src/core/ext/client_channel/lb_policy_factory.h" -#include "src/core/ext/client_channel/parse_address.h" -#include "src/core/ext/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/parse_address.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" diff --git a/test/core/end2end/fixtures/h2_census.c b/test/core/end2end/fixtures/h2_census.c index 8e60123ed6..97b27b2496 100644 --- a/test/core/end2end/fixtures/h2_census.c +++ b/test/core/end2end/fixtures/h2_census.c @@ -41,7 +41,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" diff --git a/test/core/end2end/fixtures/h2_compress.c b/test/core/end2end/fixtures/h2_compress.c index c01e45664b..8aec94d601 100644 --- a/test/core/end2end/fixtures/h2_compress.c +++ b/test/core/end2end/fixtures/h2_compress.c @@ -41,7 +41,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" diff --git a/test/core/end2end/fixtures/h2_full+pipe.c b/test/core/end2end/fixtures/h2_full+pipe.c index c6013f3040..0191e59fc8 100644 --- a/test/core/end2end/fixtures/h2_full+pipe.c +++ b/test/core/end2end/fixtures/h2_full+pipe.c @@ -46,7 +46,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/http_server_filter.h" diff --git a/test/core/end2end/fixtures/h2_full+trace.c b/test/core/end2end/fixtures/h2_full+trace.c index 01316376e0..9dbb27fc4b 100644 --- a/test/core/end2end/fixtures/h2_full+trace.c +++ b/test/core/end2end/fixtures/h2_full+trace.c @@ -46,7 +46,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/http_server_filter.h" diff --git a/test/core/end2end/fixtures/h2_full.c b/test/core/end2end/fixtures/h2_full.c index 3399f1981e..49c62b3429 100644 --- a/test/core/end2end/fixtures/h2_full.c +++ b/test/core/end2end/fixtures/h2_full.c @@ -41,7 +41,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/http_server_filter.h" diff --git a/test/core/end2end/fixtures/h2_http_proxy.c b/test/core/end2end/fixtures/h2_http_proxy.c index 55c65fa70e..62c435557d 100644 --- a/test/core/end2end/fixtures/h2_http_proxy.c +++ b/test/core/end2end/fixtures/h2_http_proxy.c @@ -42,7 +42,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/http_server_filter.h" diff --git a/test/core/end2end/fixtures/h2_load_reporting.c b/test/core/end2end/fixtures/h2_load_reporting.c index 38321f34db..79f26ed2bc 100644 --- a/test/core/end2end/fixtures/h2_load_reporting.c +++ b/test/core/end2end/fixtures/h2_load_reporting.c @@ -41,8 +41,8 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" -#include "src/core/ext/load_reporting/load_reporting.h" +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/load_reporting/load_reporting.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" diff --git a/test/core/end2end/fixtures/h2_proxy.c b/test/core/end2end/fixtures/h2_proxy.c index 9e37ed4db3..a10738fa0b 100644 --- a/test/core/end2end/fixtures/h2_proxy.c +++ b/test/core/end2end/fixtures/h2_proxy.c @@ -41,7 +41,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/http_server_filter.h" diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c index edf42a4070..5ace922f05 100644 --- a/test/core/end2end/fixtures/h2_sockpair+trace.c +++ b/test/core/end2end/fixtures/h2_sockpair+trace.c @@ -45,7 +45,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/compress_filter.h" #include "src/core/lib/channel/connected_channel.h" diff --git a/test/core/end2end/fixtures/h2_sockpair.c b/test/core/end2end/fixtures/h2_sockpair.c index 94b2623b3e..3079a42dce 100644 --- a/test/core/end2end/fixtures/h2_sockpair.c +++ b/test/core/end2end/fixtures/h2_sockpair.c @@ -40,7 +40,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/compress_filter.h" #include "src/core/lib/channel/connected_channel.h" diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c index 6f9cf8fe26..70410d75f4 100644 --- a/test/core/end2end/fixtures/h2_sockpair_1byte.c +++ b/test/core/end2end/fixtures/h2_sockpair_1byte.c @@ -40,7 +40,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/compress_filter.h" #include "src/core/lib/channel/connected_channel.h" diff --git a/test/core/end2end/fixtures/h2_uds.c b/test/core/end2end/fixtures/h2_uds.c index bc973ea8e3..7bde69d82a 100644 --- a/test/core/end2end/fixtures/h2_uds.c +++ b/test/core/end2end/fixtures/h2_uds.c @@ -44,7 +44,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/http_server_filter.h" diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c index 9cc3f56437..a0acf5bf60 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.c +++ b/test/core/end2end/fuzzers/api_fuzzer.c @@ -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-5242554383597568 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5242554383597568 Binary files differnew file mode 100644 index 0000000000..95a0b013c0 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5242554383597568 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5965570207907840 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5965570207907840 Binary files differnew file mode 100644 index 0000000000..a58dc7b244 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5965570207907840 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6499902139924480 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6499902139924480 Binary files differnew file mode 100644 index 0000000000..139fc1cf3f --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6499902139924480 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6699208922890240 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6699208922890240 Binary files differnew file mode 100644 index 0000000000..74f189b87f --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6699208922890240 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-59a56fa18034a104fb9f16cd58071b6ff93b8756 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-59a56fa18034a104fb9f16cd58071b6ff93b8756 Binary files differnew file mode 100644 index 0000000000..1460bc9fbf --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-59a56fa18034a104fb9f16cd58071b6ff93b8756 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/poc-c726ee220e980ed6ad17809fd9efe2844ee61555ac08e4f88afd8901cc2dd53a b/test/core/end2end/fuzzers/api_fuzzer_corpus/poc-c726ee220e980ed6ad17809fd9efe2844ee61555ac08e4f88afd8901cc2dd53a Binary files differnew file mode 100644 index 0000000000..01428693cf --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/poc-c726ee220e980ed6ad17809fd9efe2844ee61555ac08e4f88afd8901cc2dd53a diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-5417405008314368 b/test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-5417405008314368 Binary files differnew file mode 100644 index 0000000000..f896b66adf --- /dev/null +++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-5417405008314368 diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 0c749537e6..3c5068ff3e 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -122,6 +122,9 @@ END2END_TESTS = { 'keepalive_timeout': default_test_options._replace(proxyable=False), 'large_metadata': default_test_options, 'max_concurrent_streams': default_test_options._replace(proxyable=False), + 'max_connection_age': default_test_options, + 'max_connection_idle': connectivity_test_options._replace( + proxyable=False, exclude_iomgrs=['uv']), 'max_message_length': default_test_options, 'negative_deadline': default_test_options, 'network_status_change': default_test_options, diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 431c6995ba..1041219f03 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -109,6 +109,8 @@ END2END_TESTS = { 'keepalive_timeout': test_options(proxyable=False), 'large_metadata': test_options(), 'max_concurrent_streams': test_options(proxyable=False), + 'max_connection_age': test_options(), + 'max_connection_idle': test_options(needs_fullstack=True, proxyable=False), 'max_message_length': test_options(), 'negative_deadline': test_options(), 'network_status_change': test_options(), diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c index 4bb258e3ed..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_FROM_STATIC_STRING("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_causes_close.c b/test/core/end2end/tests/filter_causes_close.c index e6b02eaeee..62bf20809c 100644 --- a/test/core/end2end/tests/filter_causes_close.c +++ b/test/core/end2end/tests/filter_causes_close.c @@ -216,13 +216,14 @@ static void recv_im_ready(grpc_exec_ctx *exec_ctx, void *arg, GRPC_STATUS_PERMISSION_DENIED)); } -static void start_transport_stream_op(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - grpc_transport_stream_op *op) { +static void start_transport_stream_op_batch( + grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; - if (op->recv_initial_metadata != NULL) { - calld->recv_im_ready = op->recv_initial_metadata_ready; - op->recv_initial_metadata_ready = + if (op->recv_initial_metadata) { + calld->recv_im_ready = + op->payload->recv_initial_metadata.recv_initial_metadata_ready; + op->payload->recv_initial_metadata.recv_initial_metadata_ready = grpc_closure_create(recv_im_ready, elem, grpc_schedule_on_exec_ctx); } grpc_call_next_op(exec_ctx, elem, op); @@ -248,7 +249,7 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {} static const grpc_channel_filter test_filter = { - start_transport_stream_op, + start_transport_stream_op_batch, grpc_channel_next_op, sizeof(call_data), init_call_elem, diff --git a/test/core/end2end/tests/keepalive_timeout.c b/test/core/end2end/tests/keepalive_timeout.c index 4296be3619..44b6e12abc 100644 --- a/test/core/end2end/tests/keepalive_timeout.c +++ b/test/core/end2end/tests/keepalive_timeout.c @@ -41,6 +41,7 @@ #include <grpc/support/log.h> #include <grpc/support/time.h> #include <grpc/support/useful.h> +#include "src/core/ext/transport/chttp2/transport/frame_ping.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/support/env.h" @@ -109,13 +110,15 @@ static void test_keepalive_timeout(grpc_end2end_test_config config) { grpc_raw_byte_buffer_create(&response_payload_slice, 1); gpr_timespec deadline = five_seconds_time(); - grpc_arg keepalive_args[2]; - keepalive_args[0].type = GRPC_ARG_INTEGER; - keepalive_args[0].key = GRPC_ARG_HTTP2_KEEPALIVE_TIME; - keepalive_args[0].value.integer = 2; - keepalive_args[1].type = GRPC_ARG_INTEGER; - keepalive_args[1].key = GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT; - keepalive_args[1].value.integer = 0; + grpc_arg keepalive_args[] = {{.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_CLIENT_KEEPALIVE_TIME_S, + .value.integer = 2}, + {.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_CLIENT_KEEPALIVE_TIMEOUT_S, + .value.integer = 0}, + {.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_HTTP2_BDP_PROBE, + .value.integer = 1}}; grpc_channel_args *client_args = NULL; client_args = grpc_channel_args_copy_and_add(client_args, keepalive_args, 2); @@ -134,6 +137,9 @@ static void test_keepalive_timeout(grpc_end2end_test_config config) { grpc_call_error error; grpc_slice details; + /* Disable ping ack to trigger the keepalive timeout */ + grpc_set_disable_ping_ack(true); + c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, grpc_slice_from_static_string("/foo"), diff --git a/test/core/end2end/tests/load_reporting_hook.c b/test/core/end2end/tests/load_reporting_hook.c index d1ee26fe50..fd3d9163d0 100644 --- a/test/core/end2end/tests/load_reporting_hook.c +++ b/test/core/end2end/tests/load_reporting_hook.c @@ -41,8 +41,8 @@ #include <grpc/support/time.h> #include <grpc/support/useful.h> -#include "src/core/ext/load_reporting/load_reporting.h" -#include "src/core/ext/load_reporting/load_reporting_filter.h" +#include "src/core/ext/filters/load_reporting/load_reporting.h" +#include "src/core/ext/filters/load_reporting/load_reporting_filter.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/transport/static_metadata.h" diff --git a/test/core/end2end/tests/max_connection_age.c b/test/core/end2end/tests/max_connection_age.c new file mode 100644 index 0000000000..59bfdbabb9 --- /dev/null +++ b/test/core/end2end/tests/max_connection_age.c @@ -0,0 +1,380 @@ +/* + * + * 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. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include <limits.h> +#include <string.h> + +#include <grpc/support/log.h> +#include <grpc/support/sync.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> + +#include "test/core/end2end/cq_verifier.h" + +#define MAX_CONNECTION_AGE_MS 500 +#define MAX_CONNECTION_AGE_GRACE_MS 1000 +#define MAX_CONNECTION_IDLE_MS 9999 + +#define CALL_DEADLINE_S 10 +/* The amount of time we wait for the connection to time out, but after it the + connection should not use up its grace period. It should be a number between + MAX_CONNECTION_AGE_MS and MAX_CONNECTION_AGE_MS + + MAX_CONNECTION_AGE_GRACE_MS */ +#define CQ_MAX_CONNECTION_AGE_WAIT_TIME_S 1 +/* The amount of time we wait after the connection reaches its max age, it + should be shorter than CALL_DEADLINE_S - CQ_MAX_CONNECTION_AGE_WAIT_TIME_S */ +#define CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S 2 +/* The grace period for the test to observe the channel shutdown process */ +#define IMMEDIATE_SHUTDOWN_GRACE_TIME_MS 3000 + +static void *tag(intptr_t t) { return (void *)t; } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), + NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); +} + +static void test_max_age_forcibly_close(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_arg server_a[] = {{.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_MAX_CONNECTION_AGE_MS, + .value.integer = MAX_CONNECTION_AGE_MS}, + {.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS, + .value.integer = MAX_CONNECTION_AGE_GRACE_MS}, + {.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_MAX_CONNECTION_IDLE_MS, + .value.integer = MAX_CONNECTION_IDLE_MS}}; + grpc_channel_args server_args = {.num_args = GPR_ARRAY_SIZE(server_a), + .args = server_a}; + + config.init_client(&f, NULL); + config.init_server(&f, &server_args); + + grpc_call *c; + grpc_call *s; + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + cq_verify(cqv); + + gpr_timespec expect_shutdown_time = grpc_timeout_milliseconds_to_deadline( + MAX_CONNECTION_AGE_MS + MAX_CONNECTION_AGE_GRACE_MS + + IMMEDIATE_SHUTDOWN_GRACE_TIME_MS); + + /* Wait for the channel to reach its max age */ + cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S); + + /* After the channel reaches its max age, we still do nothing here. And wait + for it to use up its max age grace period. */ + CQ_EXPECT_COMPLETION(cqv, tag(1), true); + cq_verify(cqv); + + gpr_timespec channel_shutdown_time = gpr_now(GPR_CLOCK_MONOTONIC); + GPR_ASSERT(gpr_time_cmp(channel_shutdown_time, expect_shutdown_time) < 0); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(102), true); + cq_verify(cqv); + + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true); + cq_verify(cqv); + + grpc_call_destroy(s); + + /* The connection should be closed immediately after the max age grace period, + the in-progress RPC should fail. */ + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "Endpoint read failed")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_call_destroy(c); + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_max_age_gracefully_close(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_arg server_a[] = {{.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_MAX_CONNECTION_AGE_MS, + .value.integer = MAX_CONNECTION_AGE_MS}, + {.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS, + .value.integer = INT_MAX}, + {.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_MAX_CONNECTION_IDLE_MS, + .value.integer = MAX_CONNECTION_IDLE_MS}}; + grpc_channel_args server_args = {.num_args = GPR_ARRAY_SIZE(server_a), + .args = server_a}; + + config.init_client(&f, NULL); + config.init_server(&f, &server_args); + + grpc_call *c; + grpc_call *s; + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + cq_verify(cqv); + + /* Wait for the channel to reach its max age */ + cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S); + + /* The connection is shutting down gracefully. In-progress rpc should not be + closed, hence the completion queue should see nothing here. */ + cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(102), true); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); + cq_verify(cqv); + + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true); + cq_verify(cqv); + + grpc_call_destroy(s); + + /* The connection is closed gracefully with goaway, the rpc should still be + completed. */ + GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_call_destroy(c); + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +void max_connection_age(grpc_end2end_test_config config) { + test_max_age_forcibly_close(config); + test_max_age_gracefully_close(config); +} + +void max_connection_age_pre_init(void) {} diff --git a/test/core/end2end/tests/max_connection_idle.c b/test/core/end2end/tests/max_connection_idle.c new file mode 100644 index 0000000000..c0984e4d14 --- /dev/null +++ b/test/core/end2end/tests/max_connection_idle.c @@ -0,0 +1,117 @@ +/* + * + * 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. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include <limits.h> +#include <string.h> + +#include <grpc/support/log.h> +#include <grpc/support/sync.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> + +#include "test/core/end2end/cq_verifier.h" + +#define MAX_CONNECTION_IDLE_MS 500 +#define MAX_CONNECTION_AGE_MS 9999 + +static void *tag(intptr_t t) { return (void *)t; } + +static void test_max_connection_idle(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); + grpc_connectivity_state state = GRPC_CHANNEL_IDLE; + cq_verifier *cqv = cq_verifier_create(f.cq); + + grpc_arg client_a[] = {{.type = GRPC_ARG_INTEGER, + .key = "grpc.testing.fixed_reconnect_backoff_ms", + .value.integer = 1000}}; + grpc_arg server_a[] = {{.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_MAX_CONNECTION_IDLE_MS, + .value.integer = MAX_CONNECTION_IDLE_MS}, + {.type = GRPC_ARG_INTEGER, + .key = GRPC_ARG_MAX_CONNECTION_AGE_MS, + .value.integer = MAX_CONNECTION_AGE_MS}}; + grpc_channel_args client_args = {.num_args = GPR_ARRAY_SIZE(client_a), + .args = client_a}; + grpc_channel_args server_args = {.num_args = GPR_ARRAY_SIZE(server_a), + .args = server_a}; + + config.init_client(&f, &client_args); + config.init_server(&f, &server_args); + + /* check that we're still in idle, and start connecting */ + GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) == + GRPC_CHANNEL_IDLE); + /* we'll go through some set of transitions (some might be missed), until + READY is reached */ + while (state != GRPC_CHANNEL_READY) { + grpc_channel_watch_connectivity_state( + f.client, state, grpc_timeout_seconds_to_deadline(3), f.cq, tag(99)); + CQ_EXPECT_COMPLETION(cqv, tag(99), 1); + cq_verify(cqv); + state = grpc_channel_check_connectivity_state(f.client, 0); + GPR_ASSERT(state == GRPC_CHANNEL_READY || + state == GRPC_CHANNEL_CONNECTING || + state == GRPC_CHANNEL_TRANSIENT_FAILURE); + } + + /* wait for the channel to reach its maximum idle time */ + grpc_channel_watch_connectivity_state( + f.client, GRPC_CHANNEL_READY, + grpc_timeout_milliseconds_to_deadline(MAX_CONNECTION_IDLE_MS + 3000), + f.cq, tag(99)); + CQ_EXPECT_COMPLETION(cqv, tag(99), 1); + cq_verify(cqv); + state = grpc_channel_check_connectivity_state(f.client, 0); + GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || + state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_IDLE); + + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1); + cq_verify(cqv); + + grpc_server_destroy(f.server); + grpc_channel_destroy(f.client); + grpc_completion_queue_shutdown(f.cq); + grpc_completion_queue_destroy(f.cq); + config.tear_down_data(&f); + + cq_verifier_destroy(cqv); +} + +void max_connection_idle(grpc_end2end_test_config config) { + test_max_connection_idle(config); +} + +void max_connection_idle_pre_init(void) {} diff --git a/test/core/end2end/tests/ping.c b/test/core/end2end/tests/ping.c index f5bfac2255..082ac641f0 100644 --- a/test/core/end2end/tests/ping.c +++ b/test/core/end2end/tests/ping.c @@ -41,9 +41,12 @@ #include "test/core/end2end/cq_verifier.h" +#define PING_NUM 5 + static void *tag(intptr_t t) { return (void *)t; } -static void test_ping(grpc_end2end_test_config config) { +static void test_ping(grpc_end2end_test_config config, + int min_time_between_pings_ms) { grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); cq_verifier *cqv = cq_verifier_create(f.cq); grpc_connectivity_state state = GRPC_CHANNEL_IDLE; @@ -51,7 +54,7 @@ static void test_ping(grpc_end2end_test_config config) { grpc_arg a[] = {{.type = GRPC_ARG_INTEGER, .key = GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS, - .value.integer = 0}, + .value.integer = min_time_between_pings_ms}, {.type = GRPC_ARG_INTEGER, .key = GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, .value.integer = 20}}; @@ -70,7 +73,11 @@ static void test_ping(grpc_end2end_test_config config) { READY is reached */ while (state != GRPC_CHANNEL_READY) { grpc_channel_watch_connectivity_state( - f.client, state, grpc_timeout_seconds_to_deadline(3), f.cq, tag(99)); + f.client, state, + gpr_time_add(grpc_timeout_seconds_to_deadline(3), + gpr_time_from_millis(min_time_between_pings_ms * PING_NUM, + GPR_TIMESPAN)), + f.cq, tag(99)); CQ_EXPECT_COMPLETION(cqv, tag(99), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); @@ -79,7 +86,7 @@ static void test_ping(grpc_end2end_test_config config) { state == GRPC_CHANNEL_TRANSIENT_FAILURE); } - for (i = 1; i <= 5; i++) { + for (i = 1; i <= PING_NUM; i++) { grpc_channel_ping(f.client, f.cq, tag(i), NULL); CQ_EXPECT_COMPLETION(cqv, tag(i), 1); cq_verify(cqv); @@ -102,7 +109,8 @@ static void test_ping(grpc_end2end_test_config config) { void ping(grpc_end2end_test_config config) { GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - test_ping(config); + test_ping(config, 0); + test_ping(config, 100); } void ping_pre_init(void) {} diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD index eb8f3a9beb..996b503d35 100644 --- a/test/core/handshake/BUILD +++ b/test/core/handshake/BUILD @@ -34,9 +34,9 @@ cc_test( srcs = ["client_ssl.c"], copts = ["-std=c99"], data = [ - "//src/core/lib/tsi/test_creds:ca.pem", - "//src/core/lib/tsi/test_creds:server1.key", - "//src/core/lib/tsi/test_creds:server1.pem", + "//src/core/tsi/test_creds:ca.pem", + "//src/core/tsi/test_creds:server1.key", + "//src/core/tsi/test_creds:server1.pem", ], deps = [ "//:gpr", @@ -51,9 +51,9 @@ cc_test( srcs = ["server_ssl.c"], copts = ["-std=c99"], data = [ - "//src/core/lib/tsi/test_creds:ca.pem", - "//src/core/lib/tsi/test_creds:server1.key", - "//src/core/lib/tsi/test_creds:server1.pem", + "//src/core/tsi/test_creds:ca.pem", + "//src/core/tsi/test_creds:server1.key", + "//src/core/tsi/test_creds:server1.pem", ], deps = [ "//:gpr", diff --git a/test/core/handshake/client_ssl.c b/test/core/handshake/client_ssl.c index 5cfe60de4b..f291d09493 100644 --- a/test/core/handshake/client_ssl.c +++ b/test/core/handshake/client_ssl.c @@ -54,9 +54,9 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" -#define SSL_CERT_PATH "src/core/lib/tsi/test_creds/server1.pem" -#define SSL_KEY_PATH "src/core/lib/tsi/test_creds/server1.key" -#define SSL_CA_PATH "src/core/lib/tsi/test_creds/ca.pem" +#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" +#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" +#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" // Arguments for TLS server thread. typedef struct { @@ -146,7 +146,7 @@ static int alpn_select_cb(SSL *ssl, const uint8_t **out, uint8_t *out_len, // Minimal TLS server. This is largely based on the example at // https://wiki.openssl.org/index.php/Simple_TLS_Server and the gRPC core -// internals in src/core/lib/tsi/ssl_transport_security.c. +// internals in src/core/tsi/ssl_transport_security.c. static void server_thread(void *arg) { const server_args *args = (server_args *)arg; @@ -172,7 +172,7 @@ static void server_thread(void *arg) { } // Set the cipher list to match the one expressed in - // src/core/lib/tsi/ssl_transport_security.c. + // src/core/tsi/ssl_transport_security.c. const char *cipher_list = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; diff --git a/test/core/handshake/server_ssl.c b/test/core/handshake/server_ssl.c index 0bd5a03cff..e568a37014 100644 --- a/test/core/handshake/server_ssl.c +++ b/test/core/handshake/server_ssl.c @@ -49,9 +49,9 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" -#define SSL_CERT_PATH "src/core/lib/tsi/test_creds/server1.pem" -#define SSL_KEY_PATH "src/core/lib/tsi/test_creds/server1.key" -#define SSL_CA_PATH "src/core/lib/tsi/test_creds/ca.pem" +#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" +#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" +#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" // Handshake completed signal to server thread. static gpr_event client_handshake_complete; @@ -174,7 +174,7 @@ static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, } // Set the cipher list to match the one expressed in - // src/core/lib/tsi/ssl_transport_security.c. + // src/core/tsi/ssl_transport_security.c. const char *cipher_list = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; 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/http/test_server.py b/test/core/http/test_server.py index 86c2fe96bf..dbbf5ceb3c 100755 --- a/test/core/http/test_server.py +++ b/test/core/http/test_server.py @@ -36,8 +36,8 @@ import os import ssl import sys -_PEM = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/lib/tsi/test_creds/server1.pem')) -_KEY = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/lib/tsi/test_creds/server1.key')) +_PEM = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/tsi/test_creds/server1.pem')) +_KEY = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/tsi/test_creds/server1.key')) print _PEM open(_PEM).close() diff --git a/test/core/iomgr/ev_epoll_linux_test.c b/test/core/iomgr/ev_epoll_linux_test.c index d69f9a9d15..5f8124aeda 100644 --- a/test/core/iomgr/ev_epoll_linux_test.c +++ b/test/core/iomgr/ev_epoll_linux_test.c @@ -43,6 +43,8 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include <grpc/support/thd.h> +#include <grpc/support/useful.h> #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/workqueue.h" @@ -139,23 +141,25 @@ static void increment(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { * polling_island_merge()[ev_epoll_linux.c], where the parent relationship was * inverted. */ + +#define NUM_FDS 2 +#define NUM_POLLSETS 2 +#define NUM_CLOSURES 4 + static void test_pollset_queue_merge_items() { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - const int num_fds = 2; - const int num_pollsets = 2; - const int num_closures = 4; - test_fd tfds[num_fds]; - int fds[num_fds]; - test_pollset pollsets[num_pollsets]; - grpc_closure closures[num_closures]; + test_fd tfds[NUM_FDS]; + int fds[NUM_FDS]; + test_pollset pollsets[NUM_POLLSETS]; + grpc_closure closures[NUM_CLOSURES]; int i; int result = 0; - test_fd_init(tfds, fds, num_fds); - test_pollset_init(pollsets, num_pollsets); + test_fd_init(tfds, fds, NUM_FDS); + test_pollset_init(pollsets, NUM_POLLSETS); /* Two distinct polling islands, each with their own FD and pollset. */ - for (i = 0; i < num_fds; i++) { + for (i = 0; i < NUM_FDS; i++) { grpc_pollset_add_fd(&exec_ctx, pollsets[i].pollset, tfds[i].fd); grpc_exec_ctx_flush(&exec_ctx); } @@ -173,7 +177,7 @@ static void test_pollset_queue_merge_items() { grpc_closure_init( closures + 3, increment, &result, grpc_workqueue_scheduler(grpc_fd_get_polling_island(tfds[1].fd))); - for (i = 0; i < num_closures; ++i) { + for (i = 0; i < NUM_CLOSURES; ++i) { grpc_closure_sched(&exec_ctx, closures + i, GRPC_ERROR_NONE); } @@ -186,7 +190,7 @@ static void test_pollset_queue_merge_items() { * the merged polling island. */ grpc_pollset_worker *worker = NULL; - for (i = 0; i < num_closures; ++i) { + for (i = 0; i < NUM_CLOSURES; ++i) { const gpr_timespec deadline = gpr_time_add( gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(2, GPR_TIMESPAN)); gpr_mu_lock(pollsets[1].mu); @@ -196,13 +200,17 @@ static void test_pollset_queue_merge_items() { gpr_now(GPR_CLOCK_MONOTONIC), deadline)); gpr_mu_unlock(pollsets[1].mu); } - GPR_ASSERT(result == num_closures); + GPR_ASSERT(result == NUM_CLOSURES); - test_fd_cleanup(&exec_ctx, tfds, num_fds); - test_pollset_cleanup(&exec_ctx, pollsets, num_pollsets); + test_fd_cleanup(&exec_ctx, tfds, NUM_FDS); + test_pollset_cleanup(&exec_ctx, pollsets, NUM_POLLSETS); grpc_exec_ctx_finish(&exec_ctx); } +#undef NUM_FDS +#undef NUM_POLLSETS +#undef NUM_CLOSURES + /* * Cases to test: * case 1) Polling islands of both fd and pollset are NULL @@ -213,18 +221,20 @@ static void test_pollset_queue_merge_items() { * case 4.2) Polling islands of fd and pollset are NOT-equal (This results * in a merge) * */ + +#define NUM_FDS 8 +#define NUM_POLLSETS 4 + static void test_add_fd_to_pollset() { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - const int num_fds = 8; - const int num_pollsets = 4; - test_fd tfds[num_fds]; - int fds[num_fds]; - test_pollset pollsets[num_pollsets]; + test_fd tfds[NUM_FDS]; + int fds[NUM_FDS]; + test_pollset pollsets[NUM_POLLSETS]; void *expected_pi = NULL; int i; - test_fd_init(tfds, fds, num_fds); - test_pollset_init(pollsets, num_pollsets); + test_fd_init(tfds, fds, NUM_FDS); + test_pollset_init(pollsets, NUM_POLLSETS); /*Step 1. * Create three polling islands (This will exercise test case 1 and 2) with @@ -285,22 +295,107 @@ static void test_add_fd_to_pollset() { /* Compare Fd:0's polling island with that of all other Fds */ expected_pi = grpc_fd_get_polling_island(tfds[0].fd); - for (i = 1; i < num_fds; i++) { + for (i = 1; i < NUM_FDS; i++) { GPR_ASSERT(grpc_are_polling_islands_equal( expected_pi, grpc_fd_get_polling_island(tfds[i].fd))); } /* Compare Fd:0's polling island with that of all other pollsets */ - for (i = 0; i < num_pollsets; i++) { + for (i = 0; i < NUM_POLLSETS; i++) { GPR_ASSERT(grpc_are_polling_islands_equal( expected_pi, grpc_pollset_get_polling_island(pollsets[i].pollset))); } - test_fd_cleanup(&exec_ctx, tfds, num_fds); - test_pollset_cleanup(&exec_ctx, pollsets, num_pollsets); + test_fd_cleanup(&exec_ctx, tfds, NUM_FDS); + test_pollset_cleanup(&exec_ctx, pollsets, NUM_POLLSETS); grpc_exec_ctx_finish(&exec_ctx); } +#undef NUM_FDS +#undef NUM_POLLSETS + +typedef struct threading_shared { + gpr_mu *mu; + grpc_pollset *pollset; + grpc_wakeup_fd *wakeup_fd; + grpc_fd *wakeup_desc; + grpc_closure on_wakeup; + int wakeups; +} threading_shared; + +static __thread int thread_wakeups = 0; + +static void test_threading_loop(void *arg) { + threading_shared *shared = arg; + while (thread_wakeups < 1000000) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_worker *worker; + gpr_mu_lock(shared->mu); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, shared->pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), + gpr_inf_future(GPR_CLOCK_MONOTONIC)))); + gpr_mu_unlock(shared->mu); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_threading_wakeup(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + threading_shared *shared = arg; + ++shared->wakeups; + ++thread_wakeups; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "consume_wakeup", grpc_wakeup_fd_consume_wakeup(shared->wakeup_fd))); + grpc_fd_notify_on_read(exec_ctx, shared->wakeup_desc, &shared->on_wakeup); + GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_next", + grpc_wakeup_fd_wakeup(shared->wakeup_fd))); +} + +static void test_threading(void) { + threading_shared shared; + shared.pollset = gpr_zalloc(grpc_pollset_size()); + grpc_pollset_init(shared.pollset, &shared.mu); + + gpr_thd_id thds[10]; + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + gpr_thd_new(&thds[i], test_threading_loop, &shared, &opt); + } + grpc_wakeup_fd fd; + GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_fd_init", grpc_wakeup_fd_init(&fd))); + shared.wakeup_fd = &fd; + shared.wakeup_desc = grpc_fd_create(fd.read_fd, "wakeup"); + shared.wakeups = 0; + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_add_fd(&exec_ctx, shared.pollset, shared.wakeup_desc); + grpc_fd_notify_on_read( + &exec_ctx, shared.wakeup_desc, + grpc_closure_init(&shared.on_wakeup, test_threading_wakeup, &shared, + grpc_schedule_on_exec_ctx)); + grpc_exec_ctx_finish(&exec_ctx); + } + GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_first", + grpc_wakeup_fd_wakeup(shared.wakeup_fd))); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + fd.read_fd = 0; + grpc_wakeup_fd_destroy(&fd); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_fd_orphan(&exec_ctx, shared.wakeup_desc, NULL, NULL, "done"); + grpc_pollset_shutdown(&exec_ctx, shared.pollset, + grpc_closure_create(destroy_pollset, shared.pollset, + grpc_schedule_on_exec_ctx)); + grpc_exec_ctx_finish(&exec_ctx); + } + gpr_free(shared.pollset); +} + int main(int argc, char **argv) { const char *poll_strategy = NULL; grpc_test_init(argc, argv); @@ -310,6 +405,7 @@ int main(int argc, char **argv) { if (poll_strategy != NULL && strcmp(poll_strategy, "epoll") == 0) { test_add_fd_to_pollset(); test_pollset_queue_merge_items(); + test_threading(); } else { gpr_log(GPR_INFO, "Skipping the test. The test is only relevant for 'epoll' " diff --git a/test/core/iomgr/resource_quota_test.c b/test/core/iomgr/resource_quota_test.c index a5b28f210d..ebce8b9da6 100644 --- a/test/core/iomgr/resource_quota_test.c +++ b/test/core/iomgr/resource_quota_test.c @@ -682,6 +682,56 @@ static void test_one_slice_deleted_late(void) { } } +static void test_resize_to_zero(void) { + gpr_log(GPR_INFO, "** test_resize_to_zero **"); + grpc_resource_quota *q = grpc_resource_quota_create("test_resize_to_zero"); + grpc_resource_quota_resize(q, 0); + grpc_resource_quota_unref(q); +} + +static void test_negative_rq_free_pool(void) { + gpr_log(GPR_INFO, "** test_negative_rq_free_pool **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_negative_rq_free_pool"); + grpc_resource_quota_resize(q, 1024); + + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + + grpc_resource_user_slice_allocator alloc; + int num_allocs = 0; + grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs); + + grpc_slice_buffer buffer; + grpc_slice_buffer_init(&buffer); + + { + const int start_allocs = num_allocs; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(num_allocs == start_allocs + 1); + } + + grpc_resource_quota_resize(q, 512); + + double eps = 0.0001; + GPR_ASSERT(grpc_resource_quota_get_memory_pressure(q) < 1 + eps); + GPR_ASSERT(grpc_resource_quota_get_memory_pressure(q) > 1 - eps); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_unref(&exec_ctx, usr); + grpc_exec_ctx_finish(&exec_ctx); + } + + grpc_resource_quota_unref(q); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); + grpc_exec_ctx_finish(&exec_ctx); + } +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_init(); @@ -705,6 +755,8 @@ int main(int argc, char **argv) { test_reclaimers_can_be_posted_repeatedly(); test_one_slice(); test_one_slice_deleted_late(); + test_resize_to_zero(); + test_negative_rq_free_pool(); grpc_shutdown(); return 0; } diff --git a/test/core/iomgr/timer_heap_test.c b/test/core/iomgr/timer_heap_test.c index 410d972313..153304fa7b 100644 --- a/test/core/iomgr/timer_heap_test.c +++ b/test/core/iomgr/timer_heap_test.c @@ -47,13 +47,7 @@ #include "test/core/util/test_config.h" -static gpr_timespec random_deadline(void) { - gpr_timespec ts; - ts.tv_sec = rand(); - ts.tv_nsec = rand(); - ts.clock_type = GPR_CLOCK_REALTIME; - return ts; -} +static gpr_atm random_deadline(void) { return rand(); } static grpc_timer *create_test_elements(size_t num_elements) { grpc_timer *elems = gpr_malloc(num_elements * sizeof(grpc_timer)); @@ -78,12 +72,10 @@ static void check_valid(grpc_timer_heap *pq) { size_t left_child = 1u + 2u * i; size_t right_child = left_child + 1u; if (left_child < pq->timer_count) { - GPR_ASSERT(gpr_time_cmp(pq->timers[i]->deadline, - pq->timers[left_child]->deadline) <= 0); + GPR_ASSERT(pq->timers[i]->deadline <= pq->timers[left_child]->deadline); } if (right_child < pq->timer_count) { - GPR_ASSERT(gpr_time_cmp(pq->timers[i]->deadline, - pq->timers[right_child]->deadline) <= 0); + GPR_ASSERT(pq->timers[i]->deadline <= pq->timers[right_child]->deadline); } } } @@ -227,20 +219,19 @@ static void test2(void) { } if (num_inserted) { - gpr_timespec *min_deadline = NULL; + gpr_atm *min_deadline = NULL; for (size_t i = 0; i < elems_size; i++) { if (elems[i].inserted) { if (min_deadline == NULL) { min_deadline = &elems[i].elem.deadline; } else { - if (gpr_time_cmp(elems[i].elem.deadline, *min_deadline) < 0) { + if (elems[i].elem.deadline < *min_deadline) { min_deadline = &elems[i].elem.deadline; } } } } - GPR_ASSERT( - 0 == gpr_time_cmp(grpc_timer_heap_top(&pq)->deadline, *min_deadline)); + GPR_ASSERT(grpc_timer_heap_top(&pq)->deadline == *min_deadline); } } diff --git a/test/core/iomgr/timer_list_test.c b/test/core/iomgr/timer_list_test.c index 85ad5277cc..46e41dd449 100644 --- a/test/core/iomgr/timer_list_test.c +++ b/test/core/iomgr/timer_list_test.c @@ -45,6 +45,9 @@ #define MAX_CB 30 +extern int grpc_timer_trace; +extern int grpc_timer_check_trace; + static int cb_called[MAX_CB][2]; static void cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { @@ -57,7 +60,11 @@ static void add_test(void) { grpc_timer timers[20]; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_log(GPR_INFO, "add_test"); + grpc_timer_list_init(start); + grpc_timer_trace = 1; + grpc_timer_check_trace = 1; memset(cb_called, 0, sizeof(cb_called)); /* 10 ms timers. will expire in the current epoch */ @@ -120,9 +127,7 @@ static void add_test(void) { } static gpr_timespec tfm(int m) { - gpr_timespec t = gpr_time_from_millis(m, GPR_TIMESPAN); - t.clock_type = GPR_CLOCK_REALTIME; - return t; + return gpr_time_from_millis(m, GPR_CLOCK_REALTIME); } /* Cleaning up a list with pending timers. */ @@ -130,7 +135,11 @@ void destruction_test(void) { grpc_timer timers[5]; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_log(GPR_INFO, "destruction_test"); + grpc_timer_list_init(gpr_time_0(GPR_CLOCK_REALTIME)); + grpc_timer_trace = 1; + grpc_timer_check_trace = 1; memset(cb_called, 0, sizeof(cb_called)); grpc_timer_init( @@ -170,6 +179,7 @@ void destruction_test(void) { int main(int argc, char **argv) { grpc_test_init(argc, argv); + gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); add_test(); destruction_test(); return 0; 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/nanopb/fuzzer_response.c b/test/core/nanopb/fuzzer_response.c index 202c120c67..35c0efe90d 100644 --- a/test/core/nanopb/fuzzer_response.c +++ b/test/core/nanopb/fuzzer_response.c @@ -36,7 +36,7 @@ #include <grpc/support/alloc.h> -#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h" +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" bool squelch = true; bool leak_check = true; diff --git a/test/core/nanopb/fuzzer_serverlist.c b/test/core/nanopb/fuzzer_serverlist.c index b225ae0d51..e1df401968 100644 --- a/test/core/nanopb/fuzzer_serverlist.c +++ b/test/core/nanopb/fuzzer_serverlist.c @@ -36,7 +36,7 @@ #include <grpc/support/alloc.h> -#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h" +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" bool squelch = true; bool leak_check = true; diff --git a/test/core/security/BUILD b/test/core/security/BUILD index 1cb03c5cfe..8c63f9143d 100644 --- a/test/core/security/BUILD +++ b/test/core/security/BUILD @@ -55,13 +55,6 @@ cc_test( ) cc_test( - name = "b64_test", - srcs = ["b64_test.c"], - deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"], - copts = ['-std=c99'] -) - -cc_test( name = "credentials_test", srcs = ["credentials_test.c"], deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"], diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c index 5cebb09bb2..97dfe87896 100644 --- a/test/core/security/json_token_test.c +++ b/test/core/security/json_token_test.c @@ -43,7 +43,7 @@ #include "src/core/lib/json/json.h" #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" -#include "src/core/lib/security/util/b64.h" +#include "src/core/lib/slice/b64.h" #include "src/core/lib/slice/slice_internal.h" #include "test/core/util/test_config.h" diff --git a/test/core/security/jwt_verifier_test.c b/test/core/security/jwt_verifier_test.c index 0a73f67528..7eec780a91 100644 --- a/test/core/security/jwt_verifier_test.c +++ b/test/core/security/jwt_verifier_test.c @@ -44,7 +44,7 @@ #include "src/core/lib/http/httpcli.h" #include "src/core/lib/security/credentials/jwt/json_token.h" -#include "src/core/lib/security/util/b64.h" +#include "src/core/lib/slice/b64.h" #include "test/core/util/test_config.h" /* This JSON key was generated with the GCE console and revoked immediately. diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index b3775e91a7..8f11f98a9c 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -43,7 +43,7 @@ #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/tsi/fake_transport_security.h" +#include "src/core/tsi/fake_transport_security.h" #include "test/core/util/test_config.h" static gpr_mu *g_mu; diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c index 4219b134f2..6c7b8e688f 100644 --- a/test/core/security/security_connector_test.c +++ b/test/core/security/security_connector_test.c @@ -46,8 +46,8 @@ #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/tmpfile.h" -#include "src/core/lib/tsi/ssl_transport_security.h" -#include "src/core/lib/tsi/transport_security.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security.h" #include "test/core/util/test_config.h" static int check_transport_security_type(const grpc_auth_context *ctx) { diff --git a/test/core/slice/BUILD b/test/core/slice/BUILD index 67a4706348..4d64d0a818 100644 --- a/test/core/slice/BUILD +++ b/test/core/slice/BUILD @@ -52,3 +52,10 @@ cc_test( deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"], copts = ['-std=c99'] ) + +cc_test( + name = "b64_test", + srcs = ["b64_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/security/b64_test.c b/test/core/slice/b64_test.c index 28af48075e..9e5c06551c 100644 --- a/test/core/security/b64_test.c +++ b/test/core/slice/b64_test.c @@ -31,7 +31,7 @@ * */ -#include "src/core/lib/security/util/b64.h" +#include "src/core/lib/slice/b64.h" #include <string.h> diff --git a/test/core/support/arena_test.c b/test/core/support/arena_test.c index 35b2bbd1b1..9eba8a0fa6 100644 --- a/test/core/support/arena_test.c +++ b/test/core/support/arena_test.c @@ -83,9 +83,13 @@ static void test(const char *name, size_t init_size, const size_t *allocs, static const size_t allocs_##name[] = {__VA_ARGS__}; \ test(#name, init_size, allocs_##name, GPR_ARRAY_SIZE(allocs_##name)) -#define CONCURRENT_TEST_ITERATIONS 100000 #define CONCURRENT_TEST_THREADS 100 +size_t concurrent_test_iterations() { + if (sizeof(void *) < 8) return 1000; + return 100000; +} + typedef struct { gpr_event ev_start; gpr_arena *arena; @@ -94,7 +98,7 @@ typedef struct { static void concurrent_test_body(void *arg) { concurrent_test_args *a = arg; gpr_event_wait(&a->ev_start, gpr_inf_future(GPR_CLOCK_REALTIME)); - for (size_t i = 0; i < CONCURRENT_TEST_ITERATIONS; i++) { + for (size_t i = 0; i < concurrent_test_iterations(); i++) { *(char *)gpr_arena_alloc(a->arena, 1) = (char)i; } } diff --git a/test/core/support/time_test.c b/test/core/support/time_test.c index e9ca08d041..4cb36a788c 100644 --- a/test/core/support/time_test.c +++ b/test/core/support/time_test.c @@ -255,6 +255,22 @@ static void test_similar(void) { gpr_time_from_micros(10, GPR_TIMESPAN))); } +static void test_convert_extreme(void) { + gpr_timespec realtime = {INT64_MAX, 1, GPR_CLOCK_REALTIME}; + gpr_timespec monotime = gpr_convert_clock_type(realtime, GPR_CLOCK_MONOTONIC); + GPR_ASSERT(monotime.tv_sec == realtime.tv_sec); + GPR_ASSERT(monotime.clock_type == GPR_CLOCK_MONOTONIC); +} + +static void test_cmp_extreme(void) { + gpr_timespec t1 = {INT64_MAX, 1, GPR_CLOCK_REALTIME}; + gpr_timespec t2 = {INT64_MAX, 2, GPR_CLOCK_REALTIME}; + GPR_ASSERT(gpr_time_cmp(t1, t2) == 0); + t1.tv_sec = INT64_MIN; + t2.tv_sec = INT64_MIN; + GPR_ASSERT(gpr_time_cmp(t1, t2) == 0); +} + int main(int argc, char *argv[]) { grpc_test_init(argc, argv); @@ -263,5 +279,7 @@ int main(int argc, char *argv[]) { test_overflow(); test_sticky_infinities(); test_similar(); + test_convert_extreme(); + test_cmp_extreme(); return 0; } diff --git a/test/core/surface/channel_create_test.c b/test/core/surface/channel_create_test.c index 654e5324d9..21bf6a0b7d 100644 --- a/test/core/surface/channel_create_test.c +++ b/test/core/surface/channel_create_test.c @@ -36,7 +36,7 @@ #include <grpc/grpc.h> #include <grpc/support/log.h> -#include "src/core/ext/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/surface/channel.h" #include "test/core/util/test_config.h" diff --git a/test/core/surface/secure_channel_create_test.c b/test/core/surface/secure_channel_create_test.c index 567f8ae16e..adb956cd8b 100644 --- a/test/core/surface/secure_channel_create_test.c +++ b/test/core/surface/secure_channel_create_test.c @@ -36,7 +36,7 @@ #include <grpc/grpc.h> #include <grpc/grpc_security.h> #include <grpc/support/log.h> -#include "src/core/ext/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/surface/channel.h" diff --git a/test/core/surface/server_chttp2_test.c b/test/core/surface/server_chttp2_test.c index 6c178abdad..8d40c64654 100644 --- a/test/core/surface/server_chttp2_test.c +++ b/test/core/surface/server_chttp2_test.c @@ -39,7 +39,7 @@ #include <grpc/support/time.h> #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" -#include "src/core/lib/tsi/fake_transport_security.h" +#include "src/core/tsi/fake_transport_security.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" diff --git a/test/core/tsi/transport_security_test.c b/test/core/tsi/transport_security_test.c index 01e8770b24..ee4a37c314 100644 --- a/test/core/tsi/transport_security_test.c +++ b/test/core/tsi/transport_security_test.c @@ -31,7 +31,7 @@ * */ -#include "src/core/lib/tsi/transport_security.h" +#include "src/core/tsi/transport_security.h" #include <string.h> @@ -43,8 +43,8 @@ #include <openssl/crypto.h> #include "src/core/lib/support/string.h" -#include "src/core/lib/tsi/fake_transport_security.h" -#include "src/core/lib/tsi/ssl_transport_security.h" +#include "src/core/tsi/fake_transport_security.h" +#include "src/core/tsi/ssl_transport_security.h" #include "test/core/util/test_config.h" typedef struct { diff --git a/test/core/util/BUILD b/test/core/util/BUILD index e6d0d247db..03c79f1f15 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -56,9 +56,11 @@ cc_library( "reconnect_server.c", "slice_splitter.c", "test_tcp_server.c", + "trickle_endpoint.c", ], hdrs = [ "debugger_macros.h", + "trickle_endpoint.h", "grpc_profiler.h", "mock_endpoint.h", "parse_hexstring.h", diff --git a/test/core/util/debugger_macros.c b/test/core/util/debugger_macros.c index de6a2f38a7..af61d933dd 100644 --- a/test/core/util/debugger_macros.c +++ b/test/core/util/debugger_macros.c @@ -39,7 +39,7 @@ #include <stdio.h> -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/surface/call.h" diff --git a/test/cpp/common/BUILD b/test/cpp/common/BUILD index 0e2db00f0a..48ad583981 100644 --- a/test/cpp/common/BUILD +++ b/test/cpp/common/BUILD @@ -34,3 +34,27 @@ cc_test( srcs = ["alarm_cpp_test.cc"], deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util"], ) + +cc_test( + name = "auth_property_iterator_test", + srcs = ["auth_property_iterator_test.cc"], + deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util", "//test/cpp/util:test_util"], +) + +cc_test( + name = "channel_arguments_test", + srcs = ["channel_arguments_test.cc"], + deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util"], +) + +cc_test( + name = "channel_filter_test", + srcs = ["channel_filter_test.cc"], + deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util"], +) + +cc_test( + name = "secure_auth_context_test", + srcs = ["secure_auth_context_test.cc"], + deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util", "//test/cpp/util:test_util"], +) diff --git a/test/cpp/common/channel_arguments_test.cc b/test/cpp/common/channel_arguments_test.cc index 9bcc9f99f6..8e7b56cbd6 100644 --- a/test/cpp/common/channel_arguments_test.cc +++ b/test/cpp/common/channel_arguments_test.cc @@ -243,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/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 32e8a41795..0b5215ef8e 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -484,6 +484,81 @@ TEST_P(AsyncEnd2endTest, SimpleClientStreaming) { EXPECT_TRUE(recv_status.ok()); } +// Two pings and a final pong. +TEST_P(AsyncEnd2endTest, SimpleClientStreamingWithCoalescingApi) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + ClientContext cli_ctx; + ServerContext srv_ctx; + ServerAsyncReader<EchoResponse, EchoRequest> srv_stream(&srv_ctx); + + send_request.set_message(GetParam().message_content); + cli_ctx.set_initial_metadata_corked(true); + // tag:1 never comes up since no op is performed + std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream( + stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1))); + + service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), + tag(2)); + + cli_stream->Write(send_request, tag(3)); + + // 65536(64KB) is the default flow control window size. Should change this + // number when default flow control window size changes. For the write of + // send_request larger than the flow control window size, tag:3 will not come + // up until server read is initiated. For write of send_request smaller than + // the flow control window size, the request can take the free ride with + // initial metadata due to coalescing, thus write tag:3 will come up here. + if (GetParam().message_content.length() < 65536) { + Verifier(GetParam().disable_blocking) + .Expect(2, true) + .Expect(3, true) + .Verify(cq_.get()); + } else { + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); + } + + srv_stream.Read(&recv_request, tag(4)); + + if (GetParam().message_content.length() < 65536) { + Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get()); + } else { + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); + } + + EXPECT_EQ(send_request.message(), recv_request.message()); + + cli_stream->WriteLast(send_request, WriteOptions(), tag(5)); + srv_stream.Read(&recv_request, tag(6)); + Verifier(GetParam().disable_blocking) + .Expect(5, true) + .Expect(6, true) + .Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + srv_stream.Read(&recv_request, tag(7)); + Verifier(GetParam().disable_blocking).Expect(7, false).Verify(cq_.get()); + + send_response.set_message(recv_request.message()); + srv_stream.Finish(send_response, Status::OK, tag(8)); + cli_stream->Finish(&recv_status, tag(9)); + Verifier(GetParam().disable_blocking) + .Expect(8, true) + .Expect(9, true) + .Verify(cq_.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + // One ping, two pongs. TEST_P(AsyncEnd2endTest, SimpleServerStreaming) { ResetStub(); @@ -540,6 +615,112 @@ TEST_P(AsyncEnd2endTest, SimpleServerStreaming) { EXPECT_TRUE(recv_status.ok()); } +// One ping, two pongs. Using WriteAndFinish API +TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWAF) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + ClientContext cli_ctx; + ServerContext srv_ctx; + ServerAsyncWriter<EchoResponse> srv_stream(&srv_ctx); + + send_request.set_message(GetParam().message_content); + std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( + stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1))); + + service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, + cq_.get(), cq_.get(), tag(2)); + + Verifier(GetParam().disable_blocking) + .Expect(1, true) + .Expect(2, true) + .Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + srv_stream.Write(send_response, tag(3)); + cli_stream->Read(&recv_response, tag(4)); + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + srv_stream.WriteAndFinish(send_response, WriteOptions(), Status::OK, tag(5)); + cli_stream->Read(&recv_response, tag(6)); + Verifier(GetParam().disable_blocking) + .Expect(5, true) + .Expect(6, true) + .Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->Read(&recv_response, tag(7)); + Verifier(GetParam().disable_blocking).Expect(7, false).Verify(cq_.get()); + + cli_stream->Finish(&recv_status, tag(8)); + Verifier(GetParam().disable_blocking).Expect(8, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +// One ping, two pongs. Using WriteLast API +TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWL) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + ClientContext cli_ctx; + ServerContext srv_ctx; + ServerAsyncWriter<EchoResponse> srv_stream(&srv_ctx); + + send_request.set_message(GetParam().message_content); + std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( + stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1))); + + service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, + cq_.get(), cq_.get(), tag(2)); + + Verifier(GetParam().disable_blocking) + .Expect(1, true) + .Expect(2, true) + .Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + srv_stream.Write(send_response, tag(3)); + cli_stream->Read(&recv_response, tag(4)); + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + srv_stream.WriteLast(send_response, WriteOptions(), tag(5)); + cli_stream->Read(&recv_response, tag(6)); + srv_stream.Finish(Status::OK, tag(7)); + Verifier(GetParam().disable_blocking) + .Expect(5, true) + .Expect(6, true) + .Expect(7, true) + .Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->Read(&recv_response, tag(8)); + Verifier(GetParam().disable_blocking).Expect(8, false).Verify(cq_.get()); + + cli_stream->Finish(&recv_status, tag(9)); + Verifier(GetParam().disable_blocking).Expect(9, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + // One ping, one pong. TEST_P(AsyncEnd2endTest, SimpleBidiStreaming) { ResetStub(); @@ -599,6 +780,144 @@ TEST_P(AsyncEnd2endTest, SimpleBidiStreaming) { EXPECT_TRUE(recv_status.ok()); } +// One ping, one pong. Using server:WriteAndFinish api +TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWAF) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + ClientContext cli_ctx; + ServerContext srv_ctx; + ServerAsyncReaderWriter<EchoResponse, EchoRequest> srv_stream(&srv_ctx); + + send_request.set_message(GetParam().message_content); + cli_ctx.set_initial_metadata_corked(true); + std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>> + cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1))); + + service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), + tag(2)); + + cli_stream->WriteLast(send_request, WriteOptions(), tag(3)); + + // 65536(64KB) is the default flow control window size. Should change this + // number when default flow control window size changes. For the write of + // send_request larger than the flow control window size, tag:3 will not come + // up until server read is initiated. For write of send_request smaller than + // the flow control window size, the request can take the free ride with + // initial metadata due to coalescing, thus write tag:3 will come up here. + if (GetParam().message_content.length() < 65536) { + Verifier(GetParam().disable_blocking) + .Expect(2, true) + .Expect(3, true) + .Verify(cq_.get()); + } else { + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); + } + + srv_stream.Read(&recv_request, tag(4)); + + if (GetParam().message_content.length() < 65536) { + Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get()); + } else { + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); + } + EXPECT_EQ(send_request.message(), recv_request.message()); + + srv_stream.Read(&recv_request, tag(5)); + Verifier(GetParam().disable_blocking).Expect(5, false).Verify(cq_.get()); + + send_response.set_message(recv_request.message()); + srv_stream.WriteAndFinish(send_response, WriteOptions(), Status::OK, tag(6)); + cli_stream->Read(&recv_response, tag(7)); + Verifier(GetParam().disable_blocking) + .Expect(6, true) + .Expect(7, true) + .Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->Finish(&recv_status, tag(8)); + Verifier(GetParam().disable_blocking).Expect(8, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +// One ping, one pong. Using server:WriteLast api +TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWL) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + ClientContext cli_ctx; + ServerContext srv_ctx; + ServerAsyncReaderWriter<EchoResponse, EchoRequest> srv_stream(&srv_ctx); + + send_request.set_message(GetParam().message_content); + cli_ctx.set_initial_metadata_corked(true); + std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>> + cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1))); + + service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), + tag(2)); + + cli_stream->WriteLast(send_request, WriteOptions(), tag(3)); + + // 65536(64KB) is the default flow control window size. Should change this + // number when default flow control window size changes. For the write of + // send_request larger than the flow control window size, tag:3 will not come + // up until server read is initiated. For write of send_request smaller than + // the flow control window size, the request can take the free ride with + // initial metadata due to coalescing, thus write tag:3 will come up here. + if (GetParam().message_content.length() < 65536) { + Verifier(GetParam().disable_blocking) + .Expect(2, true) + .Expect(3, true) + .Verify(cq_.get()); + } else { + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); + } + + srv_stream.Read(&recv_request, tag(4)); + + if (GetParam().message_content.length() < 65536) { + Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get()); + } else { + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); + } + EXPECT_EQ(send_request.message(), recv_request.message()); + + srv_stream.Read(&recv_request, tag(5)); + Verifier(GetParam().disable_blocking).Expect(5, false).Verify(cq_.get()); + + send_response.set_message(recv_request.message()); + srv_stream.WriteLast(send_response, WriteOptions(), tag(6)); + srv_stream.Finish(Status::OK, tag(7)); + cli_stream->Read(&recv_response, tag(8)); + Verifier(GetParam().disable_blocking) + .Expect(6, true) + .Expect(7, true) + .Expect(8, true) + .Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->Finish(&recv_status, tag(9)); + Verifier(GetParam().disable_blocking).Expect(9, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + // Metadata tests TEST_P(AsyncEnd2endTest, ClientInitialMetadataRpc) { ResetStub(); diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index df78557c43..d3a83b188f 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -702,6 +702,21 @@ TEST_P(End2endTest, RequestStreamOneRequest) { EXPECT_TRUE(s.ok()); } +TEST_P(End2endTest, RequestStreamOneRequestWithCoalescingApi) { + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + context.set_initial_metadata_corked(true); + auto stream = stub_->RequestStream(&context, &response); + request.set_message("hello"); + stream->WriteLast(request, WriteOptions()); + Status s = stream->Finish(); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); +} + TEST_P(End2endTest, RequestStreamTwoRequests) { ResetStub(); EchoRequest request; @@ -718,6 +733,22 @@ TEST_P(End2endTest, RequestStreamTwoRequests) { EXPECT_TRUE(s.ok()); } +TEST_P(End2endTest, RequestStreamTwoRequestsWithCoalescingApi) { + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + context.set_initial_metadata_corked(true); + auto stream = stub_->RequestStream(&context, &response); + request.set_message("hello"); + EXPECT_TRUE(stream->Write(request)); + stream->WriteLast(request, WriteOptions()); + Status s = stream->Finish(); + EXPECT_EQ(response.message(), "hellohello"); + EXPECT_TRUE(s.ok()); +} + TEST_P(End2endTest, ResponseStream) { ResetStub(); EchoRequest request; @@ -738,6 +769,27 @@ TEST_P(End2endTest, ResponseStream) { EXPECT_TRUE(s.ok()); } +TEST_P(End2endTest, ResponseStreamWithCoalescingApi) { + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); + context.AddMetadata(kServerUseCoalescingApi, "1"); + + auto stream = stub_->ResponseStream(&context, request); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "0"); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "1"); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "2"); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); +} + TEST_P(End2endTest, BidiStream) { ResetStub(); EchoRequest request; @@ -770,6 +822,39 @@ TEST_P(End2endTest, BidiStream) { EXPECT_TRUE(s.ok()); } +TEST_P(End2endTest, BidiStreamWithCoalescingApi) { + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.AddMetadata(kServerFinishAfterNReads, "3"); + context.set_initial_metadata_corked(true); + grpc::string msg("hello"); + + auto stream = stub_->BidiStream(&context); + + request.set_message(msg + "0"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "1"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "2"); + stream->WriteLast(request, WriteOptions()); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + EXPECT_FALSE(stream->Read(&response)); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); +} + // Talk to the two services with the same name but different package names. // The two stubs are created on the same channel. TEST_P(End2endTest, DiffPackageServices) { diff --git a/test/cpp/end2end/filter_end2end_test.cc b/test/cpp/end2end/filter_end2end_test.cc index bd384f68b4..2f873eeaa8 100644 --- a/test/cpp/end2end/filter_end2end_test.cc +++ b/test/cpp/end2end/filter_end2end_test.cc @@ -122,8 +122,9 @@ class ChannelDataImpl : public ChannelData { class CallDataImpl : public CallData { public: - void StartTransportStreamOp(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, - TransportStreamOp* op) override { + void StartTransportStreamOpBatch(grpc_exec_ctx* exec_ctx, + grpc_call_element* elem, + TransportStreamOpBatch* op) override { // Incrementing the counter could be done from Init(), but we want // to test that the individual methods are actually called correctly. if (op->recv_initial_metadata() != nullptr) IncrementCallCounter(); diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc index d6664da5a0..fdb2732e50 100644 --- a/test/cpp/end2end/mock_test.cc +++ b/test/cpp/end2end/mock_test.cc @@ -89,7 +89,7 @@ class MockClientReaderWriter<EchoRequest, EchoResponse> final return true; } - bool Write(const EchoRequest& msg, const WriteOptions& options) override { + bool Write(const EchoRequest& msg, WriteOptions options) override { gpr_log(GPR_INFO, "mock recv msg %s", msg.message().c_str()); last_message_ = msg.message(); return true; diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc index 59d36e9cb5..11729c425c 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -246,6 +246,9 @@ Status TestServiceImpl::ResponseStream(ServerContext* context, int server_try_cancel = GetIntValueFromMetadata( kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + int server_coalescing_api = GetIntValueFromMetadata( + kServerUseCoalescingApi, context->client_metadata(), 0); + if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { ServerTryCancel(context); return Status::CANCELLED; @@ -260,7 +263,11 @@ Status TestServiceImpl::ResponseStream(ServerContext* context, for (int i = 0; i < kNumResponseStreamsMsgs; i++) { response.set_message(request->message() + grpc::to_string(i)); - writer->Write(response); + if (i == kNumResponseStreamsMsgs - 1 && server_coalescing_api != 0) { + writer->WriteLast(response, WriteOptions()); + } else { + writer->Write(response); + } } if (server_try_cancel_thd != nullptr) { @@ -305,10 +312,21 @@ Status TestServiceImpl::BidiStream( new std::thread(&TestServiceImpl::ServerTryCancel, this, context); } + // kServerFinishAfterNReads suggests after how many reads, the server should + // write the last message and send status (coalesced using WriteLast) + int server_write_last = GetIntValueFromMetadata( + kServerFinishAfterNReads, context->client_metadata(), 0); + + int read_counts = 0; while (stream->Read(&request)) { + read_counts++; gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); response.set_message(request.message()); - stream->Write(response); + if (read_counts == server_write_last) { + stream->WriteLast(response, WriteOptions()); + } else { + stream->Write(response); + } } if (server_try_cancel_thd != nullptr) { diff --git a/test/cpp/end2end/test_service_impl.h b/test/cpp/end2end/test_service_impl.h index 88e0be7bca..b1f02f93f6 100644 --- a/test/cpp/end2end/test_service_impl.h +++ b/test/cpp/end2end/test_service_impl.h @@ -48,6 +48,8 @@ const int kNumResponseStreamsMsgs = 3; const char* const kServerCancelAfterReads = "cancel_after_reads"; const char* const kServerTryCancelRequest = "server_try_cancel"; const char* const kDebugInfoTrailerKey = "debug-info-bin"; +const char* const kServerFinishAfterNReads = "server_finish_after_n_reads"; +const char* const kServerUseCoalescingApi = "server_use_coalescing_api"; typedef enum { DO_NOT_CANCEL = 0, diff --git a/test/cpp/grpclb/grpclb_api_test.cc b/test/cpp/grpclb/grpclb_api_test.cc index 82ccf436f8..d9df2bb673 100644 --- a/test/cpp/grpclb/grpclb_api_test.cc +++ b/test/cpp/grpclb/grpclb_api_test.cc @@ -34,7 +34,7 @@ #include <grpc++/impl/codegen/config.h> #include <gtest/gtest.h> -#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h" +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/proto/grpc/lb/v1/load_balancer.pb.h" // C++ version diff --git a/test/cpp/grpclb/grpclb_test.cc b/test/cpp/grpclb/grpclb_test.cc index 89ed9249ad..eb3e5b644d 100644 --- a/test/cpp/grpclb/grpclb_test.cc +++ b/test/cpp/grpclb/grpclb_test.cc @@ -51,7 +51,7 @@ #include <grpc++/impl/codegen/config.h> extern "C" { -#include "src/core/ext/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/iomgr/sockaddr.h" diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD new file mode 100644 index 0000000000..38619666dc --- /dev/null +++ b/test/cpp/microbenchmarks/BUILD @@ -0,0 +1,93 @@ +# 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. + +licenses(["notice"]) # 3-clause BSD + +cc_test( + name = "noop-benchmark", + srcs = ["noop-benchmark.cc"], + deps = ["//external:benchmark"], + linkopts = ["-pthread"], +) + +cc_library( + name = "helpers", + srcs = ["helpers.cc"], + hdrs = ["helpers.h", "fullstack_fixtures.h", "fullstack_context_mutators.h"], + deps = ["//:grpc++", "//external:benchmark", "//test/core/util:grpc_test_util", "//src/proto/grpc/testing:echo_proto"], + linkopts = ["-pthread"], +) + +cc_test( + name = "bm_closure", + srcs = ["bm_closure.cc"], + deps = [":helpers"], +) + +cc_test( + name = "bm_cq", + srcs = ["bm_cq.cc"], + deps = [":helpers"], +) + +cc_test( + name = "bm_error", + srcs = ["bm_error.cc"], + deps = [":helpers"], +) + +cc_test( + name = "bm_fullstack_streaming_ping_pong", + srcs = ["bm_fullstack_streaming_ping_pong.cc"], + deps = [":helpers"], + + ) +cc_test( + name = "bm_fullstack_streaming_pump", + srcs = ["bm_fullstack_streaming_pump.cc"], + deps = [":helpers"], +) + +cc_test( + name = "bm_fullstack_trickle", + srcs = ["bm_fullstack_trickle.cc"], + deps = [":helpers"], +) + +cc_test( + name = "bm_fullstack_unary_ping_pong", + srcs = ["bm_fullstack_unary_ping_pong.cc"], + deps = [":helpers"], +) + +cc_test( + name = "bm_metadata", + srcs = ["bm_metadata.cc"], + deps = [":helpers"], +) diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index 1ef8caa690..cc37f0c9e9 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -34,6 +34,7 @@ /* This benchmark exists to ensure that the benchmark integration is * working */ +#include <benchmark/benchmark.h> #include <string.h> #include <sstream> @@ -44,8 +45,8 @@ #include <grpc/support/string_util.h> extern "C" { -#include "src/core/ext/client_channel/client_channel.h" -#include "src/core/ext/load_reporting/load_reporting_filter.h" +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/load_reporting/load_reporting_filter.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/compress_filter.h" #include "src/core/lib/channel/connected_channel.h" @@ -60,7 +61,6 @@ extern "C" { #include "src/cpp/client/create_channel_internal.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/cpp/microbenchmarks/helpers.h" -#include "third_party/benchmark/include/benchmark/benchmark.h" auto &force_library_initialization = Library::get(); @@ -221,7 +221,7 @@ namespace dummy_filter { static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_transport_stream_op *op) {} + grpc_transport_stream_op_batch *op) {} static void StartTransportOp(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, @@ -296,7 +296,7 @@ void SetPollsetSet(grpc_exec_ctx *exec_ctx, grpc_transport *self, /* implementation of grpc_transport_perform_stream_op */ void PerformStreamOp(grpc_exec_ctx *exec_ctx, grpc_transport *self, - grpc_stream *stream, grpc_transport_stream_op *op) { + grpc_stream *stream, grpc_transport_stream_op_batch *op) { grpc_closure_sched(exec_ctx, op->on_complete, GRPC_ERROR_NONE); } @@ -346,13 +346,15 @@ class SendEmptyMetadata { memset(&op_, 0, sizeof(op_)); op_.on_complete = grpc_closure_init(&closure_, DoNothing, nullptr, grpc_schedule_on_exec_ctx); + op_.send_initial_metadata = true; + op_.payload = &op_payload_; } class Op { public: Op(grpc_exec_ctx *exec_ctx, SendEmptyMetadata *p, grpc_call_stack *s) { grpc_metadata_batch_init(&batch_); - p->op_.send_initial_metadata = &batch_; + p->op_payload_.send_initial_metadata.send_initial_metadata = &batch_; } void Finish(grpc_exec_ctx *exec_ctx) { grpc_metadata_batch_destroy(exec_ctx, &batch_); @@ -366,7 +368,8 @@ class SendEmptyMetadata { const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC); const gpr_timespec start_time_ = gpr_now(GPR_CLOCK_MONOTONIC); const grpc_slice method_ = grpc_slice_from_static_string("/foo/bar"); - grpc_transport_stream_op op_; + grpc_transport_stream_op_batch op_; + grpc_transport_stream_op_batch_payload op_payload_; grpc_closure closure_; }; @@ -488,13 +491,16 @@ namespace isolated_call_filter { static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_transport_stream_op *op) { + grpc_transport_stream_op_batch *op) { if (op->recv_initial_metadata) { - grpc_closure_sched(exec_ctx, op->recv_initial_metadata_ready, - GRPC_ERROR_NONE); + grpc_closure_sched( + exec_ctx, + op->payload->recv_initial_metadata.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->payload->recv_message.recv_message_ready, + GRPC_ERROR_NONE); } grpc_closure_sched(exec_ctx, op->on_complete, GRPC_ERROR_NONE); } diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc index 563db758f7..55d2d2f58d 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc @@ -33,6 +33,7 @@ /* Microbenchmarks around CHTTP2 HPACK operations */ +#include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <string.h> #include <sstream> @@ -40,6 +41,7 @@ extern "C" { #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/transport/static_metadata.h" } #include "test/cpp/microbenchmarks/helpers.h" @@ -69,6 +71,7 @@ template <class Fixture> static void BM_HpackEncoderEncodeHeader(benchmark::State &state) { TrackCounters track_counters; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + static bool logged_representative_output = false; grpc_metadata_batch b; grpc_metadata_batch_init(&b); @@ -87,8 +90,17 @@ static void BM_HpackEncoderEncodeHeader(benchmark::State &state) { grpc_slice_buffer outbuf; grpc_slice_buffer_init(&outbuf); while (state.KeepRunning()) { - grpc_chttp2_encode_header(&exec_ctx, &c, (uint32_t)state.iterations(), &b, - state.range(0), state.range(1), &stats, &outbuf); + uint32_t stream_id = static_cast<uint32_t>(state.iterations()); + grpc_chttp2_encode_header(&exec_ctx, &c, stream_id, &b, state.range(0), + state.range(1), &stats, &outbuf); + if (!logged_representative_output) { + logged_representative_output = true; + for (size_t i = 0; i < outbuf.count; i++) { + char *s = grpc_dump_slice(outbuf.slices[i], GPR_DUMP_HEX); + gpr_log(GPR_DEBUG, "%" PRIdPTR ": %s", i, s); + gpr_free(s); + } + } grpc_slice_buffer_reset_and_unref_internal(&exec_ctx, &outbuf); grpc_exec_ctx_flush(&exec_ctx); } @@ -131,6 +143,28 @@ class SingleInternedElem { } }; +template <int kLength> +class SingleInternedBinaryElem { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + grpc_slice bytes = MakeBytes(); + std::vector<grpc_mdelem> out = {grpc_mdelem_from_slices( + exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("abc-bin")), + grpc_slice_intern(bytes))}; + grpc_slice_unref(bytes); + return out; + } + + private: + static grpc_slice MakeBytes() { + std::vector<char> v; + for (int i = 0; i < kLength; i++) { + v.push_back(static_cast<char>(rand())); + } + return grpc_slice_from_copied_buffer(v.data(), v.size()); + } +}; + class SingleInternedKeyElem { public: static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { @@ -149,6 +183,24 @@ class SingleNonInternedElem { } }; +template <int kLength> +class SingleNonInternedBinaryElem { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + return {grpc_mdelem_from_slices( + exec_ctx, grpc_slice_from_static_string("abc-bin"), MakeBytes())}; + } + + private: + static grpc_slice MakeBytes() { + std::vector<char> v; + for (int i = 0; i < kLength; i++) { + v.push_back(static_cast<char>(rand())); + } + return grpc_slice_from_copied_buffer(v.data(), v.size()); + } +}; + class RepresentativeClientInitialMetadata { public: static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { @@ -195,8 +247,29 @@ BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedKeyElem) ->Args({0, 16384}); BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedElem) ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedBinaryElem<1>) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedBinaryElem<3>) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedBinaryElem<10>) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedBinaryElem<31>) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedBinaryElem<100>) + ->Args({0, 16384}); BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedElem) ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedBinaryElem<1>) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedBinaryElem<3>) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedBinaryElem<10>) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedBinaryElem<31>) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, + SingleNonInternedBinaryElem<100>) + ->Args({0, 16384}); // test with a tiny frame size, to highlight continuation costs BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedElem) ->Args({0, 1}); @@ -255,6 +328,8 @@ static void BM_HpackParserParseHeader(benchmark::State &state) { } grpc_exec_ctx_flush(&exec_ctx); } + for (auto slice : init_slices) grpc_slice_unref(slice); + for (auto slice : benchmark_slices) grpc_slice_unref(slice); grpc_chttp2_hpack_parser_destroy(&exec_ctx, &p); grpc_exec_ctx_finish(&exec_ctx); track_counters.Finish(state); @@ -262,7 +337,7 @@ static void BM_HpackParserParseHeader(benchmark::State &state) { namespace hpack_parser_fixtures { -static grpc_slice MakeSlice(std::initializer_list<uint8_t> bytes) { +static grpc_slice MakeSlice(std::vector<uint8_t> bytes) { grpc_slice s = grpc_slice_malloc(bytes.size()); uint8_t *p = GRPC_SLICE_START_PTR(s); for (auto b : bytes) { @@ -346,6 +421,64 @@ class NonIndexedElem { } }; +class NonIndexedBinaryElem1 { + public: + static std::vector<grpc_slice> GetInitSlices() { return {}; } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice( + {0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x82, 0xf7, 0xb3})}; + } +}; + +class NonIndexedBinaryElem3 { + public: + static std::vector<grpc_slice> GetInitSlices() { return {}; } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x84, + 0x7f, 0x4e, 0x29, 0x3f})}; + } +}; + +class NonIndexedBinaryElem10 { + public: + static std::vector<grpc_slice> GetInitSlices() { return {}; } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', + 'i', 'n', 0x8b, 0x71, 0x0c, 0xa5, 0x81, + 0x73, 0x7b, 0x47, 0x13, 0xe9, 0xf7, 0xe3})}; + } +}; + +class NonIndexedBinaryElem31 { + public: + static std::vector<grpc_slice> GetInitSlices() { return {}; } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', + 0xa3, 0x92, 0x43, 0x7f, 0xbe, 0x7c, 0xea, 0x6f, 0xf3, + 0x3d, 0xa7, 0xa7, 0x67, 0xfb, 0xe2, 0x82, 0xf7, 0xf2, + 0x8f, 0x1f, 0x9d, 0xdf, 0xf1, 0x7e, 0xb3, 0xef, 0xb2, + 0x8f, 0x53, 0x77, 0xce, 0x0c, 0x13, 0xe3, 0xfd, 0x87})}; + } +}; + +class NonIndexedBinaryElem100 { + public: + static std::vector<grpc_slice> GetInitSlices() { return {}; } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice( + {0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0xeb, 0x1d, 0x4d, + 0xe8, 0x96, 0x8c, 0x14, 0x20, 0x06, 0xc1, 0xc3, 0xdf, 0x6e, 0x1f, 0xef, + 0xde, 0x2f, 0xde, 0xb7, 0xf2, 0xfe, 0x6d, 0xd4, 0xe4, 0x7d, 0xf5, 0x55, + 0x46, 0x52, 0x3d, 0x91, 0xf2, 0xd4, 0x6f, 0xca, 0x34, 0xcd, 0xd9, 0x39, + 0xbd, 0x03, 0x27, 0xe3, 0x9c, 0x74, 0xcc, 0x17, 0x34, 0xed, 0xa6, 0x6a, + 0x77, 0x73, 0x10, 0xcd, 0x8e, 0x4e, 0x5c, 0x7c, 0x72, 0x39, 0xd8, 0xe6, + 0x78, 0x6b, 0xdb, 0xa5, 0xb7, 0xab, 0xe7, 0x46, 0xae, 0x21, 0xab, 0x7f, + 0x01, 0x89, 0x13, 0xd7, 0xca, 0x17, 0x6e, 0xcb, 0xd6, 0x79, 0x71, 0x68, + 0xbf, 0x8a, 0x3f, 0x32, 0xe8, 0xba, 0xf5, 0xbe, 0xb3, 0xbc, 0xde, 0x28, + 0xc7, 0xcf, 0x62, 0x7a, 0x58, 0x2c, 0xcf, 0x4d, 0xe3})}; + } +}; + class RepresentativeClientInitialMetadata { public: static std::vector<grpc_slice> GetInitSlices() { @@ -437,6 +570,11 @@ BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleInternedElem); BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleInternedElem); BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleInternedElem); BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedElem); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem1); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem3); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem10); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem31); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem100); BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, RepresentativeClientInitialMetadata); BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, @@ -446,4 +584,23 @@ BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, } // namespace hpack_parser_fixtures +static void BM_Base16SomeStuff(benchmark::State &state) { + uint8_t *bytes = new uint8_t[state.range(0)]; + for (int i = 0; i < state.range(0); i++) { + bytes[i] = static_cast<uint8_t>(rand()); + } + uint8_t *encoded = new uint8_t[state.range(0) * 2]; + static const uint8_t hex[] = "0123456789abcdef"; + while (state.KeepRunning()) { + for (int i = 0; i < state.range(0); i++) { + encoded[2 * i + 0] = hex[encoded[i] >> 8]; + encoded[2 * i + 1] = hex[encoded[i] & 0xf]; + } + } + delete[] encoded; + delete[] bytes; + state.SetBytesProcessed(state.iterations() * state.range(0)); +} +BENCHMARK(BM_Base16SomeStuff)->Range(1, 4096); + BENCHMARK_MAIN(); diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc index 265a5a6b22..1611250850 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc @@ -207,7 +207,7 @@ class Stream { static_cast<grpc_stream *>(stream_), closure); } - void Op(grpc_transport_stream_op *op) { + void Op(grpc_transport_stream_op_batch *op) { grpc_transport_perform_stream_op(f_->exec_ctx(), f_->transport(), static_cast<grpc_stream *>(stream_), op); } @@ -305,10 +305,16 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State &state) { TrackCounters track_counters; Fixture f(grpc::ChannelArguments(), true); Stream s(&f); - grpc_transport_stream_op op; + grpc_transport_stream_op_batch op; + grpc_transport_stream_op_batch_payload op_payload; std::unique_ptr<Closure> start; std::unique_ptr<Closure> done; + auto reset_op = [&]() { + memset(&op, 0, sizeof(op)); + op.payload = &op_payload; + }; + grpc_metadata_batch b; grpc_metadata_batch_init(&b); b.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); @@ -324,14 +330,16 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State &state) { start = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) { if (!state.KeepRunning()) return; s.Init(state); - memset(&op, 0, sizeof(op)); + reset_op(); op.on_complete = done.get(); - op.send_initial_metadata = &b; + op.send_initial_metadata = true; + op.payload->send_initial_metadata.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; + reset_op(); + op.cancel_stream = true; + op.payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED; s.Op(&op); s.DestroyThen(start.get()); }); @@ -348,11 +356,16 @@ static void BM_TransportEmptyOp(benchmark::State &state) { Fixture f(grpc::ChannelArguments(), true); Stream s(&f); s.Init(state); - grpc_transport_stream_op op; + grpc_transport_stream_op_batch op; + grpc_transport_stream_op_batch_payload op_payload; + auto reset_op = [&]() { + memset(&op, 0, sizeof(op)); + op.payload = &op_payload; + }; std::unique_ptr<Closure> c = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) { if (!state.KeepRunning()) return; - memset(&op, 0, sizeof(op)); + reset_op(); op.on_complete = c.get(); s.Op(&op); }); @@ -370,7 +383,12 @@ static void BM_TransportStreamSend(benchmark::State &state) { Fixture f(grpc::ChannelArguments(), true); Stream s(&f); s.Init(state); - grpc_transport_stream_op op; + grpc_transport_stream_op_batch op; + grpc_transport_stream_op_batch_payload op_payload; + auto reset_op = [&]() { + memset(&op, 0, sizeof(op)); + op.payload = &op_payload; + }; grpc_slice_buffer_stream send_stream; grpc_slice_buffer send_buffer; grpc_slice_buffer_init(&send_buffer); @@ -397,20 +415,23 @@ static void BM_TransportStreamSend(benchmark::State &state) { 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)); + reset_op(); op.on_complete = c.get(); - op.send_message = &send_stream.base; + op.send_message = true; + op.payload->send_message.send_message = &send_stream.base; s.Op(&op); }); - memset(&op, 0, sizeof(op)); - op.send_initial_metadata = &b; + reset_op(); + op.send_initial_metadata = true; + op.payload->send_initial_metadata.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; + reset_op(); + op.cancel_stream = true; + op.payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED; s.Op(&op); s.DestroyThen( MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {})); @@ -483,10 +504,16 @@ static void BM_TransportStreamRecv(benchmark::State &state) { Fixture f(grpc::ChannelArguments(), true); Stream s(&f); s.Init(state); - grpc_transport_stream_op op; + grpc_transport_stream_op_batch_payload op_payload; + grpc_transport_stream_op_batch op; grpc_byte_stream *recv_stream; grpc_slice incoming_data = CreateIncomingDataSlice(state.range(0), 16384); + auto reset_op = [&]() { + memset(&op, 0, sizeof(op)); + op.payload = &op_payload; + }; + grpc_metadata_batch b; grpc_metadata_batch_init(&b); grpc_metadata_batch b_recv; @@ -518,10 +545,11 @@ static void BM_TransportStreamRecv(benchmark::State &state) { s.chttp2_stream()->incoming_window_delta = 1024 * 1024 * 1024; f.chttp2_transport()->incoming_window = 1024 * 1024 * 1024; received = 0; - memset(&op, 0, sizeof(op)); + reset_op(); op.on_complete = do_nothing.get(); - op.recv_message = &recv_stream; - op.recv_message_ready = drain_start.get(); + op.recv_message = true; + op.payload->recv_message.recv_message = &recv_stream; + op.payload->recv_message.recv_message_ready = drain_start.get(); s.Op(&op); f.PushInput(grpc_slice_ref(incoming_data)); }); @@ -554,9 +582,13 @@ static void BM_TransportStreamRecv(benchmark::State &state) { 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; + reset_op(); + op.send_initial_metadata = true; + op.payload->send_initial_metadata.send_initial_metadata = &b; + op.recv_initial_metadata = true; + op.payload->recv_initial_metadata.recv_initial_metadata = &b_recv; + op.payload->recv_initial_metadata.recv_initial_metadata_ready = + do_nothing.get(); op.on_complete = c.get(); s.Op(&op); f.PushInput(SLICE_FROM_BUFFER( @@ -573,8 +605,9 @@ static void BM_TransportStreamRecv(benchmark::State &state) { "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip")); f.FlushExecCtx(); - memset(&op, 0, sizeof(op)); - op.cancel_error = GRPC_ERROR_CANCELLED; + reset_op(); + op.cancel_stream = true; + op.payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED; s.Op(&op); s.DestroyThen( MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {})); diff --git a/test/cpp/microbenchmarks/bm_closure.cc b/test/cpp/microbenchmarks/bm_closure.cc index 28a385b6c1..d52fe4ee30 100644 --- a/test/cpp/microbenchmarks/bm_closure.cc +++ b/test/cpp/microbenchmarks/bm_closure.cc @@ -33,7 +33,9 @@ /* Test various closure related operations */ +#include <benchmark/benchmark.h> #include <grpc/grpc.h> +#include <sstream> extern "C" { #include "src/core/lib/iomgr/closure.h" @@ -43,7 +45,6 @@ extern "C" { } #include "test/cpp/microbenchmarks/helpers.h" -#include "third_party/benchmark/include/benchmark/benchmark.h" auto& force_library_initialization = Library::get(); diff --git a/test/cpp/microbenchmarks/bm_cq.cc b/test/cpp/microbenchmarks/bm_cq.cc index 91e6a85101..38ac9d2705 100644 --- a/test/cpp/microbenchmarks/bm_cq.cc +++ b/test/cpp/microbenchmarks/bm_cq.cc @@ -34,12 +34,11 @@ /* This benchmark exists to ensure that the benchmark integration is * working */ +#include <benchmark/benchmark.h> #include <grpc++/completion_queue.h> #include <grpc++/impl/grpc_library.h> #include <grpc/grpc.h> - #include "test/cpp/microbenchmarks/helpers.h" -#include "third_party/benchmark/include/benchmark/benchmark.h" extern "C" { #include "src/core/lib/surface/completion_queue.h" @@ -59,6 +58,17 @@ static void BM_CreateDestroyCpp(benchmark::State& state) { } BENCHMARK(BM_CreateDestroyCpp); +/* Create cq using a different constructor */ +static void BM_CreateDestroyCpp2(benchmark::State& state) { + TrackCounters track_counters; + while (state.KeepRunning()) { + grpc_completion_queue* core_cq = grpc_completion_queue_create(NULL); + CompletionQueue cq(core_cq); + } + track_counters.Finish(state); +} +BENCHMARK(BM_CreateDestroyCpp2); + static void BM_CreateDestroyCore(benchmark::State& state) { TrackCounters track_counters; while (state.KeepRunning()) { diff --git a/test/cpp/microbenchmarks/bm_error.cc b/test/cpp/microbenchmarks/bm_error.cc index 00e1a08cab..ea9777bbe6 100644 --- a/test/cpp/microbenchmarks/bm_error.cc +++ b/test/cpp/microbenchmarks/bm_error.cc @@ -33,6 +33,7 @@ /* Test various operations on grpc_error */ +#include <benchmark/benchmark.h> #include <memory> extern "C" { @@ -41,7 +42,6 @@ extern "C" { } #include "test/cpp/microbenchmarks/helpers.h" -#include "third_party/benchmark/include/benchmark/benchmark.h" auto& force_library_initialization = Library::get(); diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc index 00e37f7912..c536e15a2c 100644 --- a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc +++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc @@ -33,14 +33,13 @@ /* Benchmark gRPC end2end in various configurations */ +#include <benchmark/benchmark.h> #include <sstream> - #include "src/core/lib/profiling/timers.h" #include "src/cpp/client/create_channel_internal.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/cpp/microbenchmarks/fullstack_context_mutators.h" #include "test/cpp/microbenchmarks/fullstack_fixtures.h" -#include "third_party/benchmark/include/benchmark/benchmark.h" namespace grpc { namespace testing { @@ -240,6 +239,173 @@ static void BM_StreamingPingPongMsgs(benchmark::State& state) { state.SetBytesProcessed(msg_size * state.iterations() * 2); } +// Repeatedly makes Streaming Bidi calls (exchanging a configurable number of +// messages in each call) in a loop on a single channel. Different from +// BM_StreamingPingPong we are using stream coalescing api, e.g. WriteLast, +// WriteAndFinish, set_initial_metadata_corked. These apis aim at saving +// sendmsg syscalls for streaming by coalescing 1. initial metadata with first +// message; 2. final streaming message with trailing metadata. +// +// 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): +// Third parameter (i.e state.range(2)): Switch between using WriteAndFinish +// API and WriteLast API for server. +template <class Fixture, class ClientContextMutator, class ServerContextMutator> +static void BM_StreamingPingPongWithCoalescingApi(benchmark::State& state) { + const int msg_size = state.range(0); + const int max_ping_pongs = state.range(1); + // This options is used to test out server API: WriteLast and WriteAndFinish + // respectively, since we can not use both of them on server side at the same + // time. Value 1 means we are testing out the WriteAndFinish API, and + // otherwise we are testing out the WriteLast API. + const int write_and_finish = state.range(2); + + EchoTestService::AsyncService service; + std::unique_ptr<Fixture> fixture(new Fixture(&service)); + { + EchoResponse send_response; + EchoResponse recv_response; + 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')); + } + + std::unique_ptr<EchoTestService::Stub> stub( + EchoTestService::NewStub(fixture->channel())); + + while (state.KeepRunning()) { + 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); + cli_ctx.set_initial_metadata_corked(true); + // tag:1 here will never comes up, since we are not performing any op due + // to initial metadata coalescing. + auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1)); + + void* t; + bool ok; + int need_tags; + + // Send 'max_ping_pongs' number of ping pong messages + int ping_pong_cnt = 0; + while (ping_pong_cnt < max_ping_pongs) { + if (ping_pong_cnt == max_ping_pongs - 1) { + request_rw->WriteLast(send_request, WriteOptions(), tag(2)); + } else { + request_rw->Write(send_request, tag(2)); // Start client send + } + + need_tags = (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5); + + if (ping_pong_cnt == 0) { + // wait for the server call structure (call_hook, etc.) to be + // initialized (async stream between client side and server side + // established). It is necessary when client init metadata is + // coalesced + GPR_ASSERT(fixture->cq()->Next(&t, &ok)); + while ((int)(intptr_t)t != 0) { + // In some cases tag:2 comes before tag:0 (write tag comes out + // first), this while loop is to make sure get tag:0. + int i = (int)(intptr_t)t; + GPR_ASSERT(need_tags & (1 << i)); + need_tags &= ~(1 << i); + GPR_ASSERT(fixture->cq()->Next(&t, &ok)); + } + } + + response_rw.Read(&recv_request, tag(3)); // Start server recv + request_rw->Read(&recv_response, tag(4)); // Start client recv + + 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 == 3) { + if (ping_pong_cnt == max_ping_pongs - 1) { + if (write_and_finish == 1) { + response_rw.WriteAndFinish(send_response, WriteOptions(), + Status::OK, tag(5)); + } else { + response_rw.WriteLast(send_response, WriteOptions(), tag(5)); + // WriteLast buffers the write, so neither server write op nor + // client read op will finish inside the while loop. + need_tags &= ~(1 << 4); + need_tags &= ~(1 << 5); + } + } else { + response_rw.Write(send_response, tag(5)); + } + } + + GPR_ASSERT(need_tags & (1 << i)); + need_tags &= ~(1 << i); + } + + ping_pong_cnt++; + } + + if (max_ping_pongs == 0) { + need_tags = (1 << 6) | (1 << 7) | (1 << 8); + } else { + if (write_and_finish == 1) { + need_tags = (1 << 8); + } else { + // server's buffered write and the client's read of the buffered write + // tags should come up. + need_tags = (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8); + } + } + + // No message write or initial metadata write happened yet. + if (max_ping_pongs == 0) { + request_rw->WritesDone(tag(6)); + // wait for server call data structure(call_hook, etc.) to be + // initialized, since initial metadata is corked. + GPR_ASSERT(fixture->cq()->Next(&t, &ok)); + while ((int)(intptr_t)t != 0) { + int i = (int)(intptr_t)t; + GPR_ASSERT(need_tags & (1 << i)); + need_tags &= ~(1 << i); + GPR_ASSERT(fixture->cq()->Next(&t, &ok)); + } + response_rw.Finish(Status::OK, tag(7)); + } else { + if (write_and_finish != 1) { + response_rw.Finish(Status::OK, tag(7)); + } + } + + Status recv_status; + request_rw->Finish(&recv_status, tag(8)); + + 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(msg_size * state.iterations() * max_ping_pongs * 2); +} + /******************************************************************************* * CONFIGURATIONS */ @@ -270,6 +436,30 @@ BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcessCHTTP2, NoOpMutator, BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, TCP, NoOpMutator, NoOpMutator) ->Range(0, 128 * 1024 * 1024); +// Generate Args for StreamingPingPongWithCoalescingApi benchmarks. Currently +// generates args for only "small streams" (i.e streams with 0, 1 or 2 messages) +static void StreamingPingPongWithCoalescingApiArgs( + benchmark::internal::Benchmark* b) { + int msg_size = 0; + + b->Args( + {0, 0, 0}); // spl case: 0 ping-pong msgs (msg_size doesn't matter here) + b->Args( + {0, 0, 1}); // 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, 0}); + b->Args({msg_size, 2, 0}); + b->Args({msg_size, 1, 1}); + b->Args({msg_size, 2, 1}); + } +} + +BENCHMARK_TEMPLATE(BM_StreamingPingPongWithCoalescingApi, InProcessCHTTP2, + NoOpMutator, NoOpMutator) + ->Apply(StreamingPingPongWithCoalescingApiArgs); + } // namespace testing } // namespace grpc diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc index dc0e7d769a..5c1eb1165b 100644 --- a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc +++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc @@ -33,14 +33,13 @@ /* Benchmark gRPC end2end in various configurations */ +#include <benchmark/benchmark.h> #include <sstream> - #include "src/core/lib/profiling/timers.h" #include "src/cpp/client/create_channel_internal.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/cpp/microbenchmarks/fullstack_context_mutators.h" #include "test/cpp/microbenchmarks/fullstack_fixtures.h" -#include "third_party/benchmark/include/benchmark/benchmark.h" namespace grpc { namespace testing { diff --git a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc index 5011f06368..c563f28b55 100644 --- a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc +++ b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc @@ -33,12 +33,12 @@ /* Benchmark gRPC end2end in various configurations */ +#include <benchmark/benchmark.h> #include "src/core/lib/profiling/timers.h" #include "src/cpp/client/create_channel_internal.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/cpp/microbenchmarks/fullstack_context_mutators.h" #include "test/cpp/microbenchmarks/fullstack_fixtures.h" -#include "third_party/benchmark/include/benchmark/benchmark.h" extern "C" { #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/ext/transport/chttp2/transport/internal.h" diff --git a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc index e51d272b10..615b05b7c7 100644 --- a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc +++ b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc @@ -33,14 +33,13 @@ /* Benchmark gRPC end2end in various configurations */ +#include <benchmark/benchmark.h> #include <sstream> - #include "src/core/lib/profiling/timers.h" #include "src/cpp/client/create_channel_internal.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/cpp/microbenchmarks/fullstack_context_mutators.h" #include "test/cpp/microbenchmarks/fullstack_fixtures.h" -#include "third_party/benchmark/include/benchmark/benchmark.h" namespace grpc { namespace testing { diff --git a/test/cpp/microbenchmarks/bm_metadata.cc b/test/cpp/microbenchmarks/bm_metadata.cc index 34874b57f5..7029f369ad 100644 --- a/test/cpp/microbenchmarks/bm_metadata.cc +++ b/test/cpp/microbenchmarks/bm_metadata.cc @@ -33,17 +33,15 @@ /* Test out various metadata handling primitives */ +#include <benchmark/benchmark.h> #include <grpc/grpc.h> extern "C" { -#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/static_metadata.h" -#include "src/core/lib/transport/transport.h" } #include "test/cpp/microbenchmarks/helpers.h" -#include "third_party/benchmark/include/benchmark/benchmark.h" auto& force_library_initialization = Library::get(); @@ -65,19 +63,6 @@ static void BM_SliceFromCopied(benchmark::State& state) { } BENCHMARK(BM_SliceFromCopied); -static void BM_SliceFromStreamOwnedBuffer(benchmark::State& state) { - grpc_stream_refcount r; - GRPC_STREAM_REF_INIT(&r, 1, NULL, NULL, "test"); - char buffer[64]; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - while (state.KeepRunning()) { - grpc_slice_unref_internal(&exec_ctx, grpc_slice_from_stream_owned_buffer( - &r, buffer, sizeof(buffer))); - } - grpc_exec_ctx_finish(&exec_ctx); -} -BENCHMARK(BM_SliceFromStreamOwnedBuffer); - static void BM_SliceIntern(benchmark::State& state) { TrackCounters track_counters; gpr_slice slice = grpc_slice_from_static_string("abc"); diff --git a/test/cpp/microbenchmarks/helpers.h b/test/cpp/microbenchmarks/helpers.h index f44b7cf83a..49ed517b1d 100644 --- a/test/cpp/microbenchmarks/helpers.h +++ b/test/cpp/microbenchmarks/helpers.h @@ -41,8 +41,8 @@ extern "C" { #include "test/core/util/memory_counters.h" } +#include <benchmark/benchmark.h> #include <grpc++/impl/grpc_library.h> -#include "third_party/benchmark/include/benchmark/benchmark.h" class Library { public: diff --git a/test/cpp/microbenchmarks/noop-benchmark.cc b/test/cpp/microbenchmarks/noop-benchmark.cc index 99fa6d5f6e..7372ad04f2 100644 --- a/test/cpp/microbenchmarks/noop-benchmark.cc +++ b/test/cpp/microbenchmarks/noop-benchmark.cc @@ -34,7 +34,7 @@ /* This benchmark exists to ensure that the benchmark integration is * working */ -#include "third_party/benchmark/include/benchmark/benchmark.h" +#include <benchmark/benchmark.h> static void BM_NoOp(benchmark::State& state) { while (state.KeepRunning()) { diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD new file mode 100644 index 0000000000..6492b63ec3 --- /dev/null +++ b/test/cpp/qps/BUILD @@ -0,0 +1,194 @@ +# 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. + +licenses(["notice"]) # 3-clause BSD + +cc_library( + name = "parse_json", + srcs = ["parse_json.cc"], + hdrs = ["parse_json.h"], + deps = ["//:grpc++"], +) + +cc_library( + name = "qps_worker_impl", + srcs = [ + "client_async.cc", + "client_sync.cc", + "qps_worker.cc", + "server_async.cc", + "server_sync.cc", + ], + hdrs = [ + "client.h", + "qps_worker.h", + "server.h", + ], + deps = [ + ":histogram", + ":interarrival", + ":usage_timer", + "//:grpc", + "//:grpc++", + "//external:gtest", + "//src/proto/grpc/testing:control_proto", + "//src/proto/grpc/testing:payloads_proto", + "//src/proto/grpc/testing:services_proto", + "//test/core/end2end:ssl_test_data", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + +cc_library( + name = "driver_impl", + srcs = [ + "driver.cc", + "report.cc", + ], + hdrs = [ + "driver.h", + "report.h", + ], + deps = [ + ":histogram", + ":parse_json", + ":qps_worker_impl", + "//:grpc++", + "//src/proto/grpc/testing:control_proto", + "//src/proto/grpc/testing:messages_proto", + "//src/proto/grpc/testing:services_proto", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + +cc_library( + name = "benchmark_config", + srcs = [ + "benchmark_config.cc", + ], + hdrs = [ + "benchmark_config.h", + ], + deps = [ + ":driver_impl", + ":histogram", + "//:grpc++", + "//external:gflags", + "//src/proto/grpc/testing:control_proto", + ], +) + +cc_library( + name = "histogram", + hdrs = [ + "histogram.h", + "stats.h", + ], + deps = ["//:gpr"], +) + +cc_library( + name = "interarrival", + hdrs = ["interarrival.h"], + deps = ["//:grpc++"], +) + +cc_binary( + name = "json_run_localhost", + srcs = ["json_run_localhost.cc"], + deps = [ + "//:gpr", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + +cc_test( + name = "qps_interarrival_test", + srcs = ["qps_interarrival_test.cc"], + deps = [ + ":histogram", + ":interarrival", + ], +) + +cc_binary( + name = "qps_json_driver", + srcs = ["qps_json_driver.cc"], + deps = [ + ":benchmark_config", + ":driver_impl", + "//:grpc++", + "//external:gflags", + ], +) + +cc_test( + name = "qps_openloop_test", + srcs = ["qps_openloop_test.cc"], + deps = [ + ":benchmark_config", + ":driver_impl", + ":qps_worker_impl", + ], +) + +cc_test( + name = "secure_sync_unary_ping_pong_test", + srcs = ["secure_sync_unary_ping_pong_test.cc"], + deps = [ + ":benchmark_config", + ":driver_impl", + "//:grpc++", + ], +) + +cc_library( + name = "usage_timer", + srcs = ["usage_timer.cc"], + hdrs = ["usage_timer.h"], + deps = ["//:gpr"], +) + +cc_binary( + name = "qps_worker", + srcs = ["worker.cc"], + deps = [ + ":qps_worker_impl", + "//:grpc++", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_config", + "//test/cpp/util:test_util", + ], +) diff --git a/test/cpp/util/benchmark_config.cc b/test/cpp/qps/benchmark_config.cc index 6fc864069e..98b8d0ba37 100644 --- a/test/cpp/util/benchmark_config.cc +++ b/test/cpp/qps/benchmark_config.cc @@ -31,7 +31,7 @@ * */ -#include "test/cpp/util/benchmark_config.h" +#include "test/cpp/qps/benchmark_config.h" #include <gflags/gflags.h> DEFINE_bool(enable_log_reporter, true, diff --git a/test/cpp/util/benchmark_config.h b/test/cpp/qps/benchmark_config.h index 6b308a15ff..6b308a15ff 100644 --- a/test/cpp/util/benchmark_config.h +++ b/test/cpp/qps/benchmark_config.h diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index 396d308e2a..29a79e7343 100644 --- a/test/cpp/qps/client_async.cc +++ b/test/cpp/qps/client_async.cc @@ -63,13 +63,13 @@ class ClientRpcContext { virtual ~ClientRpcContext() {} // next state, return false if done. Collect stats when appropriate virtual bool RunNextState(bool, HistogramEntry* entry) = 0; - virtual ClientRpcContext* StartNewClone() = 0; + virtual void StartNewClone(CompletionQueue* cq) = 0; static void* tag(ClientRpcContext* c) { return reinterpret_cast<void*>(c); } static ClientRpcContext* detag(void* t) { return reinterpret_cast<ClientRpcContext*>(t); } - virtual void Start(CompletionQueue* cq) = 0; + virtual void Start(CompletionQueue* cq, const ClientConfig& config) = 0; }; template <class RequestType, class ResponseType> @@ -94,22 +94,17 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { next_issue_(next_issue), start_req_(start_req) {} ~ClientRpcContextUnaryImpl() override {} - void Start(CompletionQueue* cq) override { - cq_ = cq; - if (!next_issue_) { // ready to issue - RunNextState(true, nullptr); - } else { // wait for the issue time - alarm_.reset(new Alarm(cq_, next_issue_(), ClientRpcContext::tag(this))); - } + void Start(CompletionQueue* cq, const ClientConfig& config) override { + StartInternal(cq); } bool RunNextState(bool ok, HistogramEntry* entry) override { switch (next_state_) { case State::READY: start_ = UsageTimer::Now(); response_reader_ = start_req_(stub_, &context_, req_, cq_); + next_state_ = State::RESP_DONE; response_reader_->Finish(&response_, &status_, ClientRpcContext::tag(this)); - next_state_ = State::RESP_DONE; return true; case State::RESP_DONE: if (status_.ok()) { @@ -123,9 +118,10 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { return false; } } - ClientRpcContext* StartNewClone() override { - return new ClientRpcContextUnaryImpl(stub_, req_, next_issue_, start_req_, - callback_); + void StartNewClone(CompletionQueue* cq) override { + auto* clone = new ClientRpcContextUnaryImpl(stub_, req_, next_issue_, + start_req_, callback_); + clone->StartInternal(cq); } private: @@ -147,6 +143,15 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { double start_; std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>> response_reader_; + + void StartInternal(CompletionQueue* cq) { + cq_ = cq; + if (!next_issue_) { // ready to issue + RunNextState(true, nullptr); + } else { // wait for the issue time + alarm_.reset(new Alarm(cq_, next_issue_(), ClientRpcContext::tag(this))); + } + } }; typedef std::forward_list<ClientRpcContext*> context_list; @@ -185,7 +190,7 @@ class AsyncClient : public ClientImpl<StubType, RequestType> { auto* cq = cli_cqs_[t].get(); auto ctx = setup_ctx(channels_[ch].get_stub(), next_issuers_[t], request_); - ctx->Start(cq); + ctx->Start(cq, config); } t = (t + 1) % cli_cqs_.size(); } @@ -248,8 +253,7 @@ class AsyncClient : public ClientImpl<StubType, RequestType> { } else if (!ctx->RunNextState(ok, entry)) { // The RPC and callback are done, so clone the ctx // and kickstart the new one - auto clone = ctx->StartNewClone(); - clone->Start(cli_cqs_[thread_idx].get()); + ctx->StartNewClone(cli_cqs_[thread_idx].get()); // delete the old version delete ctx; } @@ -330,10 +334,8 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext { next_issue_(next_issue), start_req_(start_req) {} ~ClientRpcContextStreamingImpl() override {} - void Start(CompletionQueue* cq) override { - cq_ = cq; - stream_ = start_req_(stub_, &context_, cq, ClientRpcContext::tag(this)); - next_state_ = State::STREAM_IDLE; + void Start(CompletionQueue* cq, const ClientConfig& config) override { + StartInternal(cq, config.messages_per_stream()); } bool RunNextState(bool ok, HistogramEntry* entry) override { while (true) { @@ -346,9 +348,9 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext { } break; // loop around, don't return case State::WAIT: + next_state_ = State::READY_TO_WRITE; alarm_.reset( new Alarm(cq_, next_issue_(), ClientRpcContext::tag(this))); - next_state_ = State::READY_TO_WRITE; return true; case State::READY_TO_WRITE: if (!ok) { @@ -369,17 +371,32 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext { case State::READ_DONE: entry->set_value((UsageTimer::Now() - start_) * 1e9); callback_(status_, &response_); + if ((messages_per_stream_ != 0) && + (++messages_issued_ >= messages_per_stream_)) { + next_state_ = State::WRITES_DONE_DONE; + stream_->WritesDone(ClientRpcContext::tag(this)); + return true; + } next_state_ = State::STREAM_IDLE; break; // loop around + case State::WRITES_DONE_DONE: + next_state_ = State::FINISH_DONE; + stream_->Finish(&status_, ClientRpcContext::tag(this)); + return true; + case State::FINISH_DONE: + next_state_ = State::INVALID; + return false; + break; default: GPR_ASSERT(false); return false; } } } - ClientRpcContext* StartNewClone() override { - return new ClientRpcContextStreamingImpl(stub_, req_, next_issue_, - start_req_, callback_); + void StartNewClone(CompletionQueue* cq) override { + auto* clone = new ClientRpcContextStreamingImpl(stub_, req_, next_issue_, + start_req_, callback_); + clone->StartInternal(cq, messages_per_stream_); } private: @@ -395,7 +412,9 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext { WAIT, READY_TO_WRITE, WRITE_DONE, - READ_DONE + READ_DONE, + WRITES_DONE_DONE, + FINISH_DONE }; State next_state_; std::function<void(grpc::Status, ResponseType*)> callback_; @@ -408,6 +427,18 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext { double start_; std::unique_ptr<grpc::ClientAsyncReaderWriter<RequestType, ResponseType>> stream_; + + // Allow a limit on number of messages in a stream + int messages_per_stream_; + int messages_issued_; + + void StartInternal(CompletionQueue* cq, int messages_per_stream) { + cq_ = cq; + next_state_ = State::STREAM_IDLE; + stream_ = start_req_(stub_, &context_, cq, ClientRpcContext::tag(this)); + messages_per_stream_ = messages_per_stream; + messages_issued_ = 0; + } }; class AsyncStreamingClient final @@ -459,13 +490,8 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext { next_issue_(next_issue), start_req_(start_req) {} ~ClientRpcContextGenericStreamingImpl() override {} - void Start(CompletionQueue* cq) override { - cq_ = cq; - const grpc::string kMethodName( - "/grpc.testing.BenchmarkService/StreamingCall"); - stream_ = start_req_(stub_, &context_, kMethodName, cq, - ClientRpcContext::tag(this)); - next_state_ = State::STREAM_IDLE; + void Start(CompletionQueue* cq, const ClientConfig& config) override { + StartInternal(cq, config.messages_per_stream()); } bool RunNextState(bool ok, HistogramEntry* entry) override { while (true) { @@ -478,9 +504,9 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext { } break; // loop around, don't return case State::WAIT: + next_state_ = State::READY_TO_WRITE; alarm_.reset( new Alarm(cq_, next_issue_(), ClientRpcContext::tag(this))); - next_state_ = State::READY_TO_WRITE; return true; case State::READY_TO_WRITE: if (!ok) { @@ -501,17 +527,32 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext { case State::READ_DONE: entry->set_value((UsageTimer::Now() - start_) * 1e9); callback_(status_, &response_); + if ((messages_per_stream_ != 0) && + (++messages_issued_ >= messages_per_stream_)) { + next_state_ = State::WRITES_DONE_DONE; + stream_->WritesDone(ClientRpcContext::tag(this)); + return true; + } next_state_ = State::STREAM_IDLE; break; // loop around + case State::WRITES_DONE_DONE: + next_state_ = State::FINISH_DONE; + stream_->Finish(&status_, ClientRpcContext::tag(this)); + return true; + case State::FINISH_DONE: + next_state_ = State::INVALID; + return false; + break; default: GPR_ASSERT(false); return false; } } } - ClientRpcContext* StartNewClone() override { - return new ClientRpcContextGenericStreamingImpl(stub_, req_, next_issue_, - start_req_, callback_); + void StartNewClone(CompletionQueue* cq) override { + auto* clone = new ClientRpcContextGenericStreamingImpl( + stub_, req_, next_issue_, start_req_, callback_); + clone->StartInternal(cq, messages_per_stream_); } private: @@ -527,7 +568,9 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext { WAIT, READY_TO_WRITE, WRITE_DONE, - READ_DONE + READ_DONE, + WRITES_DONE_DONE, + FINISH_DONE }; State next_state_; std::function<void(grpc::Status, ByteBuffer*)> callback_; @@ -539,6 +582,21 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext { grpc::Status status_; double start_; std::unique_ptr<grpc::GenericClientAsyncReaderWriter> stream_; + + // Allow a limit on number of messages in a stream + int messages_per_stream_; + int messages_issued_; + + void StartInternal(CompletionQueue* cq, int messages_per_stream) { + cq_ = cq; + const grpc::string kMethodName( + "/grpc.testing.BenchmarkService/StreamingCall"); + next_state_ = State::STREAM_IDLE; + stream_ = start_req_(stub_, &context_, kMethodName, cq, + ClientRpcContext::tag(this)); + messages_per_stream_ = messages_per_stream; + messages_issued_ = 0; + } }; static std::unique_ptr<grpc::GenericStub> GenericStubCreator( diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc index a944c45496..a020adde51 100644 --- a/test/cpp/qps/client_sync.cc +++ b/test/cpp/qps/client_sync.cc @@ -142,10 +142,13 @@ class SynchronousStreamingClient final : public SynchronousClient { SynchronousStreamingClient(const ClientConfig& config) : SynchronousClient(config), context_(num_threads_), - stream_(num_threads_) { + stream_(num_threads_), + messages_per_stream_(config.messages_per_stream()), + messages_issued_(num_threads_) { for (size_t thread_idx = 0; thread_idx < num_threads_; thread_idx++) { auto* stub = channels_[thread_idx % channels_.size()].get_stub(); stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]); + messages_issued_[thread_idx] = 0; } StartThreads(num_threads_); } @@ -173,11 +176,17 @@ class SynchronousStreamingClient final : public SynchronousClient { stream_[thread_idx]->Read(&responses_[thread_idx])) { entry->set_value((UsageTimer::Now() - start) * 1e9); // don't set the status since there isn't one yet - return true; + if ((messages_per_stream_ != 0) && + (++messages_issued_[thread_idx] < messages_per_stream_)) { + return true; + } else { + // Fall through to the below resetting code after finish + } } stream_[thread_idx]->WritesDone(); Status s = stream_[thread_idx]->Finish(); - // don't set the value since the stream is failed and shouldn't be timed + // don't set the value since this is either a failure (shouldn't be timed) + // or a stream-end (already has been timed) entry->set_status(s.error_code()); if (!s.ok()) { gpr_log(GPR_ERROR, "Stream %" PRIuPTR " received an error %s", thread_idx, @@ -187,6 +196,7 @@ class SynchronousStreamingClient final : public SynchronousClient { context_[thread_idx].~ClientContext(); new (&context_[thread_idx]) ClientContext(); stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]); + messages_issued_[thread_idx] = 0; return true; } @@ -197,6 +207,8 @@ class SynchronousStreamingClient final : public SynchronousClient { std::vector< std::unique_ptr<grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>>> stream_; + const int messages_per_stream_; + std::vector<int> messages_issued_; }; std::unique_ptr<Client> CreateSynchronousUnaryClient( diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc index bd2c1f0ec6..a906137474 100644 --- a/test/cpp/qps/qps_json_driver.cc +++ b/test/cpp/qps/qps_json_driver.cc @@ -40,10 +40,10 @@ #include <gflags/gflags.h> #include <grpc/support/log.h> +#include "test/cpp/qps/benchmark_config.h" #include "test/cpp/qps/driver.h" #include "test/cpp/qps/parse_json.h" #include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" DEFINE_string(scenarios_file, "", "JSON file containing an array of Scenario objects"); diff --git a/test/cpp/qps/qps_openloop_test.cc b/test/cpp/qps/qps_openloop_test.cc index 70e2709ac0..28b396739f 100644 --- a/test/cpp/qps/qps_openloop_test.cc +++ b/test/cpp/qps/qps_openloop_test.cc @@ -36,9 +36,9 @@ #include <grpc/support/log.h> #include "test/core/util/test_config.h" +#include "test/cpp/qps/benchmark_config.h" #include "test/cpp/qps/driver.h" #include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" namespace grpc { namespace testing { diff --git a/test/cpp/qps/qps_test.cc b/test/cpp/qps/qps_test.cc index f94ea0cb49..7c4e2cfd3e 100644 --- a/test/cpp/qps/qps_test.cc +++ b/test/cpp/qps/qps_test.cc @@ -35,9 +35,9 @@ #include <grpc/support/log.h> +#include "test/cpp/qps/benchmark_config.h" #include "test/cpp/qps/driver.h" #include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" namespace grpc { namespace testing { diff --git a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc index d0c47d102a..509d9f89c3 100644 --- a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc +++ b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc @@ -35,9 +35,9 @@ #include <grpc/support/log.h> +#include "test/cpp/qps/benchmark_config.h" #include "test/cpp/qps/driver.h" #include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" namespace grpc { namespace testing { diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index b58d91eea6..b499b82091 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -235,18 +235,17 @@ class AsyncQpsServerTest final : public grpc::testing::Server { return false; } - ResponseType response; - // Call the RPC processing function - grpc::Status status = invoke_method_(&req_, &response); + grpc::Status status = invoke_method_(&req_, &response_); // Have the response writer work and invoke on_finish when done next_state_ = &ServerRpcContextUnaryImpl::finisher; - response_writer_.Finish(response, status, AsyncQpsServerTest::tag(this)); + response_writer_.Finish(response_, status, AsyncQpsServerTest::tag(this)); return true; } std::unique_ptr<ServerContextType> srv_ctx_; RequestType req_; + ResponseType response_; bool (ServerRpcContextUnaryImpl::*next_state_)(bool); std::function<void(ServerContextType *, RequestType *, grpc::ServerAsyncResponseWriter<ResponseType> *, void *)> @@ -298,11 +297,10 @@ class AsyncQpsServerTest final : public grpc::testing::Server { bool read_done(bool ok) { if (ok) { // invoke the method - ResponseType response; // Call the RPC processing function - grpc::Status status = invoke_method_(&req_, &response); + grpc::Status status = invoke_method_(&req_, &response_); // initiate the write - stream_.Write(response, AsyncQpsServerTest::tag(this)); + stream_.Write(response_, AsyncQpsServerTest::tag(this)); next_state_ = &ServerRpcContextStreamingImpl::write_done; } else { // client has sent writes done // finish the stream @@ -326,6 +324,7 @@ class AsyncQpsServerTest final : public grpc::testing::Server { std::unique_ptr<ServerContextType> srv_ctx_; RequestType req_; + ResponseType response_; bool (ServerRpcContextStreamingImpl::*next_state_)(bool); std::function<void( ServerContextType *, |