diff options
author | Muxi Yan <muxi@users.noreply.github.com> | 2018-12-10 10:15:45 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-10 10:15:45 -0800 |
commit | 037173217011b38ff4675d028eba27a068db5975 (patch) | |
tree | 7bf135f4481365dad05cb4ce181cc8259647a3da /test | |
parent | 3f00d61b04874cc5f0159c16f2c598a8f2fb93a7 (diff) | |
parent | 60f2d379fec3364ff59f4f0d463b16275525863d (diff) |
Merge branch 'master' into config-isolation
Diffstat (limited to 'test')
251 files changed, 4749 insertions, 766 deletions
diff --git a/test/core/avl/avl_test.cc b/test/core/avl/avl_test.cc index 01002fec72..769e67563d 100644 --- a/test/core/avl/avl_test.cc +++ b/test/core/avl/avl_test.cc @@ -283,7 +283,7 @@ static void test_stress(int amount_of_stress) { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_get(); test_ll(); diff --git a/test/core/backoff/backoff_test.cc b/test/core/backoff/backoff_test.cc index 1998a83977..8fd120e042 100644 --- a/test/core/backoff/backoff_test.cc +++ b/test/core/backoff/backoff_test.cc @@ -171,7 +171,7 @@ TEST(BackOffTest, JitterBackOff) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/bad_client/bad_client.cc b/test/core/bad_client/bad_client.cc index 4f5d2a2862..ae1e42a4e0 100644 --- a/test/core/bad_client/bad_client.cc +++ b/test/core/bad_client/bad_client.cc @@ -66,7 +66,7 @@ static void server_setup_transport(void* ts, grpc_transport* transport) { thd_args* a = static_cast<thd_args*>(ts); grpc_core::ExecCtx exec_ctx; grpc_server_setup_transport(a->server, transport, nullptr, - grpc_server_get_channel_args(a->server), 0); + grpc_server_get_channel_args(a->server), nullptr); } /* Sets the read_done event */ diff --git a/test/core/bad_client/tests/badreq.cc b/test/core/bad_client/tests/badreq.cc index eeaf4c9974..c560dc5561 100644 --- a/test/core/bad_client/tests/badreq.cc +++ b/test/core/bad_client/tests/badreq.cc @@ -39,7 +39,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* invalid content type */ diff --git a/test/core/bad_client/tests/connection_prefix.cc b/test/core/bad_client/tests/connection_prefix.cc index 4aab234d3e..286a3ccafb 100644 --- a/test/core/bad_client/tests/connection_prefix.cc +++ b/test/core/bad_client/tests/connection_prefix.cc @@ -29,7 +29,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, "X", 0); diff --git a/test/core/bad_client/tests/duplicate_header.cc b/test/core/bad_client/tests/duplicate_header.cc index e3cae8b595..dfa6e51811 100644 --- a/test/core/bad_client/tests/duplicate_header.cc +++ b/test/core/bad_client/tests/duplicate_header.cc @@ -122,7 +122,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* Verify that sending multiple headers doesn't segfault */ diff --git a/test/core/bad_client/tests/head_of_line_blocking.cc b/test/core/bad_client/tests/head_of_line_blocking.cc index 427db46446..c856b9b122 100644 --- a/test/core/bad_client/tests/head_of_line_blocking.cc +++ b/test/core/bad_client/tests/head_of_line_blocking.cc @@ -109,7 +109,7 @@ static void addbuf(const void* data, size_t len) { int main(int argc, char** argv) { int i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); #define NUM_FRAMES 10 diff --git a/test/core/bad_client/tests/headers.cc b/test/core/bad_client/tests/headers.cc index 2aa1b280ce..02ea759750 100644 --- a/test/core/bad_client/tests/headers.cc +++ b/test/core/bad_client/tests/headers.cc @@ -33,7 +33,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* partial http2 header prefixes */ diff --git a/test/core/bad_client/tests/initial_settings_frame.cc b/test/core/bad_client/tests/initial_settings_frame.cc index 0220000ece..fcbb841331 100644 --- a/test/core/bad_client/tests/initial_settings_frame.cc +++ b/test/core/bad_client/tests/initial_settings_frame.cc @@ -32,7 +32,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* various partial prefixes */ diff --git a/test/core/bad_client/tests/large_metadata.cc b/test/core/bad_client/tests/large_metadata.cc index d534753f53..520a1af0c2 100644 --- a/test/core/bad_client/tests/large_metadata.cc +++ b/test/core/bad_client/tests/large_metadata.cc @@ -141,7 +141,7 @@ static void server_verifier_sends_too_much_metadata(grpc_server* server, int main(int argc, char** argv) { int i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); // Test sending more metadata than the server will accept. gpr_strvec headers; diff --git a/test/core/bad_client/tests/server_registered_method.cc b/test/core/bad_client/tests/server_registered_method.cc index c2dc9c66af..834142ac1b 100644 --- a/test/core/bad_client/tests/server_registered_method.cc +++ b/test/core/bad_client/tests/server_registered_method.cc @@ -76,7 +76,7 @@ static void verifier_fails(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* body generated with diff --git a/test/core/bad_client/tests/simple_request.cc b/test/core/bad_client/tests/simple_request.cc index c80fc5cb4a..34049aaaff 100644 --- a/test/core/bad_client/tests/simple_request.cc +++ b/test/core/bad_client/tests/simple_request.cc @@ -123,7 +123,7 @@ static void failure_verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* basic request: check that things are working */ diff --git a/test/core/bad_client/tests/unknown_frame.cc b/test/core/bad_client/tests/unknown_frame.cc index b1b618a43f..9e0cf3f6a9 100644 --- a/test/core/bad_client/tests/unknown_frame.cc +++ b/test/core/bad_client/tests/unknown_frame.cc @@ -34,7 +34,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* test adding prioritization data */ GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, diff --git a/test/core/bad_client/tests/window_overflow.cc b/test/core/bad_client/tests/window_overflow.cc index b552704e9c..87042a46f2 100644 --- a/test/core/bad_client/tests/window_overflow.cc +++ b/test/core/bad_client/tests/window_overflow.cc @@ -71,7 +71,7 @@ int main(int argc, char** argv) { #define FRAME_SIZE (MESSAGES_PER_FRAME * 5) #define SEND_SIZE (4 * 1024 * 1024) #define NUM_FRAMES (SEND_SIZE / FRAME_SIZE + 1) - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); addbuf(PFX_STR, sizeof(PFX_STR) - 1); diff --git a/test/core/channel/channel_args_test.cc b/test/core/channel/channel_args_test.cc index 41c62a8f16..087a7679bf 100644 --- a/test/core/channel/channel_args_test.cc +++ b/test/core/channel/channel_args_test.cc @@ -231,7 +231,7 @@ static void test_server_create_with_args(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_create(); test_set_compression_algorithm(); diff --git a/test/core/channel/channel_stack_builder_test.cc b/test/core/channel/channel_stack_builder_test.cc index aad6d6eee9..b5598e63f9 100644 --- a/test/core/channel/channel_stack_builder_test.cc +++ b/test/core/channel/channel_stack_builder_test.cc @@ -132,7 +132,7 @@ static void init_plugin(void) { static void destroy_plugin(void) {} int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_register_plugin(init_plugin, destroy_plugin); grpc_init(); test_channel_stack_builder_filter_replace(); diff --git a/test/core/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc index 6f0bfa06d2..14726336f9 100644 --- a/test/core/channel/channel_stack_test.cc +++ b/test/core/channel/channel_stack_test.cc @@ -147,7 +147,7 @@ static void test_create_channel_stack(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_create_channel_stack(); grpc_shutdown(); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 3d8de79e37..b3c0b36898 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -342,7 +342,7 @@ TEST(ChannelTracerTest, TestTotalEviction) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc index fdfc8eec94..ed3d629dc9 100644 --- a/test/core/channel/channelz_registry_test.cc +++ b/test/core/channel/channelz_registry_test.cc @@ -195,7 +195,7 @@ TEST_F(ChannelzRegistryTest, TestAddAfterCompaction) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 5f27320512..abd1601ad1 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -224,6 +224,11 @@ void ValidateServer(ServerNode* server, validate_channel_data_args args) { grpc::testing::ValidateServerProtoJsonTranslation(json_str); ValidateCounters(json_str, args); gpr_free(json_str); + // also check that the core API formats this the correct way + char* core_api_json_str = grpc_channelz_get_server(server->uuid()); + grpc::testing::ValidateGetServerResponseProtoJsonTranslation( + core_api_json_str); + gpr_free(core_api_json_str); } grpc_millis GetLastCallStartedMillis(CallCountingHelper* channel) { @@ -536,7 +541,7 @@ INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest, } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); diff --git a/test/core/channel/minimal_stack_is_minimal_test.cc b/test/core/channel/minimal_stack_is_minimal_test.cc index e5953acedc..bee0bfb41f 100644 --- a/test/core/channel/minimal_stack_is_minimal_test.cc +++ b/test/core/channel/minimal_stack_is_minimal_test.cc @@ -56,7 +56,7 @@ static int check_stack(const char* file, int line, const char* transport_name, #define CHECK_STACK(...) check_stack(__FILE__, __LINE__, __VA_ARGS__) int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); int errors = 0; diff --git a/test/core/client_channel/parse_address_test.cc b/test/core/client_channel/parse_address_test.cc index 004549fa62..b77a51a9e4 100644 --- a/test/core/client_channel/parse_address_test.cc +++ b/test/core/client_channel/parse_address_test.cc @@ -101,7 +101,7 @@ static void test_grpc_parse_ipv6_invalid(const char* uri_text) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_grpc_parse_unix("unix:/path/name", "/path/name"); diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc index eb5a911748..76769b2b64 100644 --- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc @@ -64,7 +64,7 @@ static grpc_ares_request* my_dns_lookup_ares_locked( const char* dns_server, const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** lb_addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout_ms, grpc_combiner* combiner) { gpr_mu_lock(&g_mu); GPR_ASSERT(0 == strcmp("test", addr)); grpc_error* error = GRPC_ERROR_NONE; @@ -145,7 +145,7 @@ static void call_resolver_next_after_locking(grpc_core::Resolver* resolver, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); gpr_mu_init(&g_mu); diff --git a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc index 1a7db40f59..cdbe33dbe7 100644 --- a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc @@ -41,7 +41,7 @@ static grpc_ares_request* (*g_default_dns_lookup_ares_locked)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner); + int query_timeout_ms, grpc_combiner* combiner); // Counter incremented by test_resolve_address_impl indicating the number of // times a system-level resolution has happened. @@ -91,10 +91,10 @@ static grpc_ares_request* test_dns_lookup_ares_locked( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout_ms, grpc_combiner* combiner) { grpc_ares_request* result = g_default_dns_lookup_ares_locked( dns_server, name, default_port, g_iomgr_args.pollset_set, on_done, addrs, - check_grpclb, service_config_json, combiner); + check_grpclb, service_config_json, query_timeout_ms, combiner); ++g_resolution_count; static grpc_millis last_resolution_time = 0; if (last_resolution_time == 0) { @@ -262,7 +262,7 @@ static void test_cooldown() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); g_combiner = grpc_combiner_create(); diff --git a/test/core/client_channel/resolvers/dns_resolver_test.cc b/test/core/client_channel/resolvers/dns_resolver_test.cc index 103b2916c4..571746abe8 100644 --- a/test/core/client_channel/resolvers/dns_resolver_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_test.cc @@ -60,7 +60,7 @@ static void test_fails(grpc_core::ResolverFactory* factory, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); g_combiner = grpc_combiner_create(); diff --git a/test/core/client_channel/resolvers/fake_resolver_test.cc b/test/core/client_channel/resolvers/fake_resolver_test.cc index f6696bf127..6362b95e50 100644 --- a/test/core/client_channel/resolvers/fake_resolver_test.cc +++ b/test/core/client_channel/resolvers/fake_resolver_test.cc @@ -213,7 +213,7 @@ static void test_fake_resolver() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_fake_resolver(); diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.cc b/test/core/client_channel/resolvers/sockaddr_resolver_test.cc index b9287c2468..ff7db6046d 100644 --- a/test/core/client_channel/resolvers/sockaddr_resolver_test.cc +++ b/test/core/client_channel/resolvers/sockaddr_resolver_test.cc @@ -84,7 +84,7 @@ static void test_fails(grpc_core::ResolverFactory* factory, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); g_combiner = grpc_combiner_create(); diff --git a/test/core/client_channel/retry_throttle_test.cc b/test/core/client_channel/retry_throttle_test.cc index c6d5d3ebbb..793e86dc06 100644 --- a/test/core/client_channel/retry_throttle_test.cc +++ b/test/core/client_channel/retry_throttle_test.cc @@ -136,7 +136,7 @@ TEST(ServerRetryThrottleMap, Replacement) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/client_channel/uri_fuzzer_test.cc b/test/core/client_channel/uri_fuzzer_test.cc index ee38453166..a88e2ac5cf 100644 --- a/test/core/client_channel/uri_fuzzer_test.cc +++ b/test/core/client_channel/uri_fuzzer_test.cc @@ -23,8 +23,8 @@ #include <grpc/grpc.h> #include <grpc/support/alloc.h> -#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/uri/uri_parser.h" bool squelch = true; bool leak_check = true; diff --git a/test/core/client_channel/uri_parser_test.cc b/test/core/client_channel/uri_parser_test.cc index 254bfddfb3..713ec32e5e 100644 --- a/test/core/client_channel/uri_parser_test.cc +++ b/test/core/client_channel/uri_parser_test.cc @@ -16,7 +16,7 @@ * */ -#include "src/core/ext/filters/client_channel/uri_parser.h" +#include "src/core/lib/uri/uri_parser.h" #include <string.h> @@ -119,7 +119,7 @@ static void test_query_parts() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_succeeds("http://www.google.com", "http", "www.google.com", "", "", ""); test_succeeds("dns:///foo", "dns", "", "/foo", "", ""); diff --git a/test/core/compression/algorithm_test.cc b/test/core/compression/algorithm_test.cc index 8989a41989..24fe83774b 100644 --- a/test/core/compression/algorithm_test.cc +++ b/test/core/compression/algorithm_test.cc @@ -105,7 +105,7 @@ static void test_algorithm_failure(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_algorithm_mesh(); diff --git a/test/core/compression/message_compress_test.cc b/test/core/compression/message_compress_test.cc index e3fe825fdf..e2abf2d321 100644 --- a/test/core/compression/message_compress_test.cc +++ b/test/core/compression/message_compress_test.cc @@ -292,7 +292,7 @@ int main(int argc, char** argv) { GRPC_SLICE_SPLIT_IDENTITY, GRPC_SLICE_SPLIT_ONE_BYTE}; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); for (i = 0; i < GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT; i++) { diff --git a/test/core/debug/BUILD b/test/core/debug/BUILD new file mode 100644 index 0000000000..1592472532 --- /dev/null +++ b/test/core/debug/BUILD @@ -0,0 +1,34 @@ +# Copyright 2018 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package") + +grpc_package(name = "test/core/debug") + +licenses(["notice"]) # Apache v2 + +grpc_cc_test( + name = "stats_test", + srcs = ["stats_test.cc"], + external_deps = [ + "gtest", + ], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) diff --git a/test/core/end2end/bad_server_response_test.cc b/test/core/end2end/bad_server_response_test.cc index f7396a1684..f8ffb55180 100644 --- a/test/core/end2end/bad_server_response_test.cc +++ b/test/core/end2end/bad_server_response_test.cc @@ -302,7 +302,7 @@ static void run_test(const char* response_payload, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* status defined in hpack static table */ diff --git a/test/core/end2end/connection_refused_test.cc b/test/core/end2end/connection_refused_test.cc index 33812ec8e5..4318811b81 100644 --- a/test/core/end2end/connection_refused_test.cc +++ b/test/core/end2end/connection_refused_test.cc @@ -142,7 +142,7 @@ static void run_test(bool wait_for_ready, bool use_service_config) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_test(false /* wait_for_ready */, false /* use_service_config */); run_test(true /* wait_for_ready */, false /* use_service_config */); run_test(true /* wait_for_ready */, true /* use_service_config */); diff --git a/test/core/end2end/dualstack_socket_test.cc b/test/core/end2end/dualstack_socket_test.cc index eb1d043fb2..330af8fce0 100644 --- a/test/core/end2end/dualstack_socket_test.cc +++ b/test/core/end2end/dualstack_socket_test.cc @@ -303,7 +303,7 @@ int external_dns_works(const char* host) { int main(int argc, char** argv) { int do_ipv6 = 1; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); if (!grpc_ipv6_loopback_available()) { diff --git a/test/core/end2end/fixtures/h2_census.cc b/test/core/end2end/fixtures/h2_census.cc index 29b1d6d883..60442ddcc7 100644 --- a/test/core/end2end/fixtures/h2_census.cc +++ b/test/core/end2end/fixtures/h2_census.cc @@ -118,7 +118,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_compress.cc b/test/core/end2end/fixtures/h2_compress.cc index 4aaadf715c..04142daf63 100644 --- a/test/core/end2end/fixtures/h2_compress.cc +++ b/test/core/end2end/fixtures/h2_compress.cc @@ -118,7 +118,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_fakesec.cc b/test/core/end2end/fixtures/h2_fakesec.cc index a653d7c477..ad83aab39f 100644 --- a/test/core/end2end/fixtures/h2_fakesec.cc +++ b/test/core/end2end/fixtures/h2_fakesec.cc @@ -142,7 +142,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_fd.cc b/test/core/end2end/fixtures/h2_fd.cc index 52be0f7fd5..5d06bd5f3b 100644 --- a/test/core/end2end/fixtures/h2_fd.cc +++ b/test/core/end2end/fixtures/h2_fd.cc @@ -104,7 +104,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_full+pipe.cc b/test/core/end2end/fixtures/h2_full+pipe.cc index c5329640dc..6d559c4e51 100644 --- a/test/core/end2end/fixtures/h2_full+pipe.cc +++ b/test/core/end2end/fixtures/h2_full+pipe.cc @@ -105,7 +105,7 @@ int main(int argc, char** argv) { grpc_allow_specialized_wakeup_fd = 0; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_full+trace.cc b/test/core/end2end/fixtures/h2_full+trace.cc index ba7a780304..2bbad48701 100644 --- a/test/core/end2end/fixtures/h2_full+trace.cc +++ b/test/core/end2end/fixtures/h2_full+trace.cc @@ -113,7 +113,7 @@ int main(int argc, char** argv) { g_fixture_slowdown_factor = 10; #endif - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_full+workarounds.cc b/test/core/end2end/fixtures/h2_full+workarounds.cc index 78da8418f6..cb0f7d275b 100644 --- a/test/core/end2end/fixtures/h2_full+workarounds.cc +++ b/test/core/end2end/fixtures/h2_full+workarounds.cc @@ -114,7 +114,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_full.cc b/test/core/end2end/fixtures/h2_full.cc index 0c826b6836..c0d21288c7 100644 --- a/test/core/end2end/fixtures/h2_full.cc +++ b/test/core/end2end/fixtures/h2_full.cc @@ -97,7 +97,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_http_proxy.cc b/test/core/end2end/fixtures/h2_http_proxy.cc index 0af8a29a15..9b6a81494e 100644 --- a/test/core/end2end/fixtures/h2_http_proxy.cc +++ b/test/core/end2end/fixtures/h2_http_proxy.cc @@ -120,7 +120,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_local.cc b/test/core/end2end/fixtures/h2_local.cc index cce8f1745a..18d690ff22 100644 --- a/test/core/end2end/fixtures/h2_local.cc +++ b/test/core/end2end/fixtures/h2_local.cc @@ -140,7 +140,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_oauth2.cc b/test/core/end2end/fixtures/h2_oauth2.cc index 37397d6450..113a6b1173 100644 --- a/test/core/end2end/fixtures/h2_oauth2.cc +++ b/test/core/end2end/fixtures/h2_oauth2.cc @@ -224,7 +224,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_proxy.cc b/test/core/end2end/fixtures/h2_proxy.cc index a32000061a..e334396ea7 100644 --- a/test/core/end2end/fixtures/h2_proxy.cc +++ b/test/core/end2end/fixtures/h2_proxy.cc @@ -124,7 +124,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.cc b/test/core/end2end/fixtures/h2_sockpair+trace.cc index eb71e24c77..45f78b5964 100644 --- a/test/core/end2end/fixtures/h2_sockpair+trace.cc +++ b/test/core/end2end/fixtures/h2_sockpair+trace.cc @@ -53,7 +53,7 @@ static void server_setup_transport(void* ts, grpc_transport* transport) { grpc_endpoint_pair* sfd = static_cast<grpc_endpoint_pair*>(f->fixture_data); grpc_endpoint_add_to_pollset(sfd->server, grpc_cq_pollset(f->cq)); grpc_server_setup_transport(f->server, transport, nullptr, - grpc_server_get_channel_args(f->server), 0); + grpc_server_get_channel_args(f->server), nullptr); } typedef struct { @@ -140,7 +140,7 @@ int main(int argc, char** argv) { g_fixture_slowdown_factor = 10; #endif - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_sockpair.cc b/test/core/end2end/fixtures/h2_sockpair.cc index 904bda5458..77bce7ebb3 100644 --- a/test/core/end2end/fixtures/h2_sockpair.cc +++ b/test/core/end2end/fixtures/h2_sockpair.cc @@ -47,7 +47,7 @@ static void server_setup_transport(void* ts, grpc_transport* transport) { grpc_endpoint_pair* sfd = static_cast<grpc_endpoint_pair*>(f->fixture_data); grpc_endpoint_add_to_pollset(sfd->server, grpc_cq_pollset(f->cq)); grpc_server_setup_transport(f->server, transport, nullptr, - grpc_server_get_channel_args(f->server), 0); + grpc_server_get_channel_args(f->server), nullptr); } typedef struct { @@ -126,7 +126,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.cc b/test/core/end2end/fixtures/h2_sockpair_1byte.cc index 45f7f254ac..ac37841dc4 100644 --- a/test/core/end2end/fixtures/h2_sockpair_1byte.cc +++ b/test/core/end2end/fixtures/h2_sockpair_1byte.cc @@ -47,7 +47,7 @@ static void server_setup_transport(void* ts, grpc_transport* transport) { grpc_endpoint_pair* sfd = static_cast<grpc_endpoint_pair*>(f->fixture_data); grpc_endpoint_add_to_pollset(sfd->server, grpc_cq_pollset(f->cq)); grpc_server_setup_transport(f->server, transport, nullptr, - grpc_server_get_channel_args(f->server), 0); + grpc_server_get_channel_args(f->server), nullptr); } typedef struct { @@ -140,7 +140,7 @@ int main(int argc, char** argv) { g_fixture_slowdown_factor = 2; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_ssl.cc b/test/core/end2end/fixtures/h2_ssl.cc index 4d6c815716..1fcd785e25 100644 --- a/test/core/end2end/fixtures/h2_ssl.cc +++ b/test/core/end2end/fixtures/h2_ssl.cc @@ -158,7 +158,7 @@ int main(int argc, char** argv) { size_t roots_size = strlen(test_root_cert); char* roots_filename; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); /* Set the SSL roots env var. */ diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.cc b/test/core/end2end/fixtures/h2_ssl_proxy.cc index 09cbf974b6..f185807942 100644 --- a/test/core/end2end/fixtures/h2_ssl_proxy.cc +++ b/test/core/end2end/fixtures/h2_ssl_proxy.cc @@ -199,7 +199,7 @@ int main(int argc, char** argv) { size_t roots_size = strlen(test_root_cert); char* roots_filename; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); /* Set the SSL roots env var. */ diff --git a/test/core/end2end/fixtures/h2_uds.cc b/test/core/end2end/fixtures/h2_uds.cc index 2c81c3d362..f251bbd28c 100644 --- a/test/core/end2end/fixtures/h2_uds.cc +++ b/test/core/end2end/fixtures/h2_uds.cc @@ -102,7 +102,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/inproc.cc b/test/core/end2end/fixtures/inproc.cc index be6eda8483..dadf3ef455 100644 --- a/test/core/end2end/fixtures/inproc.cc +++ b/test/core/end2end/fixtures/inproc.cc @@ -83,7 +83,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc index e97a544e12..a3de56d4f9 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.cc +++ b/test/core/end2end/fuzzers/api_fuzzer.cc @@ -378,7 +378,7 @@ grpc_ares_request* my_dns_lookup_ares_locked( const char* dns_server, const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** lb_addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout, grpc_combiner* combiner) { addr_req* r = static_cast<addr_req*>(gpr_malloc(sizeof(*r))); r->addr = gpr_strdup(addr); r->on_done = on_done; @@ -420,7 +420,7 @@ static void do_connect(void* arg, grpc_error* error) { grpc_transport* transport = grpc_create_chttp2_transport(nullptr, server, false); - grpc_server_setup_transport(g_server, transport, nullptr, nullptr, 0); + grpc_server_setup_transport(g_server, transport, nullptr, nullptr, nullptr); grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); GRPC_CLOSURE_SCHED(fc->closure, GRPC_ERROR_NONE); diff --git a/test/core/end2end/fuzzers/hpack.dictionary b/test/core/end2end/fuzzers/hpack.dictionary index a79fe5ad95..0469421c97 100644 --- a/test/core/end2end/fuzzers/hpack.dictionary +++ b/test/core/end2end/fuzzers/hpack.dictionary @@ -35,6 +35,7 @@ "\x1Fgrpc.max_response_message_bytes" "$/grpc.lb.v1.LoadBalancer/BalanceLoad" "\x1C/grpc.health.v1.Health/Watch" +"P/envoy.service.discovery.v2.AggregatedDiscoveryService/StreamAggregatedResources" "\x07deflate" "\x04gzip" "\x0Bstream/gzip" diff --git a/test/core/end2end/fuzzers/server_fuzzer.cc b/test/core/end2end/fuzzers/server_fuzzer.cc index bd686215dd..d370dc7de8 100644 --- a/test/core/end2end/fuzzers/server_fuzzer.cc +++ b/test/core/end2end/fuzzers/server_fuzzer.cc @@ -62,7 +62,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { grpc_server_start(server); grpc_transport* transport = grpc_create_chttp2_transport(nullptr, mock_endpoint, false); - grpc_server_setup_transport(server, transport, nullptr, nullptr, 0); + grpc_server_setup_transport(server, transport, nullptr, nullptr, nullptr); grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); grpc_call* call1 = nullptr; diff --git a/test/core/end2end/goaway_server_test.cc b/test/core/end2end/goaway_server_test.cc index 3f1c5596ad..66e8ca5161 100644 --- a/test/core/end2end/goaway_server_test.cc +++ b/test/core/end2end/goaway_server_test.cc @@ -48,7 +48,7 @@ static grpc_ares_request* (*iomgr_dns_lookup_ares_locked)( const char* dns_server, const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addresses, bool check_grpclb, - char** service_config_json, grpc_combiner* combiner); + char** service_config_json, int query_timeout_ms, grpc_combiner* combiner); static void (*iomgr_cancel_ares_request_locked)(grpc_ares_request* request); @@ -104,11 +104,11 @@ static grpc_ares_request* my_dns_lookup_ares_locked( const char* dns_server, const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** lb_addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout_ms, grpc_combiner* combiner) { if (0 != strcmp(addr, "test")) { return iomgr_dns_lookup_ares_locked( dns_server, addr, default_port, interested_parties, on_done, lb_addrs, - check_grpclb, service_config_json, combiner); + check_grpclb, service_config_json, query_timeout_ms, combiner); } grpc_error* error = GRPC_ERROR_NONE; @@ -144,7 +144,7 @@ int main(int argc, char** argv) { grpc_op ops[6]; grpc_op* op; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); gpr_mu_init(&g_mu); grpc_init(); diff --git a/test/core/end2end/h2_ssl_cert_test.cc b/test/core/end2end/h2_ssl_cert_test.cc index 2c5ee3b156..cb0800bf89 100644 --- a/test/core/end2end/h2_ssl_cert_test.cc +++ b/test/core/end2end/h2_ssl_cert_test.cc @@ -358,7 +358,7 @@ int main(int argc, char** argv) { size_t roots_size = strlen(test_root_cert); char* roots_filename; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* Set the SSL roots env var. */ roots_file = gpr_tmpfile("chttp2_simple_ssl_cert_fullstack_test", &roots_filename); diff --git a/test/core/end2end/h2_ssl_session_reuse_test.cc b/test/core/end2end/h2_ssl_session_reuse_test.cc index b2f398625a..fbcdcc4b3f 100644 --- a/test/core/end2end/h2_ssl_session_reuse_test.cc +++ b/test/core/end2end/h2_ssl_session_reuse_test.cc @@ -258,7 +258,7 @@ int main(int argc, char** argv) { size_t roots_size = strlen(test_root_cert); char* roots_filename; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* Set the SSL roots env var. */ roots_file = gpr_tmpfile("chttp2_ssl_session_reuse_test", &roots_filename); GPR_ASSERT(roots_filename != nullptr); diff --git a/test/core/end2end/inproc_callback_test.cc b/test/core/end2end/inproc_callback_test.cc index 310030046a..72ad992d54 100644 --- a/test/core/end2end/inproc_callback_test.cc +++ b/test/core/end2end/inproc_callback_test.cc @@ -495,7 +495,7 @@ static grpc_end2end_test_config configs[] = { }; int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); simple_request_pre_init(); diff --git a/test/core/end2end/invalid_call_argument_test.cc b/test/core/end2end/invalid_call_argument_test.cc index 6cb2e3ee80..bd28d19298 100644 --- a/test/core/end2end/invalid_call_argument_test.cc +++ b/test/core/end2end/invalid_call_argument_test.cc @@ -609,7 +609,7 @@ static void test_invalid_initial_metadata_reserved_key() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_invalid_initial_metadata_reserved_key(); test_non_null_reserved_on_start_batch(); diff --git a/test/core/end2end/multiple_server_queues_test.cc b/test/core/end2end/multiple_server_queues_test.cc index dfa3b48b52..5ae828c1e3 100644 --- a/test/core/end2end/multiple_server_queues_test.cc +++ b/test/core/end2end/multiple_server_queues_test.cc @@ -27,7 +27,7 @@ int main(int argc, char** argv) { grpc_server* server; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); attr.version = 1; diff --git a/test/core/end2end/no_server_test.cc b/test/core/end2end/no_server_test.cc index e8ce4032e0..5dda748f5a 100644 --- a/test/core/end2end/no_server_test.cc +++ b/test/core/end2end/no_server_test.cc @@ -107,7 +107,7 @@ void run_test(bool wait_for_ready) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_test(true /* wait_for_ready */); run_test(false /* wait_for_ready */); return 0; diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 7c61b7910b..49a0bc8011 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -29,6 +29,7 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/time.h> +#include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/string.h" #include "test/core/end2end/cq_verifier.h" @@ -238,7 +239,6 @@ static void test_channelz(grpc_end2end_test_config config) { json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); - gpr_log(GPR_INFO, "%s", json); GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); @@ -250,7 +250,6 @@ static void test_channelz(grpc_end2end_test_config config) { json = channelz_server->RenderJsonString(); GPR_ASSERT(json != nullptr); - gpr_log(GPR_INFO, "%s", json); GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); @@ -261,7 +260,7 @@ static void test_channelz(grpc_end2end_test_config config) { gpr_free(json); json = channelz_server->RenderServerSockets(0); - GPR_ASSERT(nullptr != strstr(json, "\"socketRef\":")); + GPR_ASSERT(nullptr != strstr(json, "\"end\":true")); gpr_free(json); end_test(&f); @@ -292,7 +291,6 @@ static void test_channelz_with_channel_trace(grpc_end2end_test_config config) { char* json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); - gpr_log(GPR_INFO, "%s", json); GPR_ASSERT(nullptr != strstr(json, "\"trace\"")); GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Channel created\"")); GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\"")); @@ -300,7 +298,6 @@ static void test_channelz_with_channel_trace(grpc_end2end_test_config config) { json = channelz_server->RenderJsonString(); GPR_ASSERT(json != nullptr); - gpr_log(GPR_INFO, "%s", json); GPR_ASSERT(nullptr != strstr(json, "\"trace\"")); GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Server created\"")); GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\"")); diff --git a/test/core/end2end/tests/streaming_error_response.cc b/test/core/end2end/tests/streaming_error_response.cc index 4c357e077e..713975a33f 100644 --- a/test/core/end2end/tests/streaming_error_response.cc +++ b/test/core/end2end/tests/streaming_error_response.cc @@ -89,7 +89,8 @@ static void end_test(grpc_end2end_test_fixture* f) { } /* Client sends a request with payload, server reads then returns status. */ -static void test(grpc_end2end_test_config config, bool request_status_early) { +static void test(grpc_end2end_test_config config, bool request_status_early, + bool recv_message_separately) { grpc_call* c; grpc_call* s; grpc_slice response_payload1_slice = grpc_slice_from_copied_string("hello"); @@ -116,6 +117,7 @@ static void test(grpc_end2end_test_config config, bool request_status_early) { int was_cancelled = 2; gpr_timespec deadline = five_seconds_from_now(); + GPR_ASSERT(!recv_message_separately || request_status_early); c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq, grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr); @@ -136,9 +138,11 @@ static void test(grpc_end2end_test_config config, bool request_status_early) { op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload1_recv; - op++; + if (!recv_message_separately) { + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload1_recv; + op++; + } if (request_status_early) { op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; @@ -168,10 +172,24 @@ static void test(grpc_end2end_test_config config, bool request_status_early) { nullptr); GPR_ASSERT(GRPC_CALL_OK == error); + if (recv_message_separately) { + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload1_recv; + op++; + error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(4), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + } + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); if (!request_status_early) { CQ_EXPECT_COMPLETION(cqv, tag(1), 1); } + if (recv_message_separately) { + CQ_EXPECT_COMPLETION(cqv, tag(4), 1); + } cq_verify(cqv); memset(ops, 0, sizeof(ops)); @@ -265,8 +283,9 @@ static void test(grpc_end2end_test_config config, bool request_status_early) { } void streaming_error_response(grpc_end2end_test_config config) { - test(config, false); - test(config, true); + test(config, false, false); + test(config, true, false); + test(config, true, true); } void streaming_error_response_pre_init(void) {} diff --git a/test/core/fling/client.cc b/test/core/fling/client.cc index 05dc3052d1..2a7a5ca623 100644 --- a/test/core/fling/client.cc +++ b/test/core/fling/client.cc @@ -158,11 +158,11 @@ int main(int argc, char** argv) { gpr_timers_set_log_filename("latency_trace.fling_client.txt"); - grpc_init(); - GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; - grpc_test_init(1, fake_argv); + grpc::testing::TestEnvironment env(1, fake_argv); + + grpc_init(); int warmup_seconds = 1; int benchmark_seconds = 5; diff --git a/test/core/gpr/BUILD b/test/core/gpr/BUILD index d58d4f2a14..67657ee1ce 100644 --- a/test/core/gpr/BUILD +++ b/test/core/gpr/BUILD @@ -81,12 +81,12 @@ grpc_cc_test( grpc_cc_test( name = "mpscq_test", srcs = ["mpscq_test.cc"], + exec_compatible_with = ["//third_party/toolchains/machine_size:large"], language = "C++", deps = [ "//:gpr", "//test/core/util:gpr_test_util", ], - data = ["//third_party/toolchains:RBE_USE_MACHINE_TYPE_LARGE"], ) grpc_cc_test( diff --git a/test/core/gpr/alloc_test.cc b/test/core/gpr/alloc_test.cc index 36cdc02ff2..0b110e2b77 100644 --- a/test/core/gpr/alloc_test.cc +++ b/test/core/gpr/alloc_test.cc @@ -64,7 +64,7 @@ static void test_malloc_aligned() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_custom_allocs(); test_malloc_aligned(); return 0; diff --git a/test/core/gpr/arena_test.cc b/test/core/gpr/arena_test.cc index 3e7c906591..de4bd9804e 100644 --- a/test/core/gpr/arena_test.cc +++ b/test/core/gpr/arena_test.cc @@ -116,7 +116,7 @@ static void concurrent_test(void) { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_noop(); TEST(0_1, 0, 1); diff --git a/test/core/gpr/cpu_test.cc b/test/core/gpr/cpu_test.cc index 1052d40b42..dbaeb08c18 100644 --- a/test/core/gpr/cpu_test.cc +++ b/test/core/gpr/cpu_test.cc @@ -144,7 +144,7 @@ static void cpu_test(void) { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); cpu_test(); return 0; } diff --git a/test/core/gpr/env_test.cc b/test/core/gpr/env_test.cc index 3f4b493239..a8206bd3cf 100644 --- a/test/core/gpr/env_test.cc +++ b/test/core/gpr/env_test.cc @@ -43,7 +43,7 @@ static void test_setenv_getenv(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_setenv_getenv(); return 0; } diff --git a/test/core/gpr/host_port_test.cc b/test/core/gpr/host_port_test.cc index b5d88b2b01..b01bbf4b69 100644 --- a/test/core/gpr/host_port_test.cc +++ b/test/core/gpr/host_port_test.cc @@ -50,7 +50,7 @@ static void test_join_host_port_garbage(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_join_host_port(); test_join_host_port_garbage(); diff --git a/test/core/gpr/log_test.cc b/test/core/gpr/log_test.cc index 839ff0aef9..f96257738b 100644 --- a/test/core/gpr/log_test.cc +++ b/test/core/gpr/log_test.cc @@ -53,7 +53,7 @@ static void test_should_not_log(gpr_log_func_args* args) { GPR_ASSERT(false); } gpr_log(SEVERITY, "hello %d %d %d", 1, 2, 3); int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* test logging at various verbosity levels */ gpr_log(GPR_DEBUG, "%s", "hello world"); gpr_log(GPR_INFO, "%s", "hello world"); diff --git a/test/core/gpr/mpscq_test.cc b/test/core/gpr/mpscq_test.cc index f51bdf8c50..c826ccb498 100644 --- a/test/core/gpr/mpscq_test.cc +++ b/test/core/gpr/mpscq_test.cc @@ -182,7 +182,7 @@ static void test_mt_multipop(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_serial(); test_mt(); test_mt_multipop(); diff --git a/test/core/gpr/murmur_hash_test.cc b/test/core/gpr/murmur_hash_test.cc index 2d2fa72cfb..fdc2cfa76b 100644 --- a/test/core/gpr/murmur_hash_test.cc +++ b/test/core/gpr/murmur_hash_test.cc @@ -64,7 +64,7 @@ static void verification_test(hash_func hash, uint32_t expected) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* basic tests to verify that things don't crash */ gpr_murmur_hash3("", 0, 0); gpr_murmur_hash3("xyz", 3, 0); diff --git a/test/core/gpr/spinlock_test.cc b/test/core/gpr/spinlock_test.cc index 0ee72edb15..8bd9396da6 100644 --- a/test/core/gpr/spinlock_test.cc +++ b/test/core/gpr/spinlock_test.cc @@ -149,7 +149,7 @@ static void inctry(void* v /*=m*/) { /* ------------------------------------------------- */ int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test("spinlock", &inc, 1, 1); test("spinlock try", &inctry, 1, 1); return 0; diff --git a/test/core/gpr/string_test.cc b/test/core/gpr/string_test.cc index 9f3b312465..7da7b18778 100644 --- a/test/core/gpr/string_test.cc +++ b/test/core/gpr/string_test.cc @@ -295,7 +295,7 @@ static void test_is_true(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_strdup(); test_dump(); test_parse_uint32(); diff --git a/test/core/gpr/sync_test.cc b/test/core/gpr/sync_test.cc index 24b4562819..fc7216e360 100644 --- a/test/core/gpr/sync_test.cc +++ b/test/core/gpr/sync_test.cc @@ -458,7 +458,7 @@ static void refcheck(void* v /*=m*/) { /* ------------------------------------------------- */ int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test("mutex", &inc, nullptr, 1, 1); test("mutex try", &inctry, nullptr, 1, 1); test("cv", &inc_by_turns, nullptr, 1, 1); diff --git a/test/core/gpr/time_test.cc b/test/core/gpr/time_test.cc index 6f070f58df..a32cbfb09a 100644 --- a/test/core/gpr/time_test.cc +++ b/test/core/gpr/time_test.cc @@ -254,7 +254,7 @@ static void test_cmp_extreme(void) { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_values(); test_add_sub(); diff --git a/test/core/gpr/tls_test.cc b/test/core/gpr/tls_test.cc index 0502fc7ef4..d1bed0aafe 100644 --- a/test/core/gpr/tls_test.cc +++ b/test/core/gpr/tls_test.cc @@ -50,7 +50,7 @@ static void thd_body(void* arg) { int main(int argc, char* argv[]) { grpc_core::Thread threads[NUM_THREADS]; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); gpr_tls_init(&test_var); diff --git a/test/core/gpr/useful_test.cc b/test/core/gpr/useful_test.cc index 619c800c4d..4f8582ab41 100644 --- a/test/core/gpr/useful_test.cc +++ b/test/core/gpr/useful_test.cc @@ -26,7 +26,7 @@ int main(int argc, char** argv) { int four[4]; int five[5]; uint32_t bitset = 0; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); GPR_ASSERT(GPR_MIN(1, 2) == 1); GPR_ASSERT(GPR_MAX(1, 2) == 2); diff --git a/test/core/gprpp/fork_test.cc b/test/core/gprpp/fork_test.cc index 642f910489..0f56eead49 100644 --- a/test/core/gprpp/fork_test.cc +++ b/test/core/gprpp/fork_test.cc @@ -130,7 +130,7 @@ static void test_exec_count() { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_init(); test_thd_count(); test_exec_count(); diff --git a/test/core/gprpp/inlined_vector_test.cc b/test/core/gprpp/inlined_vector_test.cc index 73e0773b31..f943128f53 100644 --- a/test/core/gprpp/inlined_vector_test.cc +++ b/test/core/gprpp/inlined_vector_test.cc @@ -116,7 +116,7 @@ typedef InlinedVector<int, kInlinedLength> IntVec8; const size_t kInlinedFillSize = kInlinedLength - 1; const size_t kAllocatedFillSize = kInlinedLength + 1; -TEST(InlinedVectorTest, CopyConstructerInlined) { +TEST(InlinedVectorTest, CopyConstructorInlined) { IntVec8 original; FillVector(&original, kInlinedFillSize); IntVec8 copy_constructed(original); @@ -125,7 +125,7 @@ TEST(InlinedVectorTest, CopyConstructerInlined) { } } -TEST(InlinedVectorTest, CopyConstructerAllocated) { +TEST(InlinedVectorTest, CopyConstructorAllocated) { IntVec8 original; FillVector(&original, kAllocatedFillSize); IntVec8 copy_constructed(original); @@ -264,6 +264,166 @@ TEST(InlinedVectorTest, MoveAssignmentAllocatedAllocated) { EXPECT_EQ(move_assigned.data(), old_data); } +// A copyable and movable value class, used to test that elements' copy +// and move methods are called correctly. +class Value { + public: + explicit Value(int v) : value_(MakeUnique<int>(v)) {} + + // copyable + Value(const Value& v) { + value_ = MakeUnique<int>(*v.value_); + copied_ = true; + } + Value& operator=(const Value& v) { + value_ = MakeUnique<int>(*v.value_); + copied_ = true; + return *this; + } + + // movable + Value(Value&& v) { + value_ = std::move(v.value_); + moved_ = true; + } + Value& operator=(Value&& v) { + value_ = std::move(v.value_); + moved_ = true; + return *this; + } + + const UniquePtr<int>& value() const { return value_; } + bool copied() const { return copied_; } + bool moved() const { return moved_; } + + private: + UniquePtr<int> value_; + bool copied_ = false; + bool moved_ = false; +}; + +TEST(InlinedVectorTest, CopyConstructorCopiesElementsInlined) { + InlinedVector<Value, 1> v1; + v1.emplace_back(3); + InlinedVector<Value, 1> v2(v1); + EXPECT_EQ(v2.size(), 1UL); + EXPECT_EQ(*v2[0].value(), 3); + // Addresses should differ. + EXPECT_NE(v1[0].value().get(), v2[0].value().get()); + EXPECT_TRUE(v2[0].copied()); +} + +TEST(InlinedVectorTest, CopyConstructorCopiesElementsAllocated) { + InlinedVector<Value, 1> v1; + v1.reserve(2); + v1.emplace_back(3); + v1.emplace_back(5); + InlinedVector<Value, 1> v2(v1); + EXPECT_EQ(v2.size(), 2UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(*v2[1].value(), 5); + // Addresses should differ. + EXPECT_NE(v1[0].value().get(), v2[0].value().get()); + EXPECT_NE(v1[1].value().get(), v2[1].value().get()); + EXPECT_TRUE(v2[0].copied()); + EXPECT_TRUE(v2[1].copied()); +} + +TEST(InlinedVectorTest, CopyAssignmentCopiesElementsInlined) { + InlinedVector<Value, 1> v1; + v1.emplace_back(3); + InlinedVector<Value, 1> v2; + EXPECT_EQ(v2.size(), 0UL); + v2 = v1; + EXPECT_EQ(v2.size(), 1UL); + EXPECT_EQ(*v2[0].value(), 3); + // Addresses should differ. + EXPECT_NE(v1[0].value().get(), v2[0].value().get()); + EXPECT_TRUE(v2[0].copied()); +} + +TEST(InlinedVectorTest, CopyAssignmentCopiesElementsAllocated) { + InlinedVector<Value, 1> v1; + v1.reserve(2); + v1.emplace_back(3); + v1.emplace_back(5); + InlinedVector<Value, 1> v2; + EXPECT_EQ(v2.size(), 0UL); + v2 = v1; + EXPECT_EQ(v2.size(), 2UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(*v2[1].value(), 5); + // Addresses should differ. + EXPECT_NE(v1[0].value().get(), v2[0].value().get()); + EXPECT_NE(v1[1].value().get(), v2[1].value().get()); + EXPECT_TRUE(v2[0].copied()); + EXPECT_TRUE(v2[1].copied()); +} + +TEST(InlinedVectorTest, MoveConstructorMovesElementsInlined) { + InlinedVector<Value, 1> v1; + v1.emplace_back(3); + int* addr = v1[0].value().get(); + InlinedVector<Value, 1> v2(std::move(v1)); + EXPECT_EQ(v2.size(), 1UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(addr, v2[0].value().get()); + EXPECT_TRUE(v2[0].moved()); +} + +TEST(InlinedVectorTest, MoveConstructorMovesElementsAllocated) { + InlinedVector<Value, 1> v1; + v1.reserve(2); + v1.emplace_back(3); + v1.emplace_back(5); + int* addr1 = v1[0].value().get(); + int* addr2 = v1[1].value().get(); + Value* data1 = v1.data(); + InlinedVector<Value, 1> v2(std::move(v1)); + EXPECT_EQ(v2.size(), 2UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(*v2[1].value(), 5); + EXPECT_EQ(addr1, v2[0].value().get()); + EXPECT_EQ(addr2, v2[1].value().get()); + // In this case, elements won't be moved, because we have just stolen + // the underlying storage. + EXPECT_EQ(data1, v2.data()); +} + +TEST(InlinedVectorTest, MoveAssignmentMovesElementsInlined) { + InlinedVector<Value, 1> v1; + v1.emplace_back(3); + int* addr = v1[0].value().get(); + InlinedVector<Value, 1> v2; + EXPECT_EQ(v2.size(), 0UL); + v2 = std::move(v1); + EXPECT_EQ(v2.size(), 1UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(addr, v2[0].value().get()); + EXPECT_TRUE(v2[0].moved()); +} + +TEST(InlinedVectorTest, MoveAssignmentMovesElementsAllocated) { + InlinedVector<Value, 1> v1; + v1.reserve(2); + v1.emplace_back(3); + v1.emplace_back(5); + int* addr1 = v1[0].value().get(); + int* addr2 = v1[1].value().get(); + Value* data1 = v1.data(); + InlinedVector<Value, 1> v2; + EXPECT_EQ(v2.size(), 0UL); + v2 = std::move(v1); + EXPECT_EQ(v2.size(), 2UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(*v2[1].value(), 5); + EXPECT_EQ(addr1, v2[0].value().get()); + EXPECT_EQ(addr2, v2[1].value().get()); + // In this case, elements won't be moved, because we have just stolen + // the underlying storage. + EXPECT_EQ(data1, v2.data()); +} + TEST(InlinedVectorTest, PopBackInlined) { InlinedVector<UniquePtr<int>, 2> v; // Add two elements, pop one out @@ -294,7 +454,7 @@ TEST(InlinedVectorTest, PopBackAllocated) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/manual_constructor_test.cc b/test/core/gprpp/manual_constructor_test.cc index af162ae8e8..a5a45133d8 100644 --- a/test/core/gprpp/manual_constructor_test.cc +++ b/test/core/gprpp/manual_constructor_test.cc @@ -92,7 +92,7 @@ static void complex_test() { /* ------------------------------------------------- */ int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); basic_test(); complex_test(); return 0; diff --git a/test/core/gprpp/memory_test.cc b/test/core/gprpp/memory_test.cc index 180c36fad7..bb6a219a84 100644 --- a/test/core/gprpp/memory_test.cc +++ b/test/core/gprpp/memory_test.cc @@ -68,7 +68,7 @@ TEST(MemoryTest, UniquePtrWithCustomDeleter) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/orphanable_test.cc b/test/core/gprpp/orphanable_test.cc index ad6b9ac867..fe13df0d0d 100644 --- a/test/core/gprpp/orphanable_test.cc +++ b/test/core/gprpp/orphanable_test.cc @@ -83,11 +83,11 @@ TEST(OrphanablePtr, InternallyRefCounted) { // things build properly in both debug and non-debug cases. DebugOnlyTraceFlag baz_tracer(true, "baz"); -class Baz : public InternallyRefCountedWithTracing<Baz> { +class Baz : public InternallyRefCounted<Baz> { public: Baz() : Baz(0) {} explicit Baz(int value) - : InternallyRefCountedWithTracing<Baz>(&baz_tracer), value_(value) {} + : InternallyRefCounted<Baz>(&baz_tracer), value_(value) {} void Orphan() override { Unref(); } int value() const { return value_; } @@ -114,7 +114,7 @@ TEST(OrphanablePtr, InternallyRefCountedWithTracing) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/ref_counted_ptr_test.cc b/test/core/gprpp/ref_counted_ptr_test.cc index 463b5e8966..96dbdf884b 100644 --- a/test/core/gprpp/ref_counted_ptr_test.cc +++ b/test/core/gprpp/ref_counted_ptr_test.cc @@ -163,9 +163,9 @@ TEST(MakeRefCounted, Args) { TraceFlag foo_tracer(true, "foo"); -class FooWithTracing : public RefCountedWithTracing<FooWithTracing> { +class FooWithTracing : public RefCounted<FooWithTracing> { public: - FooWithTracing() : RefCountedWithTracing(&foo_tracer) {} + FooWithTracing() : RefCounted(&foo_tracer) {} }; TEST(RefCountedPtr, RefCountedWithTracing) { @@ -241,7 +241,7 @@ TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingSubclass) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/ref_counted_test.cc b/test/core/gprpp/ref_counted_test.cc index f85a2e4675..1955be3311 100644 --- a/test/core/gprpp/ref_counted_test.cc +++ b/test/core/gprpp/ref_counted_test.cc @@ -29,7 +29,10 @@ namespace { class Foo : public RefCounted<Foo> { public: - Foo() {} + Foo() { + static_assert(std::has_virtual_destructor<Foo>::value, + "PolymorphicRefCount doesn't have a virtual dtor"); + } }; TEST(RefCounted, Basic) { @@ -45,13 +48,35 @@ TEST(RefCounted, ExtraRef) { foo->Unref(); } +class FooNonPolymorphic + : public RefCounted<FooNonPolymorphic, NonPolymorphicRefCount> { + public: + FooNonPolymorphic() { + static_assert(!std::has_virtual_destructor<FooNonPolymorphic>::value, + "NonPolymorphicRefCount has a virtual dtor"); + } +}; + +TEST(RefCountedNonPolymorphic, Basic) { + FooNonPolymorphic* foo = New<FooNonPolymorphic>(); + foo->Unref(); +} + +TEST(RefCountedNonPolymorphic, ExtraRef) { + FooNonPolymorphic* foo = New<FooNonPolymorphic>(); + RefCountedPtr<FooNonPolymorphic> foop = foo->Ref(); + foop.release(); + foo->Unref(); + foo->Unref(); +} + // Note: We use DebugOnlyTraceFlag instead of TraceFlag to ensure that // things build properly in both debug and non-debug cases. DebugOnlyTraceFlag foo_tracer(true, "foo"); -class FooWithTracing : public RefCountedWithTracing<FooWithTracing> { +class FooWithTracing : public RefCounted<FooWithTracing> { public: - FooWithTracing() : RefCountedWithTracing(&foo_tracer) {} + FooWithTracing() : RefCounted(&foo_tracer) {} }; TEST(RefCountedWithTracing, Basic) { @@ -66,12 +91,31 @@ TEST(RefCountedWithTracing, Basic) { foo->Unref(DEBUG_LOCATION, "original_ref"); } +class FooNonPolymorphicWithTracing + : public RefCounted<FooNonPolymorphicWithTracing, NonPolymorphicRefCount> { + public: + FooNonPolymorphicWithTracing() : RefCounted(&foo_tracer) {} +}; + +TEST(RefCountedNonPolymorphicWithTracing, Basic) { + FooNonPolymorphicWithTracing* foo = New<FooNonPolymorphicWithTracing>(); + RefCountedPtr<FooNonPolymorphicWithTracing> foop = + foo->Ref(DEBUG_LOCATION, "extra_ref"); + foop.release(); + foo->Unref(DEBUG_LOCATION, "extra_ref"); + // Can use the no-argument methods, too. + foop = foo->Ref(); + foop.release(); + foo->Unref(); + foo->Unref(DEBUG_LOCATION, "original_ref"); +} + } // namespace } // namespace testing } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/thd_test.cc b/test/core/gprpp/thd_test.cc index 82dd681049..06aa58984b 100644 --- a/test/core/gprpp/thd_test.cc +++ b/test/core/gprpp/thd_test.cc @@ -92,7 +92,7 @@ static void test2(void) { /* ------------------------------------------------- */ int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test1(); test2(); return 0; diff --git a/test/core/http/format_request_test.cc b/test/core/http/format_request_test.cc index 353e138b2a..b0a90c4613 100644 --- a/test/core/http/format_request_test.cc +++ b/test/core/http/format_request_test.cc @@ -138,7 +138,7 @@ static void test_format_post_request_content_type_override(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_format_get_request(); diff --git a/test/core/http/httpcli_test.cc b/test/core/http/httpcli_test.cc index a51a0a5f6d..bfd75f8649 100644 --- a/test/core/http/httpcli_test.cc +++ b/test/core/http/httpcli_test.cc @@ -145,7 +145,7 @@ static void destroy_pops(void* p, grpc_error* error) { int main(int argc, char** argv) { gpr_subprocess* server; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_closure destroyed; diff --git a/test/core/http/httpscli_test.cc b/test/core/http/httpscli_test.cc index 3fecf2b08b..326b0e95e2 100644 --- a/test/core/http/httpscli_test.cc +++ b/test/core/http/httpscli_test.cc @@ -201,7 +201,7 @@ int main(int argc, char** argv) { gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(5, GPR_TIMESPAN))); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); grpc_httpcli_context_init(&g_context); grpc_pollset* pollset = diff --git a/test/core/http/parser_test.cc b/test/core/http/parser_test.cc index fe824f57fc..d105b40bcd 100644 --- a/test/core/http/parser_test.cc +++ b/test/core/http/parser_test.cc @@ -218,7 +218,7 @@ int main(int argc, char** argv) { GRPC_SLICE_SPLIT_ONE_BYTE}; char *tmp1, *tmp2; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); for (i = 0; i < GPR_ARRAY_SIZE(split_modes); i++) { diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 70ee83acd2..e278632e50 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -40,7 +40,7 @@ grpc_cc_library( grpc_cc_test( name = "combiner_test", srcs = ["combiner_test.cc"], - data = ["//third_party/toolchains:RBE_USE_MACHINE_TYPE_LARGE"], + exec_compatible_with = ["//third_party/toolchains/machine_size:large"], language = "C++", deps = [ "//:gpr", diff --git a/test/core/iomgr/buffer_list_test.cc b/test/core/iomgr/buffer_list_test.cc index c7f30fa092..eca8f76e67 100644 --- a/test/core/iomgr/buffer_list_test.cc +++ b/test/core/iomgr/buffer_list_test.cc @@ -50,7 +50,7 @@ static void TestShutdownFlushesList() { grpc_core::TracedBuffer::AddNewEntry( &list, i, static_cast<void*>(&verifier_called[i])); } - grpc_core::TracedBuffer::Shutdown(&list, GRPC_ERROR_NONE); + grpc_core::TracedBuffer::Shutdown(&list, nullptr, GRPC_ERROR_NONE); GPR_ASSERT(list == nullptr); for (auto i = 0; i < NUM_ELEM; i++) { GPR_ASSERT(gpr_atm_acq_load(&verifier_called[i]) == @@ -88,7 +88,7 @@ static void TestVerifierCalledOnAck() { grpc_core::TracedBuffer::ProcessTimestamp(&list, &serr, &tss); GPR_ASSERT(gpr_atm_acq_load(&verifier_called) == static_cast<gpr_atm>(1)); GPR_ASSERT(list == nullptr); - grpc_core::TracedBuffer::Shutdown(&list, GRPC_ERROR_NONE); + grpc_core::TracedBuffer::Shutdown(&list, nullptr, GRPC_ERROR_NONE); } static void TestTcpBufferList() { @@ -97,7 +97,7 @@ static void TestTcpBufferList() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); TestTcpBufferList(); grpc_shutdown(); diff --git a/test/core/iomgr/combiner_test.cc b/test/core/iomgr/combiner_test.cc index cf2c7db846..c39c3fc8fc 100644 --- a/test/core/iomgr/combiner_test.cc +++ b/test/core/iomgr/combiner_test.cc @@ -144,7 +144,7 @@ static void test_execute_finally(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_no_op(); test_execute_one(); diff --git a/test/core/iomgr/endpoint_pair_test.cc b/test/core/iomgr/endpoint_pair_test.cc index ad38076b51..3ddbe7f2fc 100644 --- a/test/core/iomgr/endpoint_pair_test.cc +++ b/test/core/iomgr/endpoint_pair_test.cc @@ -60,7 +60,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/error_test.cc b/test/core/iomgr/error_test.cc index d78a8c2af3..3ba90147aa 100644 --- a/test/core/iomgr/error_test.cc +++ b/test/core/iomgr/error_test.cc @@ -215,7 +215,7 @@ static void test_overflow() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_set_get_int(); test_set_get_str(); diff --git a/test/core/iomgr/ev_epollex_linux_test.cc b/test/core/iomgr/ev_epollex_linux_test.cc index 08d1e68b39..faa3ef344a 100644 --- a/test/core/iomgr/ev_epollex_linux_test.cc +++ b/test/core/iomgr/ev_epollex_linux_test.cc @@ -92,7 +92,7 @@ static void test_pollable_owner_fd() { int main(int argc, char** argv) { const char* poll_strategy = nullptr; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/fd_conservation_posix_test.cc b/test/core/iomgr/fd_conservation_posix_test.cc index 4866e350d5..0d27b94dc2 100644 --- a/test/core/iomgr/fd_conservation_posix_test.cc +++ b/test/core/iomgr/fd_conservation_posix_test.cc @@ -29,7 +29,7 @@ int main(int argc, char** argv) { struct rlimit rlim; grpc_endpoint_pair p; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/fd_posix_test.cc b/test/core/iomgr/fd_posix_test.cc index 4ea2389bbd..cf5ffc6354 100644 --- a/test/core/iomgr/fd_posix_test.cc +++ b/test/core/iomgr/fd_posix_test.cc @@ -515,7 +515,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/grpc_ipv6_loopback_available_test.cc b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc index 329aa9a851..2ef1f1978d 100644 --- a/test/core/iomgr/grpc_ipv6_loopback_available_test.cc +++ b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc @@ -32,7 +32,7 @@ #endif int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); // This test assumes that the ipv6 loopback is available // in all environments in which grpc tests run in. diff --git a/test/core/iomgr/load_file_test.cc b/test/core/iomgr/load_file_test.cc index 38c8710535..a0e0e4d7a7 100644 --- a/test/core/iomgr/load_file_test.cc +++ b/test/core/iomgr/load_file_test.cc @@ -152,7 +152,7 @@ static void test_load_big_file(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_load_empty_file(); test_load_failure(); diff --git a/test/core/iomgr/resolve_address_posix_test.cc b/test/core/iomgr/resolve_address_posix_test.cc index e495e4c877..ceeb70a108 100644 --- a/test/core/iomgr/resolve_address_posix_test.cc +++ b/test/core/iomgr/resolve_address_posix_test.cc @@ -158,7 +158,7 @@ static void test_unix_socket_path_name_too_long(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { diff --git a/test/core/iomgr/resolve_address_test.cc b/test/core/iomgr/resolve_address_test.cc index 8d69bab5b1..1d9e1ee27e 100644 --- a/test/core/iomgr/resolve_address_test.cc +++ b/test/core/iomgr/resolve_address_test.cc @@ -271,7 +271,7 @@ int main(int argc, char** argv) { abort(); } // Run the test. - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/resource_quota_test.cc b/test/core/iomgr/resource_quota_test.cc index f3b35fed32..4cbc016d58 100644 --- a/test/core/iomgr/resource_quota_test.cc +++ b/test/core/iomgr/resource_quota_test.cc @@ -891,7 +891,7 @@ static void test_thread_maxquota_change() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); gpr_mu_init(&g_mu); gpr_cv_init(&g_cv); diff --git a/test/core/iomgr/sockaddr_utils_test.cc b/test/core/iomgr/sockaddr_utils_test.cc index 3783f968b7..250d36a74a 100644 --- a/test/core/iomgr/sockaddr_utils_test.cc +++ b/test/core/iomgr/sockaddr_utils_test.cc @@ -270,7 +270,7 @@ static void test_sockaddr_set_get_port(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_sockaddr_is_v4mapped(); test_sockaddr_to_v4mapped(); diff --git a/test/core/iomgr/socket_utils_test.cc b/test/core/iomgr/socket_utils_test.cc index a21f3fac62..420873734d 100644 --- a/test/core/iomgr/socket_utils_test.cc +++ b/test/core/iomgr/socket_utils_test.cc @@ -80,7 +80,7 @@ static const grpc_socket_mutator_vtable mutator_vtable = { int main(int argc, char** argv) { int sock; grpc_error* err; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); sock = socket(PF_INET, SOCK_STREAM, 0); GPR_ASSERT(sock > 0); diff --git a/test/core/iomgr/tcp_client_posix_test.cc b/test/core/iomgr/tcp_client_posix_test.cc index 90fc5aecfc..5cf3530c77 100644 --- a/test/core/iomgr/tcp_client_posix_test.cc +++ b/test/core/iomgr/tcp_client_posix_test.cc @@ -191,7 +191,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { diff --git a/test/core/iomgr/tcp_client_uv_test.cc b/test/core/iomgr/tcp_client_uv_test.cc index 27f894e3f3..bde8c2f353 100644 --- a/test/core/iomgr/tcp_client_uv_test.cc +++ b/test/core/iomgr/tcp_client_uv_test.cc @@ -188,7 +188,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/tcp_posix_test.cc b/test/core/iomgr/tcp_posix_test.cc index 6447cc234d..80f17a914f 100644 --- a/test/core/iomgr/tcp_posix_test.cc +++ b/test/core/iomgr/tcp_posix_test.cc @@ -623,7 +623,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); grpc_core::grpc_tcp_set_write_timestamps_callback(timestamps_verifier); { diff --git a/test/core/iomgr/tcp_server_posix_test.cc b/test/core/iomgr/tcp_server_posix_test.cc index d646df1dae..2c66cdec77 100644 --- a/test/core/iomgr/tcp_server_posix_test.cc +++ b/test/core/iomgr/tcp_server_posix_test.cc @@ -437,7 +437,7 @@ int main(int argc, char** argv) { // Zalloc dst_addrs to avoid oversized frames. test_addrs* dst_addrs = static_cast<test_addrs*>(gpr_zalloc(sizeof(*dst_addrs))); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/tcp_server_uv_test.cc b/test/core/iomgr/tcp_server_uv_test.cc index e99fa79bfd..625a18c0cc 100644 --- a/test/core/iomgr/tcp_server_uv_test.cc +++ b/test/core/iomgr/tcp_server_uv_test.cc @@ -288,7 +288,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/time_averaged_stats_test.cc b/test/core/iomgr/time_averaged_stats_test.cc index b932e62d1f..2923a35d1b 100644 --- a/test/core/iomgr/time_averaged_stats_test.cc +++ b/test/core/iomgr/time_averaged_stats_test.cc @@ -180,7 +180,7 @@ static void some_regress_some_persist_test(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); no_regress_no_persist_test_1(); no_regress_no_persist_test_2(); no_regress_no_persist_test_3(); diff --git a/test/core/iomgr/timer_heap_test.cc b/test/core/iomgr/timer_heap_test.cc index ebe5e6610d..872cf17486 100644 --- a/test/core/iomgr/timer_heap_test.cc +++ b/test/core/iomgr/timer_heap_test.cc @@ -286,7 +286,7 @@ static void shrink_test(void) { int main(int argc, char** argv) { int i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); for (i = 0; i < 5; i++) { test1(); diff --git a/test/core/iomgr/timer_list_test.cc b/test/core/iomgr/timer_list_test.cc index fd65d1abf1..fa2444948b 100644 --- a/test/core/iomgr/timer_list_test.cc +++ b/test/core/iomgr/timer_list_test.cc @@ -221,7 +221,7 @@ void long_running_service_cleanup_test(void) { int main(int argc, char** argv) { /* Tests with default g_start_time */ { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_core::ExecCtx::GlobalInit(); grpc_core::ExecCtx exec_ctx; grpc_determine_iomgr_platform(); @@ -235,7 +235,7 @@ int main(int argc, char** argv) { /* Begin long running service tests */ { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* Set g_start_time back 25 days. */ /* We set g_start_time here in case there are any initialization dependencies that use g_start_time. */ diff --git a/test/core/iomgr/udp_server_test.cc b/test/core/iomgr/udp_server_test.cc index d167c0131f..f65783a017 100644 --- a/test/core/iomgr/udp_server_test.cc +++ b/test/core/iomgr/udp_server_test.cc @@ -360,7 +360,7 @@ static void test_receive(int number_of_clients) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); if (grpc_is_socket_reuse_port_supported()) { g_num_listeners = 10; diff --git a/test/core/json/json_rewrite_test.cc b/test/core/json/json_rewrite_test.cc index 2fade12e13..b7e89cdb1a 100644 --- a/test/core/json/json_rewrite_test.cc +++ b/test/core/json/json_rewrite_test.cc @@ -287,7 +287,7 @@ void test_rewrites() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_rewrites(); gpr_log(GPR_INFO, "json_rewrite_test success"); return 0; diff --git a/test/core/json/json_stream_error_test.cc b/test/core/json/json_stream_error_test.cc index 00288d6d5e..53e20be206 100644 --- a/test/core/json/json_stream_error_test.cc +++ b/test/core/json/json_stream_error_test.cc @@ -49,7 +49,7 @@ static void read_error() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); read_error(); gpr_log(GPR_INFO, "json_stream_error success"); return 0; diff --git a/test/core/json/json_test.cc b/test/core/json/json_test.cc index 7f1dbb774a..03dd96a8ae 100644 --- a/test/core/json/json_test.cc +++ b/test/core/json/json_test.cc @@ -184,7 +184,7 @@ static void test_atypical() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_pairs(); test_atypical(); gpr_log(GPR_INFO, "json_test success"); diff --git a/test/core/memory_usage/BUILD b/test/core/memory_usage/BUILD new file mode 100644 index 0000000000..f39c309e36 --- /dev/null +++ b/test/core/memory_usage/BUILD @@ -0,0 +1,60 @@ +# Copyright 2017 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package") + +grpc_package(name = "test/core/memory_usage") + +licenses(["notice"]) # Apache v2 + +grpc_cc_library( + name = "client", + testonly = 1, + srcs = ["client.cc"], + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_library( + name = "server", + testonly = 1, + srcs = ["server.cc"], + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/core/end2end:ssl_test_data" + ], +) + +grpc_cc_test( + name = "memory_usage_test", + srcs = ["memory_usage_test.cc"], + language = "C++", + data = [ + ":client", + ":server", + ], + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) diff --git a/test/core/memory_usage/client.cc b/test/core/memory_usage/client.cc index 3c3fa53b51..467586ea5f 100644 --- a/test/core/memory_usage/client.cc +++ b/test/core/memory_usage/client.cc @@ -193,11 +193,11 @@ int main(int argc, char** argv) { gpr_cmdline* cl; grpc_event event; - grpc_init(); - GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; - grpc_test_init(1, fake_argv); + grpc::testing::TestEnvironment env(1, fake_argv); + + grpc_init(); int warmup_iterations = 100; int benchmark_iterations = 1000; diff --git a/test/core/memory_usage/server.cc b/test/core/memory_usage/server.cc index 3e7bb7e11f..7424797e6f 100644 --- a/test/core/memory_usage/server.cc +++ b/test/core/memory_usage/server.cc @@ -162,7 +162,7 @@ int main(int argc, char** argv) { GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; - grpc_test_init(1, fake_argv); + grpc::testing::TestEnvironment env(1, fake_argv); grpc_init(); srand(static_cast<unsigned>(clock())); @@ -292,9 +292,9 @@ int main(int argc, char** argv) { send_status(&calls[k]); } } + /* fallthrough */ // no break here since we want to continue to case // FLING_SERVER_SEND_STATUS_SNAPSHOT to destroy the snapshot call - /* fallthrough */ case FLING_SERVER_SEND_STATUS_SNAPSHOT: grpc_byte_buffer_destroy(payload_buffer); grpc_byte_buffer_destroy(terminal_buffer); diff --git a/test/core/security/auth_context_test.cc b/test/core/security/auth_context_test.cc index 58f0d8e1c2..9a39afb800 100644 --- a/test/core/security/auth_context_test.cc +++ b/test/core/security/auth_context_test.cc @@ -130,7 +130,7 @@ static void test_chained_context(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_empty_context(); test_simple_context(); test_chained_context(); diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc index 97156761bd..a7a6050ec0 100644 --- a/test/core/security/credentials_test.cc +++ b/test/core/security/credentials_test.cc @@ -43,6 +43,7 @@ #include "src/core/lib/security/transport/auth_filters.h" #include "test/core/util/test_config.h" +using grpc_core::internal::grpc_flush_cached_google_default_credentials; using grpc_core::internal::set_gce_tenancy_checker_for_testing; /* -- Mock channel credentials. -- */ @@ -918,6 +919,22 @@ static void test_google_default_creds_refresh_token(void) { gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ } +static int default_creds_metadata_server_detection_httpcli_get_success_override( + const grpc_httpcli_request* request, grpc_millis deadline, + grpc_closure* on_done, grpc_httpcli_response* response) { + *response = http_response(200, ""); + grpc_http_header* headers = + static_cast<grpc_http_header*>(gpr_malloc(sizeof(*headers) * 1)); + headers[0].key = gpr_strdup("Metadata-Flavor"); + headers[0].value = gpr_strdup("Google"); + response->hdr_count = 1; + response->hdrs = headers; + GPR_ASSERT(strcmp(request->http.path, "/") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); + return 1; +} + static char* null_well_known_creds_path_getter(void) { return nullptr; } static bool test_gce_tenancy_checker(void) { @@ -954,42 +971,81 @@ static void test_google_default_creds_gce(void) { run_request_metadata_test(creds->call_creds, auth_md_ctx, state); grpc_core::ExecCtx::Get()->Flush(); - /* Check that we get a cached creds if we call - grpc_google_default_credentials_create again. - GCE detection should not occur anymore either. */ - g_test_gce_tenancy_checker_called = false; - grpc_channel_credentials* cached_creds = - grpc_google_default_credentials_create(); - GPR_ASSERT(cached_creds == &creds->base); - GPR_ASSERT(g_test_gce_tenancy_checker_called == false); + GPR_ASSERT(g_test_gce_tenancy_checker_called == true); /* Cleanup. */ - grpc_channel_credentials_unref(cached_creds); grpc_channel_credentials_unref(&creds->base); grpc_httpcli_set_override(nullptr, nullptr); grpc_override_well_known_credentials_path_getter(nullptr); } -static void test_no_google_default_creds(void) { +static void test_google_default_creds_non_gce(void) { + grpc_core::ExecCtx exec_ctx; + expected_md emd[] = { + {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}}; + request_metadata_state* state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, + nullptr, nullptr}; grpc_flush_cached_google_default_credentials(); gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ grpc_override_well_known_credentials_path_getter( null_well_known_creds_path_getter); - set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker); g_test_gce_tenancy_checker_called = false; g_test_is_on_gce = false; + /* Simulate a successful detection of metadata server. */ + grpc_httpcli_set_override( + default_creds_metadata_server_detection_httpcli_get_success_override, + httpcli_post_should_not_be_called); + grpc_composite_channel_credentials* creds = + reinterpret_cast<grpc_composite_channel_credentials*>( + grpc_google_default_credentials_create()); + /* Verify that the default creds actually embeds a GCE creds. */ + GPR_ASSERT(creds != nullptr); + GPR_ASSERT(creds->call_creds != nullptr); + grpc_httpcli_set_override(compute_engine_httpcli_get_success_override, + httpcli_post_should_not_be_called); + run_request_metadata_test(creds->call_creds, auth_md_ctx, state); + grpc_core::ExecCtx::Get()->Flush(); + GPR_ASSERT(g_test_gce_tenancy_checker_called == true); + /* Cleanup. */ + grpc_channel_credentials_unref(&creds->base); + grpc_httpcli_set_override(nullptr, nullptr); + grpc_override_well_known_credentials_path_getter(nullptr); +} +static int default_creds_gce_detection_httpcli_get_failure_override( + const grpc_httpcli_request* request, grpc_millis deadline, + grpc_closure* on_done, grpc_httpcli_response* response) { + /* No magic header. */ + GPR_ASSERT(strcmp(request->http.path, "/") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + *response = http_response(200, ""); + GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); + return 1; +} + +static void test_no_google_default_creds(void) { + grpc_flush_cached_google_default_credentials(); + gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ + grpc_override_well_known_credentials_path_getter( + null_well_known_creds_path_getter); + set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker); + g_test_gce_tenancy_checker_called = false; + g_test_is_on_gce = false; + grpc_httpcli_set_override( + default_creds_gce_detection_httpcli_get_failure_override, + httpcli_post_should_not_be_called); /* Simulate a successful detection of GCE. */ GPR_ASSERT(grpc_google_default_credentials_create() == nullptr); - - /* Try a cached one. GCE detection should not occur anymore. */ + /* Try a second one. GCE detection should occur again. */ g_test_gce_tenancy_checker_called = false; GPR_ASSERT(grpc_google_default_credentials_create() == nullptr); - GPR_ASSERT(g_test_gce_tenancy_checker_called == false); - + GPR_ASSERT(g_test_gce_tenancy_checker_called == true); /* Cleanup. */ grpc_override_well_known_credentials_path_getter(nullptr); + grpc_httpcli_set_override(nullptr, nullptr); } typedef enum { @@ -1213,7 +1269,7 @@ static void test_auth_metadata_context(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_empty_md_array(); test_add_to_empty_md_array(); @@ -1240,6 +1296,7 @@ int main(int argc, char** argv) { test_google_default_creds_auth_key(); test_google_default_creds_refresh_token(); test_google_default_creds_gce(); + test_google_default_creds_non_gce(); test_no_google_default_creds(); test_metadata_plugin_success(); test_metadata_plugin_failure(); diff --git a/test/core/security/json_token_test.cc b/test/core/security/json_token_test.cc index 7a5b3355fe..a3ae18e6ab 100644 --- a/test/core/security/json_token_test.cc +++ b/test/core/security/json_token_test.cc @@ -482,7 +482,7 @@ static void test_parse_refresh_token_failure_no_refresh_token(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_parse_json_key_success(); test_parse_json_key_failure_bad_json(); diff --git a/test/core/security/jwt_verifier_test.cc b/test/core/security/jwt_verifier_test.cc index 9718580a08..70155cdd06 100644 --- a/test/core/security/jwt_verifier_test.cc +++ b/test/core/security/jwt_verifier_test.cc @@ -600,7 +600,7 @@ static void test_jwt_verifier_bad_format(void) { /* bad key */ int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_jwt_issuer_email_domain(); test_claims_success(); diff --git a/test/core/security/linux_system_roots_test.cc b/test/core/security/linux_system_roots_test.cc index 24d446de35..cd8bd3beb7 100644 --- a/test/core/security/linux_system_roots_test.cc +++ b/test/core/security/linux_system_roots_test.cc @@ -86,7 +86,7 @@ TEST(CreateRootCertsBundleTest, BundlesCorrectly) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/security/secure_endpoint_test.cc b/test/core/security/secure_endpoint_test.cc index 23cef99dfa..f6d02895b5 100644 --- a/test/core/security/secure_endpoint_test.cc +++ b/test/core/security/secure_endpoint_test.cc @@ -208,7 +208,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc index fef0ea71f7..e82a8627d4 100644 --- a/test/core/security/security_connector_test.cc +++ b/test/core/security/security_connector_test.cc @@ -430,7 +430,7 @@ static void test_default_ssl_roots(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_unauthenticated_ssl_peer(); diff --git a/test/core/security/ssl_credentials_test.cc b/test/core/security/ssl_credentials_test.cc index 9edcf42d3a..7c9f561665 100644 --- a/test/core/security/ssl_credentials_test.cc +++ b/test/core/security/ssl_credentials_test.cc @@ -56,7 +56,7 @@ static void test_convert_grpc_to_tsi_cert_pairs() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_convert_grpc_to_tsi_cert_pairs(); diff --git a/test/core/slice/b64_test.cc b/test/core/slice/b64_test.cc index 6b29443ba1..6677150c23 100644 --- a/test/core/slice/b64_test.cc +++ b/test/core/slice/b64_test.cc @@ -201,7 +201,7 @@ static void test_unpadded_decode(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_simple_encode_decode_b64_no_multiline(); test_simple_encode_decode_b64_multiline(); diff --git a/test/core/slice/percent_encoding_test.cc b/test/core/slice/percent_encoding_test.cc index e8d04fcc83..ae6c39eb26 100644 --- a/test/core/slice/percent_encoding_test.cc +++ b/test/core/slice/percent_encoding_test.cc @@ -118,7 +118,7 @@ static void test_nonconformant_vector(const char* encoded, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); TEST_VECTOR( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~", diff --git a/test/core/slice/slice_buffer_test.cc b/test/core/slice/slice_buffer_test.cc index e59986730b..b53e3312df 100644 --- a/test/core/slice/slice_buffer_test.cc +++ b/test/core/slice/slice_buffer_test.cc @@ -106,7 +106,7 @@ void test_slice_buffer_move_first() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_slice_buffer_add(); diff --git a/test/core/slice/slice_hash_table_test.cc b/test/core/slice/slice_hash_table_test.cc index 43ddfe9bf2..08cfe91e5a 100644 --- a/test/core/slice/slice_hash_table_test.cc +++ b/test/core/slice/slice_hash_table_test.cc @@ -217,7 +217,7 @@ TEST(SliceHashTable, CmpEmptyKeysDifferentValue) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_core::ExecCtx::GlobalInit(); int result = RUN_ALL_TESTS(); grpc_core::ExecCtx::GlobalShutdown(); diff --git a/test/core/slice/slice_string_helpers_test.cc b/test/core/slice/slice_string_helpers_test.cc index 860a1bfe03..1bbc0947bc 100644 --- a/test/core/slice/slice_string_helpers_test.cc +++ b/test/core/slice/slice_string_helpers_test.cc @@ -195,7 +195,7 @@ static void test_strsplit_nospace(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_dump_slice(); test_strsplit(); test_strsplit_nospace(); diff --git a/test/core/slice/slice_test.cc b/test/core/slice/slice_test.cc index e683c41f31..1e53a1951c 100644 --- a/test/core/slice/slice_test.cc +++ b/test/core/slice/slice_test.cc @@ -294,7 +294,7 @@ static void test_static_slice_copy_interning(void) { int main(int argc, char** argv) { unsigned length; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_slice_malloc_returns_something_sensible(); test_slice_new_returns_something_sensible(); diff --git a/test/core/slice/slice_weak_hash_table_test.cc b/test/core/slice/slice_weak_hash_table_test.cc index b0a243d572..ab0a648727 100644 --- a/test/core/slice/slice_weak_hash_table_test.cc +++ b/test/core/slice/slice_weak_hash_table_test.cc @@ -98,7 +98,7 @@ TEST(SliceWeakHashTable, ForceOverload) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_core::ExecCtx::GlobalInit(); int result = RUN_ALL_TESTS(); grpc_core::ExecCtx::GlobalShutdown(); diff --git a/test/core/surface/byte_buffer_reader_test.cc b/test/core/surface/byte_buffer_reader_test.cc index cff05caec1..301a1e283b 100644 --- a/test/core/surface/byte_buffer_reader_test.cc +++ b/test/core/surface/byte_buffer_reader_test.cc @@ -267,7 +267,7 @@ static void test_byte_buffer_copy(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_read_one_slice(); test_read_one_slice_malloc(); test_read_none_compressed_slice(); diff --git a/test/core/surface/channel_create_test.cc b/test/core/surface/channel_create_test.cc index 56f4f602e8..5f109c0f84 100644 --- a/test/core/surface/channel_create_test.cc +++ b/test/core/surface/channel_create_test.cc @@ -44,7 +44,7 @@ void test_unknown_scheme_target(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_unknown_scheme_target(); grpc_shutdown(); diff --git a/test/core/surface/completion_queue_test.cc b/test/core/surface/completion_queue_test.cc index f7ce8a7042..a157d75eda 100644 --- a/test/core/surface/completion_queue_test.cc +++ b/test/core/surface/completion_queue_test.cc @@ -440,7 +440,7 @@ struct thread_state { }; int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_no_op(); test_pollset_conversion(); diff --git a/test/core/surface/completion_queue_threading_test.cc b/test/core/surface/completion_queue_threading_test.cc index 0b82803af6..4215aad14a 100644 --- a/test/core/surface/completion_queue_threading_test.cc +++ b/test/core/surface/completion_queue_threading_test.cc @@ -288,7 +288,7 @@ static void test_threading(size_t producers, size_t consumers) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_too_many_plucks(); test_threading(1, 1); diff --git a/test/core/surface/concurrent_connectivity_test.cc b/test/core/surface/concurrent_connectivity_test.cc index fbc5ec4c54..f606e89ac8 100644 --- a/test/core/surface/concurrent_connectivity_test.cc +++ b/test/core/surface/concurrent_connectivity_test.cc @@ -300,7 +300,7 @@ int run_concurrent_watches_with_short_timeouts_test() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_concurrent_connectivity_test(); run_concurrent_watches_with_short_timeouts_test(); diff --git a/test/core/surface/init_test.cc b/test/core/surface/init_test.cc index 5749bc8b36..1bcd13a0b8 100644 --- a/test/core/surface/init_test.cc +++ b/test/core/surface/init_test.cc @@ -60,7 +60,7 @@ static void test_repeatedly() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test(1); test(2); test(3); diff --git a/test/core/surface/lame_client_test.cc b/test/core/surface/lame_client_test.cc index fac5ca8f7f..09c3d43197 100644 --- a/test/core/surface/lame_client_test.cc +++ b/test/core/surface/lame_client_test.cc @@ -75,7 +75,7 @@ int main(int argc, char** argv) { grpc_slice details; char* peer; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); grpc_metadata_array_init(&initial_metadata_recv); diff --git a/test/core/surface/num_external_connectivity_watchers_test.cc b/test/core/surface/num_external_connectivity_watchers_test.cc index 7b7a0b6dfc..454cbd5747 100644 --- a/test/core/surface/num_external_connectivity_watchers_test.cc +++ b/test/core/surface/num_external_connectivity_watchers_test.cc @@ -191,7 +191,7 @@ static const test_fixture secure_test = { }; int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_timeouts_test(&insecure_test); run_timeouts_test(&secure_test); diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 4640b8e4ca..426ef1e8b1 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -137,6 +137,7 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_resource_quota_arg_vtable); printf("%lx", (unsigned long) grpc_channelz_get_top_channels); printf("%lx", (unsigned long) grpc_channelz_get_servers); + printf("%lx", (unsigned long) grpc_channelz_get_server); printf("%lx", (unsigned long) grpc_channelz_get_server_sockets); printf("%lx", (unsigned long) grpc_channelz_get_channel); printf("%lx", (unsigned long) grpc_channelz_get_subchannel); diff --git a/test/core/surface/secure_channel_create_test.cc b/test/core/surface/secure_channel_create_test.cc index 06962179a2..5610d1ec4a 100644 --- a/test/core/surface/secure_channel_create_test.cc +++ b/test/core/surface/secure_channel_create_test.cc @@ -70,7 +70,7 @@ void test_null_creds(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_security_connector_already_in_arg(); test_null_creds(); diff --git a/test/core/surface/sequential_connectivity_test.cc b/test/core/surface/sequential_connectivity_test.cc index 10562b3be9..3f9a7baf98 100644 --- a/test/core/surface/sequential_connectivity_test.cc +++ b/test/core/surface/sequential_connectivity_test.cc @@ -168,7 +168,7 @@ static const test_fixture secure_test = { }; int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_test(&insecure_test); run_test(&secure_test); diff --git a/test/core/surface/server_chttp2_test.cc b/test/core/surface/server_chttp2_test.cc index fd8ab9cd3d..ffb7f14f98 100644 --- a/test/core/surface/server_chttp2_test.cc +++ b/test/core/surface/server_chttp2_test.cc @@ -67,7 +67,7 @@ void test_add_same_port_twice() { #endif int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_unparsable_target(); #ifndef GRPC_UV diff --git a/test/core/surface/server_test.cc b/test/core/surface/server_test.cc index b4eabd8d4d..2fc166546b 100644 --- a/test/core/surface/server_test.cc +++ b/test/core/surface/server_test.cc @@ -148,7 +148,7 @@ static void test_bind_server_to_addrs(const char** addrs, size_t n) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_register_method_fail(); test_request_call_on_no_server_cq(); diff --git a/test/core/transport/bdp_estimator_test.cc b/test/core/transport/bdp_estimator_test.cc index c7e6b2bd84..a795daaead 100644 --- a/test/core/transport/bdp_estimator_test.cc +++ b/test/core/transport/bdp_estimator_test.cc @@ -139,7 +139,7 @@ INSTANTIATE_TEST_CASE_P(TooManyNames, BdpEstimatorRandomTest, } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); gpr_now_impl = grpc_core::testing::fake_gpr_now; grpc_init(); grpc_timer_manager_set_threading(false); diff --git a/test/core/transport/byte_stream_test.cc b/test/core/transport/byte_stream_test.cc index df09637249..6c543892d0 100644 --- a/test/core/transport/byte_stream_test.cc +++ b/test/core/transport/byte_stream_test.cc @@ -245,7 +245,7 @@ TEST(CachingByteStream, SharedCache) { int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int retval = RUN_ALL_TESTS(); grpc_shutdown(); diff --git a/test/core/transport/chttp2/BUILD b/test/core/transport/chttp2/BUILD index 6eff716b01..33437373e4 100644 --- a/test/core/transport/chttp2/BUILD +++ b/test/core/transport/chttp2/BUILD @@ -67,6 +67,22 @@ grpc_cc_test( ) grpc_cc_test( + name = "context_list_test", + srcs = ["context_list_test.cc"], + external_deps = [ + "gtest", + ], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + + +grpc_cc_test( name = "hpack_encoder_test", srcs = ["hpack_encoder_test.cc"], language = "C++", diff --git a/test/core/transport/chttp2/alpn_test.cc b/test/core/transport/chttp2/alpn_test.cc index a43377393e..6da5299363 100644 --- a/test/core/transport/chttp2/alpn_test.cc +++ b/test/core/transport/chttp2/alpn_test.cc @@ -49,7 +49,7 @@ static void test_alpn_grpc_before_h2(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_alpn_success(); test_alpn_failure(); test_alpn_grpc_before_h2(); diff --git a/test/core/transport/chttp2/context_list_test.cc b/test/core/transport/chttp2/context_list_test.cc new file mode 100644 index 0000000000..edbe658a89 --- /dev/null +++ b/test/core/transport/chttp2/context_list_test.cc @@ -0,0 +1,102 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +#include <gtest/gtest.h> +#include <new> +#include <vector> + +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/ext/transport/chttp2/transport/context_list.h" +#include "src/core/lib/transport/transport.h" +#include "test/core/util/mock_endpoint.h" +#include "test/core/util/test_config.h" + +#include <grpc/grpc.h> + +namespace grpc_core { +namespace testing { +namespace { + +const uint32_t kByteOffset = 123; + +void TestExecuteFlushesListVerifier(void* arg, grpc_core::Timestamps* ts) { + ASSERT_NE(arg, nullptr); + EXPECT_EQ(ts->byte_offset, kByteOffset); + gpr_atm* done = reinterpret_cast<gpr_atm*>(arg); + gpr_atm_rel_store(done, static_cast<gpr_atm>(1)); +} + +void discard_write(grpc_slice slice) {} + +/** Tests that all ContextList elements in the list are flushed out on + * execute. + * Also tests that arg and byte_counter are passed correctly. + */ +TEST(ContextList, ExecuteFlushesList) { + grpc_core::ContextList* list = nullptr; + grpc_http2_set_write_timestamps_callback(TestExecuteFlushesListVerifier); + const int kNumElems = 5; + grpc_core::ExecCtx exec_ctx; + grpc_stream_refcount ref; + GRPC_STREAM_REF_INIT(&ref, 1, nullptr, nullptr, "dummy ref"); + grpc_resource_quota* resource_quota = + grpc_resource_quota_create("context_list_test"); + grpc_endpoint* mock_endpoint = + grpc_mock_endpoint_create(discard_write, resource_quota); + grpc_transport* t = + grpc_create_chttp2_transport(nullptr, mock_endpoint, true); + std::vector<grpc_chttp2_stream*> s; + s.reserve(kNumElems); + gpr_atm verifier_called[kNumElems]; + for (auto i = 0; i < kNumElems; i++) { + s.push_back(static_cast<grpc_chttp2_stream*>( + gpr_malloc(grpc_transport_stream_size(t)))); + grpc_transport_init_stream(reinterpret_cast<grpc_transport*>(t), + reinterpret_cast<grpc_stream*>(s[i]), &ref, + nullptr, nullptr); + s[i]->context = &verifier_called[i]; + s[i]->byte_counter = kByteOffset; + gpr_atm_rel_store(&verifier_called[i], static_cast<gpr_atm>(0)); + grpc_core::ContextList::Append(&list, s[i]); + } + grpc_core::Timestamps ts; + grpc_core::ContextList::Execute(list, &ts, GRPC_ERROR_NONE); + for (auto i = 0; i < kNumElems; i++) { + EXPECT_EQ(gpr_atm_acq_load(&verifier_called[i]), static_cast<gpr_atm>(1)); + grpc_transport_destroy_stream(reinterpret_cast<grpc_transport*>(t), + reinterpret_cast<grpc_stream*>(s[i]), + nullptr); + exec_ctx.Flush(); + gpr_free(s[i]); + } + grpc_transport_destroy(t); + grpc_resource_quota_unref(resource_quota); + exec_ctx.Flush(); +} +} // namespace +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + grpc_init(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/core/transport/chttp2/hpack_encoder_test.cc b/test/core/transport/chttp2/hpack_encoder_test.cc index ab819f9092..6cbc914c7f 100644 --- a/test/core/transport/chttp2/hpack_encoder_test.cc +++ b/test/core/transport/chttp2/hpack_encoder_test.cc @@ -261,7 +261,7 @@ static void run_test(void (*test)(), const char* name) { int main(int argc, char** argv) { size_t i; grpc_test_only_set_slice_hash_seed(0); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); TEST(test_basic_headers); TEST(test_decode_table_overflow); diff --git a/test/core/transport/chttp2/hpack_parser_test.cc b/test/core/transport/chttp2/hpack_parser_test.cc index 43b6c79e8a..882ad726b5 100644 --- a/test/core/transport/chttp2/hpack_parser_test.cc +++ b/test/core/transport/chttp2/hpack_parser_test.cc @@ -208,7 +208,7 @@ static void test_vectors(grpc_slice_split_mode mode) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_vectors(GRPC_SLICE_SPLIT_MERGE_ALL); test_vectors(GRPC_SLICE_SPLIT_ONE_BYTE); diff --git a/test/core/transport/chttp2/hpack_table_test.cc b/test/core/transport/chttp2/hpack_table_test.cc index 3ab463b631..c31975786f 100644 --- a/test/core/transport/chttp2/hpack_table_test.cc +++ b/test/core/transport/chttp2/hpack_table_test.cc @@ -268,7 +268,7 @@ static void test_find(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_static_lookup(); test_many_additions(); diff --git a/test/core/transport/chttp2/settings_timeout_test.cc b/test/core/transport/chttp2/settings_timeout_test.cc index 2d6f0a9a62..a9789edbf2 100644 --- a/test/core/transport/chttp2/settings_timeout_test.cc +++ b/test/core/transport/chttp2/settings_timeout_test.cc @@ -248,7 +248,7 @@ TEST(SettingsTimeout, Basic) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); int result = RUN_ALL_TESTS(); grpc_shutdown(); diff --git a/test/core/transport/chttp2/stream_map_test.cc b/test/core/transport/chttp2/stream_map_test.cc index 773eb3a35f..a36c496eb1 100644 --- a/test/core/transport/chttp2/stream_map_test.cc +++ b/test/core/transport/chttp2/stream_map_test.cc @@ -193,7 +193,7 @@ int main(int argc, char** argv) { uint32_t prev = 1; uint32_t tmp; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_no_op(); test_empty_find(); diff --git a/test/core/transport/chttp2/varint_test.cc b/test/core/transport/chttp2/varint_test.cc index 36760d0c72..5e00cc376a 100644 --- a/test/core/transport/chttp2/varint_test.cc +++ b/test/core/transport/chttp2/varint_test.cc @@ -44,7 +44,7 @@ static void test_varint(uint32_t value, uint32_t prefix_bits, uint8_t prefix_or, test_varint(value, prefix_bits, prefix_or, expect, sizeof(expect) - 1) int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); TEST_VARINT(0, 1, 0, "\x00"); TEST_VARINT(128, 1, 0, "\x7f\x01"); diff --git a/test/core/transport/connectivity_state_test.cc b/test/core/transport/connectivity_state_test.cc index cbd6318f52..7c7e3084bf 100644 --- a/test/core/transport/connectivity_state_test.cc +++ b/test/core/transport/connectivity_state_test.cc @@ -134,7 +134,7 @@ static void test_subscribe_with_failure_then_destroy(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); grpc_core::testing::grpc_tracer_enable_flag(&grpc_connectivity_state_trace); test_connectivity_state_name(); diff --git a/test/core/transport/metadata_test.cc b/test/core/transport/metadata_test.cc index 8ab9639dfa..9a49d28ccc 100644 --- a/test/core/transport/metadata_test.cc +++ b/test/core/transport/metadata_test.cc @@ -370,7 +370,7 @@ static void test_copied_static_metadata(bool dup_key, bool dup_value) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_no_op(); for (int k = 0; k <= 1; k++) { diff --git a/test/core/transport/pid_controller_test.cc b/test/core/transport/pid_controller_test.cc index 8d2cec4042..f6235244f6 100644 --- a/test/core/transport/pid_controller_test.cc +++ b/test/core/transport/pid_controller_test.cc @@ -85,7 +85,7 @@ INSTANTIATE_TEST_CASE_P( } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/transport/status_conversion_test.cc b/test/core/transport/status_conversion_test.cc index f7b3c62a40..949be42aeb 100644 --- a/test/core/transport/status_conversion_test.cc +++ b/test/core/transport/status_conversion_test.cc @@ -163,7 +163,7 @@ static void test_http2_status_to_grpc_status() { int main(int argc, char** argv) { int i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_grpc_status_to_http2_error(); diff --git a/test/core/transport/stream_owned_slice_test.cc b/test/core/transport/stream_owned_slice_test.cc index 7831f67a04..48a77db9a5 100644 --- a/test/core/transport/stream_owned_slice_test.cc +++ b/test/core/transport/stream_owned_slice_test.cc @@ -26,7 +26,7 @@ static void do_nothing(void* arg, grpc_error* error) {} int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); uint8_t buffer[] = "abc123"; diff --git a/test/core/transport/timeout_encoding_test.cc b/test/core/transport/timeout_encoding_test.cc index b7044b5b41..22e68fe554 100644 --- a/test/core/transport/timeout_encoding_test.cc +++ b/test/core/transport/timeout_encoding_test.cc @@ -156,7 +156,7 @@ void test_decoding_fails(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_encoding(); test_decoding(); test_decoding_fails(); diff --git a/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc b/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc index c8d88aa72c..9a4541bb7d 100644 --- a/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc +++ b/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc @@ -19,14 +19,14 @@ #include <grpc/grpc.h> #include "src/core/tsi/alts/handshaker/alts_handshaker_client.h" -#include "src/core/tsi/alts/handshaker/alts_tsi_event.h" +#include "src/core/tsi/alts/handshaker/alts_shared_resource.h" #include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" +#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h" #include "src/core/tsi/transport_security.h" #include "src/core/tsi/transport_security_interface.h" #include "test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.h" #define ALTS_HANDSHAKER_CLIENT_TEST_OUT_FRAME "Hello Google" -#define ALTS_HANDSHAKER_CLIENT_TEST_HANDSHAKER_SERVICE_URL "lame" #define ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME "bigtable.google.api.com" #define ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1 "A@google.com" #define ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2 "B@google.com" @@ -37,37 +37,22 @@ const size_t kMaxRpcVersionMinor = 2; const size_t kMinRpcVersionMajor = 2; const size_t kMinRpcVersionMinor = 1; +using grpc_core::internal::alts_handshaker_client_get_closure_for_testing; +using grpc_core::internal:: + alts_handshaker_client_get_initial_metadata_for_testing; +using grpc_core::internal:: + alts_handshaker_client_get_recv_buffer_addr_for_testing; +using grpc_core::internal::alts_handshaker_client_get_send_buffer_for_testing; using grpc_core::internal::alts_handshaker_client_set_grpc_caller_for_testing; typedef struct alts_handshaker_client_test_config { grpc_channel* channel; grpc_completion_queue* cq; alts_handshaker_client* client; + alts_handshaker_client* server; grpc_slice out_frame; } alts_handshaker_client_test_config; -static alts_tsi_event* alts_tsi_event_create_for_testing(bool is_client) { - alts_tsi_event* e = static_cast<alts_tsi_event*>(gpr_zalloc(sizeof(*e))); - grpc_metadata_array_init(&e->initial_metadata); - grpc_metadata_array_init(&e->trailing_metadata); - e->options = is_client ? grpc_alts_credentials_client_options_create() - : grpc_alts_credentials_server_options_create(); - if (is_client) { - grpc_alts_credentials_client_options_add_target_service_account( - e->options, ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1); - grpc_alts_credentials_client_options_add_target_service_account( - e->options, ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2); - } - grpc_gcp_rpc_protocol_versions* versions = &e->options->rpc_versions; - GPR_ASSERT(grpc_gcp_rpc_protocol_versions_set_max( - versions, kMaxRpcVersionMajor, kMaxRpcVersionMinor)); - GPR_ASSERT(grpc_gcp_rpc_protocol_versions_set_min( - versions, kMinRpcVersionMajor, kMinRpcVersionMinor)); - e->target_name = - grpc_slice_from_static_string(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME); - return e; -} - static void validate_rpc_protocol_versions( grpc_gcp_rpc_protocol_versions* versions) { GPR_ASSERT(versions != nullptr); @@ -101,11 +86,11 @@ static void validate_target_identities( /** * Validate if grpc operation data is correctly populated with the fields of - * ALTS TSI event. + * ALTS handshaker client. */ -static bool validate_op(alts_tsi_event* event, const grpc_op* op, size_t nops, - bool is_start) { - GPR_ASSERT(event != nullptr && op != nullptr && nops != 0); +static bool validate_op(alts_handshaker_client* c, const grpc_op* op, + size_t nops, bool is_start) { + GPR_ASSERT(c != nullptr && op != nullptr && nops != 0); bool ok = true; grpc_op* start_op = const_cast<grpc_op*>(op); if (is_start) { @@ -113,23 +98,22 @@ static bool validate_op(alts_tsi_event* event, const grpc_op* op, size_t nops, ok &= (op->data.send_initial_metadata.count == 0); op++; GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum); - ok &= (op->op == GRPC_OP_RECV_INITIAL_METADATA); ok &= (op->data.recv_initial_metadata.recv_initial_metadata == - &event->initial_metadata); + alts_handshaker_client_get_initial_metadata_for_testing(c)); op++; GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum); } ok &= (op->op == GRPC_OP_SEND_MESSAGE); - ok &= (op->data.send_message.send_message == event->send_buffer); + ok &= (op->data.send_message.send_message == + alts_handshaker_client_get_send_buffer_for_testing(c)); op++; GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum); - ok &= (op->op == GRPC_OP_RECV_MESSAGE); - ok &= (op->data.recv_message.recv_message == &event->recv_buffer); + ok &= (op->data.recv_message.recv_message == + alts_handshaker_client_get_recv_buffer_addr_for_testing(c)); op++; GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum); - return ok; } @@ -152,7 +136,7 @@ static grpc_gcp_handshaker_req* deserialize_handshaker_req( */ static grpc_call_error check_must_not_be_called(grpc_call* call, const grpc_op* ops, size_t nops, - void* tag) { + grpc_closure* tag) { GPR_ASSERT(0); } @@ -164,10 +148,14 @@ static grpc_call_error check_must_not_be_called(grpc_call* call, */ static grpc_call_error check_client_start_success(grpc_call* call, const grpc_op* op, - size_t nops, void* tag) { - alts_tsi_event* event = static_cast<alts_tsi_event*>(tag); - grpc_gcp_handshaker_req* req = - deserialize_handshaker_req(CLIENT_START_REQ, event->send_buffer); + size_t nops, + grpc_closure* closure) { + alts_handshaker_client* client = + static_cast<alts_handshaker_client*>(closure->cb_arg); + GPR_ASSERT(alts_handshaker_client_get_closure_for_testing(client) == closure); + grpc_gcp_handshaker_req* req = deserialize_handshaker_req( + CLIENT_START_REQ, + alts_handshaker_client_get_send_buffer_for_testing(client)); GPR_ASSERT(req->client_start.handshake_security_protocol == grpc_gcp_HandshakeProtocol_ALTS); const void* data = (static_cast<repeated_field*>( @@ -194,7 +182,7 @@ static grpc_call_error check_client_start_success(grpc_call* call, GRPC_SLICE_LENGTH(*target_name)) == 0); GPR_ASSERT(GRPC_SLICE_LENGTH(*target_name) == strlen(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME)); - GPR_ASSERT(validate_op(event, op, nops, true /* is_start */)); + GPR_ASSERT(validate_op(client, op, nops, true /* is_start */)); grpc_gcp_handshaker_req_destroy(req); return GRPC_CALL_OK; } @@ -207,10 +195,14 @@ static grpc_call_error check_client_start_success(grpc_call* call, */ static grpc_call_error check_server_start_success(grpc_call* call, const grpc_op* op, - size_t nops, void* tag) { - alts_tsi_event* event = static_cast<alts_tsi_event*>(tag); - grpc_gcp_handshaker_req* req = - deserialize_handshaker_req(SERVER_START_REQ, event->send_buffer); + size_t nops, + grpc_closure* closure) { + alts_handshaker_client* client = + static_cast<alts_handshaker_client*>(closure->cb_arg); + GPR_ASSERT(alts_handshaker_client_get_closure_for_testing(client) == closure); + grpc_gcp_handshaker_req* req = deserialize_handshaker_req( + SERVER_START_REQ, + alts_handshaker_client_get_send_buffer_for_testing(client)); const void* data = (static_cast<repeated_field*>( req->server_start.application_protocols.arg)) ->data; @@ -231,7 +223,7 @@ static grpc_call_error check_server_start_success(grpc_call* call, ALTS_RECORD_PROTOCOL, GRPC_SLICE_LENGTH(*record_protocol)) == 0); validate_rpc_protocol_versions(&req->server_start.rpc_versions); - GPR_ASSERT(validate_op(event, op, nops, true /* is_start */)); + GPR_ASSERT(validate_op(client, op, nops, true /* is_start */)); grpc_gcp_handshaker_req_destroy(req); return GRPC_CALL_OK; } @@ -242,16 +234,18 @@ static grpc_call_error check_server_start_success(grpc_call* call, * and op is correctly populated. */ static grpc_call_error check_next_success(grpc_call* call, const grpc_op* op, - size_t nops, void* tag) { - alts_tsi_event* event = static_cast<alts_tsi_event*>(tag); - grpc_gcp_handshaker_req* req = - deserialize_handshaker_req(NEXT_REQ, event->send_buffer); + size_t nops, grpc_closure* closure) { + alts_handshaker_client* client = + static_cast<alts_handshaker_client*>(closure->cb_arg); + GPR_ASSERT(alts_handshaker_client_get_closure_for_testing(client) == closure); + grpc_gcp_handshaker_req* req = deserialize_handshaker_req( + NEXT_REQ, alts_handshaker_client_get_send_buffer_for_testing(client)); grpc_slice* in_bytes = static_cast<grpc_slice*>(req->next.in_bytes.arg); GPR_ASSERT(in_bytes != nullptr); GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*in_bytes), ALTS_HANDSHAKER_CLIENT_TEST_OUT_FRAME, GRPC_SLICE_LENGTH(*in_bytes)) == 0); - GPR_ASSERT(validate_op(event, op, nops, false /* is_start */)); + GPR_ASSERT(validate_op(client, op, nops, false /* is_start */)); grpc_gcp_handshaker_req_destroy(req); return GRPC_CALL_OK; } @@ -262,21 +256,54 @@ static grpc_call_error check_next_success(grpc_call* call, const grpc_op* op, */ static grpc_call_error check_grpc_call_failure(grpc_call* call, const grpc_op* op, size_t nops, - void* tag) { + grpc_closure* tag) { return GRPC_CALL_ERROR; } +static grpc_alts_credentials_options* create_credentials_options( + bool is_client) { + grpc_alts_credentials_options* options = + is_client ? grpc_alts_credentials_client_options_create() + : grpc_alts_credentials_server_options_create(); + if (is_client) { + grpc_alts_credentials_client_options_add_target_service_account( + options, ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1); + grpc_alts_credentials_client_options_add_target_service_account( + options, ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2); + } + grpc_gcp_rpc_protocol_versions* versions = &options->rpc_versions; + GPR_ASSERT(grpc_gcp_rpc_protocol_versions_set_max( + versions, kMaxRpcVersionMajor, kMaxRpcVersionMinor)); + GPR_ASSERT(grpc_gcp_rpc_protocol_versions_set_min( + versions, kMinRpcVersionMajor, kMinRpcVersionMinor)); + return options; +} + static alts_handshaker_client_test_config* create_config() { alts_handshaker_client_test_config* config = static_cast<alts_handshaker_client_test_config*>( gpr_zalloc(sizeof(*config))); config->channel = grpc_insecure_channel_create( - ALTS_HANDSHAKER_CLIENT_TEST_HANDSHAKER_SERVICE_URL, nullptr, nullptr); + ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING, nullptr, nullptr); config->cq = grpc_completion_queue_create_for_next(nullptr); + grpc_alts_credentials_options* client_options = + create_credentials_options(true /* is_client */); + grpc_alts_credentials_options* server_options = + create_credentials_options(false /* is_client */); + config->server = alts_grpc_handshaker_client_create( + nullptr, config->channel, ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING, + nullptr, server_options, + grpc_slice_from_static_string(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME), + nullptr, nullptr, nullptr, nullptr, false); config->client = alts_grpc_handshaker_client_create( - config->channel, config->cq, - ALTS_HANDSHAKER_CLIENT_TEST_HANDSHAKER_SERVICE_URL); + nullptr, config->channel, ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING, + nullptr, client_options, + grpc_slice_from_static_string(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME), + nullptr, nullptr, nullptr, nullptr, true); GPR_ASSERT(config->client != nullptr); + GPR_ASSERT(config->server != nullptr); + grpc_alts_credentials_options_destroy(client_options); + grpc_alts_credentials_options_destroy(server_options); config->out_frame = grpc_slice_from_static_string(ALTS_HANDSHAKER_CLIENT_TEST_OUT_FRAME); return config; @@ -289,6 +316,7 @@ static void destroy_config(alts_handshaker_client_test_config* config) { grpc_completion_queue_destroy(config->cq); grpc_channel_destroy(config->channel); alts_handshaker_client_destroy(config->client); + alts_handshaker_client_destroy(config->server); grpc_slice_unref(config->out_frame); gpr_free(config); } @@ -296,73 +324,50 @@ static void destroy_config(alts_handshaker_client_test_config* config) { static void schedule_request_invalid_arg_test() { /* Initialization. */ alts_handshaker_client_test_config* config = create_config(); - alts_tsi_event* event = nullptr; - /* Tests. */ alts_handshaker_client_set_grpc_caller_for_testing(config->client, check_must_not_be_called); - event = alts_tsi_event_create_for_testing(true /* is_client */); /* Check client_start. */ - GPR_ASSERT(alts_handshaker_client_start_client(nullptr, event) == - TSI_INVALID_ARGUMENT); - GPR_ASSERT(alts_handshaker_client_start_client(config->client, nullptr) == + GPR_ASSERT(alts_handshaker_client_start_client(nullptr) == TSI_INVALID_ARGUMENT); - /* Check server_start. */ - GPR_ASSERT(alts_handshaker_client_start_server( - config->client, event, nullptr) == TSI_INVALID_ARGUMENT); - GPR_ASSERT(alts_handshaker_client_start_server(config->client, nullptr, - &config->out_frame) == + GPR_ASSERT(alts_handshaker_client_start_server(config->server, nullptr) == TSI_INVALID_ARGUMENT); - GPR_ASSERT(alts_handshaker_client_start_server( - nullptr, event, &config->out_frame) == TSI_INVALID_ARGUMENT); - - /* Check next. */ - GPR_ASSERT(alts_handshaker_client_next(config->client, event, nullptr) == + GPR_ASSERT(alts_handshaker_client_start_server(nullptr, &config->out_frame) == TSI_INVALID_ARGUMENT); - GPR_ASSERT(alts_handshaker_client_next(config->client, nullptr, - &config->out_frame) == + /* Check next. */ + GPR_ASSERT(alts_handshaker_client_next(config->client, nullptr) == TSI_INVALID_ARGUMENT); - GPR_ASSERT(alts_handshaker_client_next(nullptr, event, &config->out_frame) == + GPR_ASSERT(alts_handshaker_client_next(nullptr, &config->out_frame) == TSI_INVALID_ARGUMENT); - /* Check shutdown. */ alts_handshaker_client_shutdown(nullptr); - /* Cleanup. */ - alts_tsi_event_destroy(event); destroy_config(config); } static void schedule_request_success_test() { /* Initialization. */ alts_handshaker_client_test_config* config = create_config(); - alts_tsi_event* event = nullptr; - /* Check client_start success. */ alts_handshaker_client_set_grpc_caller_for_testing( config->client, check_client_start_success); - event = alts_tsi_event_create_for_testing(true /* is_client. */); - GPR_ASSERT(alts_handshaker_client_start_client(config->client, event) == - TSI_OK); - alts_tsi_event_destroy(event); - + GPR_ASSERT(alts_handshaker_client_start_client(config->client) == TSI_OK); /* Check server_start success. */ alts_handshaker_client_set_grpc_caller_for_testing( - config->client, check_server_start_success); - event = alts_tsi_event_create_for_testing(false /* is_client. */); - GPR_ASSERT(alts_handshaker_client_start_server(config->client, event, + config->server, check_server_start_success); + GPR_ASSERT(alts_handshaker_client_start_server(config->server, &config->out_frame) == TSI_OK); - alts_tsi_event_destroy(event); - - /* Check next success. */ + /* Check client next success. */ alts_handshaker_client_set_grpc_caller_for_testing(config->client, check_next_success); - event = alts_tsi_event_create_for_testing(true /* is_client. */); - GPR_ASSERT(alts_handshaker_client_next(config->client, event, - &config->out_frame) == TSI_OK); - alts_tsi_event_destroy(event); - + GPR_ASSERT(alts_handshaker_client_next(config->client, &config->out_frame) == + TSI_OK); + /* Check server next success. */ + alts_handshaker_client_set_grpc_caller_for_testing(config->server, + check_next_success); + GPR_ASSERT(alts_handshaker_client_next(config->server, &config->out_frame) == + TSI_OK); /* Cleanup. */ destroy_config(config); } @@ -370,30 +375,22 @@ static void schedule_request_success_test() { static void schedule_request_grpc_call_failure_test() { /* Initialization. */ alts_handshaker_client_test_config* config = create_config(); - alts_tsi_event* event = nullptr; - /* Check client_start failure. */ alts_handshaker_client_set_grpc_caller_for_testing(config->client, check_grpc_call_failure); - event = alts_tsi_event_create_for_testing(true /* is_client. */); - GPR_ASSERT(alts_handshaker_client_start_client(config->client, event) == + GPR_ASSERT(alts_handshaker_client_start_client(config->client) == TSI_INTERNAL_ERROR); - alts_tsi_event_destroy(event); - /* Check server_start failure. */ - event = alts_tsi_event_create_for_testing(false /* is_client. */); - GPR_ASSERT(alts_handshaker_client_start_server(config->client, event, - &config->out_frame) == + alts_handshaker_client_set_grpc_caller_for_testing(config->server, + check_grpc_call_failure); + GPR_ASSERT(alts_handshaker_client_start_server( + config->server, &config->out_frame) == TSI_INTERNAL_ERROR); + /* Check client next failure. */ + GPR_ASSERT(alts_handshaker_client_next(config->client, &config->out_frame) == + TSI_INTERNAL_ERROR); + /* Check server next failure. */ + GPR_ASSERT(alts_handshaker_client_next(config->server, &config->out_frame) == TSI_INTERNAL_ERROR); - alts_tsi_event_destroy(event); - - /* Check next failure. */ - event = alts_tsi_event_create_for_testing(true /* is_cleint. */); - GPR_ASSERT( - alts_handshaker_client_next(config->client, event, &config->out_frame) == - TSI_INTERNAL_ERROR); - alts_tsi_event_destroy(event); - /* Cleanup. */ destroy_config(config); } @@ -401,13 +398,13 @@ static void schedule_request_grpc_call_failure_test() { int main(int argc, char** argv) { /* Initialization. */ grpc_init(); - + grpc_alts_shared_resource_dedicated_init(); /* Tests. */ schedule_request_invalid_arg_test(); schedule_request_success_test(); schedule_request_grpc_call_failure_test(); - /* Cleanup. */ + grpc_alts_shared_resource_dedicated_shutdown(); grpc_shutdown(); return 0; } diff --git a/test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc b/test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc index e9eb7e175f..316ff13816 100644 --- a/test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc +++ b/test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc @@ -24,7 +24,7 @@ #include "src/core/lib/gprpp/thd.h" #include "src/core/tsi/alts/handshaker/alts_handshaker_client.h" -#include "src/core/tsi/alts/handshaker/alts_tsi_event.h" +#include "src/core/tsi/alts/handshaker/alts_shared_resource.h" #include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" #include "src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h" #include "test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.h" @@ -43,12 +43,18 @@ #define ALTS_TSI_HANDSHAKER_TEST_MIN_RPC_VERSION_MAJOR 2 #define ALTS_TSI_HANDSHAKER_TEST_MIN_RPC_VERSION_MINOR 1 +using grpc_core::internal::alts_handshaker_client_check_fields_for_testing; +using grpc_core::internal::alts_handshaker_client_get_handshaker_for_testing; using grpc_core::internal:: - alts_tsi_handshaker_get_has_sent_start_message_for_testing; + alts_handshaker_client_get_recv_buffer_addr_for_testing; +using grpc_core::internal::alts_handshaker_client_set_cb_for_testing; +using grpc_core::internal::alts_handshaker_client_set_fields_for_testing; +using grpc_core::internal::alts_handshaker_client_set_recv_bytes_for_testing; +using grpc_core::internal::alts_handshaker_client_set_vtable_for_testing; +using grpc_core::internal::alts_tsi_handshaker_get_client_for_testing; using grpc_core::internal::alts_tsi_handshaker_get_is_client_for_testing; -using grpc_core::internal::alts_tsi_handshaker_get_recv_bytes_for_testing; -using grpc_core::internal::alts_tsi_handshaker_set_client_for_testing; -using grpc_core::internal::alts_tsi_handshaker_set_recv_bytes_for_testing; +using grpc_core::internal::alts_tsi_handshaker_set_client_vtable_for_testing; +static bool should_handshaker_client_api_succeed = true; /* ALTS mock notification. */ typedef struct notification { @@ -57,12 +63,6 @@ typedef struct notification { bool notified; } notification; -/* ALTS mock handshaker client. */ -typedef struct alts_mock_handshaker_client { - alts_handshaker_client base; - bool used_for_success_test; -} alts_mock_handshaker_client; - /* Type of ALTS handshaker response. */ typedef enum { INVALID, @@ -73,10 +73,7 @@ typedef enum { SERVER_NEXT, } alts_handshaker_response_type; -static alts_tsi_event* client_start_event; -static alts_tsi_event* client_next_event; -static alts_tsi_event* server_start_event; -static alts_tsi_event* server_next_event; +static alts_handshaker_client* cb_event = nullptr; static notification caller_to_tsi_notification; static notification tsi_to_caller_notification; @@ -311,89 +308,69 @@ static void on_server_next_success_cb(tsi_result status, void* user_data, signal(&tsi_to_caller_notification); } -static tsi_result mock_client_start(alts_handshaker_client* self, - alts_tsi_event* event) { - alts_mock_handshaker_client* client = - reinterpret_cast<alts_mock_handshaker_client*>(self); - if (!client->used_for_success_test) { - alts_tsi_event_destroy(event); +static tsi_result mock_client_start(alts_handshaker_client* client) { + if (!should_handshaker_client_api_succeed) { return TSI_INTERNAL_ERROR; } - GPR_ASSERT(event->cb == on_client_start_success_cb); - GPR_ASSERT(event->user_data == nullptr); - GPR_ASSERT(!alts_tsi_handshaker_get_has_sent_start_message_for_testing( - event->handshaker)); + alts_handshaker_client_check_fields_for_testing( + client, on_client_start_success_cb, nullptr, false, nullptr); /* Populate handshaker response for client_start request. */ - event->recv_buffer = generate_handshaker_response(CLIENT_START); - client_start_event = event; + grpc_byte_buffer** recv_buffer_ptr = + alts_handshaker_client_get_recv_buffer_addr_for_testing(client); + *recv_buffer_ptr = generate_handshaker_response(CLIENT_START); + cb_event = client; signal(&caller_to_tsi_notification); return TSI_OK; } static void mock_shutdown(alts_handshaker_client* self) {} -static tsi_result mock_server_start(alts_handshaker_client* self, - alts_tsi_event* event, +static tsi_result mock_server_start(alts_handshaker_client* client, grpc_slice* bytes_received) { - alts_mock_handshaker_client* client = - reinterpret_cast<alts_mock_handshaker_client*>(self); - if (!client->used_for_success_test) { - alts_tsi_event_destroy(event); + if (!should_handshaker_client_api_succeed) { return TSI_INTERNAL_ERROR; } - GPR_ASSERT(event->cb == on_server_start_success_cb); - GPR_ASSERT(event->user_data == nullptr); + alts_handshaker_client_check_fields_for_testing( + client, on_server_start_success_cb, nullptr, false, nullptr); grpc_slice slice = grpc_empty_slice(); GPR_ASSERT(grpc_slice_cmp(*bytes_received, slice) == 0); - GPR_ASSERT(!alts_tsi_handshaker_get_has_sent_start_message_for_testing( - event->handshaker)); /* Populate handshaker response for server_start request. */ - event->recv_buffer = generate_handshaker_response(SERVER_START); - server_start_event = event; + grpc_byte_buffer** recv_buffer_ptr = + alts_handshaker_client_get_recv_buffer_addr_for_testing(client); + *recv_buffer_ptr = generate_handshaker_response(SERVER_START); + cb_event = client; grpc_slice_unref(slice); signal(&caller_to_tsi_notification); return TSI_OK; } -static tsi_result mock_next(alts_handshaker_client* self, alts_tsi_event* event, +static tsi_result mock_next(alts_handshaker_client* client, grpc_slice* bytes_received) { - alts_mock_handshaker_client* client = - reinterpret_cast<alts_mock_handshaker_client*>(self); - if (!client->used_for_success_test) { - alts_tsi_event_destroy(event); + if (!should_handshaker_client_api_succeed) { return TSI_INTERNAL_ERROR; } - bool is_client = - alts_tsi_handshaker_get_is_client_for_testing(event->handshaker); - if (is_client) { - GPR_ASSERT(event->cb == on_client_next_success_cb); - } else { - GPR_ASSERT(event->cb == on_server_next_success_cb); - } - GPR_ASSERT(event->user_data == nullptr); + alts_tsi_handshaker* handshaker = + alts_handshaker_client_get_handshaker_for_testing(client); + bool is_client = alts_tsi_handshaker_get_is_client_for_testing(handshaker); + tsi_handshaker_on_next_done_cb cb = + is_client ? on_client_next_success_cb : on_server_next_success_cb; + alts_handshaker_client_set_cb_for_testing(client, cb); + alts_handshaker_client_set_recv_bytes_for_testing(client, bytes_received); + alts_handshaker_client_check_fields_for_testing(client, cb, nullptr, true, + bytes_received); GPR_ASSERT(bytes_received != nullptr); GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*bytes_received), ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES, GRPC_SLICE_LENGTH(*bytes_received)) == 0); - GPR_ASSERT(grpc_slice_cmp(alts_tsi_handshaker_get_recv_bytes_for_testing( - event->handshaker), - *bytes_received) == 0); - GPR_ASSERT(alts_tsi_handshaker_get_has_sent_start_message_for_testing( - event->handshaker)); /* Populate handshaker response for next request. */ grpc_slice out_frame = grpc_slice_from_static_string(ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME); - if (is_client) { - event->recv_buffer = generate_handshaker_response(CLIENT_NEXT); - } else { - event->recv_buffer = generate_handshaker_response(SERVER_NEXT); - } - alts_tsi_handshaker_set_recv_bytes_for_testing(event->handshaker, &out_frame); - if (is_client) { - client_next_event = event; - } else { - server_next_event = event; - } + grpc_byte_buffer** recv_buffer_ptr = + alts_handshaker_client_get_recv_buffer_addr_for_testing(client); + *recv_buffer_ptr = is_client ? generate_handshaker_response(CLIENT_NEXT) + : generate_handshaker_response(SERVER_NEXT); + alts_handshaker_client_set_recv_bytes_for_testing(client, &out_frame); + cb_event = client; signal(&caller_to_tsi_notification); grpc_slice_unref(out_frame); return TSI_OK; @@ -401,38 +378,27 @@ static tsi_result mock_next(alts_handshaker_client* self, alts_tsi_event* event, static void mock_destruct(alts_handshaker_client* client) {} -static const alts_handshaker_client_vtable vtable = { - mock_client_start, mock_server_start, mock_next, mock_shutdown, - mock_destruct}; - -static alts_handshaker_client* alts_mock_handshaker_client_create( - bool used_for_success_test) { - alts_mock_handshaker_client* client = - static_cast<alts_mock_handshaker_client*>(gpr_zalloc(sizeof(*client))); - client->base.vtable = &vtable; - client->used_for_success_test = used_for_success_test; - return &client->base; -} +static alts_handshaker_client_vtable vtable = {mock_client_start, + mock_server_start, mock_next, + mock_shutdown, mock_destruct}; -static tsi_handshaker* create_test_handshaker(bool used_for_success_test, - bool is_client) { +static tsi_handshaker* create_test_handshaker(bool is_client) { tsi_handshaker* handshaker = nullptr; - alts_handshaker_client* client = - alts_mock_handshaker_client_create(used_for_success_test); grpc_alts_credentials_options* options = grpc_alts_credentials_client_options_create(); - alts_tsi_handshaker_create(options, "target_name", "lame", is_client, nullptr, - &handshaker); + alts_tsi_handshaker_create(options, "target_name", + ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING, is_client, + nullptr, &handshaker); alts_tsi_handshaker* alts_handshaker = reinterpret_cast<alts_tsi_handshaker*>(handshaker); - alts_tsi_handshaker_set_client_for_testing(alts_handshaker, client); + alts_tsi_handshaker_set_client_vtable_for_testing(alts_handshaker, &vtable); grpc_alts_credentials_options_destroy(options); return handshaker; } static void check_handshaker_next_invalid_input() { /* Initialization. */ - tsi_handshaker* handshaker = create_test_handshaker(true, true); + tsi_handshaker* handshaker = create_test_handshaker(true); /* Check nullptr handshaker. */ GPR_ASSERT(tsi_handshaker_next(nullptr, nullptr, 0, nullptr, nullptr, nullptr, check_must_not_be_called, @@ -447,8 +413,7 @@ static void check_handshaker_next_invalid_input() { static void check_handshaker_shutdown_invalid_input() { /* Initialization. */ - tsi_handshaker* handshaker = create_test_handshaker( - false /* used_for_success_test */, true /* is_client */); + tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */); /* Check nullptr handshaker. */ tsi_handshaker_shutdown(nullptr); /* Cleanup. */ @@ -460,10 +425,10 @@ static void check_handshaker_next_success() { * Create handshakers for which internal mock client is going to do * correctness check. */ - tsi_handshaker* client_handshaker = create_test_handshaker( - true /* used_for_success_test */, true /* is_client */); - tsi_handshaker* server_handshaker = create_test_handshaker( - true /* used_for_success_test */, false /* is_client */); + tsi_handshaker* client_handshaker = + create_test_handshaker(true /* is_client */); + tsi_handshaker* server_handshaker = + create_test_handshaker(false /* is_client */); /* Client start. */ GPR_ASSERT(tsi_handshaker_next(client_handshaker, nullptr, 0, nullptr, nullptr, nullptr, on_client_start_success_cb, @@ -494,9 +459,7 @@ static void check_handshaker_next_success() { } static void check_handshaker_next_with_shutdown() { - /* Initialization. */ - tsi_handshaker* handshaker = create_test_handshaker( - true /* used_for_success_test */, true /* is_client*/); + tsi_handshaker* handshaker = create_test_handshaker(true /* is_client*/); /* next(success) -- shutdown(success) -- next (fail) */ GPR_ASSERT(tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr, on_client_start_success_cb, @@ -514,20 +477,18 @@ static void check_handshaker_next_with_shutdown() { } static void check_handle_response_with_shutdown(void* unused) { - /* Client start. */ wait(&caller_to_tsi_notification); - alts_tsi_event_dispatch_to_handshaker(client_start_event, true /* is_ok */); - alts_tsi_event_destroy(client_start_event); + alts_handshaker_client_handle_response(cb_event, true /* is_ok */); } static void check_handshaker_next_failure() { /** * Create handshakers for which internal mock client is always going to fail. */ - tsi_handshaker* client_handshaker = create_test_handshaker( - false /* used_for_success_test */, true /* is_client */); - tsi_handshaker* server_handshaker = create_test_handshaker( - false /* used_for_success_test */, false /* is_client */); + tsi_handshaker* client_handshaker = + create_test_handshaker(true /* is_client */); + tsi_handshaker* server_handshaker = + create_test_handshaker(false /* is_client */); /* Client start. */ GPR_ASSERT(tsi_handshaker_next(client_handshaker, nullptr, 0, nullptr, nullptr, nullptr, check_must_not_be_called, @@ -578,34 +539,46 @@ static void on_failed_grpc_call_cb(tsi_result status, void* user_data, } static void check_handle_response_invalid_input() { + /* Initialization. */ + notification_init(&caller_to_tsi_notification); + notification_init(&tsi_to_caller_notification); /** * Create a handshaker at the client side, for which internal mock client is * always going to fail. */ - tsi_handshaker* handshaker = create_test_handshaker( - false /* used_for_success_test */, true /* is_client */); + tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */); + tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr, + on_client_start_success_cb, nullptr); alts_tsi_handshaker* alts_handshaker = reinterpret_cast<alts_tsi_handshaker*>(handshaker); - grpc_byte_buffer recv_buffer; + grpc_slice slice = grpc_empty_slice(); + grpc_byte_buffer* recv_buffer = grpc_raw_byte_buffer_create(&slice, 1); + alts_handshaker_client* client = + alts_tsi_handshaker_get_client_for_testing(alts_handshaker); /* Check nullptr handshaker. */ - alts_tsi_handshaker_handle_response(nullptr, &recv_buffer, GRPC_STATUS_OK, - nullptr, on_invalid_input_cb, nullptr, - true); + alts_handshaker_client_set_fields_for_testing(client, nullptr, + on_invalid_input_cb, nullptr, + recv_buffer, GRPC_STATUS_OK); + alts_handshaker_client_handle_response(client, true); /* Check nullptr recv_bytes. */ - alts_tsi_handshaker_handle_response(alts_handshaker, nullptr, GRPC_STATUS_OK, - nullptr, on_invalid_input_cb, nullptr, - true); + alts_handshaker_client_set_fields_for_testing(client, alts_handshaker, + on_invalid_input_cb, nullptr, + nullptr, GRPC_STATUS_OK); + alts_handshaker_client_handle_response(client, true); /* Check failed grpc call made to handshaker service. */ - alts_tsi_handshaker_handle_response(alts_handshaker, &recv_buffer, - GRPC_STATUS_UNKNOWN, nullptr, - on_failed_grpc_call_cb, nullptr, true); - - alts_tsi_handshaker_handle_response(alts_handshaker, &recv_buffer, - GRPC_STATUS_OK, nullptr, - on_failed_grpc_call_cb, nullptr, false); - + alts_handshaker_client_set_fields_for_testing( + client, alts_handshaker, on_failed_grpc_call_cb, nullptr, recv_buffer, + GRPC_STATUS_UNKNOWN); + alts_handshaker_client_handle_response(client, true); + alts_handshaker_client_set_fields_for_testing(client, alts_handshaker, + on_failed_grpc_call_cb, nullptr, + recv_buffer, GRPC_STATUS_OK); + alts_handshaker_client_handle_response(client, false); /* Cleanup. */ + grpc_slice_unref(slice); tsi_handshaker_destroy(handshaker); + notification_destroy(&caller_to_tsi_notification); + notification_destroy(&tsi_to_caller_notification); } static void on_invalid_resp_cb(tsi_result status, void* user_data, @@ -620,41 +593,45 @@ static void on_invalid_resp_cb(tsi_result status, void* user_data, } static void check_handle_response_invalid_resp() { + /* Initialization. */ + notification_init(&caller_to_tsi_notification); + notification_init(&tsi_to_caller_notification); /** * Create a handshaker at the client side, for which internal mock client is * always going to fail. */ - tsi_handshaker* handshaker = create_test_handshaker( - false /* used_for_success_test */, true /* is_client */); + tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */); + tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr, + on_client_start_success_cb, nullptr); alts_tsi_handshaker* alts_handshaker = reinterpret_cast<alts_tsi_handshaker*>(handshaker); + alts_handshaker_client* client = + alts_tsi_handshaker_get_client_for_testing(alts_handshaker); /* Tests. */ grpc_byte_buffer* recv_buffer = generate_handshaker_response(INVALID); - alts_tsi_handshaker_handle_response(alts_handshaker, recv_buffer, - GRPC_STATUS_OK, nullptr, - on_invalid_resp_cb, nullptr, true); + alts_handshaker_client_set_fields_for_testing(client, alts_handshaker, + on_invalid_resp_cb, nullptr, + recv_buffer, GRPC_STATUS_OK); + alts_handshaker_client_handle_response(client, true); /* Cleanup. */ - grpc_byte_buffer_destroy(recv_buffer); tsi_handshaker_destroy(handshaker); + notification_destroy(&caller_to_tsi_notification); + notification_destroy(&tsi_to_caller_notification); } static void check_handle_response_success(void* unused) { /* Client start. */ wait(&caller_to_tsi_notification); - alts_tsi_event_dispatch_to_handshaker(client_start_event, true /* is_ok */); - alts_tsi_event_destroy(client_start_event); + alts_handshaker_client_handle_response(cb_event, true /* is_ok */); /* Client next. */ wait(&caller_to_tsi_notification); - alts_tsi_event_dispatch_to_handshaker(client_next_event, true /* is_ok */); - alts_tsi_event_destroy(client_next_event); + alts_handshaker_client_handle_response(cb_event, true /* is_ok */); /* Server start. */ wait(&caller_to_tsi_notification); - alts_tsi_event_dispatch_to_handshaker(server_start_event, true /* is_ok */); - alts_tsi_event_destroy(server_start_event); + alts_handshaker_client_handle_response(cb_event, true /* is_ok */); /* Server next. */ wait(&caller_to_tsi_notification); - alts_tsi_event_dispatch_to_handshaker(server_next_event, true /* is_ok */); - alts_tsi_event_destroy(server_next_event); + alts_handshaker_client_handle_response(cb_event, true /* is_ok */); } static void on_failed_resp_cb(tsi_result status, void* user_data, @@ -669,22 +646,30 @@ static void on_failed_resp_cb(tsi_result status, void* user_data, } static void check_handle_response_failure() { + /* Initialization. */ + notification_init(&caller_to_tsi_notification); + notification_init(&tsi_to_caller_notification); /** * Create a handshaker at the client side, for which internal mock client is * always going to fail. */ - tsi_handshaker* handshaker = create_test_handshaker( - false /* used_for_success_test */, true /* is_client */); + tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */); + tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr, + on_client_start_success_cb, nullptr); alts_tsi_handshaker* alts_handshaker = reinterpret_cast<alts_tsi_handshaker*>(handshaker); + alts_handshaker_client* client = + alts_tsi_handshaker_get_client_for_testing(alts_handshaker); /* Tests. */ grpc_byte_buffer* recv_buffer = generate_handshaker_response(FAILED); - alts_tsi_handshaker_handle_response(alts_handshaker, recv_buffer, - GRPC_STATUS_OK, nullptr, - on_failed_resp_cb, nullptr, true); - grpc_byte_buffer_destroy(recv_buffer); + alts_handshaker_client_set_fields_for_testing(client, alts_handshaker, + on_failed_resp_cb, nullptr, + recv_buffer, GRPC_STATUS_OK); + alts_handshaker_client_handle_response(client, true /* is_ok*/); /* Cleanup. */ tsi_handshaker_destroy(handshaker); + notification_destroy(&caller_to_tsi_notification); + notification_destroy(&tsi_to_caller_notification); } static void on_shutdown_resp_cb(tsi_result status, void* user_data, @@ -699,26 +684,38 @@ static void on_shutdown_resp_cb(tsi_result status, void* user_data, } static void check_handle_response_after_shutdown() { - tsi_handshaker* handshaker = create_test_handshaker( - true /* used_for_success_test */, true /* is_client */); + /* Initialization. */ + notification_init(&caller_to_tsi_notification); + notification_init(&tsi_to_caller_notification); + tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */); + tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr, + on_client_start_success_cb, nullptr); alts_tsi_handshaker* alts_handshaker = reinterpret_cast<alts_tsi_handshaker*>(handshaker); + alts_handshaker_client* client = + alts_tsi_handshaker_get_client_for_testing(alts_handshaker); + grpc_byte_buffer** recv_buffer_ptr = + alts_handshaker_client_get_recv_buffer_addr_for_testing(client); + grpc_byte_buffer_destroy(*recv_buffer_ptr); + /* Tests. */ tsi_handshaker_shutdown(handshaker); grpc_byte_buffer* recv_buffer = generate_handshaker_response(CLIENT_START); - alts_tsi_handshaker_handle_response(alts_handshaker, recv_buffer, - GRPC_STATUS_OK, nullptr, - on_shutdown_resp_cb, nullptr, true); - grpc_byte_buffer_destroy(recv_buffer); + alts_handshaker_client_set_fields_for_testing(client, alts_handshaker, + on_shutdown_resp_cb, nullptr, + recv_buffer, GRPC_STATUS_OK); + alts_handshaker_client_handle_response(client, true); /* Cleanup. */ tsi_handshaker_destroy(handshaker); + notification_destroy(&caller_to_tsi_notification); + notification_destroy(&tsi_to_caller_notification); } void check_handshaker_next_fails_after_shutdown() { /* Initialization. */ notification_init(&caller_to_tsi_notification); notification_init(&tsi_to_caller_notification); - client_start_event = nullptr; + cb_event = nullptr; /* Tests. */ grpc_core::Thread thd("alts_tsi_handshaker_test", &check_handle_response_with_shutdown, nullptr); @@ -734,10 +731,6 @@ void check_handshaker_success() { /* Initialization. */ notification_init(&caller_to_tsi_notification); notification_init(&tsi_to_caller_notification); - client_start_event = nullptr; - client_next_event = nullptr; - server_start_event = nullptr; - server_next_event = nullptr; /* Tests. */ grpc_core::Thread thd("alts_tsi_handshaker_test", &check_handle_response_success, nullptr); @@ -752,17 +745,21 @@ void check_handshaker_success() { int main(int argc, char** argv) { /* Initialization. */ grpc_init(); + grpc_alts_shared_resource_dedicated_init(); /* Tests. */ + should_handshaker_client_api_succeed = true; check_handshaker_success(); check_handshaker_next_invalid_input(); - check_handshaker_shutdown_invalid_input(); check_handshaker_next_fails_after_shutdown(); + check_handle_response_after_shutdown(); + should_handshaker_client_api_succeed = false; + check_handshaker_shutdown_invalid_input(); check_handshaker_next_failure(); check_handle_response_invalid_input(); check_handle_response_invalid_resp(); check_handle_response_failure(); - check_handle_response_after_shutdown(); /* Cleanup. */ + grpc_alts_shared_resource_dedicated_shutdown(); grpc_shutdown(); return 0; } diff --git a/test/core/tsi/fake_transport_security_test.cc b/test/core/tsi/fake_transport_security_test.cc index 587d8f5dda..32361f19d3 100644 --- a/test/core/tsi/fake_transport_security_test.cc +++ b/test/core/tsi/fake_transport_security_test.cc @@ -139,7 +139,7 @@ void fake_tsi_test_do_round_trip_odd_buffer_size() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); fake_tsi_test_do_handshake_tiny_handshake_buffer(); fake_tsi_test_do_handshake_small_handshake_buffer(); diff --git a/test/core/tsi/ssl_session_cache_test.cc b/test/core/tsi/ssl_session_cache_test.cc index c86cefb3ff..b9c98c0b57 100644 --- a/test/core/tsi/ssl_session_cache_test.cc +++ b/test/core/tsi/ssl_session_cache_test.cc @@ -145,7 +145,7 @@ TEST(SslSessionCacheTest, LruCache) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); int ret = RUN_ALL_TESTS(); grpc_shutdown(); diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc index baffad6ea3..fc6c6ba320 100644 --- a/test/core/tsi/ssl_transport_security_test.cc +++ b/test/core/tsi/ssl_transport_security_test.cc @@ -777,7 +777,7 @@ void ssl_tsi_test_handshaker_factory_internals() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); ssl_tsi_test_do_handshake_tiny_handshake_buffer(); diff --git a/test/core/tsi/transport_security_test.cc b/test/core/tsi/transport_security_test.cc index 5c92912f6f..150e5745a8 100644 --- a/test/core/tsi/transport_security_test.cc +++ b/test/core/tsi/transport_security_test.cc @@ -381,7 +381,7 @@ static void test_handshaker_invalid_state(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_peer_matches_name(); test_result_strings(); test_protector_invalid_args(); diff --git a/test/core/util/cmdline_test.cc b/test/core/util/cmdline_test.cc index 9f5ad88d57..59e1bbff34 100644 --- a/test/core/util/cmdline_test.cc +++ b/test/core/util/cmdline_test.cc @@ -463,7 +463,7 @@ static void test_badargs4(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_simple_int(); test_eq_int(); test_2dash_int(); diff --git a/test/core/util/fuzzer_corpus_test.cc b/test/core/util/fuzzer_corpus_test.cc index ebf1913137..6e3785c4f7 100644 --- a/test/core/util/fuzzer_corpus_test.cc +++ b/test/core/util/fuzzer_corpus_test.cc @@ -144,7 +144,7 @@ INSTANTIATE_TEST_CASE_P( ::testing::internal::ParamGenerator<std::string>(new ExampleGenerator)); int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ParseCommandLineFlags(&argc, &argv, true); ::testing::InitGoogleTest(&argc, argv); diff --git a/test/core/util/mock_endpoint.cc b/test/core/util/mock_endpoint.cc index ef6fd62b51..e5867cd526 100644 --- a/test/core/util/mock_endpoint.cc +++ b/test/core/util/mock_endpoint.cc @@ -103,18 +103,19 @@ static grpc_resource_user* me_get_resource_user(grpc_endpoint* ep) { static int me_get_fd(grpc_endpoint* ep) { return -1; } -static const grpc_endpoint_vtable vtable = { - me_read, - me_write, - me_add_to_pollset, - me_add_to_pollset_set, - me_delete_from_pollset_set, - me_shutdown, - me_destroy, - me_get_resource_user, - me_get_peer, - me_get_fd, -}; +static bool me_can_track_err(grpc_endpoint* ep) { return false; } + +static const grpc_endpoint_vtable vtable = {me_read, + me_write, + me_add_to_pollset, + me_add_to_pollset_set, + me_delete_from_pollset_set, + me_shutdown, + me_destroy, + me_get_resource_user, + me_get_peer, + me_get_fd, + me_can_track_err}; grpc_endpoint* grpc_mock_endpoint_create(void (*on_write)(grpc_slice slice), grpc_resource_quota* resource_quota) { diff --git a/test/core/util/passthru_endpoint.cc b/test/core/util/passthru_endpoint.cc index 3cc8ad6fe1..51b6de4695 100644 --- a/test/core/util/passthru_endpoint.cc +++ b/test/core/util/passthru_endpoint.cc @@ -155,6 +155,8 @@ static char* me_get_peer(grpc_endpoint* ep) { static int me_get_fd(grpc_endpoint* ep) { return -1; } +static bool me_can_track_err(grpc_endpoint* ep) { return false; } + static grpc_resource_user* me_get_resource_user(grpc_endpoint* ep) { half* m = reinterpret_cast<half*>(ep); return m->resource_user; @@ -171,6 +173,7 @@ static const grpc_endpoint_vtable vtable = { me_get_resource_user, me_get_peer, me_get_fd, + me_can_track_err, }; static void half_init(half* m, passthru_endpoint* parent, diff --git a/test/core/util/test_config.cc b/test/core/util/test_config.cc index 6a0d444a73..fe80bb2d4d 100644 --- a/test/core/util/test_config.cc +++ b/test/core/util/test_config.cc @@ -397,3 +397,15 @@ void grpc_test_init(int argc, char** argv) { concurrently running test binary */ srand(seed()); } + +namespace grpc { +namespace testing { + +TestEnvironment::TestEnvironment(int argc, char** argv) { + grpc_test_init(argc, argv); +} + +TestEnvironment::~TestEnvironment() {} + +} // namespace testing +} // namespace grpc diff --git a/test/core/util/test_config.h b/test/core/util/test_config.h index 5b3d34799e..112af3176f 100644 --- a/test/core/util/test_config.h +++ b/test/core/util/test_config.h @@ -37,6 +37,21 @@ gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms); #define GRPC_TEST_PICK_PORT #endif +// Prefer TestEnvironment below. void grpc_test_init(int argc, char** argv); +namespace grpc { +namespace testing { + +// A TestEnvironment object should be alive in the main function of a test. It +// provides test init and shutdown inside. +class TestEnvironment { + public: + TestEnvironment(int argc, char** argv); + ~TestEnvironment(); +}; + +} // namespace testing +} // namespace grpc + #endif /* GRPC_TEST_CORE_UTIL_TEST_CONFIG_H */ diff --git a/test/core/util/trickle_endpoint.cc b/test/core/util/trickle_endpoint.cc index 62ed72a629..b0da735e57 100644 --- a/test/core/util/trickle_endpoint.cc +++ b/test/core/util/trickle_endpoint.cc @@ -131,6 +131,8 @@ static int te_get_fd(grpc_endpoint* ep) { return grpc_endpoint_get_fd(te->wrapped); } +static bool te_can_track_err(grpc_endpoint* ep) { return false; } + static void te_finish_write(void* arg, grpc_error* error) { trickle_endpoint* te = static_cast<trickle_endpoint*>(arg); gpr_mu_lock(&te->mu); @@ -148,7 +150,8 @@ static const grpc_endpoint_vtable vtable = {te_read, te_destroy, te_get_resource_user, te_get_peer, - te_get_fd}; + te_get_fd, + te_can_track_err}; grpc_endpoint* grpc_trickle_endpoint_create(grpc_endpoint* wrap, double bytes_per_second) { diff --git a/test/cpp/client/client_channel_stress_test.cc b/test/cpp/client/client_channel_stress_test.cc index 976eeb6aea..bf321d8a89 100644 --- a/test/cpp/client/client_channel_stress_test.cc +++ b/test/cpp/client/client_channel_stress_test.cc @@ -321,7 +321,7 @@ class ClientChannelStressTest { int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc::testing::ClientChannelStressTest test; test.Run(); grpc_shutdown(); diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden index 93e1e68654..1871e1375e 100644 --- a/test/cpp/codegen/compiler_test_golden +++ b/test/cpp/codegen/compiler_test_golden @@ -30,9 +30,11 @@ #include <grpcpp/impl/codegen/async_generic_service.h> #include <grpcpp/impl/codegen/async_stream.h> #include <grpcpp/impl/codegen/async_unary_call.h> +#include <grpcpp/impl/codegen/client_callback.h> #include <grpcpp/impl/codegen/method_handler_impl.h> #include <grpcpp/impl/codegen/proto_utils.h> #include <grpcpp/impl/codegen/rpc_method.h> +#include <grpcpp/impl/codegen/server_callback.h> #include <grpcpp/impl/codegen/service_type.h> #include <grpcpp/impl/codegen/status.h> #include <grpcpp/impl/codegen/stub_options.h> @@ -116,10 +118,13 @@ class ServiceA final { // // Method A2 leading comment 1 // Method A2 leading comment 2 + virtual void MethodA2(::grpc::ClientContext* context, ::grpc::testing::Response* response, ::grpc::experimental::ClientWriteReactor< ::grpc::testing::Request>* reactor) = 0; // MethodA2 trailing comment 1 // Method A3 leading comment 1 + virtual void MethodA3(::grpc::ClientContext* context, ::grpc::testing::Request* request, ::grpc::experimental::ClientReadReactor< ::grpc::testing::Response>* reactor) = 0; // Method A3 trailing comment 1 // Method A4 leading comment 1 + virtual void MethodA4(::grpc::ClientContext* context, ::grpc::experimental::ClientBidiReactor< ::grpc::testing::Request,::grpc::testing::Response>* reactor) = 0; // Method A4 trailing comment 1 }; virtual class experimental_async_interface* experimental_async() { return nullptr; } @@ -177,6 +182,9 @@ class ServiceA final { public StubInterface::experimental_async_interface { public: void MethodA1(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, std::function<void(::grpc::Status)>) override; + void MethodA2(::grpc::ClientContext* context, ::grpc::testing::Response* response, ::grpc::experimental::ClientWriteReactor< ::grpc::testing::Request>* reactor) override; + void MethodA3(::grpc::ClientContext* context, ::grpc::testing::Request* request, ::grpc::experimental::ClientReadReactor< ::grpc::testing::Response>* reactor) override; + void MethodA4(::grpc::ClientContext* context, ::grpc::experimental::ClientBidiReactor< ::grpc::testing::Request,::grpc::testing::Response>* reactor) override; private: friend class Stub; explicit experimental_async(Stub* stub): stub_(stub) { } @@ -308,6 +316,98 @@ class ServiceA final { }; typedef WithAsyncMethod_MethodA1<WithAsyncMethod_MethodA2<WithAsyncMethod_MethodA3<WithAsyncMethod_MethodA4<Service > > > > AsyncService; template <class BaseClass> + class ExperimentalWithCallbackMethod_MethodA1 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithCallbackMethod_MethodA1() { + ::grpc::Service::experimental().MarkMethodCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::testing::Request, ::grpc::testing::Response>( + [this](::grpc::ServerContext* context, + const ::grpc::testing::Request* request, + ::grpc::testing::Response* response, + ::grpc::experimental::ServerCallbackRpcController* controller) { + return this->MethodA1(context, request, response, controller); + })); + } + ~ExperimentalWithCallbackMethod_MethodA1() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodA1(::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual void MethodA1(::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, ::grpc::experimental::ServerCallbackRpcController* controller) { controller->Finish(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")); } + }; + template <class BaseClass> + class ExperimentalWithCallbackMethod_MethodA2 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithCallbackMethod_MethodA2() { + ::grpc::Service::experimental().MarkMethodCallback(1, + new ::grpc::internal::CallbackClientStreamingHandler< ::grpc::testing::Request, ::grpc::testing::Response>( + [this] { return this->MethodA2(); })); + } + ~ExperimentalWithCallbackMethod_MethodA2() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodA2(::grpc::ServerContext* context, ::grpc::ServerReader< ::grpc::testing::Request>* reader, ::grpc::testing::Response* response) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::experimental::ServerReadReactor< ::grpc::testing::Request, ::grpc::testing::Response>* MethodA2() { + return new ::grpc::internal::UnimplementedReadReactor< + ::grpc::testing::Request, ::grpc::testing::Response>;} + }; + template <class BaseClass> + class ExperimentalWithCallbackMethod_MethodA3 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithCallbackMethod_MethodA3() { + ::grpc::Service::experimental().MarkMethodCallback(2, + new ::grpc::internal::CallbackServerStreamingHandler< ::grpc::testing::Request, ::grpc::testing::Response>( + [this] { return this->MethodA3(); })); + } + ~ExperimentalWithCallbackMethod_MethodA3() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodA3(::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::ServerWriter< ::grpc::testing::Response>* writer) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::experimental::ServerWriteReactor< ::grpc::testing::Request, ::grpc::testing::Response>* MethodA3() { + return new ::grpc::internal::UnimplementedWriteReactor< + ::grpc::testing::Request, ::grpc::testing::Response>;} + }; + template <class BaseClass> + class ExperimentalWithCallbackMethod_MethodA4 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithCallbackMethod_MethodA4() { + ::grpc::Service::experimental().MarkMethodCallback(3, + new ::grpc::internal::CallbackBidiHandler< ::grpc::testing::Request, ::grpc::testing::Response>( + [this] { return this->MethodA4(); })); + } + ~ExperimentalWithCallbackMethod_MethodA4() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodA4(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::grpc::testing::Response, ::grpc::testing::Request>* stream) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::experimental::ServerBidiReactor< ::grpc::testing::Request, ::grpc::testing::Response>* MethodA4() { + return new ::grpc::internal::UnimplementedBidiReactor< + ::grpc::testing::Request, ::grpc::testing::Response>;} + }; + typedef ExperimentalWithCallbackMethod_MethodA1<ExperimentalWithCallbackMethod_MethodA2<ExperimentalWithCallbackMethod_MethodA3<ExperimentalWithCallbackMethod_MethodA4<Service > > > > ExperimentalCallbackService; + template <class BaseClass> class WithGenericMethod_MethodA1 : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service *service) {} @@ -456,6 +556,97 @@ class ServiceA final { } }; template <class BaseClass> + class ExperimentalWithRawCallbackMethod_MethodA1 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithRawCallbackMethod_MethodA1() { + ::grpc::Service::experimental().MarkMethodRawCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this](::grpc::ServerContext* context, + const ::grpc::ByteBuffer* request, + ::grpc::ByteBuffer* response, + ::grpc::experimental::ServerCallbackRpcController* controller) { + this->MethodA1(context, request, response, controller); + })); + } + ~ExperimentalWithRawCallbackMethod_MethodA1() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodA1(::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual void MethodA1(::grpc::ServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response, ::grpc::experimental::ServerCallbackRpcController* controller) { controller->Finish(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")); } + }; + template <class BaseClass> + class ExperimentalWithRawCallbackMethod_MethodA2 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithRawCallbackMethod_MethodA2() { + ::grpc::Service::experimental().MarkMethodRawCallback(1, + new ::grpc::internal::CallbackClientStreamingHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this] { return this->MethodA2(); })); + } + ~ExperimentalWithRawCallbackMethod_MethodA2() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodA2(::grpc::ServerContext* context, ::grpc::ServerReader< ::grpc::testing::Request>* reader, ::grpc::testing::Response* response) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::experimental::ServerReadReactor< ::grpc::ByteBuffer, ::grpc::ByteBuffer>* MethodA2() { + return new ::grpc::internal::UnimplementedReadReactor< + ::grpc::ByteBuffer, ::grpc::ByteBuffer>;} + }; + template <class BaseClass> + class ExperimentalWithRawCallbackMethod_MethodA3 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithRawCallbackMethod_MethodA3() { + ::grpc::Service::experimental().MarkMethodRawCallback(2, + new ::grpc::internal::CallbackServerStreamingHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this] { return this->MethodA3(); })); + } + ~ExperimentalWithRawCallbackMethod_MethodA3() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodA3(::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::ServerWriter< ::grpc::testing::Response>* writer) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::experimental::ServerWriteReactor< ::grpc::ByteBuffer, ::grpc::ByteBuffer>* MethodA3() { + return new ::grpc::internal::UnimplementedWriteReactor< + ::grpc::ByteBuffer, ::grpc::ByteBuffer>;} + }; + template <class BaseClass> + class ExperimentalWithRawCallbackMethod_MethodA4 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithRawCallbackMethod_MethodA4() { + ::grpc::Service::experimental().MarkMethodRawCallback(3, + new ::grpc::internal::CallbackBidiHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this] { return this->MethodA4(); })); + } + ~ExperimentalWithRawCallbackMethod_MethodA4() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodA4(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::grpc::testing::Response, ::grpc::testing::Request>* stream) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::experimental::ServerBidiReactor< ::grpc::ByteBuffer, ::grpc::ByteBuffer>* MethodA4() { + return new ::grpc::internal::UnimplementedBidiReactor< + ::grpc::ByteBuffer, ::grpc::ByteBuffer>;} + }; + template <class BaseClass> class WithStreamedUnaryMethod_MethodA1 : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service *service) {} @@ -591,6 +782,32 @@ class ServiceB final { }; typedef WithAsyncMethod_MethodB1<Service > AsyncService; template <class BaseClass> + class ExperimentalWithCallbackMethod_MethodB1 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithCallbackMethod_MethodB1() { + ::grpc::Service::experimental().MarkMethodCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::testing::Request, ::grpc::testing::Response>( + [this](::grpc::ServerContext* context, + const ::grpc::testing::Request* request, + ::grpc::testing::Response* response, + ::grpc::experimental::ServerCallbackRpcController* controller) { + return this->MethodB1(context, request, response, controller); + })); + } + ~ExperimentalWithCallbackMethod_MethodB1() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodB1(::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual void MethodB1(::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, ::grpc::experimental::ServerCallbackRpcController* controller) { controller->Finish(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")); } + }; + typedef ExperimentalWithCallbackMethod_MethodB1<Service > ExperimentalCallbackService; + template <class BaseClass> class WithGenericMethod_MethodB1 : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service *service) {} @@ -628,6 +845,31 @@ class ServiceB final { } }; template <class BaseClass> + class ExperimentalWithRawCallbackMethod_MethodB1 : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + ExperimentalWithRawCallbackMethod_MethodB1() { + ::grpc::Service::experimental().MarkMethodRawCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this](::grpc::ServerContext* context, + const ::grpc::ByteBuffer* request, + ::grpc::ByteBuffer* response, + ::grpc::experimental::ServerCallbackRpcController* controller) { + this->MethodB1(context, request, response, controller); + })); + } + ~ExperimentalWithRawCallbackMethod_MethodB1() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status MethodB1(::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual void MethodB1(::grpc::ServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response, ::grpc::experimental::ServerCallbackRpcController* controller) { controller->Finish(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")); } + }; + template <class BaseClass> class WithStreamedUnaryMethod_MethodB1 : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service *service) {} diff --git a/test/cpp/common/alarm_test.cc b/test/cpp/common/alarm_test.cc index e909d03658..802cdc209a 100644 --- a/test/cpp/common/alarm_test.cc +++ b/test/cpp/common/alarm_test.cc @@ -313,7 +313,7 @@ TEST(AlarmTest, UnsetDestruction) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 0415efc1ef..eb600ffb17 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -35,6 +35,32 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "test_health_check_service_impl", + testonly = True, + srcs = ["test_health_check_service_impl.cc"], + hdrs = ["test_health_check_service_impl.h"], + deps = [ + "//:grpc", + "//:grpc++", + "//src/proto/grpc/health/v1:health_proto", + ], +) + +grpc_cc_library( + name = "interceptors_util", + testonly = True, + srcs = ["interceptors_util.cc"], + hdrs = ["interceptors_util.h"], + external_deps = [ + "gtest", + ], + deps = [ + "//src/proto/grpc/testing:echo_proto", + "//test/cpp/util:test_util", + ], +) + grpc_cc_test( name = "async_end2end_test", srcs = ["async_end2end_test.cc"], @@ -110,6 +136,27 @@ grpc_cc_test( "//:grpc", "//:grpc++", "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:simple_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + +grpc_cc_test( + name = "client_interceptors_end2end_test", + srcs = ["client_interceptors_end2end_test.cc"], + external_deps = [ + "gtest", + ], + deps = [ + ":interceptors_util", + ":test_service_impl", + "//:gpr", + "//:grpc", + "//:grpc++", + "//src/proto/grpc/testing:echo_messages_proto", "//src/proto/grpc/testing:echo_proto", "//test/core/util:gpr_test_util", "//test/core/util:grpc_test_util", @@ -125,6 +172,7 @@ grpc_cc_library( "gtest", ], deps = [ + ":interceptors_util", ":test_service_impl", "//:gpr", "//:grpc", @@ -247,6 +295,7 @@ grpc_cc_test( "gtest", ], deps = [ + ":test_health_check_service_impl", ":test_service_impl", "//:gpr", "//:grpc", @@ -470,6 +519,26 @@ grpc_cc_binary( ) grpc_cc_test( + name = "server_interceptors_end2end_test", + srcs = ["server_interceptors_end2end_test.cc"], + external_deps = [ + "gtest", + ], + deps = [ + ":interceptors_util", + ":test_service_impl", + "//:gpr", + "//:grpc", + "//:grpc++", + "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + +grpc_cc_test( name = "server_load_reporting_end2end_test", srcs = ["server_load_reporting_end2end_test.cc"], external_deps = [ diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 6ecb957801..e09f54dcc3 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -1884,7 +1884,7 @@ int main(int argc, char** argv) { // Change the backup poll interval from 5s to 100ms to speed up the // ReconnectChannel test gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "100"); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc index 7a7a716e79..29b59e4e5e 100644 --- a/test/cpp/end2end/channelz_service_test.cc +++ b/test/cpp/end2end/channelz_service_test.cc @@ -41,6 +41,8 @@ using grpc::channelz::v1::GetChannelRequest; using grpc::channelz::v1::GetChannelResponse; +using grpc::channelz::v1::GetServerRequest; +using grpc::channelz::v1::GetServerResponse; using grpc::channelz::v1::GetServerSocketsRequest; using grpc::channelz::v1::GetServerSocketsResponse; using grpc::channelz::v1::GetServersRequest; @@ -460,6 +462,29 @@ TEST_F(ChannelzServerTest, BasicServerTest) { EXPECT_EQ(response.server_size(), 1); } +TEST_F(ChannelzServerTest, BasicGetServerTest) { + ResetStubs(); + ConfigureProxy(1); + GetServersRequest get_servers_request; + GetServersResponse get_servers_response; + get_servers_request.set_start_server_id(0); + ClientContext get_servers_context; + Status s = channelz_stub_->GetServers( + &get_servers_context, get_servers_request, &get_servers_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_servers_response.server_size(), 1); + GetServerRequest get_server_request; + GetServerResponse get_server_response; + get_server_request.set_server_id( + get_servers_response.server(0).ref().server_id()); + ClientContext get_server_context; + s = channelz_stub_->GetServer(&get_server_context, get_server_request, + &get_server_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_servers_response.server(0).ref().server_id(), + get_server_response.server().ref().server_id()); +} + TEST_F(ChannelzServerTest, ServerCallTest) { ResetStubs(); ConfigureProxy(1); @@ -626,11 +651,33 @@ TEST_F(ChannelzServerTest, GetServerSocketsTest) { EXPECT_EQ(get_server_sockets_response.socket_ref_size(), 1); } +TEST_F(ChannelzServerTest, GetServerListenSocketsTest) { + ResetStubs(); + ConfigureProxy(1); + GetServersRequest get_server_request; + GetServersResponse get_server_response; + get_server_request.set_start_server_id(0); + ClientContext get_server_context; + Status s = channelz_stub_->GetServers(&get_server_context, get_server_request, + &get_server_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_response.server_size(), 1); + EXPECT_EQ(get_server_response.server(0).listen_socket_size(), 1); + GetSocketRequest get_socket_request; + GetSocketResponse get_socket_response; + get_socket_request.set_socket_id( + get_server_response.server(0).listen_socket(0).socket_id()); + ClientContext get_socket_context; + s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request, + &get_socket_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); +} + } // namespace testing } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/client_callback_end2end_test.cc b/test/cpp/end2end/client_callback_end2end_test.cc index 62a85641c7..a999321992 100644 --- a/test/cpp/end2end/client_callback_end2end_test.cc +++ b/test/cpp/end2end/client_callback_end2end_test.cc @@ -34,6 +34,7 @@ #include "test/core/util/test_config.h" #include "test/cpp/end2end/test_service_impl.h" #include "test/cpp/util/byte_buffer_proto_helper.h" +#include "test/cpp/util/string_ref_helper.h" #include <gtest/gtest.h> @@ -41,13 +42,38 @@ namespace grpc { namespace testing { namespace { -class ClientCallbackEnd2endTest : public ::testing::Test { +class TestScenario { + public: + TestScenario(bool serve_callback) : callback_server(serve_callback) {} + void Log() const; + bool callback_server; +}; + +static std::ostream& operator<<(std::ostream& out, + const TestScenario& scenario) { + return out << "TestScenario{callback_server=" + << (scenario.callback_server ? "true" : "false") << "}"; +} + +void TestScenario::Log() const { + std::ostringstream out; + out << *this; + gpr_log(GPR_DEBUG, "%s", out.str().c_str()); +} + +class ClientCallbackEnd2endTest + : public ::testing::TestWithParam<TestScenario> { protected: - ClientCallbackEnd2endTest() {} + ClientCallbackEnd2endTest() { GetParam().Log(); } void SetUp() override { ServerBuilder builder; - builder.RegisterService(&service_); + + if (!GetParam().callback_server) { + builder.RegisterService(&service_); + } else { + builder.RegisterService(&callback_service_); + } server_ = builder.BuildAndStart(); is_server_started_ = true; @@ -75,11 +101,13 @@ class ClientCallbackEnd2endTest : public ::testing::Test { test_string += "Hello world. "; request.set_message(test_string); - + grpc::string val; if (with_binary_metadata) { + request.mutable_param()->set_echo_metadata(true); char bytes[8] = {'\0', '\1', '\2', '\3', '\4', '\5', '\6', static_cast<char>(i)}; - cli_ctx.AddMetadata("custom-bin", grpc::string(bytes, 8)); + val = grpc::string(bytes, 8); + cli_ctx.AddMetadata("custom-bin", val); } cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP); @@ -89,10 +117,18 @@ class ClientCallbackEnd2endTest : public ::testing::Test { bool done = false; stub_->experimental_async()->Echo( &cli_ctx, &request, &response, - [&request, &response, &done, &mu, &cv](Status s) { + [&cli_ctx, &request, &response, &done, &mu, &cv, val, + with_binary_metadata](Status s) { GPR_ASSERT(s.ok()); EXPECT_EQ(request.message(), response.message()); + if (with_binary_metadata) { + EXPECT_EQ( + 1u, cli_ctx.GetServerTrailingMetadata().count("custom-bin")); + EXPECT_EQ(val, ToString(cli_ctx.GetServerTrailingMetadata() + .find("custom-bin") + ->second)); + } std::lock_guard<std::mutex> l(mu); done = true; cv.notify_one(); @@ -146,42 +182,145 @@ class ClientCallbackEnd2endTest : public ::testing::Test { } } + void SendGenericEchoAsBidi(int num_rpcs, int reuses) { + const grpc::string kMethodName("/grpc.testing.EchoTestService/Echo"); + grpc::string test_string(""); + for (int i = 0; i < num_rpcs; i++) { + test_string += "Hello world. "; + class Client : public grpc::experimental::ClientBidiReactor<ByteBuffer, + ByteBuffer> { + public: + Client(ClientCallbackEnd2endTest* test, const grpc::string& method_name, + const grpc::string& test_str, int reuses) + : reuses_remaining_(reuses) { + activate_ = [this, test, method_name, test_str] { + if (reuses_remaining_ > 0) { + cli_ctx_.reset(new ClientContext); + reuses_remaining_--; + test->generic_stub_->experimental().PrepareBidiStreamingCall( + cli_ctx_.get(), method_name, this); + request_.set_message(test_str); + send_buf_ = SerializeToByteBuffer(&request_); + StartWrite(send_buf_.get()); + StartRead(&recv_buf_); + StartCall(); + } else { + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + }; + activate_(); + } + void OnWriteDone(bool ok) override { StartWritesDone(); } + void OnReadDone(bool ok) override { + EchoResponse response; + EXPECT_TRUE(ParseFromByteBuffer(&recv_buf_, &response)); + EXPECT_EQ(request_.message(), response.message()); + }; + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + activate_(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + EchoRequest request_; + std::unique_ptr<ByteBuffer> send_buf_; + ByteBuffer recv_buf_; + std::unique_ptr<ClientContext> cli_ctx_; + int reuses_remaining_; + std::function<void()> activate_; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; + } rpc{this, kMethodName, test_string, reuses}; + + rpc.Await(); + } + } bool is_server_started_; std::shared_ptr<Channel> channel_; std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; std::unique_ptr<grpc::GenericStub> generic_stub_; TestServiceImpl service_; + CallbackTestServiceImpl callback_service_; std::unique_ptr<Server> server_; }; -TEST_F(ClientCallbackEnd2endTest, SimpleRpc) { +TEST_P(ClientCallbackEnd2endTest, SimpleRpc) { ResetStub(); SendRpcs(1, false); } -TEST_F(ClientCallbackEnd2endTest, SequentialRpcs) { +TEST_P(ClientCallbackEnd2endTest, SequentialRpcs) { ResetStub(); SendRpcs(10, false); } -TEST_F(ClientCallbackEnd2endTest, SequentialRpcsWithVariedBinaryMetadataValue) { +TEST_P(ClientCallbackEnd2endTest, SendClientInitialMetadata) { + ResetStub(); + SimpleRequest request; + SimpleResponse response; + ClientContext cli_ctx; + + cli_ctx.AddMetadata(kCheckClientInitialMetadataKey, + kCheckClientInitialMetadataVal); + + std::mutex mu; + std::condition_variable cv; + bool done = false; + stub_->experimental_async()->CheckClientInitialMetadata( + &cli_ctx, &request, &response, [&done, &mu, &cv](Status s) { + GPR_ASSERT(s.ok()); + + std::lock_guard<std::mutex> l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } +} + +TEST_P(ClientCallbackEnd2endTest, SimpleRpcWithBinaryMetadata) { + ResetStub(); + SendRpcs(1, true); +} + +TEST_P(ClientCallbackEnd2endTest, SequentialRpcsWithVariedBinaryMetadataValue) { ResetStub(); SendRpcs(10, true); } -TEST_F(ClientCallbackEnd2endTest, SequentialGenericRpcs) { +TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcs) { ResetStub(); SendRpcsGeneric(10, false); } +TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidi) { + ResetStub(); + SendGenericEchoAsBidi(10, 1); +} + +TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidiWithReactorReuse) { + ResetStub(); + SendGenericEchoAsBidi(10, 10); +} + #if GRPC_ALLOW_EXCEPTIONS -TEST_F(ClientCallbackEnd2endTest, ExceptingRpc) { +TEST_P(ClientCallbackEnd2endTest, ExceptingRpc) { ResetStub(); SendRpcsGeneric(10, true); } #endif -TEST_F(ClientCallbackEnd2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { +TEST_P(ClientCallbackEnd2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { ResetStub(); std::vector<std::thread> threads; threads.reserve(10); @@ -193,7 +332,7 @@ TEST_F(ClientCallbackEnd2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { } } -TEST_F(ClientCallbackEnd2endTest, MultipleRpcs) { +TEST_P(ClientCallbackEnd2endTest, MultipleRpcs) { ResetStub(); std::vector<std::thread> threads; threads.reserve(10); @@ -205,7 +344,7 @@ TEST_F(ClientCallbackEnd2endTest, MultipleRpcs) { } } -TEST_F(ClientCallbackEnd2endTest, CancelRpcBeforeStart) { +TEST_P(ClientCallbackEnd2endTest, CancelRpcBeforeStart) { ResetStub(); EchoRequest request; EchoResponse response; @@ -230,12 +369,167 @@ TEST_F(ClientCallbackEnd2endTest, CancelRpcBeforeStart) { } } +TEST_P(ClientCallbackEnd2endTest, RequestStream) { + ResetStub(); + class Client : public grpc::experimental::ClientWriteReactor<EchoRequest> { + public: + explicit Client(grpc::testing::EchoTestService::Stub* stub) { + context_.set_initial_metadata_corked(true); + stub->experimental_async()->RequestStream(&context_, &response_, this); + StartCall(); + request_.set_message("Hello server."); + StartWrite(&request_); + } + void OnWriteDone(bool ok) override { + writes_left_--; + if (writes_left_ > 1) { + StartWrite(&request_); + } else if (writes_left_ == 1) { + StartWriteLast(&request_, WriteOptions()); + } + } + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + EXPECT_EQ(response_.message(), "Hello server.Hello server.Hello server."); + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + int writes_left_{3}; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; + } test{stub_.get()}; + + test.Await(); +} + +TEST_P(ClientCallbackEnd2endTest, ResponseStream) { + ResetStub(); + class Client : public grpc::experimental::ClientReadReactor<EchoResponse> { + public: + explicit Client(grpc::testing::EchoTestService::Stub* stub) { + request_.set_message("Hello client "); + stub->experimental_async()->ResponseStream(&context_, &request_, this); + StartCall(); + StartRead(&response_); + } + void OnReadDone(bool ok) override { + if (!ok) { + EXPECT_EQ(reads_complete_, kServerDefaultResponseStreamsToSend); + } else { + EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); + EXPECT_EQ(response_.message(), + request_.message() + grpc::to_string(reads_complete_)); + reads_complete_++; + StartRead(&response_); + } + } + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + int reads_complete_{0}; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; + } test{stub_.get()}; + + test.Await(); +} + +TEST_P(ClientCallbackEnd2endTest, BidiStream) { + ResetStub(); + class Client : public grpc::experimental::ClientBidiReactor<EchoRequest, + EchoResponse> { + public: + explicit Client(grpc::testing::EchoTestService::Stub* stub) { + request_.set_message("Hello fren "); + stub->experimental_async()->BidiStream(&context_, this); + StartCall(); + StartRead(&response_); + StartWrite(&request_); + } + void OnReadDone(bool ok) override { + if (!ok) { + EXPECT_EQ(reads_complete_, kServerDefaultResponseStreamsToSend); + } else { + EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); + EXPECT_EQ(response_.message(), request_.message()); + reads_complete_++; + StartRead(&response_); + } + } + void OnWriteDone(bool ok) override { + EXPECT_TRUE(ok); + if (++writes_complete_ == kServerDefaultResponseStreamsToSend) { + StartWritesDone(); + } else { + StartWrite(&request_); + } + } + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + int reads_complete_{0}; + int writes_complete_{0}; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; + } test{stub_.get()}; + + test.Await(); +} + +TestScenario scenarios[] = {TestScenario{false}, TestScenario{true}}; + +INSTANTIATE_TEST_CASE_P(ClientCallbackEnd2endTest, ClientCallbackEnd2endTest, + ::testing::ValuesIn(scenarios)); + } // namespace } // namespace testing } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc index 2a06f44c60..992f3c488f 100644 --- a/test/cpp/end2end/client_crash_test.cc +++ b/test/cpp/end2end/client_crash_test.cc @@ -135,7 +135,7 @@ int main(int argc, char** argv) { g_root = "."; } - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); // Order seems to matter on these tests: run three times to eliminate that for (int i = 0; i < 3; i++) { diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc new file mode 100644 index 0000000000..968b5d49d1 --- /dev/null +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -0,0 +1,651 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <memory> +#include <vector> + +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/generic/generic_stub.h> +#include <grpcpp/impl/codegen/client_interceptor.h> +#include <grpcpp/impl/codegen/proto_utils.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/interceptors_util.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" +#include "test/cpp/util/string_ref_helper.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { +namespace { + +/* Hijacks Echo RPC and fills in the expected values */ +class HijackingInterceptor : public experimental::Interceptor { + public: + HijackingInterceptor(experimental::ClientRpcInfo* info) { + info_ = info; + // Make sure it is the right method + EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); + EXPECT_EQ(info->type(), experimental::ClientRpcInfo::Type::UNARY); + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + bool hijack = false; + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Check that we can see the test metadata + ASSERT_EQ(map->size(), static_cast<unsigned>(1)); + auto iterator = map->begin(); + EXPECT_EQ("testkey", iterator->first); + EXPECT_EQ("testvalue", iterator->second); + hijack = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_EQ(req.message(), "Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here for now + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + // Check that we got the hijacked message, and re-insert the expected + // message + EXPECT_EQ(resp->message(), "Hello1"); + resp->set_message("Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.starts_with("testkey") && + pair.second.starts_with("testvalue"); + if (found) break; + } + EXPECT_EQ(found, true); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here at the moment + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { + // Insert a different message than expected + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + resp->set_message("Hello1"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + // insert the metadata that we want + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + map->insert(std::make_pair("testkey", "testvalue")); + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::OK, ""); + } + if (hijack) { + methods->Hijack(); + } else { + methods->Proceed(); + } + } + + private: + experimental::ClientRpcInfo* info_; +}; + +class HijackingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new HijackingInterceptor(info); + } +}; + +class HijackingInterceptorMakesAnotherCall : public experimental::Interceptor { + public: + HijackingInterceptorMakesAnotherCall(experimental::ClientRpcInfo* info) { + info_ = info; + // Make sure it is the right method + EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Check that we can see the test metadata + ASSERT_EQ(map->size(), static_cast<unsigned>(1)); + auto iterator = map->begin(); + EXPECT_EQ("testkey", iterator->first); + EXPECT_EQ("testvalue", iterator->second); + // Make a copy of the map + metadata_map_ = *map; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_EQ(req.message(), "Hello"); + req_ = req; + stub_ = grpc::testing::EchoTestService::NewStub( + methods->GetInterceptedChannel()); + ctx_.AddMetadata(metadata_map_.begin()->first, + metadata_map_.begin()->second); + stub_->experimental_async()->Echo(&ctx_, &req_, &resp_, + [this, methods](Status s) { + EXPECT_EQ(s.ok(), true); + EXPECT_EQ(resp_.message(), "Hello"); + methods->Hijack(); + }); + // There isn't going to be any other interesting operation in this batch, + // so it is fine to return + return; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here for now + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + // Check that we got the hijacked message, and re-insert the expected + // message + EXPECT_EQ(resp->message(), "Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.starts_with("testkey") && + pair.second.starts_with("testvalue"); + if (found) break; + } + EXPECT_EQ(found, true); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here at the moment + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { + // Insert a different message than expected + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + resp->set_message(resp_.message()); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + // insert the metadata that we want + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + map->insert(std::make_pair("testkey", "testvalue")); + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::OK, ""); + } + + methods->Proceed(); + } + + private: + experimental::ClientRpcInfo* info_; + std::multimap<grpc::string, grpc::string> metadata_map_; + ClientContext ctx_; + EchoRequest req_; + EchoResponse resp_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; +}; + +class HijackingInterceptorMakesAnotherCallFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new HijackingInterceptorMakesAnotherCall(info); + } +}; + +class LoggingInterceptor : public experimental::Interceptor { + public: + LoggingInterceptor(experimental::ClientRpcInfo* info) { info_ = info; } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Check that we can see the test metadata + ASSERT_EQ(map->size(), static_cast<unsigned>(1)); + auto iterator = map->begin(); + EXPECT_EQ("testkey", iterator->first); + EXPECT_EQ("testvalue", iterator->second); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_TRUE(req.message().find("Hello") == 0); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here for now + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + EXPECT_TRUE(resp->message().find("Hello") == 0); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.starts_with("testkey") && + pair.second.starts_with("testvalue"); + if (found) break; + } + EXPECT_EQ(found, true); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + } + methods->Proceed(); + } + + private: + experimental::ClientRpcInfo* info_; +}; + +class LoggingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new LoggingInterceptor(info); + } +}; + +class ClientInterceptorsEnd2endTest : public ::testing::Test { + protected: + ClientInterceptorsEnd2endTest() { + int port = grpc_pick_unused_port_or_die(); + + ServerBuilder builder; + server_address_ = "localhost:" + std::to_string(port); + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + ~ClientInterceptorsEnd2endTest() { server_->Shutdown(); } + + std::string server_address_; + TestServiceImpl service_; + std::unique_ptr<Server> server_; +}; + +TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLoggingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorHijackingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors before hijacking interceptor + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + creators.push_back(std::unique_ptr<HijackingInterceptorFactory>( + new HijackingInterceptorFactory())); + // Add 20 dummy interceptors after hijacking interceptor + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + + MakeCall(channel); + // Make sure only 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLogThenHijackTest) { + ChannelArguments args; + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + creators.push_back(std::unique_ptr<HijackingInterceptorFactory>( + new HijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + + MakeCall(channel); +} + +TEST_F(ClientInterceptorsEnd2endTest, + ClientInterceptorHijackingMakesAnotherCallTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 5 dummy interceptors before hijacking interceptor + creators.reserve(5); + for (auto i = 0; i < 5; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + creators.push_back( + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>( + new HijackingInterceptorMakesAnotherCallFactory())); + // Add 7 dummy interceptors after hijacking interceptor + for (auto i = 0; i < 7; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = server_->experimental().InProcessChannelWithInterceptors( + args, std::move(creators)); + + MakeCall(channel); + // Make sure all interceptors were run once, since the hijacking interceptor + // makes an RPC on the intercepted channel + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 12); +} + +TEST_F(ClientInterceptorsEnd2endTest, + ClientInterceptorLoggingTestWithCallback) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = server_->experimental().InProcessChannelWithInterceptors( + args, std::move(creators)); + MakeCallbackCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +class ClientInterceptorsStreamingEnd2endTest : public ::testing::Test { + protected: + ClientInterceptorsStreamingEnd2endTest() { + int port = grpc_pick_unused_port_or_die(); + + ServerBuilder builder; + server_address_ = "localhost:" + std::to_string(port); + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + ~ClientInterceptorsStreamingEnd2endTest() { server_->Shutdown(); } + + std::string server_address_; + EchoTestServiceStreamingImpl service_; + std::unique_ptr<Server> server_; +}; + +TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeClientStreamingCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeServerStreamingCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeBidiStreamingCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +class ClientGlobalInterceptorEnd2endTest : public ::testing::Test { + protected: + ClientGlobalInterceptorEnd2endTest() { + int port = grpc_pick_unused_port_or_die(); + + ServerBuilder builder; + server_address_ = "localhost:" + std::to_string(port); + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + ~ClientGlobalInterceptorEnd2endTest() { server_->Shutdown(); } + + std::string server_address_; + TestServiceImpl service_; + std::unique_ptr<Server> server_; +}; + +TEST_F(ClientGlobalInterceptorEnd2endTest, DummyGlobalInterceptor) { + // We should ideally be registering a global interceptor only once per + // process, but for the purposes of testing, it should be fine to modify the + // registered global interceptor when there are no ongoing gRPC operations + DummyInterceptorFactory global_factory; + experimental::RegisterGlobalClientInterceptorFactory(&global_factory); + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeCall(channel); + // Make sure all 20 dummy interceptors were run with the global interceptor + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 21); + // Reset the global interceptor. This is again 'safe' because there are no + // other ongoing gRPC operations + experimental::RegisterGlobalClientInterceptorFactory(nullptr); +} + +TEST_F(ClientGlobalInterceptorEnd2endTest, LoggingGlobalInterceptor) { + // We should ideally be registering a global interceptor only once per + // process, but for the purposes of testing, it should be fine to modify the + // registered global interceptor when there are no ongoing gRPC operations + LoggingInterceptorFactory global_factory; + experimental::RegisterGlobalClientInterceptorFactory(&global_factory); + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + // Reset the global interceptor. This is again 'safe' because there are no + // other ongoing gRPC operations + experimental::RegisterGlobalClientInterceptorFactory(nullptr); +} + +TEST_F(ClientGlobalInterceptorEnd2endTest, HijackingGlobalInterceptor) { + // We should ideally be registering a global interceptor only once per + // process, but for the purposes of testing, it should be fine to modify the + // registered global interceptor when there are no ongoing gRPC operations + HijackingInterceptorFactory global_factory; + experimental::RegisterGlobalClientInterceptorFactory(&global_factory); + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + // Reset the global interceptor. This is again 'safe' because there are no + // other ongoing gRPC operations + experimental::RegisterGlobalClientInterceptorFactory(nullptr); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index 77c25c1416..1dfa91a76c 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -42,6 +42,9 @@ #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/tcp_client.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/cpp/client/secure_credentials.h" +#include "src/cpp/server/secure_server_credentials.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/core/util/port.h" @@ -113,7 +116,10 @@ class MyTestServiceImpl : public TestServiceImpl { class ClientLbEnd2endTest : public ::testing::Test { protected: ClientLbEnd2endTest() - : server_host_("localhost"), kRequestMessage_("Live long and prosper.") { + : server_host_("localhost"), + kRequestMessage_("Live long and prosper."), + creds_(new SecureChannelCredentials( + grpc_fake_transport_security_credentials_create())) { // Make the backup poller poll very frequently in order to pick up // updates from all the subchannels's FDs. gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "1"); @@ -146,7 +152,7 @@ class ClientLbEnd2endTest : public ::testing::Test { void StartServers(size_t num_servers, std::vector<int> ports = std::vector<int>()) { - CreateServers(num_servers, ports); + CreateServers(num_servers, std::move(ports)); for (size_t i = 0; i < num_servers; ++i) { StartServer(i); } @@ -188,6 +194,11 @@ class ClientLbEnd2endTest : public ::testing::Test { grpc_channel_args_destroy(fake_results); } + void SetFailureOnReresolution() { + grpc_core::ExecCtx exec_ctx; + response_generator_->SetFailureOnReresolution(); + } + std::vector<int> GetServersPorts() { std::vector<int> ports; for (const auto& server : servers_) ports.push_back(server->port_); @@ -207,19 +218,20 @@ class ClientLbEnd2endTest : public ::testing::Test { } // else, default to pick first args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, response_generator_.get()); - return CreateCustomChannel("fake:///", InsecureChannelCredentials(), args); + return CreateCustomChannel("fake:///", creds_, args); } bool SendRpc( const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub, EchoResponse* response = nullptr, int timeout_ms = 1000, - Status* result = nullptr) { + Status* result = nullptr, bool wait_for_ready = false) { const bool local_response = (response == nullptr); if (local_response) response = new EchoResponse; EchoRequest request; request.set_message(kRequestMessage_); ClientContext context; context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms)); + if (wait_for_ready) context.set_wait_for_ready(true); Status status = stub->Echo(&context, request, response); if (result != nullptr) *result = status; if (local_response) delete response; @@ -228,10 +240,11 @@ class ClientLbEnd2endTest : public ::testing::Test { void CheckRpcSendOk( const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub, - const grpc_core::DebugLocation& location) { + const grpc_core::DebugLocation& location, bool wait_for_ready = false) { EchoResponse response; Status status; - const bool success = SendRpc(stub, &response, 2000, &status); + const bool success = + SendRpc(stub, &response, 2000, &status, wait_for_ready); ASSERT_TRUE(success) << "From " << location.file() << ":" << location.line() << "\n" << "Error: " << status.error_message() << " " @@ -253,6 +266,7 @@ class ClientLbEnd2endTest : public ::testing::Test { MyTestServiceImpl service_; std::unique_ptr<std::thread> thread_; bool server_ready_ = false; + bool started_ = false; explicit ServerData(int port = 0) { port_ = port > 0 ? port : grpc_pick_unused_port_or_die(); @@ -260,6 +274,7 @@ class ClientLbEnd2endTest : public ::testing::Test { void Start(const grpc::string& server_host) { gpr_log(GPR_INFO, "starting server on port %d", port_); + started_ = true; std::mutex mu; std::unique_lock<std::mutex> lock(mu); std::condition_variable cond; @@ -275,8 +290,9 @@ class ClientLbEnd2endTest : public ::testing::Test { std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; - builder.AddListeningPort(server_address.str(), - InsecureServerCredentials()); + std::shared_ptr<ServerCredentials> creds(new SecureServerCredentials( + grpc_fake_transport_security_server_credentials_create())); + builder.AddListeningPort(server_address.str(), std::move(creds)); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); std::lock_guard<std::mutex> lock(*mu); @@ -284,9 +300,11 @@ class ClientLbEnd2endTest : public ::testing::Test { cond->notify_one(); } - void Shutdown(bool join = true) { + void Shutdown() { + if (!started_) return; server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0)); - if (join) thread_->join(); + thread_->join(); + started_ = false; } void SetServingStatus(const grpc::string& service, bool serving) { @@ -306,7 +324,7 @@ class ClientLbEnd2endTest : public ::testing::Test { if (ignore_failure) { SendRpc(stub); } else { - CheckRpcSendOk(stub, location); + CheckRpcSendOk(stub, location, true); } } while (servers_[server_idx]->service_.request_count() == 0); ResetCounters(); @@ -365,6 +383,7 @@ class ClientLbEnd2endTest : public ::testing::Test { grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator> response_generator_; const grpc::string kRequestMessage_; + std::shared_ptr<ChannelCredentials> creds_; }; TEST_F(ClientLbEnd2endTest, PickFirst) { @@ -409,6 +428,30 @@ TEST_F(ClientLbEnd2endTest, PickFirstProcessPending) { CheckRpcSendOk(second_stub, DEBUG_LOCATION); } +TEST_F(ClientLbEnd2endTest, PickFirstSelectsReadyAtStartup) { + ChannelArguments args; + constexpr int kInitialBackOffMs = 5000; + args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); + // Create 2 servers, but start only the second one. + std::vector<int> ports = {grpc_pick_unused_port_or_die(), + grpc_pick_unused_port_or_die()}; + CreateServers(2, ports); + StartServer(1); + auto channel1 = BuildChannel("pick_first", args); + auto stub1 = BuildStub(channel1); + SetNextResolution(ports); + // Wait for second server to be ready. + WaitForServer(stub1, 1, DEBUG_LOCATION); + // Create a second channel with the same addresses. Its PF instance + // should immediately pick the second subchannel, since it's already + // in READY state. + auto channel2 = BuildChannel("pick_first", args); + SetNextResolution(ports); + // Check that the channel reports READY without waiting for the + // initial backoff. + EXPECT_TRUE(WaitForChannelReady(channel2.get(), 1 /* timeout_seconds */)); +} + TEST_F(ClientLbEnd2endTest, PickFirstBackOffInitialReconnect) { ChannelArguments args; constexpr int kInitialBackOffMs = 100; @@ -494,6 +537,51 @@ TEST_F(ClientLbEnd2endTest, PickFirstResetConnectionBackoff) { EXPECT_LT(waited_ms, kInitialBackOffMs); } +TEST_F(ClientLbEnd2endTest, + PickFirstResetConnectionBackoffNextAttemptStartsImmediately) { + ChannelArguments args; + constexpr int kInitialBackOffMs = 1000; + args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); + const std::vector<int> ports = {grpc_pick_unused_port_or_die()}; + auto channel = BuildChannel("pick_first", args); + auto stub = BuildStub(channel); + SetNextResolution(ports); + // Wait for connect, which should fail ~immediately, because the server + // is not up. + gpr_log(GPR_INFO, "=== INITIAL CONNECTION ATTEMPT"); + EXPECT_FALSE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); + // Reset connection backoff. + // Note that the time at which the third attempt will be started is + // actually computed at this point, so we record the start time here. + gpr_log(GPR_INFO, "=== RESETTING BACKOFF"); + const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); + experimental::ChannelResetConnectionBackoff(channel.get()); + // Trigger a second connection attempt. This should also fail + // ~immediately, but the retry should be scheduled for + // kInitialBackOffMs instead of applying the multiplier. + gpr_log(GPR_INFO, "=== POLLING FOR SECOND CONNECTION ATTEMPT"); + EXPECT_FALSE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); + // Bring up a server on the chosen port. + gpr_log(GPR_INFO, "=== STARTING BACKEND"); + StartServers(1, ports); + // Wait for connect. Should happen within kInitialBackOffMs. + // Give an extra 100ms to account for the time spent in the second and + // third connection attempts themselves (since what we really want to + // measure is the time between the two). As long as this is less than + // the 1.6x increase we would see if the backoff state was not reset + // properly, the test is still proving that the backoff was reset. + constexpr int kWaitMs = kInitialBackOffMs + 100; + gpr_log(GPR_INFO, "=== POLLING FOR THIRD CONNECTION ATTEMPT"); + EXPECT_TRUE(channel->WaitForConnected( + grpc_timeout_milliseconds_to_deadline(kWaitMs))); + const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); + const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); + gpr_log(GPR_DEBUG, "Waited %" PRId64 " milliseconds", waited_ms); + EXPECT_LT(waited_ms, kWaitMs); +} + TEST_F(ClientLbEnd2endTest, PickFirstUpdates) { // Start servers and send one RPC per server. const int kNumServers = 3; @@ -518,7 +606,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstUpdates) { do { channel_state = channel->GetState(true /* try to connect */); } while (channel_state == GRPC_CHANNEL_READY); - GPR_ASSERT(channel_state != GRPC_CHANNEL_READY); + ASSERT_NE(channel_state, GRPC_CHANNEL_READY); servers_[0]->service_.ResetCounters(); // Next update introduces servers_[1], making the channel recover. @@ -720,6 +808,23 @@ TEST_F(ClientLbEnd2endTest, PickFirstCheckStateBeforeStartWatch) { EXPECT_EQ("pick_first", channel_2->GetLoadBalancingPolicyName()); } +TEST_F(ClientLbEnd2endTest, PickFirstIdleOnDisconnect) { + // Start server, send RPC, and make sure channel is READY. + const int kNumServers = 1; + StartServers(kNumServers); + auto channel = BuildChannel(""); // pick_first is the default. + auto stub = BuildStub(channel); + SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); + // Stop server. Channel should go into state IDLE. + SetFailureOnReresolution(); + servers_[0]->Shutdown(); + EXPECT_TRUE(WaitForChannelNotReady(channel.get())); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); + servers_.clear(); +} + TEST_F(ClientLbEnd2endTest, RoundRobin) { // Start servers and send one RPC per server. const int kNumServers = 3; @@ -835,7 +940,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) { do { channel_state = channel->GetState(true /* try to connect */); } while (channel_state == GRPC_CHANNEL_READY); - GPR_ASSERT(channel_state != GRPC_CHANNEL_READY); + ASSERT_NE(channel_state, GRPC_CHANNEL_READY); servers_[0]->service_.ResetCounters(); // Next update introduces servers_[1], making the channel recover. @@ -844,7 +949,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) { SetNextResolution(ports); WaitForServer(stub, 1, DEBUG_LOCATION); channel_state = channel->GetState(false /* try to connect */); - GPR_ASSERT(channel_state == GRPC_CHANNEL_READY); + ASSERT_EQ(channel_state, GRPC_CHANNEL_READY); // Check LB policy name for the channel. EXPECT_EQ("round_robin", channel->GetLoadBalancingPolicyName()); @@ -869,7 +974,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdateInError) { servers_[0]->service_.ResetCounters(); // Shutdown one of the servers to be sent in the update. - servers_[1]->Shutdown(false); + servers_[1]->Shutdown(); ports.emplace_back(servers_[1]->port_); ports.emplace_back(servers_[2]->port_); SetNextResolution(ports); @@ -928,7 +1033,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinReresolve) { // Kill all servers gpr_log(GPR_INFO, "****** ABOUT TO KILL SERVERS *******"); for (size_t i = 0; i < servers_.size(); ++i) { - servers_[i]->Shutdown(true); + servers_[i]->Shutdown(); } gpr_log(GPR_INFO, "****** SERVERS KILLED *******"); gpr_log(GPR_INFO, "****** SENDING DOOMED REQUESTS *******"); @@ -954,7 +1059,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinReresolve) { if (SendRpc(stub)) break; now = gpr_now(GPR_CLOCK_MONOTONIC); } - GPR_ASSERT(gpr_time_cmp(deadline, now) > 0); + ASSERT_GT(gpr_time_cmp(deadline, now), 0); } TEST_F(ClientLbEnd2endTest, RoundRobinSingleReconnect) { @@ -976,7 +1081,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinSingleReconnect) { } const auto pre_death = servers_[0]->service_.request_count(); // Kill the first server. - servers_[0]->Shutdown(true); + servers_[0]->Shutdown(); // Client request still succeed. May need retrying if RR had returned a pick // before noticing the change in the server's connectivity. while (!SendRpc(stub)) { @@ -1123,7 +1228,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingInhibitPerChannel) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); const auto result = RUN_ALL_TESTS(); return result; } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index fc07681535..05cd4330c6 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -40,6 +40,7 @@ #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" +#include "test/cpp/end2end/interceptors_util.h" #include "test/cpp/end2end/test_service_impl.h" #include "test/cpp/util/string_ref_helper.h" #include "test/cpp/util/test_credentials_provider.h" @@ -179,7 +180,7 @@ class Proxy : public ::grpc::testing::EchoTestService::Service { } private: - std::unique_ptr< ::grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<::grpc::testing::EchoTestService::Stub> stub_; }; class TestServiceImplDupPkg @@ -194,19 +195,29 @@ class TestServiceImplDupPkg class TestScenario { public: - TestScenario(bool proxy, bool inproc_stub, const grpc::string& creds_type) - : use_proxy(proxy), inproc(inproc_stub), credentials_type(creds_type) {} + TestScenario(bool interceptors, bool proxy, bool inproc_stub, + const grpc::string& creds_type, bool use_callback_server) + : use_interceptors(interceptors), + use_proxy(proxy), + inproc(inproc_stub), + credentials_type(creds_type), + callback_server(use_callback_server) {} void Log() const; + bool use_interceptors; bool use_proxy; bool inproc; const grpc::string credentials_type; + bool callback_server; }; static std::ostream& operator<<(std::ostream& out, const TestScenario& scenario) { - return out << "TestScenario{use_proxy=" - << (scenario.use_proxy ? "true" : "false") + return out << "TestScenario{use_interceptors=" + << (scenario.use_interceptors ? "true" : "false") + << ", use_proxy=" << (scenario.use_proxy ? "true" : "false") << ", inproc=" << (scenario.inproc ? "true" : "false") + << ", server_type=" + << (scenario.callback_server ? "callback" : "sync") << ", credentials='" << scenario.credentials_type << "'}"; } @@ -260,8 +271,24 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> { if (GetParam().credentials_type != kInsecureCredentialsType) { server_creds->SetAuthMetadataProcessor(processor); } + if (GetParam().use_interceptors) { + std::vector< + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + // Add 20 dummy server interceptors + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + } builder.AddListeningPort(server_address_.str(), server_creds); - builder.RegisterService(&service_); + if (!GetParam().callback_server) { + builder.RegisterService(&service_); + } else { + builder.RegisterService(&callback_service_); + } builder.RegisterService("foo.test.youtube.com", &special_service_); builder.RegisterService(&dup_pkg_service_); @@ -292,10 +319,21 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> { args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test"); if (!GetParam().inproc) { - channel_ = - CreateCustomChannel(server_address_.str(), channel_creds, args); + if (!GetParam().use_interceptors) { + channel_ = + CreateCustomChannel(server_address_.str(), channel_creds, args); + } else { + channel_ = CreateCustomChannelWithInterceptors( + server_address_.str(), channel_creds, args, + CreateDummyClientInterceptors()); + } } else { - channel_ = server_->InProcessChannel(args); + if (!GetParam().use_interceptors) { + channel_ = server_->InProcessChannel(args); + } else { + channel_ = server_->experimental().InProcessChannelWithInterceptors( + args, CreateDummyClientInterceptors()); + } } } @@ -320,6 +358,7 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> { } stub_ = grpc::testing::EchoTestService::NewStub(channel_); + DummyInterceptor::Reset(); } bool is_server_started_; @@ -331,6 +370,7 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> { std::ostringstream server_address_; const int kMaxMessageSize_; TestServiceImpl service_; + CallbackTestServiceImpl callback_service_; TestServiceImpl special_service_; TestServiceImplDupPkg dup_pkg_service_; grpc::string user_agent_prefix_; @@ -376,6 +416,7 @@ class End2endServerTryCancelTest : public End2endTest { // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. void TestRequestStreamServerCancel( ServerTryCancelRequestPhase server_try_cancel, int num_msgs_to_send) { + RestartServer(std::shared_ptr<AuthMetadataProcessor>()); ResetStub(); EchoRequest request; EchoResponse response; @@ -432,6 +473,10 @@ class End2endServerTryCancelTest : public End2endTest { EXPECT_FALSE(s.ok()); EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } } // Helper for testing server-streaming RPCs which are cancelled on the server. @@ -449,6 +494,7 @@ class End2endServerTryCancelTest : public End2endTest { // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. void TestResponseStreamServerCancel( ServerTryCancelRequestPhase server_try_cancel) { + RestartServer(std::shared_ptr<AuthMetadataProcessor>()); ResetStub(); EchoRequest request; EchoResponse response; @@ -508,7 +554,10 @@ class End2endServerTryCancelTest : public End2endTest { } EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } } // Helper for testing bidirectional-streaming RPCs which are cancelled on the @@ -526,6 +575,7 @@ class End2endServerTryCancelTest : public End2endTest { // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. void TestBidiStreamServerCancel(ServerTryCancelRequestPhase server_try_cancel, int num_messages) { + RestartServer(std::shared_ptr<AuthMetadataProcessor>()); ResetStub(); EchoRequest request; EchoResponse response; @@ -592,6 +642,10 @@ class End2endServerTryCancelTest : public End2endTest { EXPECT_FALSE(s.ok()); EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } } }; @@ -971,7 +1025,8 @@ TEST_P(End2endTest, DiffPackageServices) { EXPECT_TRUE(s.ok()); } -void CancelRpc(ClientContext* context, int delay_us, TestServiceImpl* service) { +template <class ServiceType> +void CancelRpc(ClientContext* context, int delay_us, ServiceType* service) { gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(delay_us, GPR_TIMESPAN))); while (!service->signal_client()) { @@ -989,6 +1044,9 @@ TEST_P(End2endTest, CancelRpcBeforeStart) { Status s = stub_->Echo(&context, request, &response); EXPECT_EQ("", response.message()); EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } } // Client cancels request stream after sending two messages @@ -1009,6 +1067,9 @@ TEST_P(End2endTest, ClientCancelsRequestStream) { EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); EXPECT_EQ(response.message(), ""); + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } } // Client cancels server stream after sending some messages @@ -1041,6 +1102,9 @@ TEST_P(End2endTest, ClientCancelsResponseStream) { // The final status could be either of CANCELLED or OK depending on // who won the race. EXPECT_GE(grpc::StatusCode::CANCELLED, s.error_code()); + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } } // Client cancels bidi stream after sending some messages @@ -1074,6 +1138,9 @@ TEST_P(End2endTest, ClientCancelsBidi) { Status s = stream->Finish(); EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } } TEST_P(End2endTest, RpcMaxMessageSize) { @@ -1389,7 +1456,24 @@ TEST_P(ProxyEnd2endTest, ClientCancelsRpc) { request.mutable_param()->set_client_cancel_after_us(kCancelDelayUs); ClientContext context; - std::thread cancel_thread(CancelRpc, &context, kCancelDelayUs, &service_); + std::thread cancel_thread; + if (!GetParam().callback_server) { + cancel_thread = std::thread( + [&context, this](int delay) { CancelRpc(&context, delay, &service_); }, + kCancelDelayUs); + // Note: the unusual pattern above (and below) is caused by a conflict + // between two sets of compiler expectations. clang allows const to be + // captured without mention, so there is no need to capture kCancelDelayUs + // (and indeed clang-tidy complains if you do so). OTOH, a Windows compiler + // in our tests requires an explicit capture even for const. We square this + // circle by passing the const value in as an argument to the lambda. + } else { + cancel_thread = std::thread( + [&context, this](int delay) { + CancelRpc(&context, delay, &callback_service_); + }, + kCancelDelayUs); + } Status s = stub_->Echo(&context, request, &response); cancel_thread.join(); EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); @@ -1781,10 +1865,12 @@ TEST_P(ResourceQuotaEnd2endTest, SimpleRequest) { EXPECT_TRUE(s.ok()); } +// TODO(vjpai): refactor arguments into a struct if it makes sense std::vector<TestScenario> CreateTestScenarios(bool use_proxy, bool test_insecure, bool test_secure, - bool test_inproc) { + bool test_inproc, + bool test_callback_server) { std::vector<TestScenario> scenarios; std::vector<grpc::string> credentials_types; if (test_secure) { @@ -1800,38 +1886,48 @@ std::vector<TestScenario> CreateTestScenarios(bool use_proxy, if (test_insecure && insec_ok()) { credentials_types.push_back(kInsecureCredentialsType); } + + // For now test callback server only with inproc GPR_ASSERT(!credentials_types.empty()); for (const auto& cred : credentials_types) { - scenarios.emplace_back(false, false, cred); + scenarios.emplace_back(false, false, false, cred, false); + scenarios.emplace_back(true, false, false, cred, false); if (use_proxy) { - scenarios.emplace_back(true, false, cred); + scenarios.emplace_back(false, true, false, cred, false); + scenarios.emplace_back(true, true, false, cred, false); } } if (test_inproc && insec_ok()) { - scenarios.emplace_back(false, true, kInsecureCredentialsType); + scenarios.emplace_back(false, false, true, kInsecureCredentialsType, false); + scenarios.emplace_back(true, false, true, kInsecureCredentialsType, false); + if (test_callback_server) { + scenarios.emplace_back(false, false, true, kInsecureCredentialsType, + true); + scenarios.emplace_back(true, false, true, kInsecureCredentialsType, true); + } } return scenarios; } -INSTANTIATE_TEST_CASE_P(End2end, End2endTest, - ::testing::ValuesIn(CreateTestScenarios(false, true, - true, true))); +INSTANTIATE_TEST_CASE_P( + End2end, End2endTest, + ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); -INSTANTIATE_TEST_CASE_P(End2endServerTryCancel, End2endServerTryCancelTest, - ::testing::ValuesIn(CreateTestScenarios(false, true, - true, true))); +INSTANTIATE_TEST_CASE_P( + End2endServerTryCancel, End2endServerTryCancelTest, + ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); -INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(true, true, - true, true))); +INSTANTIATE_TEST_CASE_P( + ProxyEnd2end, ProxyEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(true, true, true, true, false))); -INSTANTIATE_TEST_CASE_P(SecureEnd2end, SecureEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(false, false, - true, false))); +INSTANTIATE_TEST_CASE_P( + SecureEnd2end, SecureEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(false, false, true, false, true))); -INSTANTIATE_TEST_CASE_P(ResourceQuotaEnd2end, ResourceQuotaEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(false, true, - true, true))); +INSTANTIATE_TEST_CASE_P( + ResourceQuotaEnd2end, ResourceQuotaEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, false))); } // namespace } // namespace testing @@ -1839,7 +1935,7 @@ INSTANTIATE_TEST_CASE_P(ResourceQuotaEnd2end, ResourceQuotaEnd2endTest, int main(int argc, char** argv) { gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "200"); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/exception_test.cc b/test/cpp/end2end/exception_test.cc index 5343997663..0d2c00263b 100644 --- a/test/cpp/end2end/exception_test.cc +++ b/test/cpp/end2end/exception_test.cc @@ -117,7 +117,7 @@ TEST_F(ExceptionTest, RequestStream) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/filter_end2end_test.cc b/test/cpp/end2end/filter_end2end_test.cc index 88f8f380c3..ad67402e3d 100644 --- a/test/cpp/end2end/filter_end2end_test.cc +++ b/test/cpp/end2end/filter_end2end_test.cc @@ -331,7 +331,7 @@ void RegisterFilter() { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); grpc::testing::RegisterFilter(); return RUN_ALL_TESTS(); diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc index 88a1227ca2..015862bfe8 100644 --- a/test/cpp/end2end/generic_end2end_test.cc +++ b/test/cpp/end2end/generic_end2end_test.cc @@ -333,7 +333,7 @@ TEST_F(GenericEnd2endTest, Deadline) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index b69b861fcf..9c4cd05061 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -539,22 +539,25 @@ class GrpclbEnd2endTest : public ::testing::Test { balancers_.at(i)->add_response(response, delay_ms); } - Status SendRpc(EchoResponse* response = nullptr, int timeout_ms = 1000) { + Status SendRpc(EchoResponse* response = nullptr, int timeout_ms = 1000, + bool wait_for_ready = false) { const bool local_response = (response == nullptr); if (local_response) response = new EchoResponse; EchoRequest request; request.set_message(kRequestMessage_); ClientContext context; context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms)); + if (wait_for_ready) context.set_wait_for_ready(true); Status status = stub_->Echo(&context, request, response); if (local_response) delete response; return status; } - void CheckRpcSendOk(const size_t times = 1, const int timeout_ms = 1000) { + void CheckRpcSendOk(const size_t times = 1, const int timeout_ms = 1000, + bool wait_for_ready = false) { for (size_t i = 0; i < times; ++i) { EchoResponse response; - const Status status = SendRpc(&response, timeout_ms); + const Status status = SendRpc(&response, timeout_ms, wait_for_ready); EXPECT_TRUE(status.ok()) << "code=" << status.error_code() << " message=" << status.error_message(); EXPECT_EQ(response.message(), kRequestMessage_); @@ -715,10 +718,9 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) { ScheduleResponseForBalancer( 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), kServerlistDelayMs); - const auto t0 = system_clock::now(); // Client will block: LB will initially send empty serverlist. - CheckRpcSendOk(1, kCallDeadlineMs); + CheckRpcSendOk(1, kCallDeadlineMs, true /* wait_for_ready */); const auto ellapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>( system_clock::now() - t0); @@ -1366,7 +1368,7 @@ TEST_F(SingleBalancerTest, DropAllFirst) { {}, {{"rate_limiting", num_of_drop_by_rate_limiting_addresses}, {"load_balancing", num_of_drop_by_load_balancing_addresses}}), 0); - const Status status = SendRpc(); + const Status status = SendRpc(nullptr, 1000, true); EXPECT_FALSE(status.ok()); EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy"); } @@ -1391,7 +1393,7 @@ TEST_F(SingleBalancerTest, DropAll) { // fail. Status status; do { - status = SendRpc(); + status = SendRpc(nullptr, 1000, true); } while (status.ok()); EXPECT_FALSE(status.ok()); EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy"); @@ -1516,7 +1518,7 @@ TEST_F(SingleBalancerWithClientLoadReportingTest, Drop) { int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); const auto result = RUN_ALL_TESTS(); grpc_shutdown(); diff --git a/test/cpp/end2end/health_service_end2end_test.cc b/test/cpp/end2end/health_service_end2end_test.cc index fca65dfc13..b96ff53a3e 100644 --- a/test/cpp/end2end/health_service_end2end_test.cc +++ b/test/cpp/end2end/health_service_end2end_test.cc @@ -37,6 +37,7 @@ #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_health_check_service_impl.h" #include "test/cpp/end2end/test_service_impl.h" #include <gtest/gtest.h> @@ -49,62 +50,6 @@ namespace grpc { namespace testing { namespace { -// A sample sync implementation of the health checking service. This does the -// same thing as the default one. -class HealthCheckServiceImpl : public ::grpc::health::v1::Health::Service { - public: - Status Check(ServerContext* context, const HealthCheckRequest* request, - HealthCheckResponse* response) override { - std::lock_guard<std::mutex> lock(mu_); - auto iter = status_map_.find(request->service()); - if (iter == status_map_.end()) { - return Status(StatusCode::NOT_FOUND, ""); - } - response->set_status(iter->second); - return Status::OK; - } - - Status Watch(ServerContext* context, const HealthCheckRequest* request, - ::grpc::ServerWriter<HealthCheckResponse>* writer) override { - auto last_state = HealthCheckResponse::UNKNOWN; - while (!context->IsCancelled()) { - { - std::lock_guard<std::mutex> lock(mu_); - HealthCheckResponse response; - auto iter = status_map_.find(request->service()); - if (iter == status_map_.end()) { - response.set_status(response.SERVICE_UNKNOWN); - } else { - response.set_status(iter->second); - } - if (response.status() != last_state) { - writer->Write(response, ::grpc::WriteOptions()); - } - } - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis(1000, GPR_TIMESPAN))); - } - return Status::OK; - } - - void SetStatus(const grpc::string& service_name, - HealthCheckResponse::ServingStatus status) { - std::lock_guard<std::mutex> lock(mu_); - status_map_[service_name] = status; - } - - void SetAll(HealthCheckResponse::ServingStatus status) { - std::lock_guard<std::mutex> lock(mu_); - for (auto iter = status_map_.begin(); iter != status_map_.end(); ++iter) { - iter->second = status; - } - } - - private: - std::mutex mu_; - std::map<const grpc::string, HealthCheckResponse::ServingStatus> status_map_; -}; - // A custom implementation of the health checking service interface. This is // used to test that it prevents the server from creating a default service and // also serves as an example of how to override the default service. @@ -125,6 +70,8 @@ class CustomHealthCheckService : public HealthCheckServiceInterface { : HealthCheckResponse::NOT_SERVING); } + void Shutdown() override { impl_->Shutdown(); } + private: HealthCheckServiceImpl* impl_; // not owned }; @@ -260,6 +207,74 @@ class HealthServiceEnd2endTest : public ::testing::Test { context.TryCancel(); } + // Verify that after HealthCheckServiceInterface::Shutdown is called + // 1. unary client will see NOT_SERVING. + // 2. unary client still sees NOT_SERVING after a SetServing(true) is called. + // 3. streaming (Watch) client will see an update. + // 4. setting a new service to serving after shutdown will add the service + // name but return NOT_SERVING to client. + // This has to be called last. + void VerifyHealthCheckServiceShutdown() { + HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + EXPECT_TRUE(service != nullptr); + const grpc::string kHealthyService("healthy_service"); + const grpc::string kUnhealthyService("unhealthy_service"); + const grpc::string kNotRegisteredService("not_registered"); + const grpc::string kNewService("add_after_shutdown"); + service->SetServingStatus(kHealthyService, true); + service->SetServingStatus(kUnhealthyService, false); + + ResetStubs(); + + // Start Watch for service. + ClientContext context; + HealthCheckRequest request; + request.set_service(kHealthyService); + std::unique_ptr<::grpc::ClientReaderInterface<HealthCheckResponse>> reader = + hc_stub_->Watch(&context, request); + + HealthCheckResponse response; + EXPECT_TRUE(reader->Read(&response)); + EXPECT_EQ(response.SERVING, response.status()); + + SendHealthCheckRpc("", Status::OK, HealthCheckResponse::SERVING); + SendHealthCheckRpc(kHealthyService, Status::OK, + HealthCheckResponse::SERVING); + SendHealthCheckRpc(kUnhealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kNotRegisteredService, + Status(StatusCode::NOT_FOUND, "")); + SendHealthCheckRpc(kNewService, Status(StatusCode::NOT_FOUND, "")); + + // Shutdown health check service. + service->Shutdown(); + + // Watch client gets another update. + EXPECT_TRUE(reader->Read(&response)); + EXPECT_EQ(response.NOT_SERVING, response.status()); + // Finish Watch call. + context.TryCancel(); + + SendHealthCheckRpc("", Status::OK, HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kHealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kUnhealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kNotRegisteredService, + Status(StatusCode::NOT_FOUND, "")); + + // Setting status after Shutdown has no effect. + service->SetServingStatus(kHealthyService, true); + SendHealthCheckRpc(kHealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + + // Adding serving status for a new service after shutdown will return + // NOT_SERVING. + service->SetServingStatus(kNewService, true); + SendHealthCheckRpc(kNewService, Status::OK, + HealthCheckResponse::NOT_SERVING); + } + TestServiceImpl echo_test_service_; HealthCheckServiceImpl health_check_service_impl_; std::unique_ptr<Health::Stub> hc_stub_; @@ -295,6 +310,13 @@ TEST_F(HealthServiceEnd2endTest, DefaultHealthService) { Status(StatusCode::INVALID_ARGUMENT, "")); } +TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceShutdown) { + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + SetUpServer(true, false, false, nullptr); + VerifyHealthCheckServiceShutdown(); +} + // Provide an empty service to disable the default service. TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) { EnableDefaultHealthCheckService(true); @@ -326,12 +348,27 @@ TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) { VerifyHealthCheckServiceStreaming(); } +TEST_F(HealthServiceEnd2endTest, ExplicitlyHealthServiceShutdown) { + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + std::unique_ptr<HealthCheckServiceInterface> override_service( + new CustomHealthCheckService(&health_check_service_impl_)); + HealthCheckServiceInterface* underlying_service = override_service.get(); + SetUpServer(false, false, true, std::move(override_service)); + HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + EXPECT_TRUE(service == underlying_service); + + ResetStubs(); + + VerifyHealthCheckServiceShutdown(); +} + } // namespace } // namespace testing } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/hybrid_end2end_test.cc b/test/cpp/end2end/hybrid_end2end_test.cc index 339eadde92..18bb1ff4b9 100644 --- a/test/cpp/end2end/hybrid_end2end_test.cc +++ b/test/cpp/end2end/hybrid_end2end_test.cc @@ -894,7 +894,7 @@ TEST_F(HybridEnd2endTest, GenericMethodWithoutGenericService) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/interceptors_util.cc b/test/cpp/end2end/interceptors_util.cc new file mode 100644 index 0000000000..e0ad7d1526 --- /dev/null +++ b/test/cpp/end2end/interceptors_util.cc @@ -0,0 +1,149 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/cpp/end2end/interceptors_util.h" + +namespace grpc { +namespace testing { + +std::atomic<int> DummyInterceptor::num_times_run_; +std::atomic<int> DummyInterceptor::num_times_run_reverse_; +std::atomic<int> DummyInterceptor::num_times_cancel_; + +void MakeCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + req.mutable_param()->set_echo_metadata(true); + ctx.AddMetadata("testkey", "testvalue"); + req.set_message("Hello"); + EchoResponse resp; + Status s = stub->Echo(&ctx, req, &resp); + EXPECT_EQ(s.ok(), true); + EXPECT_EQ(resp.message(), "Hello"); +} + +void MakeClientStreamingCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + req.mutable_param()->set_echo_metadata(true); + ctx.AddMetadata("testkey", "testvalue"); + req.set_message("Hello"); + EchoResponse resp; + string expected_resp = ""; + auto writer = stub->RequestStream(&ctx, &resp); + for (int i = 0; i < 10; i++) { + writer->Write(req); + expected_resp += "Hello"; + } + writer->WritesDone(); + Status s = writer->Finish(); + EXPECT_EQ(s.ok(), true); + EXPECT_EQ(resp.message(), expected_resp); +} + +void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + req.mutable_param()->set_echo_metadata(true); + ctx.AddMetadata("testkey", "testvalue"); + req.set_message("Hello"); + EchoResponse resp; + string expected_resp = ""; + auto reader = stub->ResponseStream(&ctx, req); + int count = 0; + while (reader->Read(&resp)) { + EXPECT_EQ(resp.message(), "Hello"); + count++; + } + ASSERT_EQ(count, 10); + Status s = reader->Finish(); + EXPECT_EQ(s.ok(), true); +} + +void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + EchoResponse resp; + ctx.AddMetadata("testkey", "testvalue"); + auto stream = stub->BidiStream(&ctx); + for (auto i = 0; i < 10; i++) { + req.set_message("Hello" + std::to_string(i)); + stream->Write(req); + stream->Read(&resp); + EXPECT_EQ(req.message(), resp.message()); + } + ASSERT_TRUE(stream->WritesDone()); + Status s = stream->Finish(); + EXPECT_EQ(s.ok(), true); +} + +void MakeCallbackCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + std::mutex mu; + std::condition_variable cv; + bool done = false; + req.mutable_param()->set_echo_metadata(true); + ctx.AddMetadata("testkey", "testvalue"); + req.set_message("Hello"); + EchoResponse resp; + stub->experimental_async()->Echo(&ctx, &req, &resp, + [&resp, &mu, &done, &cv](Status s) { + // gpr_log(GPR_ERROR, "got the callback"); + EXPECT_EQ(s.ok(), true); + EXPECT_EQ(resp.message(), "Hello"); + std::lock_guard<std::mutex> l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } +} + +bool CheckMetadata(const std::multimap<grpc::string_ref, grpc::string_ref>& map, + const string& key, const string& value) { + for (const auto& pair : map) { + if (pair.first.starts_with(key) && pair.second.starts_with(value)) { + return true; + } + } + return false; +} + +std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> +CreateDummyClientInterceptors() { + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors before hijacking interceptor + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + return creators; +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/end2end/interceptors_util.h b/test/cpp/end2end/interceptors_util.h new file mode 100644 index 0000000000..d886e32494 --- /dev/null +++ b/test/cpp/end2end/interceptors_util.h @@ -0,0 +1,278 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <condition_variable> + +#include <grpcpp/channel.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/cpp/util/string_ref_helper.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { +/* This interceptor does nothing. Just keeps a global count on the number of + * times it was invoked. */ +class DummyInterceptor : public experimental::Interceptor { + public: + DummyInterceptor() {} + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + num_times_run_++; + } else if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints:: + POST_RECV_INITIAL_METADATA)) { + num_times_run_reverse_++; + } else if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CANCEL)) { + num_times_cancel_++; + } + methods->Proceed(); + } + + static void Reset() { + num_times_run_.store(0); + num_times_run_reverse_.store(0); + num_times_cancel_.store(0); + } + + static int GetNumTimesRun() { + EXPECT_EQ(num_times_run_.load(), num_times_run_reverse_.load()); + return num_times_run_.load(); + } + + static int GetNumTimesCancel() { return num_times_cancel_.load(); } + + private: + static std::atomic<int> num_times_run_; + static std::atomic<int> num_times_run_reverse_; + static std::atomic<int> num_times_cancel_; +}; + +class DummyInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface, + public experimental::ServerInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new DummyInterceptor(); + } + + virtual experimental::Interceptor* CreateServerInterceptor( + experimental::ServerRpcInfo* info) override { + return new DummyInterceptor(); + } +}; + +class EchoTestServiceStreamingImpl : public EchoTestService::Service { + public: + ~EchoTestServiceStreamingImpl() override {} + + Status BidiStream( + ServerContext* context, + grpc::ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { + EchoRequest req; + EchoResponse resp; + auto client_metadata = context->client_metadata(); + for (const auto& pair : client_metadata) { + context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second)); + } + + while (stream->Read(&req)) { + resp.set_message(req.message()); + EXPECT_TRUE(stream->Write(resp, grpc::WriteOptions())); + } + return Status::OK; + } + + Status RequestStream(ServerContext* context, + ServerReader<EchoRequest>* reader, + EchoResponse* resp) override { + auto client_metadata = context->client_metadata(); + for (const auto& pair : client_metadata) { + context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second)); + } + + EchoRequest req; + string response_str = ""; + while (reader->Read(&req)) { + response_str += req.message(); + } + resp->set_message(response_str); + return Status::OK; + } + + Status ResponseStream(ServerContext* context, const EchoRequest* req, + ServerWriter<EchoResponse>* writer) override { + auto client_metadata = context->client_metadata(); + for (const auto& pair : client_metadata) { + context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second)); + } + + EchoResponse resp; + resp.set_message(req->message()); + for (int i = 0; i < 10; i++) { + EXPECT_TRUE(writer->Write(resp)); + } + return Status::OK; + } +}; + +void MakeCall(const std::shared_ptr<Channel>& channel); + +void MakeClientStreamingCall(const std::shared_ptr<Channel>& channel); + +void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel); + +void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel); + +void MakeCallbackCall(const std::shared_ptr<Channel>& channel); + +bool CheckMetadata(const std::multimap<grpc::string_ref, grpc::string_ref>& map, + const string& key, const string& value); + +std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> +CreateDummyClientInterceptors(); + +inline void* tag(int i) { return (void*)static_cast<intptr_t>(i); } +inline int detag(void* p) { + return static_cast<int>(reinterpret_cast<intptr_t>(p)); +} + +class Verifier { + public: + Verifier() : lambda_run_(false) {} + // Expect sets the expected ok value for a specific tag + Verifier& Expect(int i, bool expect_ok) { + return ExpectUnless(i, expect_ok, false); + } + // ExpectUnless sets the expected ok value for a specific tag + // unless the tag was already marked seen (as a result of ExpectMaybe) + Verifier& ExpectUnless(int i, bool expect_ok, bool seen) { + if (!seen) { + expectations_[tag(i)] = expect_ok; + } + return *this; + } + // ExpectMaybe sets the expected ok value for a specific tag, but does not + // require it to appear + // If it does, sets *seen to true + Verifier& ExpectMaybe(int i, bool expect_ok, bool* seen) { + if (!*seen) { + maybe_expectations_[tag(i)] = MaybeExpect{expect_ok, seen}; + } + return *this; + } + + // Next waits for 1 async tag to complete, checks its + // expectations, and returns the tag + int Next(CompletionQueue* cq, bool ignore_ok) { + bool ok; + void* got_tag; + EXPECT_TRUE(cq->Next(&got_tag, &ok)); + GotTag(got_tag, ok, ignore_ok); + return detag(got_tag); + } + + template <typename T> + CompletionQueue::NextStatus DoOnceThenAsyncNext( + CompletionQueue* cq, void** got_tag, bool* ok, T deadline, + std::function<void(void)> lambda) { + if (lambda_run_) { + return cq->AsyncNext(got_tag, ok, deadline); + } else { + lambda_run_ = true; + return cq->DoThenAsyncNext(lambda, got_tag, ok, deadline); + } + } + + // Verify keeps calling Next until all currently set + // expected tags are complete + void Verify(CompletionQueue* cq) { Verify(cq, false); } + + // This version of Verify allows optionally ignoring the + // outcome of the expectation + void Verify(CompletionQueue* cq, bool ignore_ok) { + GPR_ASSERT(!expectations_.empty() || !maybe_expectations_.empty()); + while (!expectations_.empty()) { + Next(cq, ignore_ok); + } + } + + // This version of Verify stops after a certain deadline, and uses the + // DoThenAsyncNext API + // to call the lambda + void Verify(CompletionQueue* cq, + std::chrono::system_clock::time_point deadline, + const std::function<void(void)>& lambda) { + if (expectations_.empty()) { + bool ok; + void* got_tag; + EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), + CompletionQueue::TIMEOUT); + } else { + while (!expectations_.empty()) { + bool ok; + void* got_tag; + EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), + CompletionQueue::GOT_EVENT); + GotTag(got_tag, ok, false); + } + } + } + + private: + void GotTag(void* got_tag, bool ok, bool ignore_ok) { + auto it = expectations_.find(got_tag); + if (it != expectations_.end()) { + if (!ignore_ok) { + EXPECT_EQ(it->second, ok); + } + expectations_.erase(it); + } else { + auto it2 = maybe_expectations_.find(got_tag); + if (it2 != maybe_expectations_.end()) { + if (it2->second.seen != nullptr) { + EXPECT_FALSE(*it2->second.seen); + *it2->second.seen = true; + } + if (!ignore_ok) { + EXPECT_EQ(it2->second.ok, ok); + } + } else { + gpr_log(GPR_ERROR, "Unexpected tag: %p", got_tag); + abort(); + } + } + } + + struct MaybeExpect { + bool ok; + bool* seen; + }; + + std::map<void*, bool> expectations_; + std::map<void*, MaybeExpect> maybe_expectations_; + bool lambda_run_; +}; + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc index ba3122c895..917ca28020 100644 --- a/test/cpp/end2end/mock_test.cc +++ b/test/cpp/end2end/mock_test.cc @@ -345,7 +345,7 @@ TEST_F(MockTest, BidiStream) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/nonblocking_test.cc b/test/cpp/end2end/nonblocking_test.cc index d8337baca2..36dea1fcb3 100644 --- a/test/cpp/end2end/nonblocking_test.cc +++ b/test/cpp/end2end/nonblocking_test.cc @@ -187,7 +187,7 @@ int main(int argc, char** argv) { grpc_poll_function = maybe_assert_non_blocking_poll; #endif // GRPC_POSIX_SOCKET - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; diff --git a/test/cpp/end2end/proto_server_reflection_test.cc b/test/cpp/end2end/proto_server_reflection_test.cc index 21a275ef62..ff097aa9a7 100644 --- a/test/cpp/end2end/proto_server_reflection_test.cc +++ b/test/cpp/end2end/proto_server_reflection_test.cc @@ -144,7 +144,7 @@ TEST_F(ProtoServerReflectionTest, CheckResponseWithLocalDescriptorPool) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/raw_end2end_test.cc b/test/cpp/end2end/raw_end2end_test.cc index a413905ef7..c8556bae95 100644 --- a/test/cpp/end2end/raw_end2end_test.cc +++ b/test/cpp/end2end/raw_end2end_test.cc @@ -363,7 +363,7 @@ TEST_F(RawEnd2EndTest, CompileTest) { int main(int argc, char** argv) { // Change the backup poll interval from 5s to 100ms to speed up the // ReconnectChannel test - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; diff --git a/test/cpp/end2end/server_builder_plugin_test.cc b/test/cpp/end2end/server_builder_plugin_test.cc index d54523fcbb..d744a93912 100644 --- a/test/cpp/end2end/server_builder_plugin_test.cc +++ b/test/cpp/end2end/server_builder_plugin_test.cc @@ -264,7 +264,7 @@ INSTANTIATE_TEST_CASE_P(ServerBuilderPluginTest, ServerBuilderPluginTest, } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc index 93257b2705..353ebf713a 100644 --- a/test/cpp/end2end/server_crash_test.cc +++ b/test/cpp/end2end/server_crash_test.cc @@ -153,7 +153,7 @@ int main(int argc, char** argv) { g_root = "."; } - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/server_early_return_test.cc b/test/cpp/end2end/server_early_return_test.cc index 8948e5b854..c47e25052e 100644 --- a/test/cpp/end2end/server_early_return_test.cc +++ b/test/cpp/end2end/server_early_return_test.cc @@ -226,7 +226,7 @@ TEST_F(ServerEarlyReturnTest, RequestStreamEarlyCancel) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/server_interceptors_end2end_test.cc b/test/cpp/end2end/server_interceptors_end2end_test.cc new file mode 100644 index 0000000000..9460a7d6c6 --- /dev/null +++ b/test/cpp/end2end/server_interceptors_end2end_test.cc @@ -0,0 +1,610 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <memory> +#include <vector> + +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/generic/generic_stub.h> +#include <grpcpp/impl/codegen/proto_utils.h> +#include <grpcpp/impl/codegen/server_interceptor.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/interceptors_util.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { +namespace { + +class LoggingInterceptor : public experimental::Interceptor { + public: + LoggingInterceptor(experimental::ServerRpcInfo* info) { + info_ = info; + + // Check the method name and compare to the type + const char* method = info->method(); + experimental::ServerRpcInfo::Type type = info->type(); + + // Check that we use one of our standard methods with expected type. + // Also allow the health checking service. + // We accept BIDI_STREAMING for Echo in case it's an AsyncGenericService + // being tested (the GenericRpc test). + // The empty method is for the Unimplemented requests that arise + // when draining the CQ. + EXPECT_TRUE( + strstr(method, "/grpc.health") == method || + (strcmp(method, "/grpc.testing.EchoTestService/Echo") == 0 && + (type == experimental::ServerRpcInfo::Type::UNARY || + type == experimental::ServerRpcInfo::Type::BIDI_STREAMING)) || + (strcmp(method, "/grpc.testing.EchoTestService/RequestStream") == 0 && + type == experimental::ServerRpcInfo::Type::CLIENT_STREAMING) || + (strcmp(method, "/grpc.testing.EchoTestService/ResponseStream") == 0 && + type == experimental::ServerRpcInfo::Type::SERVER_STREAMING) || + (strcmp(method, "/grpc.testing.EchoTestService/BidiStream") == 0 && + type == experimental::ServerRpcInfo::Type::BIDI_STREAMING) || + strcmp(method, "/grpc.testing.EchoTestService/Unimplemented") == 0 || + (strcmp(method, "") == 0 && + type == experimental::ServerRpcInfo::Type::BIDI_STREAMING)); + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Got nothing better to do here for now + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_TRUE(req.message().find("Hello") == 0); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_STATUS)) { + auto* map = methods->GetSendTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.find("testkey") == 0 && + pair.second.find("testvalue") == 0; + if (found) break; + } + EXPECT_EQ(found, true); + auto status = methods->GetSendStatus(); + EXPECT_EQ(status.ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.find("testkey") == 0 && + pair.second.find("testvalue") == 0; + if (found) break; + } + EXPECT_EQ(found, true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + EXPECT_TRUE(resp->message().find("Hello") == 0); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_CLOSE)) { + // Got nothing interesting to do here + } + methods->Proceed(); + } + + private: + experimental::ServerRpcInfo* info_; +}; + +class LoggingInterceptorFactory + : public experimental::ServerInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateServerInterceptor( + experimental::ServerRpcInfo* info) override { + return new LoggingInterceptor(info); + } +}; + +void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + EchoResponse resp; + ctx.AddMetadata("testkey", "testvalue"); + auto stream = stub->BidiStream(&ctx); + for (auto i = 0; i < 10; i++) { + req.set_message("Hello" + std::to_string(i)); + stream->Write(req); + stream->Read(&resp); + EXPECT_EQ(req.message(), resp.message()); + } + ASSERT_TRUE(stream->WritesDone()); + Status s = stream->Finish(); + EXPECT_EQ(s.ok(), true); +} + +class ServerInterceptorsEnd2endSyncUnaryTest : public ::testing::Test { + protected: + ServerInterceptorsEnd2endSyncUnaryTest() { + int port = grpc_pick_unused_port_or_die(); + + ServerBuilder builder; + server_address_ = "localhost:" + std::to_string(port); + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + + std::vector< + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new LoggingInterceptorFactory())); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + server_ = builder.BuildAndStart(); + } + std::string server_address_; + TestServiceImpl service_; + std::unique_ptr<Server> server_; +}; + +TEST_F(ServerInterceptorsEnd2endSyncUnaryTest, UnaryTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + auto channel = CreateChannel(server_address_, InsecureChannelCredentials()); + MakeCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +class ServerInterceptorsEnd2endSyncStreamingTest : public ::testing::Test { + protected: + ServerInterceptorsEnd2endSyncStreamingTest() { + int port = grpc_pick_unused_port_or_die(); + + ServerBuilder builder; + server_address_ = "localhost:" + std::to_string(port); + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + + std::vector< + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new LoggingInterceptorFactory())); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + server_ = builder.BuildAndStart(); + } + std::string server_address_; + EchoTestServiceStreamingImpl service_; + std::unique_ptr<Server> server_; +}; + +TEST_F(ServerInterceptorsEnd2endSyncStreamingTest, ClientStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + auto channel = CreateChannel(server_address_, InsecureChannelCredentials()); + MakeClientStreamingCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ServerInterceptorsEnd2endSyncStreamingTest, ServerStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + auto channel = CreateChannel(server_address_, InsecureChannelCredentials()); + MakeServerStreamingCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ServerInterceptorsEnd2endSyncStreamingTest, BidiStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + auto channel = CreateChannel(server_address_, InsecureChannelCredentials()); + MakeBidiStreamingCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +class ServerInterceptorsAsyncEnd2endTest : public ::testing::Test {}; + +TEST_F(ServerInterceptorsAsyncEnd2endTest, UnaryTest) { + DummyInterceptor::Reset(); + int port = grpc_pick_unused_port_or_die(); + string server_address = "localhost:" + std::to_string(port); + ServerBuilder builder; + EchoTestService::AsyncService service; + builder.AddListeningPort(server_address, InsecureServerCredentials()); + builder.RegisterService(&service); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new LoggingInterceptorFactory())); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto cq = builder.AddCompletionQueue(); + auto server = builder.BuildAndStart(); + + ChannelArguments args; + auto channel = CreateChannel(server_address, InsecureChannelCredentials()); + auto stub = grpc::testing::EchoTestService::NewStub(channel); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message("Hello"); + cli_ctx.AddMetadata("testkey", "testvalue"); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub->AsyncEcho(&cli_ctx, send_request, cq.get())); + + service.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq.get(), + cq.get(), tag(2)); + + response_reader->Finish(&recv_response, &recv_status, tag(4)); + + Verifier().Expect(2, true).Verify(cq.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); + srv_ctx.AddTrailingMetadata("testkey", "testvalue"); + + send_response.set_message(recv_request.message()); + response_writer.Finish(send_response, Status::OK, tag(3)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + EXPECT_TRUE(CheckMetadata(cli_ctx.GetServerTrailingMetadata(), "testkey", + "testvalue")); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + cq->Shutdown(); + void* ignored_tag; + bool ignored_ok; + while (cq->Next(&ignored_tag, &ignored_ok)) + ; + grpc_recycle_unused_port(port); +} + +TEST_F(ServerInterceptorsAsyncEnd2endTest, BidiStreamingTest) { + DummyInterceptor::Reset(); + int port = grpc_pick_unused_port_or_die(); + string server_address = "localhost:" + std::to_string(port); + ServerBuilder builder; + EchoTestService::AsyncService service; + builder.AddListeningPort(server_address, InsecureServerCredentials()); + builder.RegisterService(&service); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new LoggingInterceptorFactory())); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto cq = builder.AddCompletionQueue(); + auto server = builder.BuildAndStart(); + + ChannelArguments args; + auto channel = CreateChannel(server_address, InsecureChannelCredentials()); + auto stub = grpc::testing::EchoTestService::NewStub(channel); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncReaderWriter<EchoResponse, EchoRequest> srv_stream(&srv_ctx); + + send_request.set_message("Hello"); + cli_ctx.AddMetadata("testkey", "testvalue"); + 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)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq.get()); + + EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); + srv_ctx.AddTrailingMetadata("testkey", "testvalue"); + + cli_stream->Write(send_request, tag(3)); + srv_stream.Read(&recv_request, tag(4)); + Verifier().Expect(3, true).Expect(4, 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(5)); + cli_stream->Read(&recv_response, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->WritesDone(tag(7)); + srv_stream.Read(&recv_request, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq.get()); + + srv_stream.Finish(Status::OK, tag(9)); + cli_stream->Finish(&recv_status, tag(10)); + Verifier().Expect(9, true).Expect(10, true).Verify(cq.get()); + + EXPECT_TRUE(recv_status.ok()); + EXPECT_TRUE(CheckMetadata(cli_ctx.GetServerTrailingMetadata(), "testkey", + "testvalue")); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + cq->Shutdown(); + void* ignored_tag; + bool ignored_ok; + while (cq->Next(&ignored_tag, &ignored_ok)) + ; + grpc_recycle_unused_port(port); +} + +TEST_F(ServerInterceptorsAsyncEnd2endTest, GenericRPCTest) { + DummyInterceptor::Reset(); + int port = grpc_pick_unused_port_or_die(); + string server_address = "localhost:" + std::to_string(port); + ServerBuilder builder; + AsyncGenericService service; + builder.AddListeningPort(server_address, InsecureServerCredentials()); + builder.RegisterAsyncGenericService(&service); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto cq = builder.AddCompletionQueue(); + auto server = builder.BuildAndStart(); + + ChannelArguments args; + auto channel = CreateChannel(server_address, InsecureChannelCredentials()); + GenericStub generic_stub(channel); + + const grpc::string kMethodName("/grpc.cpp.test.util.EchoTestService/Echo"); + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + GenericServerContext srv_ctx; + GenericServerAsyncReaderWriter stream(&srv_ctx); + + // The string needs to be long enough to test heap-based slice. + send_request.set_message("Hello"); + cli_ctx.AddMetadata("testkey", "testvalue"); + + std::unique_ptr<GenericClientAsyncReaderWriter> call = + generic_stub.PrepareCall(&cli_ctx, kMethodName, cq.get()); + call->StartCall(tag(1)); + Verifier().Expect(1, true).Verify(cq.get()); + std::unique_ptr<ByteBuffer> send_buffer = + SerializeToByteBuffer(&send_request); + call->Write(*send_buffer, tag(2)); + // Send ByteBuffer can be destroyed after calling Write. + send_buffer.reset(); + Verifier().Expect(2, true).Verify(cq.get()); + call->WritesDone(tag(3)); + Verifier().Expect(3, true).Verify(cq.get()); + + service.RequestCall(&srv_ctx, &stream, cq.get(), cq.get(), tag(4)); + + Verifier().Expect(4, true).Verify(cq.get()); + EXPECT_EQ(kMethodName, srv_ctx.method()); + EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); + srv_ctx.AddTrailingMetadata("testkey", "testvalue"); + + ByteBuffer recv_buffer; + stream.Read(&recv_buffer, tag(5)); + Verifier().Expect(5, true).Verify(cq.get()); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + send_buffer = SerializeToByteBuffer(&send_response); + stream.Write(*send_buffer, tag(6)); + send_buffer.reset(); + Verifier().Expect(6, true).Verify(cq.get()); + + stream.Finish(Status::OK, tag(7)); + Verifier().Expect(7, true).Verify(cq.get()); + + recv_buffer.Clear(); + call->Read(&recv_buffer, tag(8)); + Verifier().Expect(8, true).Verify(cq.get()); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); + + call->Finish(&recv_status, tag(9)); + Verifier().Expect(9, true).Verify(cq.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + EXPECT_TRUE(CheckMetadata(cli_ctx.GetServerTrailingMetadata(), "testkey", + "testvalue")); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + cq->Shutdown(); + void* ignored_tag; + bool ignored_ok; + while (cq->Next(&ignored_tag, &ignored_ok)) + ; + grpc_recycle_unused_port(port); +} + +TEST_F(ServerInterceptorsAsyncEnd2endTest, UnimplementedRpcTest) { + DummyInterceptor::Reset(); + int port = grpc_pick_unused_port_or_die(); + string server_address = "localhost:" + std::to_string(port); + ServerBuilder builder; + builder.AddListeningPort(server_address, InsecureServerCredentials()); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto cq = builder.AddCompletionQueue(); + auto server = builder.BuildAndStart(); + + ChannelArguments args; + std::shared_ptr<Channel> channel = + CreateChannel(server_address, InsecureChannelCredentials()); + std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; + stub = grpc::testing::UnimplementedEchoService::NewStub(channel); + EchoRequest send_request; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + send_request.set_message("Hello"); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub->AsyncUnimplemented(&cli_ctx, send_request, cq.get())); + + response_reader->Finish(&recv_response, &recv_status, tag(4)); + Verifier().Expect(4, true).Verify(cq.get()); + + EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code()); + EXPECT_EQ("", recv_status.error_message()); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + cq->Shutdown(); + void* ignored_tag; + bool ignored_ok; + while (cq->Next(&ignored_tag, &ignored_ok)) + ; + grpc_recycle_unused_port(port); +} + +class ServerInterceptorsSyncUnimplementedEnd2endTest : public ::testing::Test { +}; + +TEST_F(ServerInterceptorsSyncUnimplementedEnd2endTest, UnimplementedRpcTest) { + DummyInterceptor::Reset(); + int port = grpc_pick_unused_port_or_die(); + string server_address = "localhost:" + std::to_string(port); + ServerBuilder builder; + TestServiceImpl service; + builder.RegisterService(&service); + builder.AddListeningPort(server_address, InsecureServerCredentials()); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto server = builder.BuildAndStart(); + + ChannelArguments args; + std::shared_ptr<Channel> channel = + CreateChannel(server_address, InsecureChannelCredentials()); + std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; + stub = grpc::testing::UnimplementedEchoService::NewStub(channel); + EchoRequest send_request; + EchoResponse recv_response; + + ClientContext cli_ctx; + send_request.set_message("Hello"); + Status recv_status = + stub->Unimplemented(&cli_ctx, send_request, &recv_response); + + EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code()); + EXPECT_EQ("", recv_status.error_message()); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + grpc_recycle_unused_port(port); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc index a53de691bc..da42178d67 100644 --- a/test/cpp/end2end/shutdown_test.cc +++ b/test/cpp/end2end/shutdown_test.cc @@ -164,7 +164,7 @@ TEST_P(ShutdownTest, ShutdownTest) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/streaming_throughput_test.cc b/test/cpp/end2end/streaming_throughput_test.cc index 898d1ec118..440656588b 100644 --- a/test/cpp/end2end/streaming_throughput_test.cc +++ b/test/cpp/end2end/streaming_throughput_test.cc @@ -187,7 +187,7 @@ TEST_F(End2endTest, StreamingThroughput) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/test_health_check_service_impl.cc b/test/cpp/end2end/test_health_check_service_impl.cc new file mode 100644 index 0000000000..0801e30199 --- /dev/null +++ b/test/cpp/end2end/test_health_check_service_impl.cc @@ -0,0 +1,97 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/cpp/end2end/test_health_check_service_impl.h" + +#include <grpc/grpc.h> + +using grpc::health::v1::HealthCheckRequest; +using grpc::health::v1::HealthCheckResponse; + +namespace grpc { +namespace testing { + +Status HealthCheckServiceImpl::Check(ServerContext* context, + const HealthCheckRequest* request, + HealthCheckResponse* response) { + std::lock_guard<std::mutex> lock(mu_); + auto iter = status_map_.find(request->service()); + if (iter == status_map_.end()) { + return Status(StatusCode::NOT_FOUND, ""); + } + response->set_status(iter->second); + return Status::OK; +} + +Status HealthCheckServiceImpl::Watch( + ServerContext* context, const HealthCheckRequest* request, + ::grpc::ServerWriter<HealthCheckResponse>* writer) { + auto last_state = HealthCheckResponse::UNKNOWN; + while (!context->IsCancelled()) { + { + std::lock_guard<std::mutex> lock(mu_); + HealthCheckResponse response; + auto iter = status_map_.find(request->service()); + if (iter == status_map_.end()) { + response.set_status(response.SERVICE_UNKNOWN); + } else { + response.set_status(iter->second); + } + if (response.status() != last_state) { + writer->Write(response, ::grpc::WriteOptions()); + } + } + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis(1000, GPR_TIMESPAN))); + } + return Status::OK; +} + +void HealthCheckServiceImpl::SetStatus( + const grpc::string& service_name, + HealthCheckResponse::ServingStatus status) { + std::lock_guard<std::mutex> lock(mu_); + if (shutdown_) { + status = HealthCheckResponse::NOT_SERVING; + } + status_map_[service_name] = status; +} + +void HealthCheckServiceImpl::SetAll(HealthCheckResponse::ServingStatus status) { + std::lock_guard<std::mutex> lock(mu_); + if (shutdown_) { + return; + } + for (auto iter = status_map_.begin(); iter != status_map_.end(); ++iter) { + iter->second = status; + } +} + +void HealthCheckServiceImpl::Shutdown() { + std::lock_guard<std::mutex> lock(mu_); + if (shutdown_) { + return; + } + shutdown_ = true; + for (auto iter = status_map_.begin(); iter != status_map_.end(); ++iter) { + iter->second = HealthCheckResponse::NOT_SERVING; + } +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/end2end/test_health_check_service_impl.h b/test/cpp/end2end/test_health_check_service_impl.h new file mode 100644 index 0000000000..5d36ce5320 --- /dev/null +++ b/test/cpp/end2end/test_health_check_service_impl.h @@ -0,0 +1,58 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef GRPC_TEST_CPP_END2END_TEST_HEALTH_CHECK_SERVICE_IMPL_H +#define GRPC_TEST_CPP_END2END_TEST_HEALTH_CHECK_SERVICE_IMPL_H + +#include <map> +#include <mutex> + +#include <grpcpp/server_context.h> +#include <grpcpp/support/status.h> + +#include "src/proto/grpc/health/v1/health.grpc.pb.h" + +namespace grpc { +namespace testing { + +// A sample sync implementation of the health checking service. This does the +// same thing as the default one. +class HealthCheckServiceImpl : public health::v1::Health::Service { + public: + Status Check(ServerContext* context, + const health::v1::HealthCheckRequest* request, + health::v1::HealthCheckResponse* response) override; + Status Watch(ServerContext* context, + const health::v1::HealthCheckRequest* request, + ServerWriter<health::v1::HealthCheckResponse>* writer) override; + void SetStatus(const grpc::string& service_name, + health::v1::HealthCheckResponse::ServingStatus status); + void SetAll(health::v1::HealthCheckResponse::ServingStatus status); + + void Shutdown(); + + private: + std::mutex mu_; + bool shutdown_ = false; + std::map<const grpc::string, health::v1::HealthCheckResponse::ServingStatus> + status_map_; +}; + +} // namespace testing +} // namespace grpc + +#endif // GRPC_TEST_CPP_END2END_TEST_HEALTH_CHECK_SERVICE_IMPL_H diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc index 3c3a5d9cd4..6729ad14f4 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -69,6 +69,62 @@ void CheckServerAuthContext( EXPECT_EQ(expected_client_identity, identity[0]); } } + +// Returns the number of pairs in metadata that exactly match the given +// key-value pair. Returns -1 if the pair wasn't found. +int MetadataMatchCount( + const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, + const grpc::string& key, const grpc::string& value) { + int count = 0; + for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator iter = + metadata.begin(); + iter != metadata.end(); ++iter) { + if (ToString(iter->first) == key && ToString(iter->second) == value) { + count++; + } + } + return count; +} +} // namespace + +namespace { +int GetIntValueFromMetadataHelper( + const char* key, + const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, + int default_value) { + if (metadata.find(key) != metadata.end()) { + std::istringstream iss(ToString(metadata.find(key)->second)); + iss >> default_value; + gpr_log(GPR_INFO, "%s : %d", key, default_value); + } + + return default_value; +} + +int GetIntValueFromMetadata( + const char* key, + const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, + int default_value) { + return GetIntValueFromMetadataHelper(key, metadata, default_value); +} + +void ServerTryCancel(ServerContext* context) { + EXPECT_FALSE(context->IsCancelled()); + context->TryCancel(); + gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); + // Now wait until it's really canceled + while (!context->IsCancelled()) { + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000, GPR_TIMESPAN))); + } +} + +void ServerTryCancelNonblocking(ServerContext* context) { + EXPECT_FALSE(context->IsCancelled()); + context->TryCancel(); + gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); +} + } // namespace Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request, @@ -165,6 +221,166 @@ Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request, return Status::OK; } +Status TestServiceImpl::CheckClientInitialMetadata(ServerContext* context, + const SimpleRequest* request, + SimpleResponse* response) { + EXPECT_EQ(MetadataMatchCount(context->client_metadata(), + kCheckClientInitialMetadataKey, + kCheckClientInitialMetadataVal), + 1); + EXPECT_EQ(1u, + context->client_metadata().count(kCheckClientInitialMetadataKey)); + return Status::OK; +} + +void CallbackTestServiceImpl::Echo( + ServerContext* context, const EchoRequest* request, EchoResponse* response, + experimental::ServerCallbackRpcController* controller) { + // A bit of sleep to make sure that short deadline tests fail + if (request->has_param() && request->param().server_sleep_us() > 0) { + // Set an alarm for that much time + alarm_.experimental().Set( + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_micros(request->param().server_sleep_us(), + GPR_TIMESPAN)), + [this, context, request, response, controller](bool) { + EchoNonDelayed(context, request, response, controller); + }); + } else { + EchoNonDelayed(context, request, response, controller); + } +} + +void CallbackTestServiceImpl::CheckClientInitialMetadata( + ServerContext* context, const SimpleRequest* request, + SimpleResponse* response, + experimental::ServerCallbackRpcController* controller) { + EXPECT_EQ(MetadataMatchCount(context->client_metadata(), + kCheckClientInitialMetadataKey, + kCheckClientInitialMetadataVal), + 1); + EXPECT_EQ(1u, + context->client_metadata().count(kCheckClientInitialMetadataKey)); + controller->Finish(Status::OK); +} + +void CallbackTestServiceImpl::EchoNonDelayed( + ServerContext* context, const EchoRequest* request, EchoResponse* response, + experimental::ServerCallbackRpcController* controller) { + if (request->has_param() && request->param().server_die()) { + gpr_log(GPR_ERROR, "The request should not reach application handler."); + GPR_ASSERT(0); + } + if (request->has_param() && request->param().has_expected_error()) { + const auto& error = request->param().expected_error(); + controller->Finish(Status(static_cast<StatusCode>(error.code()), + error.error_message(), + error.binary_error_details())); + return; + } + int server_try_cancel = GetIntValueFromMetadata( + kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + if (server_try_cancel > DO_NOT_CANCEL) { + // Since this is a unary RPC, by the time this server handler is called, + // the 'request' message is already read from the client. So the scenarios + // in server_try_cancel don't make much sense. Just cancel the RPC as long + // as server_try_cancel is not DO_NOT_CANCEL + EXPECT_FALSE(context->IsCancelled()); + context->TryCancel(); + gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); + // Now wait until it's really canceled + + std::function<void(bool)> recurrence = [this, context, controller, + &recurrence](bool) { + if (!context->IsCancelled()) { + alarm_.experimental().Set( + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000, GPR_TIMESPAN)), + recurrence); + } else { + controller->Finish(Status::CANCELLED); + } + }; + recurrence(true); + return; + } + + gpr_log(GPR_DEBUG, "Request message was %s", request->message().c_str()); + response->set_message(request->message()); + MaybeEchoDeadline(context, request, response); + if (host_) { + response->mutable_param()->set_host(*host_); + } + if (request->has_param() && request->param().client_cancel_after_us()) { + { + std::unique_lock<std::mutex> lock(mu_); + signal_client_ = true; + } + std::function<void(bool)> recurrence = [this, context, request, controller, + &recurrence](bool) { + if (!context->IsCancelled()) { + alarm_.experimental().Set( + gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(request->param().client_cancel_after_us(), + GPR_TIMESPAN)), + recurrence); + } else { + controller->Finish(Status::CANCELLED); + } + }; + recurrence(true); + return; + } else if (request->has_param() && + request->param().server_cancel_after_us()) { + alarm_.experimental().Set( + gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(request->param().server_cancel_after_us(), + GPR_TIMESPAN)), + [controller](bool) { controller->Finish(Status::CANCELLED); }); + return; + } else if (!request->has_param() || + !request->param().skip_cancelled_check()) { + EXPECT_FALSE(context->IsCancelled()); + } + + if (request->has_param() && request->param().echo_metadata()) { + const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata = + context->client_metadata(); + for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator + iter = client_metadata.begin(); + iter != client_metadata.end(); ++iter) { + context->AddTrailingMetadata(ToString(iter->first), + ToString(iter->second)); + } + // Terminate rpc with error and debug info in trailer. + if (request->param().debug_info().stack_entries_size() || + !request->param().debug_info().detail().empty()) { + grpc::string serialized_debug_info = + request->param().debug_info().SerializeAsString(); + context->AddTrailingMetadata(kDebugInfoTrailerKey, serialized_debug_info); + controller->Finish(Status::CANCELLED); + return; + } + } + if (request->has_param() && + (request->param().expected_client_identity().length() > 0 || + request->param().check_auth_context())) { + CheckServerAuthContext(context, + request->param().expected_transport_security_type(), + request->param().expected_client_identity()); + } + if (request->has_param() && request->param().response_message_length() > 0) { + response->set_message( + grpc::string(request->param().response_message_length(), '\0')); + } + if (request->has_param() && request->param().echo_peer()) { + response->mutable_param()->set_peer(context->peer()); + } + controller->Finish(Status::OK); +} + // Unimplemented is left unimplemented to test the returned error. Status TestServiceImpl::RequestStream(ServerContext* context, @@ -192,7 +408,7 @@ Status TestServiceImpl::RequestStream(ServerContext* context, std::thread* server_try_cancel_thd = nullptr; if (server_try_cancel == CANCEL_DURING_PROCESSING) { server_try_cancel_thd = - new std::thread(&TestServiceImpl::ServerTryCancel, this, context); + new std::thread([context] { ServerTryCancel(context); }); } int num_msgs_read = 0; @@ -247,7 +463,7 @@ Status TestServiceImpl::ResponseStream(ServerContext* context, std::thread* server_try_cancel_thd = nullptr; if (server_try_cancel == CANCEL_DURING_PROCESSING) { server_try_cancel_thd = - new std::thread(&TestServiceImpl::ServerTryCancel, this, context); + new std::thread([context] { ServerTryCancel(context); }); } for (int i = 0; i < server_responses_to_send; i++) { @@ -298,7 +514,7 @@ Status TestServiceImpl::BidiStream( std::thread* server_try_cancel_thd = nullptr; if (server_try_cancel == CANCEL_DURING_PROCESSING) { server_try_cancel_thd = - new std::thread(&TestServiceImpl::ServerTryCancel, this, context); + new std::thread([context] { ServerTryCancel(context); }); } // kServerFinishAfterNReads suggests after how many reads, the server should @@ -332,28 +548,244 @@ Status TestServiceImpl::BidiStream( return Status::OK; } -int TestServiceImpl::GetIntValueFromMetadata( - const char* key, - const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, - int default_value) { - if (metadata.find(key) != metadata.end()) { - std::istringstream iss(ToString(metadata.find(key)->second)); - iss >> default_value; - gpr_log(GPR_INFO, "%s : %d", key, default_value); - } +experimental::ServerReadReactor<EchoRequest, EchoResponse>* +CallbackTestServiceImpl::RequestStream() { + class Reactor : public ::grpc::experimental::ServerReadReactor<EchoRequest, + EchoResponse> { + public: + Reactor() {} + void OnStarted(ServerContext* context, EchoResponse* response) override { + ctx_ = context; + response_ = response; + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by + // the server by calling ServerContext::TryCancel() depending on the + // value: + // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server + // reads any message from the client CANCEL_DURING_PROCESSING: The RPC + // is cancelled while the server is reading messages from the client + // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads + // all the messages from the client + server_try_cancel_ = GetIntValueFromMetadata( + kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + + response_->set_message(""); + + if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + return; + } + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + ctx_->TryCancel(); + // Don't wait for it here + } + + StartRead(&request_); + } + void OnDone() override { delete this; } + void OnCancel() override { FinishOnce(Status::CANCELLED); } + void OnReadDone(bool ok) override { + if (ok) { + response_->mutable_message()->append(request_.message()); + num_msgs_read_++; + StartRead(&request_); + } else { + gpr_log(GPR_INFO, "Read: %d messages", num_msgs_read_); + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + // Let OnCancel recover this + return; + } + if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + return; + } + FinishOnce(Status::OK); + } + } - return default_value; + private: + void FinishOnce(const Status& s) { + std::lock_guard<std::mutex> l(finish_mu_); + if (!finished_) { + Finish(s); + finished_ = true; + } + } + + ServerContext* ctx_; + EchoResponse* response_; + EchoRequest request_; + int num_msgs_read_{0}; + int server_try_cancel_; + std::mutex finish_mu_; + bool finished_{false}; + }; + + return new Reactor; } -void TestServiceImpl::ServerTryCancel(ServerContext* context) { - EXPECT_FALSE(context->IsCancelled()); - context->TryCancel(); - gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); - // Now wait until it's really canceled - while (!context->IsCancelled()) { - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(1000, GPR_TIMESPAN))); - } +// Return 'kNumResponseStreamMsgs' messages. +// TODO(yangg) make it generic by adding a parameter into EchoRequest +experimental::ServerWriteReactor<EchoRequest, EchoResponse>* +CallbackTestServiceImpl::ResponseStream() { + class Reactor + : public ::grpc::experimental::ServerWriteReactor<EchoRequest, + EchoResponse> { + public: + Reactor() {} + void OnStarted(ServerContext* context, + const EchoRequest* request) override { + ctx_ = context; + request_ = request; + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by + // the server by calling ServerContext::TryCancel() depending on the + // value: + // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server + // reads any message from the client CANCEL_DURING_PROCESSING: The RPC + // is cancelled while the server is reading messages from the client + // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads + // all the messages from the client + server_try_cancel_ = GetIntValueFromMetadata( + kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + server_coalescing_api_ = GetIntValueFromMetadata( + kServerUseCoalescingApi, context->client_metadata(), 0); + server_responses_to_send_ = GetIntValueFromMetadata( + kServerResponseStreamsToSend, context->client_metadata(), + kServerDefaultResponseStreamsToSend); + if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + return; + } + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + ctx_->TryCancel(); + } + if (num_msgs_sent_ < server_responses_to_send_) { + NextWrite(); + } + } + void OnDone() override { delete this; } + void OnCancel() override { FinishOnce(Status::CANCELLED); } + void OnWriteDone(bool ok) override { + if (num_msgs_sent_ < server_responses_to_send_) { + NextWrite(); + } else if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + // Let OnCancel recover this + } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + } else { + FinishOnce(Status::OK); + } + } + + private: + void FinishOnce(const Status& s) { + std::lock_guard<std::mutex> l(finish_mu_); + if (!finished_) { + Finish(s); + finished_ = true; + } + } + + void NextWrite() { + response_.set_message(request_->message() + + grpc::to_string(num_msgs_sent_)); + if (num_msgs_sent_ == server_responses_to_send_ - 1 && + server_coalescing_api_ != 0) { + num_msgs_sent_++; + StartWriteLast(&response_, WriteOptions()); + } else { + num_msgs_sent_++; + StartWrite(&response_); + } + } + ServerContext* ctx_; + const EchoRequest* request_; + EchoResponse response_; + int num_msgs_sent_{0}; + int server_try_cancel_; + int server_coalescing_api_; + int server_responses_to_send_; + std::mutex finish_mu_; + bool finished_{false}; + }; + return new Reactor; +} + +experimental::ServerBidiReactor<EchoRequest, EchoResponse>* +CallbackTestServiceImpl::BidiStream() { + class Reactor : public ::grpc::experimental::ServerBidiReactor<EchoRequest, + EchoResponse> { + public: + Reactor() {} + void OnStarted(ServerContext* context) override { + ctx_ = context; + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by + // the server by calling ServerContext::TryCancel() depending on the + // value: + // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server + // reads any message from the client CANCEL_DURING_PROCESSING: The RPC + // is cancelled while the server is reading messages from the client + // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads + // all the messages from the client + server_try_cancel_ = GetIntValueFromMetadata( + kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + server_write_last_ = GetIntValueFromMetadata( + kServerFinishAfterNReads, context->client_metadata(), 0); + if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + return; + } + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + ctx_->TryCancel(); + } + + StartRead(&request_); + } + void OnDone() override { delete this; } + void OnCancel() override { FinishOnce(Status::CANCELLED); } + void OnReadDone(bool ok) override { + if (ok) { + num_msgs_read_++; + gpr_log(GPR_INFO, "recv msg %s", request_.message().c_str()); + response_.set_message(request_.message()); + if (num_msgs_read_ == server_write_last_) { + StartWriteLast(&response_, WriteOptions()); + } else { + StartWrite(&response_); + } + } else if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + // Let OnCancel handle this + } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + } else { + FinishOnce(Status::OK); + } + } + void OnWriteDone(bool ok) override { StartRead(&request_); } + + private: + void FinishOnce(const Status& s) { + std::lock_guard<std::mutex> l(finish_mu_); + if (!finished_) { + Finish(s); + finished_ = true; + } + } + + ServerContext* ctx_; + EchoRequest request_; + EchoResponse response_; + int num_msgs_read_{0}; + int server_try_cancel_; + int server_write_last_; + std::mutex finish_mu_; + bool finished_{false}; + }; + + return new Reactor; } } // namespace testing diff --git a/test/cpp/end2end/test_service_impl.h b/test/cpp/end2end/test_service_impl.h index 052543a03e..e36423d44e 100644 --- a/test/cpp/end2end/test_service_impl.h +++ b/test/cpp/end2end/test_service_impl.h @@ -22,6 +22,7 @@ #include <mutex> #include <grpc/grpc.h> +#include <grpcpp/alarm.h> #include <grpcpp/server_context.h> #include "src/proto/grpc/testing/echo.grpc.pb.h" @@ -35,6 +36,8 @@ 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"; +const char* const kCheckClientInitialMetadataKey = "custom_client_metadata"; +const char* const kCheckClientInitialMetadataVal = "Value for client metadata"; typedef enum { DO_NOT_CANCEL = 0, @@ -52,6 +55,10 @@ class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) override; + Status CheckClientInitialMetadata(ServerContext* context, + const SimpleRequest* request, + SimpleResponse* response) override; + // Unimplemented is left unimplemented to test the returned error. Status RequestStream(ServerContext* context, @@ -71,14 +78,48 @@ class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { } private: - int GetIntValueFromMetadata( - const char* key, - const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, - int default_value); + bool signal_client_; + std::mutex mu_; + std::unique_ptr<grpc::string> host_; +}; + +class CallbackTestServiceImpl + : public ::grpc::testing::EchoTestService::ExperimentalCallbackService { + public: + CallbackTestServiceImpl() : signal_client_(false), host_() {} + explicit CallbackTestServiceImpl(const grpc::string& host) + : signal_client_(false), host_(new grpc::string(host)) {} + + void Echo(ServerContext* context, const EchoRequest* request, + EchoResponse* response, + experimental::ServerCallbackRpcController* controller) override; + + void CheckClientInitialMetadata( + ServerContext* context, const SimpleRequest* request, + SimpleResponse* response, + experimental::ServerCallbackRpcController* controller) override; - void ServerTryCancel(ServerContext* context); + experimental::ServerReadReactor<EchoRequest, EchoResponse>* RequestStream() + override; + + experimental::ServerWriteReactor<EchoRequest, EchoResponse>* ResponseStream() + override; + + experimental::ServerBidiReactor<EchoRequest, EchoResponse>* BidiStream() + override; + + // Unimplemented is left unimplemented to test the returned error. + bool signal_client() { + std::unique_lock<std::mutex> lock(mu_); + return signal_client_; + } private: + void EchoNonDelayed(ServerContext* context, const EchoRequest* request, + EchoResponse* response, + experimental::ServerCallbackRpcController* controller); + + Alarm alarm_; bool signal_client_; std::mutex mu_; std::unique_ptr<grpc::string> host_; diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index 1a5ed28a2c..e30ce0dbcb 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -429,7 +429,7 @@ TYPED_TEST(AsyncClientEnd2endTest, ThreadStress) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc index 664504a090..7339402830 100644 --- a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc +++ b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc @@ -370,7 +370,7 @@ TEST_F(StatsPluginEnd2EndTest, RequestReceivedMessagesPerRpc) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/interop/client_helper.h b/test/cpp/interop/client_helper.h index eada2f671f..7dee85cc98 100644 --- a/test/cpp/interop/client_helper.h +++ b/test/cpp/interop/client_helper.h @@ -19,10 +19,12 @@ #ifndef GRPC_TEST_CPP_INTEROP_CLIENT_HELPER_H #define GRPC_TEST_CPP_INTEROP_CLIENT_HELPER_H +#include <functional> #include <memory> #include <unordered_map> #include <grpcpp/channel.h> +#include <grpcpp/client_context.h> #include "src/core/lib/surface/call_test_only.h" diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc index a99cf8122f..4ff153f980 100644 --- a/test/cpp/interop/interop_client.cc +++ b/test/cpp/interop/interop_client.cc @@ -76,7 +76,7 @@ void UnaryCompressionChecks(const InteropClientContextInspector& inspector, InteropClient::ServiceStub::ServiceStub( ChannelCreationFunc channel_creation_func, bool new_stub_every_call) - : channel_creation_func_(channel_creation_func), + : channel_creation_func_(std::move(channel_creation_func)), channel_(channel_creation_func_()), new_stub_every_call_(new_stub_every_call) { // If new_stub_every_call is false, then this is our chance to initialize @@ -112,7 +112,7 @@ void InteropClient::ServiceStub::ResetChannel() { InteropClient::InteropClient(ChannelCreationFunc channel_creation_func, bool new_stub_every_test_case, bool do_not_abort_on_transient_failures) - : serviceStub_(channel_creation_func, new_stub_every_test_case), + : serviceStub_(std::move(channel_creation_func), new_stub_every_test_case), do_not_abort_on_transient_failures_(do_not_abort_on_transient_failures) {} bool InteropClient::AssertStatusOk(const Status& s, diff --git a/test/cpp/interop/stress_interop_client.cc b/test/cpp/interop/stress_interop_client.cc index 7dc1956f78..5bbe913365 100644 --- a/test/cpp/interop/stress_interop_client.cc +++ b/test/cpp/interop/stress_interop_client.cc @@ -73,7 +73,7 @@ StressTestInteropClient::StressTestInteropClient( long sleep_duration_ms, bool do_not_abort_on_transient_failures) : test_id_(test_id), server_address_(server_address), - channel_creation_func_(channel_creation_func), + channel_creation_func_(std::move(channel_creation_func)), interop_client_(new InteropClient(channel_creation_func_, false, do_not_abort_on_transient_failures)), test_selector_(test_selector), diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index 1f7831096c..8d12606434 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -135,7 +135,8 @@ static void BM_LameChannelCallCreateCpp(benchmark::State& state) { "", grpc_lame_client_channel_create("localhost:1234", GRPC_STATUS_UNAUTHENTICATED, "blah"), - nullptr)); + std::vector<std::unique_ptr< + grpc::experimental::ClientInterceptorFactoryInterface>>())); grpc::CompletionQueue cq; grpc::testing::EchoRequest send_request; grpc::testing::EchoResponse recv_response; @@ -468,7 +469,7 @@ class NoOp { class SendEmptyMetadata { public: - SendEmptyMetadata() { + SendEmptyMetadata() : op_payload_(nullptr) { memset(&op_, 0, sizeof(op_)); op_.on_complete = GRPC_CLOSURE_INIT(&closure_, DoNothing, nullptr, grpc_schedule_on_exec_ctx); diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc index ba4b57ad22..85d233dd26 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc @@ -778,8 +778,7 @@ static void free_timeout(void* p) { gpr_free(p); } // Benchmark the current on_initial_header implementation static void OnInitialHeader(void* user_data, grpc_mdelem md) { // Setup for benchmark. This will bloat the absolute values of this benchmark - grpc_chttp2_incoming_metadata_buffer buffer; - grpc_chttp2_incoming_metadata_buffer_init(&buffer, (gpr_arena*)user_data); + grpc_chttp2_incoming_metadata_buffer buffer((gpr_arena*)user_data); bool seen_error = false; // Below here is the code we actually care about benchmarking @@ -822,7 +821,6 @@ static void OnInitialHeader(void* user_data, grpc_mdelem md) { GPR_ASSERT(0); } } - grpc_chttp2_incoming_metadata_buffer_destroy(&buffer); } // Benchmark timeout handling diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc index 189923a841..650152ecc0 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc @@ -54,7 +54,8 @@ class DummyEndpoint : public grpc_endpoint { destroy, get_resource_user, get_peer, - get_fd}; + get_fd, + can_track_err}; grpc_endpoint::vtable = &my_vtable; ru_ = grpc_resource_user_create(Library::get().rq(), "dummy_endpoint"); } @@ -125,6 +126,7 @@ class DummyEndpoint : public grpc_endpoint { } static char* get_peer(grpc_endpoint* ep) { return gpr_strdup("test"); } static int get_fd(grpc_endpoint* ep) { return 0; } + static bool can_track_err(grpc_endpoint* ep) { return false; } }; class Fixture { @@ -262,7 +264,7 @@ static void BM_StreamCreateDestroy(benchmark::State& state) { Fixture f(grpc::ChannelArguments(), true); Stream s(&f); grpc_transport_stream_op_batch op; - grpc_transport_stream_op_batch_payload op_payload; + grpc_transport_stream_op_batch_payload op_payload(nullptr); memset(&op, 0, sizeof(op)); op.cancel_stream = true; op.payload = &op_payload; @@ -308,8 +310,7 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State& state) { Fixture f(grpc::ChannelArguments(), true); Stream s(&f); grpc_transport_stream_op_batch op; - grpc_transport_stream_op_batch_payload op_payload; - memset(&op_payload, 0, sizeof(op_payload)); + grpc_transport_stream_op_batch_payload op_payload(nullptr); std::unique_ptr<Closure> start; std::unique_ptr<Closure> done; @@ -360,8 +361,7 @@ static void BM_TransportEmptyOp(benchmark::State& state) { Stream s(&f); s.Init(state); grpc_transport_stream_op_batch op; - grpc_transport_stream_op_batch_payload op_payload; - memset(&op_payload, 0, sizeof(op_payload)); + grpc_transport_stream_op_batch_payload op_payload(nullptr); auto reset_op = [&]() { memset(&op, 0, sizeof(op)); op.payload = &op_payload; @@ -393,8 +393,7 @@ static void BM_TransportStreamSend(benchmark::State& state) { auto s = std::unique_ptr<Stream>(new Stream(&f)); s->Init(state); grpc_transport_stream_op_batch op; - grpc_transport_stream_op_batch_payload op_payload; - memset(&op_payload, 0, sizeof(op_payload)); + grpc_transport_stream_op_batch_payload op_payload(nullptr); auto reset_op = [&]() { memset(&op, 0, sizeof(op)); op.payload = &op_payload; @@ -526,8 +525,7 @@ static void BM_TransportStreamRecv(benchmark::State& state) { Fixture f(grpc::ChannelArguments(), true); Stream s(&f); s.Init(state); - grpc_transport_stream_op_batch_payload op_payload; - memset(&op_payload, 0, sizeof(op_payload)); + grpc_transport_stream_op_batch_payload op_payload(nullptr); grpc_transport_stream_op_batch op; grpc_core::OrphanablePtr<grpc_core::ByteStream> recv_stream; grpc_slice incoming_data = CreateIncomingDataSlice(state.range(0), 16384); diff --git a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc index 85767c8758..dca97c85b1 100644 --- a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc +++ b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc @@ -94,6 +94,7 @@ static const grpc_event_engine_vtable* init_engine_vtable(bool) { g_vtable.pollset_destroy = pollset_destroy; g_vtable.pollset_work = pollset_work; g_vtable.pollset_kick = pollset_kick; + g_vtable.shutdown_background_closure = [] {}; g_vtable.shutdown_engine = [] {}; return &g_vtable; diff --git a/test/cpp/microbenchmarks/fullstack_fixtures.h b/test/cpp/microbenchmarks/fullstack_fixtures.h index e57eb6ddd1..6bbf553bbd 100644 --- a/test/cpp/microbenchmarks/fullstack_fixtures.h +++ b/test/cpp/microbenchmarks/fullstack_fixtures.h @@ -200,7 +200,7 @@ class EndpointPairFixture : public BaseFixture { } grpc_server_setup_transport(server_->c_server(), server_transport_, - nullptr, server_args, 0); + nullptr, server_args, nullptr); grpc_chttp2_transport_start_reading(server_transport_, nullptr, nullptr); } @@ -218,7 +218,10 @@ class EndpointPairFixture : public BaseFixture { "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, client_transport_); grpc_chttp2_transport_start_reading(client_transport_, nullptr, nullptr); - channel_ = CreateChannelInternal("", channel, nullptr); + channel_ = CreateChannelInternal( + "", channel, + std::vector<std::unique_ptr< + experimental::ClientInterceptorFactoryInterface>>()); } } diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index fc6721d0ba..3eb0e7d725 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -838,7 +838,7 @@ int main(int argc, char** argv) { gpr_log(GPR_INFO, "GRPC_DNS_RESOLVER != ares: %s.", resolver); } gpr_free(resolver); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); auto result = RUN_ALL_TESTS(); // Test sequential and nested inits and shutdowns. diff --git a/test/cpp/naming/cancel_ares_query_test.cc b/test/cpp/naming/cancel_ares_query_test.cc index dec7c171dc..3e789f0b14 100644 --- a/test/cpp/naming/cancel_ares_query_test.cc +++ b/test/cpp/naming/cancel_ares_query_test.cc @@ -260,8 +260,15 @@ TEST(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) { grpc_pollset_set_destroy(fake_other_pollset_set); } -TEST(CancelDuringAresQuery, - TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful) { +// Settings for TestCancelDuringActiveQuery test +typedef enum { + NONE, + SHORT, + ZERO, +} cancellation_test_query_timeout_setting; + +void TestCancelDuringActiveQuery( + cancellation_test_query_timeout_setting query_timeout_setting) { // Start up fake non responsive DNS server int fake_dns_port = grpc_pick_unused_port_or_die(); FakeNonResponsiveDNSServer fake_dns_server(fake_dns_port); @@ -271,9 +278,33 @@ TEST(CancelDuringAresQuery, &client_target, "dns://[::1]:%d/dont-care-since-wont-be-resolved.test.com:1234", fake_dns_port)); + gpr_log(GPR_DEBUG, "TestCancelActiveDNSQuery. query timeout setting: %d", + query_timeout_setting); + grpc_channel_args* client_args = nullptr; + grpc_status_code expected_status_code = GRPC_STATUS_OK; + if (query_timeout_setting == NONE) { + expected_status_code = GRPC_STATUS_DEADLINE_EXCEEDED; + client_args = nullptr; + } else if (query_timeout_setting == SHORT) { + expected_status_code = GRPC_STATUS_UNAVAILABLE; + grpc_arg arg; + arg.type = GRPC_ARG_INTEGER; + arg.key = const_cast<char*>(GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS); + arg.value.integer = + 1; // Set this shorter than the call deadline so that it goes off. + client_args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); + } else if (query_timeout_setting == ZERO) { + expected_status_code = GRPC_STATUS_DEADLINE_EXCEEDED; + grpc_arg arg; + arg.type = GRPC_ARG_INTEGER; + arg.key = const_cast<char*>(GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS); + arg.value.integer = 0; // Set this to zero to disable query timeouts. + client_args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); + } else { + abort(); + } grpc_channel* client = - grpc_insecure_channel_create(client_target, - /* client_args */ nullptr, nullptr); + grpc_insecure_channel_create(client_target, client_args, nullptr); gpr_free(client_target); grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr); cq_verifier* cqv = cq_verifier_create(cq); @@ -325,8 +356,9 @@ TEST(CancelDuringAresQuery, EXPECT_EQ(GRPC_CALL_OK, error); CQ_EXPECT_COMPLETION(cqv, Tag(1), 1); cq_verify(cqv); - EXPECT_EQ(status, GRPC_STATUS_DEADLINE_EXCEEDED); + EXPECT_EQ(status, expected_status_code); // Teardown + grpc_channel_args_destroy(client_args); grpc_slice_unref(details); gpr_free((void*)error_string); grpc_metadata_array_destroy(&initial_metadata_recv); @@ -338,10 +370,27 @@ TEST(CancelDuringAresQuery, EndTest(client, cq); } +TEST(CancelDuringAresQuery, + TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful) { + TestCancelDuringActiveQuery(NONE /* don't set query timeouts */); +} + +TEST( + CancelDuringAresQuery, + TestHitDeadlineAndDestroyChannelDuringAresResolutionWithQueryTimeoutIsGraceful) { + TestCancelDuringActiveQuery(SHORT /* set short query timeout */); +} + +TEST( + CancelDuringAresQuery, + TestHitDeadlineAndDestroyChannelDuringAresResolutionWithZeroQueryTimeoutIsGraceful) { + TestCancelDuringActiveQuery(ZERO /* disable query timeouts */); +} + } // namespace int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); gpr_setenv("GRPC_DNS_RESOLVER", "ares"); // Sanity check the time that it takes to run the test diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc index 3dc6e7178c..fe6fcb8d9c 100644 --- a/test/cpp/naming/resolver_component_test.cc +++ b/test/cpp/naming/resolver_component_test.cc @@ -477,7 +477,7 @@ TEST(ResolverComponentTest, TestResolvesRelevantRecordsWithConcurrentFdStress) { int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); ParseCommandLineFlags(&argc, &argv, true); if (FLAGS_target_name == "") { diff --git a/test/cpp/performance/writes_per_rpc_test.cc b/test/cpp/performance/writes_per_rpc_test.cc index 32eab1fc44..7b22f23cf0 100644 --- a/test/cpp/performance/writes_per_rpc_test.cc +++ b/test/cpp/performance/writes_per_rpc_test.cc @@ -100,7 +100,7 @@ class EndpointPairFixture { } grpc_server_setup_transport(server_->c_server(), transport, nullptr, - server_args, 0); + server_args, nullptr); grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); } @@ -118,7 +118,10 @@ class EndpointPairFixture { "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, transport); grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); - channel_ = CreateChannelInternal("", channel, nullptr); + channel_ = CreateChannelInternal( + "", channel, + std::vector<std::unique_ptr< + experimental::ClientInterceptorFactoryInterface>>()); } } @@ -252,7 +255,7 @@ TEST(WritesPerRpcTest, UnaryPingPong) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD index 2ef7441371..626ac5f3f2 100644 --- a/test/cpp/qps/BUILD +++ b/test/cpp/qps/BUILD @@ -36,6 +36,7 @@ grpc_cc_library( "qps_server_builder.cc", "qps_worker.cc", "server_async.cc", + "server_callback.cc", "server_sync.cc", ], hdrs = [ @@ -169,7 +170,7 @@ grpc_cc_test( grpc_cc_test( name = "qps_openloop_test", srcs = ["qps_openloop_test.cc"], - data = ["//third_party/toolchains:RBE_USE_MACHINE_TYPE_LARGE"], + exec_compatible_with = ["//third_party/toolchains/machine_size:large"], deps = [ ":benchmark_config", ":driver_impl", diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index 4ed34e0405..668d941916 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -94,9 +94,11 @@ class ClientRequestCreator<ByteBuffer> { public: ClientRequestCreator(ByteBuffer* req, const PayloadConfig& payload_config) { if (payload_config.has_bytebuf_params()) { - std::unique_ptr<char[]> buf( - new char[payload_config.bytebuf_params().req_size()]); - Slice slice(buf.get(), payload_config.bytebuf_params().req_size()); + size_t req_sz = + static_cast<size_t>(payload_config.bytebuf_params().req_size()); + std::unique_ptr<char[]> buf(new char[req_sz]); + memset(buf.get(), 0, req_sz); + Slice slice(buf.get(), req_sz); *req = ByteBuffer(&slice, 1); } else { GPR_ASSERT(false); // not appropriate for this specialization diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index 11cfb4aa05..181e11f12b 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -95,6 +95,17 @@ static deque<string> get_workers(const string& env_name) { return out; } +std::string GetCredType( + const std::string& worker_addr, + const std::map<std::string, std::string>& per_worker_credential_types, + const std::string& credential_type) { + auto it = per_worker_credential_types.find(worker_addr); + if (it != per_worker_credential_types.end()) { + return it->second; + } + return credential_type; +} + // helpers for postprocess_scenario_result static double WallTime(const ClientStats& s) { return s.time_elapsed(); } static double SystemTime(const ClientStats& s) { return s.time_system(); } @@ -198,8 +209,9 @@ std::unique_ptr<ScenarioResult> RunScenario( const ServerConfig& initial_server_config, size_t num_servers, int warmup_seconds, int benchmark_seconds, int spawn_local_worker_count, const grpc::string& qps_server_target_override, - const grpc::string& credential_type, bool run_inproc, - int32_t median_latency_collection_interval_millis) { + const grpc::string& credential_type, + const std::map<std::string, std::string>& per_worker_credential_types, + bool run_inproc, int32_t median_latency_collection_interval_millis) { if (run_inproc) { g_inproc_servers = new std::vector<grpc::testing::Server*>; } @@ -278,7 +290,9 @@ std::unique_ptr<ScenarioResult> RunScenario( if (!run_inproc) { servers[i].stub = WorkerService::NewStub(CreateChannel( workers[i], GetCredentialsProvider()->GetChannelCredentials( - credential_type, &channel_args))); + GetCredType(workers[i], per_worker_credential_types, + credential_type), + &channel_args))); } else { servers[i].stub = WorkerService::NewStub( local_workers[i]->InProcessChannel(channel_args)); @@ -335,9 +349,11 @@ std::unique_ptr<ScenarioResult> RunScenario( gpr_log(GPR_INFO, "Starting client on %s (worker #%" PRIuPTR ")", worker.c_str(), i + num_servers); if (!run_inproc) { - clients[i].stub = WorkerService::NewStub( - CreateChannel(worker, GetCredentialsProvider()->GetChannelCredentials( - credential_type, &channel_args))); + clients[i].stub = WorkerService::NewStub(CreateChannel( + worker, + GetCredentialsProvider()->GetChannelCredentials( + GetCredType(worker, per_worker_credential_types, credential_type), + &channel_args))); } else { clients[i].stub = WorkerService::NewStub( local_workers[i + num_servers]->InProcessChannel(channel_args)); @@ -529,7 +545,9 @@ std::unique_ptr<ScenarioResult> RunScenario( return result; } -bool RunQuit(const grpc::string& credential_type) { +bool RunQuit( + const grpc::string& credential_type, + const std::map<std::string, std::string>& per_worker_credential_types) { // Get client, server lists bool result = true; auto workers = get_workers("QPS_WORKERS"); @@ -541,7 +559,9 @@ bool RunQuit(const grpc::string& credential_type) { for (size_t i = 0; i < workers.size(); i++) { auto stub = WorkerService::NewStub(CreateChannel( workers[i], GetCredentialsProvider()->GetChannelCredentials( - credential_type, &channel_args))); + GetCredType(workers[i], per_worker_credential_types, + credential_type), + &channel_args))); Void dummy; grpc::ClientContext ctx; ctx.set_wait_for_ready(true); diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h index cda89f7ddf..568871d2da 100644 --- a/test/cpp/qps/driver.h +++ b/test/cpp/qps/driver.h @@ -32,10 +32,13 @@ std::unique_ptr<ScenarioResult> RunScenario( const grpc::testing::ServerConfig& server_config, size_t num_servers, int warmup_seconds, int benchmark_seconds, int spawn_local_worker_count, const grpc::string& qps_server_target_override, - const grpc::string& credential_type, bool run_inproc, - int32_t median_latency_collection_interval_millis); + const grpc::string& credential_type, + const std::map<std::string, std::string>& per_worker_credential_types, + bool run_inproc, int32_t median_latency_collection_interval_millis); -bool RunQuit(const grpc::string& credential_type); +bool RunQuit( + const grpc::string& credential_type, + const std::map<std::string, std::string>& per_worker_credential_types); } // namespace testing } // namespace grpc diff --git a/test/cpp/qps/inproc_sync_unary_ping_pong_test.cc b/test/cpp/qps/inproc_sync_unary_ping_pong_test.cc index 56d1730252..6257e42ebf 100644 --- a/test/cpp/qps/inproc_sync_unary_ping_pong_test.cc +++ b/test/cpp/qps/inproc_sync_unary_ping_pong_test.cc @@ -48,7 +48,7 @@ static void RunSynchronousUnaryPingPong() { const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2, "", - kInsecureCredentialsType, true, 0); + kInsecureCredentialsType, {}, true, 0); GetReporter()->ReportQPS(*result); GetReporter()->ReportLatency(*result); diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc index eaa0dd992c..1d67e79b86 100644 --- a/test/cpp/qps/qps_json_driver.cc +++ b/test/cpp/qps/qps_json_driver.cc @@ -65,6 +65,16 @@ DEFINE_string(json_file_out, "", "File to write the JSON output to."); DEFINE_string(credential_type, grpc::testing::kInsecureCredentialsType, "Credential type for communication with workers"); +DEFINE_string( + per_worker_credential_types, "", + "A map of QPS worker addresses to credential types. When creating a " + "channel to a QPS worker's driver port, the qps_json_driver first checks " + "if the 'name:port' string is in the map, and it uses the corresponding " + "credential type if so. If the QPS worker's 'name:port' string is not " + "in the map, then the driver -> worker channel will be created with " + "the credentials specified in --credential_type. The value of this flag " + "is a semicolon-separated list of map entries, where each map entry is " + "a comma-separated pair."); DEFINE_bool(run_inproc, false, "Perform an in-process transport test"); DEFINE_int32( median_latency_collection_interval_millis, 0, @@ -75,16 +85,53 @@ DEFINE_int32( namespace grpc { namespace testing { -static std::unique_ptr<ScenarioResult> RunAndReport(const Scenario& scenario, - bool* success) { +static std::map<std::string, std::string> +ConstructPerWorkerCredentialTypesMap() { + // Parse a list of the form: "addr1,cred_type1;addr2,cred_type2;..." into + // a map. + std::string remaining = FLAGS_per_worker_credential_types; + std::map<std::string, std::string> out; + while (!remaining.empty()) { + size_t next_semicolon = remaining.find(';'); + std::string next_entry = remaining.substr(0, next_semicolon); + if (next_semicolon == std::string::npos) { + remaining = ""; + } else { + remaining = remaining.substr(next_semicolon + 1, std::string::npos); + } + size_t comma = next_entry.find(','); + if (comma == std::string::npos) { + gpr_log(GPR_ERROR, + "Expectd --per_worker_credential_types to be a list " + "of the form: 'addr1,cred_type1;addr2,cred_type2;...' " + "into."); + abort(); + } + std::string addr = next_entry.substr(0, comma); + std::string cred_type = next_entry.substr(comma + 1, std::string::npos); + if (out.find(addr) != out.end()) { + gpr_log(GPR_ERROR, + "Found duplicate addr in per_worker_credential_types."); + abort(); + } + out[addr] = cred_type; + } + return out; +} + +static std::unique_ptr<ScenarioResult> RunAndReport( + const Scenario& scenario, + const std::map<std::string, std::string>& per_worker_credential_types, + bool* success) { std::cerr << "RUNNING SCENARIO: " << scenario.name() << "\n"; - auto result = RunScenario( - scenario.client_config(), scenario.num_clients(), - scenario.server_config(), scenario.num_servers(), - scenario.warmup_seconds(), scenario.benchmark_seconds(), - !FLAGS_run_inproc ? scenario.spawn_local_worker_count() : -2, - FLAGS_qps_server_target_override, FLAGS_credential_type, FLAGS_run_inproc, - FLAGS_median_latency_collection_interval_millis); + auto result = + RunScenario(scenario.client_config(), scenario.num_clients(), + scenario.server_config(), scenario.num_servers(), + scenario.warmup_seconds(), scenario.benchmark_seconds(), + !FLAGS_run_inproc ? scenario.spawn_local_worker_count() : -2, + FLAGS_qps_server_target_override, FLAGS_credential_type, + per_worker_credential_types, FLAGS_run_inproc, + FLAGS_median_latency_collection_interval_millis); // Amend the result with scenario config. Eventually we should adjust // RunScenario contract so we don't need to touch the result here. @@ -115,21 +162,26 @@ static std::unique_ptr<ScenarioResult> RunAndReport(const Scenario& scenario, return result; } -static double GetCpuLoad(Scenario* scenario, double offered_load, - bool* success) { +static double GetCpuLoad( + Scenario* scenario, double offered_load, + const std::map<std::string, std::string>& per_worker_credential_types, + bool* success) { scenario->mutable_client_config() ->mutable_load_params() ->mutable_poisson() ->set_offered_load(offered_load); - auto result = RunAndReport(*scenario, success); + auto result = RunAndReport(*scenario, per_worker_credential_types, success); return result->summary().server_cpu_usage(); } -static double BinarySearch(Scenario* scenario, double targeted_cpu_load, - double low, double high, bool* success) { +static double BinarySearch( + Scenario* scenario, double targeted_cpu_load, double low, double high, + const std::map<std::string, std::string>& per_worker_credential_types, + bool* success) { while (low <= high * (1 - FLAGS_error_tolerance)) { double mid = low + (high - low) / 2; - double current_cpu_load = GetCpuLoad(scenario, mid, success); + double current_cpu_load = + GetCpuLoad(scenario, mid, per_worker_credential_types, success); gpr_log(GPR_DEBUG, "Binary Search: current_offered_load %.0f", mid); if (!*success) { gpr_log(GPR_ERROR, "Client/Server Failure"); @@ -145,12 +197,14 @@ static double BinarySearch(Scenario* scenario, double targeted_cpu_load, return low; } -static double SearchOfferedLoad(double initial_offered_load, - double targeted_cpu_load, Scenario* scenario, - bool* success) { +static double SearchOfferedLoad( + double initial_offered_load, double targeted_cpu_load, Scenario* scenario, + const std::map<std::string, std::string>& per_worker_credential_types, + bool* success) { std::cerr << "RUNNING SCENARIO: " << scenario->name() << "\n"; double current_offered_load = initial_offered_load; - double current_cpu_load = GetCpuLoad(scenario, current_offered_load, success); + double current_cpu_load = GetCpuLoad(scenario, current_offered_load, + per_worker_credential_types, success); if (current_cpu_load > targeted_cpu_load) { gpr_log(GPR_ERROR, "Initial offered load too high"); return -1; @@ -158,14 +212,15 @@ static double SearchOfferedLoad(double initial_offered_load, while (*success && (current_cpu_load < targeted_cpu_load)) { current_offered_load *= 2; - current_cpu_load = GetCpuLoad(scenario, current_offered_load, success); + current_cpu_load = GetCpuLoad(scenario, current_offered_load, + per_worker_credential_types, success); gpr_log(GPR_DEBUG, "Binary Search: current_offered_load %.0f", current_offered_load); } double targeted_offered_load = BinarySearch(scenario, targeted_cpu_load, current_offered_load / 2, - current_offered_load, success); + current_offered_load, per_worker_credential_types, success); return targeted_offered_load; } @@ -183,6 +238,7 @@ static bool QpsDriver() { abort(); } + auto per_worker_credential_types = ConstructPerWorkerCredentialTypesMap(); if (scfile) { // Read the json data from disk FILE* json_file = fopen(FLAGS_scenarios_file.c_str(), "r"); @@ -198,7 +254,7 @@ static bool QpsDriver() { } else if (scjson) { json = FLAGS_scenarios_json.c_str(); } else if (FLAGS_quit) { - return RunQuit(FLAGS_credential_type); + return RunQuit(FLAGS_credential_type, per_worker_credential_types); } // Parse into an array of scenarios @@ -212,15 +268,16 @@ static bool QpsDriver() { for (int i = 0; i < scenarios.scenarios_size(); i++) { if (FLAGS_search_param == "") { const Scenario& scenario = scenarios.scenarios(i); - RunAndReport(scenario, &success); + RunAndReport(scenario, per_worker_credential_types, &success); } else { if (FLAGS_search_param == "offered_load") { Scenario* scenario = scenarios.mutable_scenarios(i); - double targeted_offered_load = - SearchOfferedLoad(FLAGS_initial_search_value, - FLAGS_targeted_cpu_load, scenario, &success); + double targeted_offered_load = SearchOfferedLoad( + FLAGS_initial_search_value, FLAGS_targeted_cpu_load, scenario, + per_worker_credential_types, &success); gpr_log(GPR_INFO, "targeted_offered_load %f", targeted_offered_load); - GetCpuLoad(scenario, targeted_offered_load, &success); + GetCpuLoad(scenario, targeted_offered_load, per_worker_credential_types, + &success); } else { gpr_log(GPR_ERROR, "Unimplemented search param"); } diff --git a/test/cpp/qps/qps_openloop_test.cc b/test/cpp/qps/qps_openloop_test.cc index 6044f4265a..68062e66f2 100644 --- a/test/cpp/qps/qps_openloop_test.cc +++ b/test/cpp/qps/qps_openloop_test.cc @@ -52,7 +52,7 @@ static void RunQPS() { const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2, "", - kInsecureCredentialsType, false, 0); + kInsecureCredentialsType, {}, false, 0); GetReporter()->ReportQPSPerCore(*result); GetReporter()->ReportLatency(*result); diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc index d97d95d8f3..23fe72316a 100644 --- a/test/cpp/qps/qps_worker.cc +++ b/test/cpp/qps/qps_worker.cc @@ -79,6 +79,8 @@ static std::unique_ptr<Server> CreateServer(const ServerConfig& config) { return CreateAsyncServer(config); case ServerType::ASYNC_GENERIC_SERVER: return CreateAsyncGenericServer(config); + case ServerType::CALLBACK_SERVER: + return CreateCallbackServer(config); default: abort(); } 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 a559c82cc8..422bd617eb 100644 --- a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc +++ b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc @@ -55,7 +55,7 @@ static void RunSynchronousUnaryPingPong() { const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2, "", - kInsecureCredentialsType, false, 0); + kInsecureCredentialsType, {}, false, 0); GetReporter()->ReportQPS(*result); GetReporter()->ReportLatency(*result); diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index 6b1ef93617..89b0e3af4b 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -152,6 +152,7 @@ class Server { std::unique_ptr<Server> CreateSynchronousServer(const ServerConfig& config); std::unique_ptr<Server> CreateAsyncServer(const ServerConfig& config); std::unique_ptr<Server> CreateAsyncGenericServer(const ServerConfig& config); +std::unique_ptr<Server> CreateCallbackServer(const ServerConfig& config); } // namespace testing } // namespace grpc diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index 5cd975cf74..a5f8347c26 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -562,6 +562,7 @@ static Status ProcessGenericRPC(const PayloadConfig& payload_config, request->Clear(); int resp_size = payload_config.bytebuf_params().resp_size(); std::unique_ptr<char[]> buf(new char[resp_size]); + memset(buf.get(), 0, static_cast<size_t>(resp_size)); Slice slice(buf.get(), resp_size); *response = ByteBuffer(&slice, 1); return Status::OK; diff --git a/test/cpp/qps/server_callback.cc b/test/cpp/qps/server_callback.cc new file mode 100644 index 0000000000..8bedd44739 --- /dev/null +++ b/test/cpp/qps/server_callback.cc @@ -0,0 +1,96 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpcpp/security/server_credentials.h> +#include <grpcpp/server.h> +#include <grpcpp/server_context.h> + +#include "src/core/lib/gpr/host_port.h" +#include "src/proto/grpc/testing/benchmark_service.grpc.pb.h" +#include "test/cpp/qps/qps_server_builder.h" +#include "test/cpp/qps/server.h" +#include "test/cpp/qps/usage_timer.h" + +namespace grpc { +namespace testing { + +class BenchmarkCallbackServiceImpl final + : public BenchmarkService::ExperimentalCallbackService { + public: + void UnaryCall( + ServerContext* context, const SimpleRequest* request, + SimpleResponse* response, + experimental::ServerCallbackRpcController* controller) override { + auto s = SetResponse(request, response); + controller->Finish(s); + } + + private: + static Status SetResponse(const SimpleRequest* request, + SimpleResponse* response) { + if (request->response_size() > 0) { + if (!Server::SetPayload(request->response_type(), + request->response_size(), + response->mutable_payload())) { + return Status(grpc::StatusCode::INTERNAL, "Error creating payload."); + } + } + return Status::OK; + } +}; + +class CallbackServer final : public grpc::testing::Server { + public: + explicit CallbackServer(const ServerConfig& config) : Server(config) { + std::unique_ptr<ServerBuilder> builder = CreateQpsServerBuilder(); + + auto port_num = port(); + // Negative port number means inproc server, so no listen port needed + if (port_num >= 0) { + char* server_address = nullptr; + gpr_join_host_port(&server_address, "::", port_num); + builder->AddListeningPort(server_address, + Server::CreateServerCredentials(config)); + gpr_free(server_address); + } + + ApplyConfigToBuilder(config, builder.get()); + + builder->RegisterService(&service_); + + impl_ = builder->BuildAndStart(); + } + + std::shared_ptr<Channel> InProcessChannel( + const ChannelArguments& args) override { + return impl_->InProcessChannel(args); + } + + private: + BenchmarkCallbackServiceImpl service_; + std::unique_ptr<grpc::Server> impl_; +}; + +std::unique_ptr<grpc::testing::Server> CreateCallbackServer( + const ServerConfig& config) { + return std::unique_ptr<Server>(new CallbackServer(config)); +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/server/load_reporter/get_cpu_stats_test.cc b/test/cpp/server/load_reporter/get_cpu_stats_test.cc index 5b1d5fa3a4..98c15b2c69 100644 --- a/test/cpp/server/load_reporter/get_cpu_stats_test.cc +++ b/test/cpp/server/load_reporter/get_cpu_stats_test.cc @@ -55,7 +55,7 @@ TEST(GetCpuStatsTest, Ascending) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/server/load_reporter/load_data_store_test.cc b/test/cpp/server/load_reporter/load_data_store_test.cc index c92c407e4f..a3a67a2851 100644 --- a/test/cpp/server/load_reporter/load_data_store_test.cc +++ b/test/cpp/server/load_reporter/load_data_store_test.cc @@ -475,7 +475,7 @@ TEST_F(PerBalancerStoreTest, DataAggregation) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/server/load_reporter/load_reporter_test.cc b/test/cpp/server/load_reporter/load_reporter_test.cc index 0d56cdf431..9d2ebfb0b4 100644 --- a/test/cpp/server/load_reporter/load_reporter_test.cc +++ b/test/cpp/server/load_reporter/load_reporter_test.cc @@ -501,7 +501,7 @@ TEST_F(LoadReportTest, BasicReport) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/util/BUILD b/test/cpp/util/BUILD index c8d4333ef0..61e65029ff 100644 --- a/test/cpp/util/BUILD +++ b/test/cpp/util/BUILD @@ -181,16 +181,19 @@ grpc_cc_test( data = [ "//src/proto/grpc/testing:echo.proto", "//src/proto/grpc/testing:echo_messages.proto", + "//src/proto/grpc/testing:simple_messages.proto", ], external_deps = [ "gtest", ], + tags = ["nomsan"], # death tests seem to be incompatible with msan deps = [ ":grpc_cli_libs", ":test_util", "//:grpc++_reflection", "//src/proto/grpc/testing:echo_messages_proto", "//src/proto/grpc/testing:echo_proto", + "//src/proto/grpc/testing:simple_messages_proto", "//test/core/end2end:ssl_test_data", "//test/core/util:grpc_test_util", ], diff --git a/test/cpp/util/byte_buffer_proto_helper.h b/test/cpp/util/byte_buffer_proto_helper.h index eb923eccb5..3d01fb2468 100644 --- a/test/cpp/util/byte_buffer_proto_helper.h +++ b/test/cpp/util/byte_buffer_proto_helper.h @@ -27,12 +27,13 @@ namespace grpc { namespace testing { -bool ParseFromByteBuffer(ByteBuffer* buffer, grpc::protobuf::Message* message); +bool ParseFromByteBuffer(ByteBuffer* buffer, + ::grpc::protobuf::Message* message); std::unique_ptr<ByteBuffer> SerializeToByteBuffer( - grpc::protobuf::Message* message); + ::grpc::protobuf::Message* message); -bool SerializeToByteBufferInPlace(grpc::protobuf::Message* message, +bool SerializeToByteBufferInPlace(::grpc::protobuf::Message* message, ByteBuffer* buffer); } // namespace testing diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index 42a436d49b..ff9d887385 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -82,6 +82,11 @@ void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str) { json_c_str); } +void ValidateGetServerResponseProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation<grpc::channelz::v1::GetServerResponse>( + json_c_str); +} + void ValidateSubchannelProtoJsonTranslation(char* json_c_str) { VaidateProtoJsonTranslation<grpc::channelz::v1::Subchannel>(json_c_str); } diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h index 67c363e89b..4f74e02f10 100644 --- a/test/cpp/util/channel_trace_proto_helper.h +++ b/test/cpp/util/channel_trace_proto_helper.h @@ -26,6 +26,7 @@ void ValidateChannelTraceProtoJsonTranslation(char* json_c_str); void ValidateChannelProtoJsonTranslation(char* json_c_str); void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str); void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str); +void ValidateGetServerResponseProtoJsonTranslation(char* json_c_str); void ValidateSubchannelProtoJsonTranslation(char* json_c_str); void ValidateServerProtoJsonTranslation(char* json_c_str); void ValidateGetServersResponseProtoJsonTranslation(char* json_c_str); diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc index 516f3fa53d..1d641535e2 100644 --- a/test/cpp/util/cli_call_test.cc +++ b/test/cpp/util/cli_call_test.cc @@ -122,7 +122,7 @@ TEST_F(CliCallTest, SimpleRpc) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc index be9a624a2c..b96b00f2db 100644 --- a/test/cpp/util/grpc_tool_test.cc +++ b/test/cpp/util/grpc_tool_test.cc @@ -48,6 +48,7 @@ using grpc::testing::EchoResponse; #define ECHO_TEST_SERVICE_SUMMARY \ "Echo\n" \ + "CheckClientInitialMetadata\n" \ "RequestStream\n" \ "ResponseStream\n" \ "BidiStream\n" \ @@ -59,6 +60,8 @@ using grpc::testing::EchoResponse; "service EchoTestService {\n" \ " rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \ "{}\n" \ + " rpc CheckClientInitialMetadata(grpc.testing.SimpleRequest) returns " \ + "(grpc.testing.SimpleResponse) {}\n" \ " rpc RequestStream(stream grpc.testing.EchoRequest) returns " \ "(grpc.testing.EchoResponse) {}\n" \ " rpc ResponseStream(grpc.testing.EchoRequest) returns (stream " \ @@ -1173,7 +1176,7 @@ TEST_F(GrpcToolTest, ListCommand_OverrideSslHostName) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); ::testing::FLAGS_gtest_death_test_style = "threadsafe"; return RUN_ALL_TESTS(); |