diff options
author | ncteisen <ncteisen@gmail.com> | 2017-11-14 17:12:24 -0800 |
---|---|---|
committer | ncteisen <ncteisen@gmail.com> | 2017-11-14 17:12:24 -0800 |
commit | 50cfbe358e2d8c4bb3ddfe3921fce09499ad65a8 (patch) | |
tree | c2371dfc050dcd2f201b0d8d1d090357fc8a726f | |
parent | 751c3245f8807c8f2468b4d8ca4d7da8d7607221 (diff) | |
parent | 070f0c4b677c89052fa92bd24e9541ac1c0ef827 (diff) |
Merge branch 'master' of https://github.com/grpc/grpc into more-eager-free
-rw-r--r-- | BUILD | 88 | ||||
-rw-r--r-- | CMakeLists.txt | 87 | ||||
-rw-r--r-- | Makefile | 98 | ||||
-rw-r--r-- | bazel/grpc_build_system.bzl | 4 | ||||
-rw-r--r-- | build.yaml | 35 | ||||
-rw-r--r-- | include/grpc++/impl/codegen/completion_queue.h | 32 | ||||
-rw-r--r-- | src/compiler/protobuf_plugin.h | 1 | ||||
-rw-r--r-- | src/compiler/python_generator_helpers.h | 2 | ||||
-rw-r--r-- | src/core/lib/security/transport/security_handshaker.cc | 45 | ||||
-rw-r--r-- | src/core/lib/support/cpu_linux.cc | 10 | ||||
-rw-r--r-- | src/proto/grpc/testing/BUILD | 1 | ||||
-rw-r--r-- | src/proto/grpc/testing/services.proto | 1 | ||||
-rw-r--r-- | test/core/handshake/BUILD | 31 | ||||
-rw-r--r-- | test/core/handshake/readahead_handshaker_server_ssl.cc | 103 | ||||
-rw-r--r-- | test/core/handshake/server_ssl.cc | 201 | ||||
-rw-r--r-- | test/core/handshake/server_ssl_common.cc | 238 | ||||
-rw-r--r-- | test/core/handshake/server_ssl_common.h | 36 | ||||
-rw-r--r-- | test/core/util/BUILD | 1 | ||||
-rw-r--r-- | test/cpp/client/BUILD | 51 | ||||
-rw-r--r-- | test/cpp/client/client_channel_stress_test.cc | 329 | ||||
-rw-r--r-- | tools/run_tests/generated/sources_and_headers.json | 52 | ||||
-rw-r--r-- | tools/run_tests/generated/tests.json | 44 |
22 files changed, 1213 insertions, 277 deletions
@@ -316,36 +316,12 @@ grpc_cc_library( grpc_cc_library( name = "grpc_plugin_support", - srcs = [ - "src/compiler/cpp_generator.cc", - "src/compiler/csharp_generator.cc", - "src/compiler/node_generator.cc", - "src/compiler/objective_c_generator.cc", - "src/compiler/php_generator.cc", - "src/compiler/python_generator.cc", - "src/compiler/ruby_generator.cc", - ], hdrs = [ "src/compiler/config.h", - "src/compiler/cpp_generator.h", "src/compiler/cpp_generator_helpers.h", - "src/compiler/csharp_generator.h", - "src/compiler/csharp_generator_helpers.h", "src/compiler/generator_helpers.h", - "src/compiler/node_generator.h", - "src/compiler/node_generator_helpers.h", - "src/compiler/objective_c_generator.h", - "src/compiler/objective_c_generator_helpers.h", - "src/compiler/php_generator.h", - "src/compiler/php_generator_helpers.h", "src/compiler/protobuf_plugin.h", - "src/compiler/python_generator.h", "src/compiler/python_generator_helpers.h", - "src/compiler/python_private_generator.h", - "src/compiler/ruby_generator.h", - "src/compiler/ruby_generator_helpers-inl.h", - "src/compiler/ruby_generator_map-inl.h", - "src/compiler/ruby_generator_string-inl.h", "src/compiler/schema_interface.h", ], external_deps = [ @@ -359,43 +335,93 @@ grpc_cc_library( grpc_proto_plugin( name = "grpc_cpp_plugin", - srcs = ["src/compiler/cpp_plugin.cc"], + srcs = [ + "src/compiler/cpp_generator.cc", + "src/compiler/cpp_plugin.cc", + ], + hdrs = [ + "src/compiler/cpp_generator.h", + ], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_csharp_plugin", - srcs = ["src/compiler/csharp_plugin.cc"], + srcs = [ + "src/compiler/csharp_generator.cc", + "src/compiler/csharp_plugin.cc", + ], + hdrs = [ + "src/compiler/csharp_generator.h", + "src/compiler/csharp_generator_helpers.h", + ], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_node_plugin", - srcs = ["src/compiler/node_plugin.cc"], + srcs = [ + "src/compiler/node_generator.cc", + "src/compiler/node_plugin.cc", + ], + hdrs = [ + "src/compiler/node_generator.h", + "src/compiler/node_generator_helpers.h", + ], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_objective_c_plugin", - srcs = ["src/compiler/objective_c_plugin.cc"], + srcs = [ + "src/compiler/objective_c_generator.cc", + "src/compiler/objective_c_plugin.cc", + ], + hdrs = [ + "src/compiler/objective_c_generator.h", + "src/compiler/objective_c_generator_helpers.h", + ], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_php_plugin", - srcs = ["src/compiler/php_plugin.cc"], + srcs = [ + "src/compiler/php_generator.cc", + "src/compiler/php_plugin.cc", + ], + hdrs = [ + "src/compiler/php_generator.h", + "src/compiler/php_generator_helpers.h", + ], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_python_plugin", - srcs = ["src/compiler/python_plugin.cc"], + srcs = [ + "src/compiler/python_generator.cc", + "src/compiler/python_plugin.cc", + ], + hdrs = [ + "src/compiler/python_generator.h", + "src/compiler/python_private_generator.h", + ], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_ruby_plugin", - srcs = ["src/compiler/ruby_plugin.cc"], + srcs = [ + "src/compiler/ruby_generator.cc", + "src/compiler/ruby_plugin.cc", + ], + hdrs = [ + "src/compiler/ruby_generator.h", + "src/compiler/ruby_generator_helpers-inl.h", + "src/compiler/ruby_generator_map-inl.h", + "src/compiler/ruby_generator_string-inl.h", + ], deps = [":grpc_plugin_support"], ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4daff95efd..153e3a0a01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -462,6 +462,9 @@ endif() if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c handshake_server) endif() +if(_gRPC_PLATFORM_LINUX) +add_dependencies(buildtests_c handshake_server_with_readahead_handshaker) +endif() add_dependencies(buildtests_c hpack_parser_test) add_dependencies(buildtests_c hpack_table_test) add_dependencies(buildtests_c http_parser_test) @@ -675,6 +678,7 @@ endif() add_dependencies(buildtests_cxx channel_arguments_test) add_dependencies(buildtests_cxx channel_filter_test) add_dependencies(buildtests_cxx cli_call_test) +add_dependencies(buildtests_cxx client_channel_stress_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx client_crash_test) endif() @@ -7236,6 +7240,7 @@ if(_gRPC_PLATFORM_LINUX) add_executable(handshake_server test/core/handshake/server_ssl.cc + test/core/handshake/server_ssl_common.cc ) @@ -7265,6 +7270,40 @@ target_link_libraries(handshake_server endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX) + +add_executable(handshake_server_with_readahead_handshaker + test/core/handshake/readahead_handshaker_server_ssl.cc + test/core/handshake/server_ssl_common.cc +) + + +target_include_directories(handshake_server_with_readahead_handshaker + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp +) + +target_link_libraries(handshake_server_with_readahead_handshaker + ${_gRPC_SSL_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + +endif() +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) add_executable(hpack_parser_test test/core/transport/chttp2/hpack_parser_test.cc @@ -10030,6 +10069,54 @@ target_link_libraries(cli_call_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) + +add_executable(client_channel_stress_test + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.h + test/cpp/client/client_channel_stress_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +protobuf_generate_grpc_cpp( + src/proto/grpc/lb/v1/load_balancer.proto +) + +target_include_directories(client_channel_stress_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(client_channel_stress_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_util + grpc_test_util + grpc++ + grpc + gpr_test_util + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(client_crash_test @@ -1019,6 +1019,7 @@ grpc_ssl_credentials_test: $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt handshake_client: $(BINDIR)/$(CONFIG)/handshake_client handshake_server: $(BINDIR)/$(CONFIG)/handshake_server +handshake_server_with_readahead_handshaker: $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker hpack_parser_fuzzer_test: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test hpack_table_test: $(BINDIR)/$(CONFIG)/hpack_table_test @@ -1113,6 +1114,7 @@ bm_pollset: $(BINDIR)/$(CONFIG)/bm_pollset channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test +client_channel_stress_test: $(BINDIR)/$(CONFIG)/client_channel_stress_test client_crash_test: $(BINDIR)/$(CONFIG)/client_crash_test client_crash_test_server: $(BINDIR)/$(CONFIG)/client_crash_test_server client_lb_end2end_test: $(BINDIR)/$(CONFIG)/client_lb_end2end_test @@ -1408,6 +1410,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test \ $(BINDIR)/$(CONFIG)/handshake_client \ $(BINDIR)/$(CONFIG)/handshake_server \ + $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker \ $(BINDIR)/$(CONFIG)/hpack_parser_test \ $(BINDIR)/$(CONFIG)/hpack_table_test \ $(BINDIR)/$(CONFIG)/http_parser_test \ @@ -1553,6 +1556,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/cli_call_test \ + $(BINDIR)/$(CONFIG)/client_channel_stress_test \ $(BINDIR)/$(CONFIG)/client_crash_test \ $(BINDIR)/$(CONFIG)/client_crash_test_server \ $(BINDIR)/$(CONFIG)/client_lb_end2end_test \ @@ -1678,6 +1682,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/cli_call_test \ + $(BINDIR)/$(CONFIG)/client_channel_stress_test \ $(BINDIR)/$(CONFIG)/client_crash_test \ $(BINDIR)/$(CONFIG)/client_crash_test_server \ $(BINDIR)/$(CONFIG)/client_lb_end2end_test \ @@ -1876,6 +1881,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/handshake_client || ( echo test handshake_client failed ; exit 1 ) $(E) "[RUN] Testing handshake_server" $(Q) $(BINDIR)/$(CONFIG)/handshake_server || ( echo test handshake_server failed ; exit 1 ) + $(E) "[RUN] Testing handshake_server_with_readahead_handshaker" + $(Q) $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker || ( echo test handshake_server_with_readahead_handshaker failed ; exit 1 ) $(E) "[RUN] Testing hpack_parser_test" $(Q) $(BINDIR)/$(CONFIG)/hpack_parser_test || ( echo test hpack_parser_test failed ; exit 1 ) $(E) "[RUN] Testing hpack_table_test" @@ -2060,6 +2067,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/channel_filter_test || ( echo test channel_filter_test failed ; exit 1 ) $(E) "[RUN] Testing cli_call_test" $(Q) $(BINDIR)/$(CONFIG)/cli_call_test || ( echo test cli_call_test failed ; exit 1 ) + $(E) "[RUN] Testing client_channel_stress_test" + $(Q) $(BINDIR)/$(CONFIG)/client_channel_stress_test || ( echo test client_channel_stress_test failed ; exit 1 ) $(E) "[RUN] Testing client_crash_test" $(Q) $(BINDIR)/$(CONFIG)/client_crash_test || ( echo test client_crash_test failed ; exit 1 ) $(E) "[RUN] Testing client_lb_end2end_test" @@ -2499,12 +2508,12 @@ $(GENDIR)/src/proto/grpc/testing/services.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: protoc_dep_error else -$(GENDIR)/src/proto/grpc/testing/services.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc +$(GENDIR)/src/proto/grpc/testing/services.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< -$(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: src/proto/grpc/testing/services.proto $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc +$(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: src/proto/grpc/testing/services.proto $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< @@ -11040,6 +11049,7 @@ endif HANDSHAKE_SERVER_SRC = \ test/core/handshake/server_ssl.cc \ + test/core/handshake/server_ssl_common.cc \ HANDSHAKE_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_SERVER_SRC)))) ifeq ($(NO_SECURE),true) @@ -11061,6 +11071,8 @@ endif $(OBJDIR)/$(CONFIG)/test/core/handshake/server_ssl.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/core/handshake/server_ssl_common.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + deps_handshake_server: $(HANDSHAKE_SERVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) @@ -11070,6 +11082,41 @@ endif endif +HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_SRC = \ + test/core/handshake/readahead_handshaker_server_ssl.cc \ + test/core/handshake/server_ssl_common.cc \ + +HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker: $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker + +endif + +$(OBJDIR)/$(CONFIG)/test/core/handshake/readahead_handshaker_server_ssl.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +$(OBJDIR)/$(CONFIG)/test/core/handshake/server_ssl_common.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_handshake_server_with_readahead_handshaker: $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS:.o=.dep) +endif +endif + + HPACK_PARSER_FUZZER_TEST_SRC = \ test/core/transport/chttp2/hpack_parser_fuzzer_test.cc \ @@ -14326,6 +14373,53 @@ endif endif +CLIENT_CHANNEL_STRESS_TEST_SRC = \ + $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \ + test/cpp/client/client_channel_stress_test.cc \ + +CLIENT_CHANNEL_STRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_CHANNEL_STRESS_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/client_channel_stress_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/client_channel_stress_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/client_channel_stress_test: $(PROTOBUF_DEP) $(CLIENT_CHANNEL_STRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(CLIENT_CHANNEL_STRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/client_channel_stress_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v1/load_balancer.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +$(OBJDIR)/$(CONFIG)/test/cpp/client/client_channel_stress_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_client_channel_stress_test: $(CLIENT_CHANNEL_STRESS_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CLIENT_CHANNEL_STRESS_TEST_OBJS:.o=.dep) +endif +endif +$(OBJDIR)/$(CONFIG)/test/cpp/client/client_channel_stress_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc + + CLIENT_CRASH_TEST_SRC = \ test/cpp/end2end/client_crash_test.cc \ diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index b35ca73745..8a8ec9bc84 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -49,10 +49,10 @@ def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [], alwayslink = alwayslink, ) -def grpc_proto_plugin(name, srcs = [], deps = []): +def grpc_proto_plugin(name, srcs = [], hdrs = [], deps = []): native.cc_binary( name = name, - srcs = srcs, + srcs = srcs + hdrs, deps = deps, ) diff --git a/build.yaml b/build.yaml index cd6486ea29..18f9449243 100644 --- a/build.yaml +++ b/build.yaml @@ -2511,8 +2511,29 @@ targets: - name: handshake_server build: test language: c + headers: + - test/core/handshake/server_ssl_common.h src: - test/core/handshake/server_ssl.cc + - test/core/handshake/server_ssl_common.cc + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + exclude_iomgrs: + - uv + platforms: + - linux + secure: true +- name: handshake_server_with_readahead_handshaker + build: test + language: c + headers: + - test/core/handshake/server_ssl_common.h + src: + - test/core/handshake/readahead_handshaker_server_ssl.cc + - test/core/handshake/server_ssl_common.cc deps: - grpc_test_util - grpc @@ -3807,6 +3828,20 @@ targets: - grpc - gpr_test_util - gpr +- name: client_channel_stress_test + gtest: false + build: test + language: c++ + src: + - src/proto/grpc/lb/v1/load_balancer.proto + - test/cpp/client/client_channel_stress_test.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - gpr_test_util + - gpr - name: client_crash_test gtest: true cpu_cost: 0.1 diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h index 11cc588879..b8a7862578 100644 --- a/include/grpc++/impl/codegen/completion_queue.h +++ b/include/grpc++/impl/codegen/completion_queue.h @@ -65,6 +65,7 @@ class CompletionQueue; class Server; class ServerBuilder; class ServerContext; +class ServerInterface; namespace internal { class CompletionQueueTag; @@ -187,21 +188,6 @@ class CompletionQueue : private GrpcLibraryCodegen { /// owership is performed. grpc_completion_queue* cq() { return cq_; } - /// Manage state of avalanching operations : completion queue tags that - /// trigger other completion queue operations. The underlying core completion - /// queue should not really shutdown until all avalanching operations have - /// been finalized. Note that we maintain the requirement that an avalanche - /// registration must take place before CQ shutdown (which must be maintained - /// elsehwere) - void InitialAvalanching() { - gpr_atm_rel_store(&avalanches_in_flight_, static_cast<gpr_atm>(1)); - } - void RegisterAvalanching() { - gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, - static_cast<gpr_atm>(1)); - } - void CompleteAvalanching(); - protected: /// Private constructor of CompletionQueue only visible to friend classes CompletionQueue(const grpc_completion_queue_attributes& attributes) { @@ -238,6 +224,7 @@ class CompletionQueue : private GrpcLibraryCodegen { friend class ::grpc::internal::UnknownMethodHandler; friend class ::grpc::Server; friend class ::grpc::ServerContext; + friend class ::grpc::ServerInterface; template <class InputMessage, class OutputMessage> friend class ::grpc::internal::BlockingUnaryCallImpl; @@ -309,6 +296,21 @@ class CompletionQueue : private GrpcLibraryCodegen { GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); } + /// Manage state of avalanching operations : completion queue tags that + /// trigger other completion queue operations. The underlying core completion + /// queue should not really shutdown until all avalanching operations have + /// been finalized. Note that we maintain the requirement that an avalanche + /// registration must take place before CQ shutdown (which must be maintained + /// elsehwere) + void InitialAvalanching() { + gpr_atm_rel_store(&avalanches_in_flight_, static_cast<gpr_atm>(1)); + } + void RegisterAvalanching() { + gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, + static_cast<gpr_atm>(1)); + } + void CompleteAvalanching(); + grpc_completion_queue* cq_; // owned gpr_atm avalanches_in_flight_; diff --git a/src/compiler/protobuf_plugin.h b/src/compiler/protobuf_plugin.h index 1551908156..0f22dd4f33 100644 --- a/src/compiler/protobuf_plugin.h +++ b/src/compiler/protobuf_plugin.h @@ -22,7 +22,6 @@ #include "src/compiler/config.h" #include "src/compiler/cpp_generator_helpers.h" #include "src/compiler/python_generator_helpers.h" -#include "src/compiler/python_private_generator.h" #include "src/compiler/schema_interface.h" #include <vector> diff --git a/src/compiler/python_generator_helpers.h b/src/compiler/python_generator_helpers.h index b1b58befdf..5ecd192163 100644 --- a/src/compiler/python_generator_helpers.h +++ b/src/compiler/python_generator_helpers.h @@ -26,8 +26,6 @@ #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" -#include "src/compiler/python_generator.h" -#include "src/compiler/python_private_generator.h" using grpc::protobuf::Descriptor; using grpc::protobuf::FileDescriptor; diff --git a/src/core/lib/security/transport/security_handshaker.cc b/src/core/lib/security/transport/security_handshaker.cc index c540445792..7067b70cb6 100644 --- a/src/core/lib/security/transport/security_handshaker.cc +++ b/src/core/lib/security/transport/security_handshaker.cc @@ -65,6 +65,25 @@ typedef struct { tsi_handshaker_result* handshaker_result; } security_handshaker; +static size_t move_read_buffer_into_handshake_buffer(grpc_exec_ctx* exec_ctx, + security_handshaker* h) { + size_t bytes_in_read_buffer = h->args->read_buffer->length; + if (h->handshake_buffer_size < bytes_in_read_buffer) { + h->handshake_buffer = + (uint8_t*)gpr_realloc(h->handshake_buffer, bytes_in_read_buffer); + h->handshake_buffer_size = bytes_in_read_buffer; + } + size_t offset = 0; + while (h->args->read_buffer->count > 0) { + grpc_slice next_slice = grpc_slice_buffer_take_first(h->args->read_buffer); + memcpy(h->handshake_buffer + offset, GRPC_SLICE_START_PTR(next_slice), + GRPC_SLICE_LENGTH(next_slice)); + offset += GRPC_SLICE_LENGTH(next_slice); + grpc_slice_unref_internal(exec_ctx, next_slice); + } + return bytes_in_read_buffer; +} + static void security_handshaker_unref(grpc_exec_ctx* exec_ctx, security_handshaker* h) { if (gpr_unref(&h->refs)) { @@ -177,8 +196,6 @@ static void on_peer_checked_inner(grpc_exec_ctx* exec_ctx, } tsi_handshaker_result_destroy(h->handshaker_result); h->handshaker_result = nullptr; - // Clear out the read buffer before it gets passed to the transport. - grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer); // Add auth context to channel args. grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context); grpc_channel_args* tmp_args = h->args->args; @@ -312,23 +329,8 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx* exec_ctx, return; } // Copy all slices received. - size_t i; - size_t bytes_received_size = 0; - for (i = 0; i < h->args->read_buffer->count; i++) { - bytes_received_size += GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]); - } - if (bytes_received_size > h->handshake_buffer_size) { - h->handshake_buffer = - (uint8_t*)gpr_realloc(h->handshake_buffer, bytes_received_size); - h->handshake_buffer_size = bytes_received_size; - } - size_t offset = 0; - for (i = 0; i < h->args->read_buffer->count; i++) { - size_t slice_size = GPR_SLICE_LENGTH(h->args->read_buffer->slices[i]); - memcpy(h->handshake_buffer + offset, - GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]), slice_size); - offset += slice_size; - } + size_t bytes_received_size = + move_read_buffer_into_handshake_buffer(exec_ctx, h); // Call TSI handshaker. error = do_handshaker_next_locked(exec_ctx, h, h->handshake_buffer, bytes_received_size); @@ -405,7 +407,10 @@ static void security_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, h->args = args; h->on_handshake_done = on_handshake_done; gpr_ref(&h->refs); - grpc_error* error = do_handshaker_next_locked(exec_ctx, h, nullptr, 0); + size_t bytes_received_size = + move_read_buffer_into_handshake_buffer(exec_ctx, h); + grpc_error* error = do_handshaker_next_locked( + exec_ctx, h, h->handshake_buffer, bytes_received_size); if (error != GRPC_ERROR_NONE) { security_handshake_failed_locked(exec_ctx, h, error); gpr_mu_unlock(&h->mu); diff --git a/src/core/lib/support/cpu_linux.cc b/src/core/lib/support/cpu_linux.cc index 2280668442..21b1a71dc9 100644 --- a/src/core/lib/support/cpu_linux.cc +++ b/src/core/lib/support/cpu_linux.cc @@ -36,6 +36,13 @@ static int ncpus = 0; static void init_num_cpus() { +#ifndef GPR_MUSL_LIBC_COMPAT + if (sched_getcpu() < 0) { + gpr_log(GPR_ERROR, "Error determining current CPU: %s\n", strerror(errno)); + ncpus = 1; + return; + } +#endif /* This must be signed. sysconf returns -1 when the number cannot be determined */ ncpus = (int)sysconf(_SC_NPROCESSORS_ONLN); @@ -56,6 +63,9 @@ unsigned gpr_cpu_current_cpu(void) { // sched_getcpu() is undefined on musl return 0; #else + if (gpr_cpu_num_cores() == 1) { + return 0; + } int cpu = sched_getcpu(); if (cpu < 0) { gpr_log(GPR_ERROR, "Error determining current CPU: %s\n", strerror(errno)); diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD index 36d3782262..7c49fe2472 100644 --- a/src/proto/grpc/testing/BUILD +++ b/src/proto/grpc/testing/BUILD @@ -76,7 +76,6 @@ grpc_proto_library( deps = [ "control_proto", "messages_proto", - "stats_proto", ], ) diff --git a/src/proto/grpc/testing/services.proto b/src/proto/grpc/testing/services.proto index 2e6583d99c..93c21f42d1 100644 --- a/src/proto/grpc/testing/services.proto +++ b/src/proto/grpc/testing/services.proto @@ -18,7 +18,6 @@ syntax = "proto3"; import "src/proto/grpc/testing/messages.proto"; import "src/proto/grpc/testing/control.proto"; -import "src/proto/grpc/testing/stats.proto"; package grpc.testing; diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD index aea4a27e99..a3276b9343 100644 --- a/test/core/handshake/BUILD +++ b/test/core/handshake/BUILD @@ -35,6 +35,18 @@ grpc_cc_test( ], ) +grpc_cc_library( + name = "server_ssl_common", + hdrs = ["server_ssl_common.h"], + srcs = ["server_ssl_common.cc"], + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_test( name = "server_ssl", srcs = ["server_ssl.cc"], @@ -45,6 +57,25 @@ grpc_cc_test( "//src/core/tsi/test_creds:server1.pem", ], deps = [ + ":server_ssl_common", + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_test( + name = "handshake_server_with_readahead_handshaker", + srcs = ["readahead_handshaker_server_ssl.cc"], + language = "C++", + data = [ + "//src/core/tsi/test_creds:ca.pem", + "//src/core/tsi/test_creds:server1.key", + "//src/core/tsi/test_creds:server1.pem", + ], + deps = [ + ":server_ssl_common", "//:gpr", "//:grpc", "//test/core/util:gpr_test_util", diff --git a/test/core/handshake/readahead_handshaker_server_ssl.cc b/test/core/handshake/readahead_handshaker_server_ssl.cc new file mode 100644 index 0000000000..2810082837 --- /dev/null +++ b/test/core/handshake/readahead_handshaker_server_ssl.cc @@ -0,0 +1,103 @@ +/* + * + * Copyright 2016 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 <arpa/inet.h> +#include <openssl/err.h> +#include <openssl/ssl.h> +#include <string.h> +#include <sys/socket.h> +#include <unistd.h> + +#include <grpc/grpc.h> +#include <grpc/grpc_security.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/sync.h> +#include <grpc/support/thd.h> +#include "src/core/lib/iomgr/load_file.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#include "src/core/lib/channel/handshaker_factory.h" +#include "src/core/lib/channel/handshaker_registry.h" +#include "src/core/lib/security/transport/security_handshaker.h" + +#include "test/core/handshake/server_ssl_common.h" + +/* The purpose of this test is to exercise the case when a + * grpc *security_handshaker* begins its handshake with data already + * in the read buffer of the handshaker arg. This scenario is created by + * adding a fake "readahead" handshaker at the beginning of the server's + * handshaker list, which just reads from the connection and then places + * read bytes into the read buffer of the handshake arg (to be passed down + * to the security_handshaker). This test is meant to protect code relying on + * this functionality that lives outside of this repo. */ + +static void readahead_handshaker_destroy(grpc_exec_ctx* ctx, + grpc_handshaker* handshaker) { + gpr_free(handshaker); +} + +static void readahead_handshaker_shutdown(grpc_exec_ctx* ctx, + grpc_handshaker* handshaker, + grpc_error* error) {} + +static void readahead_handshaker_do_handshake( + grpc_exec_ctx* ctx, grpc_handshaker* handshaker, + grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, + grpc_handshaker_args* args) { + grpc_endpoint_read(ctx, args->endpoint, args->read_buffer, on_handshake_done); +} + +const grpc_handshaker_vtable readahead_handshaker_vtable = { + readahead_handshaker_destroy, readahead_handshaker_shutdown, + readahead_handshaker_do_handshake}; + +static grpc_handshaker* readahead_handshaker_create(grpc_exec_ctx* ctx) { + grpc_handshaker* h = (grpc_handshaker*)gpr_zalloc(sizeof(grpc_handshaker)); + grpc_handshaker_init(&readahead_handshaker_vtable, h); + return h; +} + +static void readahead_handshaker_factory_add_handshakers( + grpc_exec_ctx* exec_ctx, grpc_handshaker_factory* hf, + const grpc_channel_args* args, grpc_handshake_manager* handshake_mgr) { + grpc_handshake_manager_add(handshake_mgr, + readahead_handshaker_create(exec_ctx)); +} + +static void readahead_handshaker_factory_destroy( + grpc_exec_ctx* exec_ctx, grpc_handshaker_factory* handshaker_factory) {} + +static const grpc_handshaker_factory_vtable + readahead_handshaker_factory_vtable = { + readahead_handshaker_factory_add_handshakers, + readahead_handshaker_factory_destroy}; + +int main(int argc, char* argv[]) { + grpc_handshaker_factory readahead_handshaker_factory = { + &readahead_handshaker_factory_vtable}; + grpc_init(); + grpc_handshaker_factory_register(true /* at_start */, HANDSHAKER_SERVER, + &readahead_handshaker_factory); + const char* full_alpn_list[] = {"grpc-exp", "h2"}; + GPR_ASSERT(server_ssl_test(full_alpn_list, 2, "grpc-exp")); + grpc_shutdown(); + return 0; +} diff --git a/test/core/handshake/server_ssl.cc b/test/core/handshake/server_ssl.cc index 69c4fdc11b..736d3e578e 100644 --- a/test/core/handshake/server_ssl.cc +++ b/test/core/handshake/server_ssl.cc @@ -34,206 +34,7 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" -#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" -#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" -#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" - -// Handshake completed signal to server thread. -static gpr_event client_handshake_complete; - -static int create_socket(int port) { - int s; - struct sockaddr_in addr; - - addr.sin_family = AF_INET; - addr.sin_port = htons((uint16_t)port); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - - s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) { - perror("Unable to create socket"); - return -1; - } - - if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - perror("Unable to connect"); - return -1; - } - - return s; -} - -// Simple gRPC server. This listens until client_handshake_complete occurs. -static void server_thread(void* arg) { - const int port = *(int*)arg; - - // Load key pair and establish server SSL credentials. - grpc_ssl_pem_key_cert_pair pem_key_cert_pair; - grpc_slice ca_slice, cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); - const char* ca_cert = (const char*)GRPC_SLICE_START_PTR(ca_slice); - pem_key_cert_pair.private_key = (const char*)GRPC_SLICE_START_PTR(key_slice); - pem_key_cert_pair.cert_chain = (const char*)GRPC_SLICE_START_PTR(cert_slice); - grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( - ca_cert, &pem_key_cert_pair, 1, 0, nullptr); - - // Start server listening on local port. - char* addr; - gpr_asprintf(&addr, "127.0.0.1:%d", port); - grpc_server* server = grpc_server_create(nullptr, nullptr); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); - free(addr); - - grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr); - - grpc_server_register_completion_queue(server, cq, nullptr); - grpc_server_start(server); - - // Wait a bounded number of time until client_handshake_complete is set, - // sleeping between polls. - int retries = 10; - while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) { - const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr); - GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); - } - - gpr_log(GPR_INFO, "Shutting down server"); - grpc_server_shutdown_and_notify(server, cq, nullptr); - grpc_completion_queue_shutdown(cq); - - const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - - grpc_server_destroy(server); - grpc_completion_queue_destroy(cq); - grpc_server_credentials_release(ssl_creds); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); -} - -// This test launches a gRPC server on a separate thread and then establishes a -// TLS handshake via a minimal TLS client. The TLS client has configurable (via -// alpn_list) ALPN settings and can probe at the supported ALPN preferences -// using this (via alpn_expected). -static bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len, - const char* alpn_expected) { - bool success = true; - - grpc_init(); - int port = grpc_pick_unused_port_or_die(); - gpr_event_init(&client_handshake_complete); - - // Launch the gRPC server thread. - gpr_thd_options thdopt = gpr_thd_options_default(); - gpr_thd_id thdid; - gpr_thd_options_set_joinable(&thdopt); - GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt)); - - SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); - - const SSL_METHOD* method = TLSv1_2_client_method(); - SSL_CTX* ctx = SSL_CTX_new(method); - if (!ctx) { - perror("Unable to create SSL context"); - ERR_print_errors_fp(stderr); - abort(); - } - - // Load key pair. - if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { - ERR_print_errors_fp(stderr); - abort(); - } - if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { - ERR_print_errors_fp(stderr); - abort(); - } - - // Set the cipher list to match the one expressed in - // src/core/tsi/ssl_transport_security.c. - const char* cipher_list = - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" - "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; - if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { - ERR_print_errors_fp(stderr); - gpr_log(GPR_ERROR, "Couldn't set server cipher list."); - abort(); - } - - // Configure ALPN list the client will send to the server. This must match the - // wire format, see documentation for SSL_CTX_set_alpn_protos. - unsigned int alpn_protos_len = alpn_list_len; - for (unsigned int i = 0; i < alpn_list_len; ++i) { - alpn_protos_len += (unsigned int)strlen(alpn_list[i]); - } - unsigned char* alpn_protos = - static_cast<unsigned char*>(gpr_malloc(alpn_protos_len)); - unsigned char* p = alpn_protos; - for (unsigned int i = 0; i < alpn_list_len; ++i) { - const uint8_t len = (uint8_t)strlen(alpn_list[i]); - *p++ = len; - memcpy(p, alpn_list[i], len); - p += len; - } - GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0); - - // Try and connect to server. We allow a bounded number of retries as we might - // be racing with the server setup on its separate thread. - int retries = 10; - int sock = -1; - while (sock == -1 && retries-- > 0) { - sock = create_socket(port); - if (sock < 0) { - sleep(1); - } - } - GPR_ASSERT(sock > 0); - gpr_log(GPR_INFO, "Connected to server on port %d", port); - - // Establish a SSL* and connect at SSL layer. - SSL* ssl = SSL_new(ctx); - GPR_ASSERT(ssl); - SSL_set_fd(ssl, sock); - if (SSL_connect(ssl) <= 0) { - ERR_print_errors_fp(stderr); - gpr_log(GPR_ERROR, "Handshake failed."); - success = false; - } else { - gpr_log(GPR_INFO, "Handshake successful."); - // Validate ALPN preferred by server matches alpn_expected. - const unsigned char* alpn_selected; - unsigned int alpn_selected_len; - SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len); - if (strlen(alpn_expected) != alpn_selected_len || - strncmp((const char*)alpn_selected, alpn_expected, alpn_selected_len) != - 0) { - gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference"); - success = false; - } - } - gpr_event_set(&client_handshake_complete, &client_handshake_complete); - - SSL_free(ssl); - gpr_free(alpn_protos); - SSL_CTX_free(ctx); - EVP_cleanup(); - close(sock); - - gpr_thd_join(thdid); - - grpc_shutdown(); - - return success; -} +#include "test/core/handshake/server_ssl_common.h" int main(int argc, char* argv[]) { // Handshake succeeeds when the client supplies the standard ALPN list. diff --git a/test/core/handshake/server_ssl_common.cc b/test/core/handshake/server_ssl_common.cc new file mode 100644 index 0000000000..599b2814e0 --- /dev/null +++ b/test/core/handshake/server_ssl_common.cc @@ -0,0 +1,238 @@ +/* + * + * Copyright 2016 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/core/handshake/server_ssl_common.h" + +#include <arpa/inet.h> +#include <openssl/err.h> +#include <openssl/ssl.h> +#include <string.h> +#include <sys/socket.h> +#include <unistd.h> + +#include <grpc/grpc.h> +#include <grpc/grpc_security.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/sync.h> +#include <grpc/support/thd.h> +#include "src/core/lib/iomgr/load_file.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" +#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" +#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" + +// Handshake completed signal to server thread. +static gpr_event client_handshake_complete; + +static int create_socket(int port) { + int s; + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_port = htons((uint16_t)port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + perror("Unable to create socket"); + return -1; + } + + if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("Unable to connect"); + return -1; + } + + return s; +} + +// Simple gRPC server. This listens until client_handshake_complete occurs. +static void server_thread(void* arg) { + const int port = *(int*)arg; + + // Load key pair and establish server SSL credentials. + grpc_ssl_pem_key_cert_pair pem_key_cert_pair; + grpc_slice ca_slice, cert_slice, key_slice; + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); + const char* ca_cert = (const char*)GRPC_SLICE_START_PTR(ca_slice); + pem_key_cert_pair.private_key = (const char*)GRPC_SLICE_START_PTR(key_slice); + pem_key_cert_pair.cert_chain = (const char*)GRPC_SLICE_START_PTR(cert_slice); + grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( + ca_cert, &pem_key_cert_pair, 1, 0, nullptr); + + // Start server listening on local port. + char* addr; + gpr_asprintf(&addr, "127.0.0.1:%d", port); + grpc_server* server = grpc_server_create(nullptr, nullptr); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); + free(addr); + + grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr); + + grpc_server_register_completion_queue(server, cq, nullptr); + grpc_server_start(server); + + // Wait a bounded number of time until client_handshake_complete is set, + // sleeping between polls. + int retries = 10; + while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) { + const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr); + GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); + } + + gpr_log(GPR_INFO, "Shutting down server"); + grpc_server_shutdown_and_notify(server, cq, nullptr); + grpc_completion_queue_shutdown(cq); + + const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); + grpc_server_credentials_release(ssl_creds); + grpc_slice_unref(cert_slice); + grpc_slice_unref(key_slice); + grpc_slice_unref(ca_slice); +} + +// This test launches a gRPC server on a separate thread and then establishes a +// TLS handshake via a minimal TLS client. The TLS client has configurable (via +// alpn_list) ALPN settings and can probe at the supported ALPN preferences +// using this (via alpn_expected). +bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len, + const char* alpn_expected) { + bool success = true; + + grpc_init(); + int port = grpc_pick_unused_port_or_die(); + gpr_event_init(&client_handshake_complete); + + // Launch the gRPC server thread. + gpr_thd_options thdopt = gpr_thd_options_default(); + gpr_thd_id thdid; + gpr_thd_options_set_joinable(&thdopt); + GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt)); + + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); + + const SSL_METHOD* method = TLSv1_2_client_method(); + SSL_CTX* ctx = SSL_CTX_new(method); + if (!ctx) { + perror("Unable to create SSL context"); + ERR_print_errors_fp(stderr); + abort(); + } + + // Load key pair. + if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { + ERR_print_errors_fp(stderr); + abort(); + } + if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { + ERR_print_errors_fp(stderr); + abort(); + } + + // Set the cipher list to match the one expressed in + // src/core/tsi/ssl_transport_security.c. + const char* cipher_list = + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" + "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; + if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { + ERR_print_errors_fp(stderr); + gpr_log(GPR_ERROR, "Couldn't set server cipher list."); + abort(); + } + + // Configure ALPN list the client will send to the server. This must match the + // wire format, see documentation for SSL_CTX_set_alpn_protos. + unsigned int alpn_protos_len = alpn_list_len; + for (unsigned int i = 0; i < alpn_list_len; ++i) { + alpn_protos_len += (unsigned int)strlen(alpn_list[i]); + } + unsigned char* alpn_protos = + static_cast<unsigned char*>(gpr_malloc(alpn_protos_len)); + unsigned char* p = alpn_protos; + for (unsigned int i = 0; i < alpn_list_len; ++i) { + const uint8_t len = (uint8_t)strlen(alpn_list[i]); + *p++ = len; + memcpy(p, alpn_list[i], len); + p += len; + } + GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0); + + // Try and connect to server. We allow a bounded number of retries as we might + // be racing with the server setup on its separate thread. + int retries = 10; + int sock = -1; + while (sock == -1 && retries-- > 0) { + sock = create_socket(port); + if (sock < 0) { + sleep(1); + } + } + GPR_ASSERT(sock > 0); + gpr_log(GPR_INFO, "Connected to server on port %d", port); + + // Establish a SSL* and connect at SSL layer. + SSL* ssl = SSL_new(ctx); + GPR_ASSERT(ssl); + SSL_set_fd(ssl, sock); + if (SSL_connect(ssl) <= 0) { + ERR_print_errors_fp(stderr); + gpr_log(GPR_ERROR, "Handshake failed."); + success = false; + } else { + gpr_log(GPR_INFO, "Handshake successful."); + // Validate ALPN preferred by server matches alpn_expected. + const unsigned char* alpn_selected; + unsigned int alpn_selected_len; + SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len); + if (strlen(alpn_expected) != alpn_selected_len || + strncmp((const char*)alpn_selected, alpn_expected, alpn_selected_len) != + 0) { + gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference"); + success = false; + } + } + gpr_event_set(&client_handshake_complete, &client_handshake_complete); + + SSL_free(ssl); + gpr_free(alpn_protos); + SSL_CTX_free(ctx); + EVP_cleanup(); + close(sock); + + gpr_thd_join(thdid); + + grpc_shutdown(); + + return success; +} diff --git a/test/core/handshake/server_ssl_common.h b/test/core/handshake/server_ssl_common.h new file mode 100644 index 0000000000..77865a408f --- /dev/null +++ b/test/core/handshake/server_ssl_common.h @@ -0,0 +1,36 @@ +/* + * + * Copyright 2016 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_SERVER_SSL_COMMON_H +#define GRPC_SERVER_SSL_COMMON_H + +#include <grpc/grpc.h> +#include <grpc/grpc_security.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/sync.h> +#include <grpc/support/thd.h> +#include "src/core/lib/iomgr/load_file.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len, + const char* alpn_expected); + +#endif // GRPC_SERVER_SSL_COMMON_H diff --git a/test/core/util/BUILD b/test/core/util/BUILD index bc6fe9dd64..2437923435 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -103,6 +103,7 @@ grpc_cc_library( grpc_cc_library( name = "fuzzer_corpus_test", + testonly = 1, srcs = ["fuzzer_corpus_test.cc"], deps = [ ":gpr_test_util", diff --git a/test/cpp/client/BUILD b/test/cpp/client/BUILD new file mode 100644 index 0000000000..12825e88c2 --- /dev/null +++ b/test/cpp/client/BUILD @@ -0,0 +1,51 @@ +# 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. + +licenses(["notice"]) # Apache v2 + +load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package") + +grpc_package(name = "test/cpp/client") + +grpc_cc_test( + name = "credentials_test", + srcs = ["credentials_test.cc"], + external_deps = [ + "gtest", + ], + deps = [ + "//:gpr", + "//:grpc", + "//:grpc++", + ], +) + +grpc_cc_test( + name = "client_channel_stress_test", + srcs = ["client_channel_stress_test.cc"], + deps = [ + "//:gpr", + "//:grpc", + "//:grpc++", + "//:grpc_resolver_fake", + "//src/proto/grpc/lb/v1:load_balancer_proto", + "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/end2end:test_service_impl", + "//test/cpp/util:test_util", + ], +) diff --git a/test/cpp/client/client_channel_stress_test.cc b/test/cpp/client/client_channel_stress_test.cc new file mode 100644 index 0000000000..8940f6ff9e --- /dev/null +++ b/test/cpp/client/client_channel_stress_test.cc @@ -0,0 +1,329 @@ +/* + * + * 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. + * + */ + +#include <atomic> +#include <memory> +#include <mutex> +#include <sstream> +#include <thread> + +#include <grpc++/channel.h> +#include <grpc++/client_context.h> +#include <grpc++/create_channel.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/thd.h> +#include <grpc/support/time.h> + +extern "C" { +#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" +#include "src/core/lib/iomgr/sockaddr.h" +} + +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" + +#include "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" + +using grpc::lb::v1::LoadBalanceRequest; +using grpc::lb::v1::LoadBalanceResponse; +using grpc::lb::v1::LoadBalancer; + +namespace grpc { +namespace testing { +namespace { + +const size_t kNumBackends = 10; +const size_t kNumBalancers = 5; +const size_t kNumClientThreads = 100; +const int kResolutionUpdateIntervalMs = 50; +const int kServerlistUpdateIntervalMs = 10; +const int kTestDurationSec = 30; + +using BackendServiceImpl = TestServiceImpl; + +class BalancerServiceImpl : public LoadBalancer::Service { + public: + using Stream = ServerReaderWriter<LoadBalanceResponse, LoadBalanceRequest>; + + explicit BalancerServiceImpl(const std::vector<int>& all_backend_ports) + : all_backend_ports_(all_backend_ports) {} + + Status BalanceLoad(ServerContext* context, Stream* stream) override { + gpr_log(GPR_INFO, "LB[%p]: Start BalanceLoad.", this); + LoadBalanceRequest request; + stream->Read(&request); + while (!shutdown_) { + stream->Write(BuildRandomResponseForBackends()); + std::this_thread::sleep_for( + std::chrono::milliseconds(kServerlistUpdateIntervalMs)); + } + gpr_log(GPR_INFO, "LB[%p]: Finish BalanceLoad.", this); + return Status::OK; + } + + void Shutdown() { shutdown_ = true; } + + private: + grpc::string Ip4ToPackedString(const char* ip_str) { + struct in_addr ip4; + GPR_ASSERT(inet_pton(AF_INET, ip_str, &ip4) == 1); + return grpc::string(reinterpret_cast<const char*>(&ip4), sizeof(ip4)); + } + + LoadBalanceResponse BuildRandomResponseForBackends() { + // Generate a random serverlist with varying size (if N = + // all_backend_ports_.size(), num_non_drop_entry is in [0, 2N], + // num_drop_entry is in [0, N]), order, duplicate, and drop rate. + size_t num_non_drop_entry = + std::rand() % (all_backend_ports_.size() * 2 + 1); + size_t num_drop_entry = std::rand() % (all_backend_ports_.size() + 1); + std::vector<int> random_backend_indices; + for (size_t i = 0; i < num_non_drop_entry; ++i) { + random_backend_indices.push_back(std::rand() % all_backend_ports_.size()); + } + for (size_t i = 0; i < num_drop_entry; ++i) { + random_backend_indices.push_back(-1); + } + std::random_shuffle(random_backend_indices.begin(), + random_backend_indices.end()); + // Build the response according to the random list generated above. + LoadBalanceResponse response; + for (int index : random_backend_indices) { + auto* server = response.mutable_server_list()->add_servers(); + if (index < 0) { + server->set_drop(true); + server->set_load_balance_token("load_balancing"); + } else { + server->set_ip_address(Ip4ToPackedString("127.0.0.1")); + server->set_port(all_backend_ports_[index]); + } + } + return response; + } + + std::atomic_bool shutdown_{false}; + const std::vector<int> all_backend_ports_; +}; + +class ClientChannelStressTest { + public: + void Run() { + Start(); + // Keep updating resolution for the test duration. + gpr_log(GPR_INFO, "Start updating resolution."); + const auto wait_duration = + std::chrono::milliseconds(kResolutionUpdateIntervalMs); + std::vector<AddressData> addresses; + auto start_time = std::chrono::steady_clock::now(); + while (true) { + if (std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::steady_clock::now() - start_time) + .count() > kTestDurationSec) { + break; + } + // Generate a random subset of balancers. + addresses.clear(); + for (const auto& balancer_server : balancer_servers_) { + // Select each address with probability of 0.8. + if (std::rand() % 10 < 8) { + addresses.emplace_back(AddressData{balancer_server.port_, true, ""}); + } + } + std::random_shuffle(addresses.begin(), addresses.end()); + SetNextResolution(addresses); + std::this_thread::sleep_for(wait_duration); + } + gpr_log(GPR_INFO, "Finish updating resolution."); + Shutdown(); + } + + private: + template <typename T> + struct ServerThread { + explicit ServerThread(const grpc::string& type, + const grpc::string& server_host, T* service) + : type_(type), service_(service) { + std::mutex mu; + // We need to acquire the lock here in order to prevent the notify_one + // by ServerThread::Start from firing before the wait below is hit. + std::unique_lock<std::mutex> lock(mu); + port_ = grpc_pick_unused_port_or_die(); + gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); + std::condition_variable cond; + thread_.reset(new std::thread( + std::bind(&ServerThread::Start, this, server_host, &mu, &cond))); + cond.wait(lock); + gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); + } + + void Start(const grpc::string& server_host, std::mutex* mu, + std::condition_variable* cond) { + // We need to acquire the lock here in order to prevent the notify_one + // below from firing before its corresponding wait is executed. + std::lock_guard<std::mutex> lock(*mu); + std::ostringstream server_address; + server_address << server_host << ":" << port_; + ServerBuilder builder; + builder.AddListeningPort(server_address.str(), + InsecureServerCredentials()); + builder.RegisterService(service_); + server_ = builder.BuildAndStart(); + cond->notify_one(); + } + + void Shutdown() { + gpr_log(GPR_INFO, "%s about to shutdown", type_.c_str()); + server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0)); + thread_->join(); + gpr_log(GPR_INFO, "%s shutdown completed", type_.c_str()); + } + + int port_; + grpc::string type_; + std::unique_ptr<Server> server_; + T* service_; + std::unique_ptr<std::thread> thread_; + }; + + struct AddressData { + int port; + bool is_balancer; + grpc::string balancer_name; + }; + + void SetNextResolution(const std::vector<AddressData>& address_data) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_lb_addresses* addresses = + grpc_lb_addresses_create(address_data.size(), nullptr); + for (size_t i = 0; i < address_data.size(); ++i) { + char* lb_uri_str; + gpr_asprintf(&lb_uri_str, "ipv4:127.0.0.1:%d", address_data[i].port); + grpc_uri* lb_uri = grpc_uri_parse(&exec_ctx, lb_uri_str, true); + GPR_ASSERT(lb_uri != nullptr); + grpc_lb_addresses_set_address_from_uri( + addresses, i, lb_uri, address_data[i].is_balancer, + address_data[i].balancer_name.c_str(), nullptr); + grpc_uri_destroy(lb_uri); + gpr_free(lb_uri_str); + } + grpc_arg fake_addresses = grpc_lb_addresses_create_channel_arg(addresses); + grpc_channel_args fake_result = {1, &fake_addresses}; + grpc_fake_resolver_response_generator_set_response( + &exec_ctx, response_generator_, &fake_result); + grpc_lb_addresses_destroy(&exec_ctx, addresses); + grpc_exec_ctx_finish(&exec_ctx); + } + + void KeepSendingRequests() { + gpr_log(GPR_INFO, "Start sending requests."); + while (!shutdown_) { + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(1000)); + EchoRequest request; + request.set_message("test"); + EchoResponse response; + { + std::lock_guard<std::mutex> lock(stub_mutex_); + stub_->Echo(&context, request, &response); + } + } + gpr_log(GPR_INFO, "Finish sending requests."); + } + + void CreateStub() { + ChannelArguments args; + response_generator_ = grpc_fake_resolver_response_generator_create(); + args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, + response_generator_); + std::ostringstream uri; + uri << "fake:///servername_not_used"; + channel_ = + CreateCustomChannel(uri.str(), InsecureChannelCredentials(), args); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + void Start() { + // Start the backends. + std::vector<int> backend_ports; + for (size_t i = 0; i < kNumBackends; ++i) { + backends_.emplace_back(new BackendServiceImpl()); + backend_servers_.emplace_back(ServerThread<BackendServiceImpl>( + "backend", server_host_, backends_.back().get())); + backend_ports.push_back(backend_servers_.back().port_); + } + // Start the load balancers. + for (size_t i = 0; i < kNumBalancers; ++i) { + balancers_.emplace_back(new BalancerServiceImpl(backend_ports)); + balancer_servers_.emplace_back(ServerThread<BalancerServiceImpl>( + "balancer", server_host_, balancers_.back().get())); + } + // Start sending RPCs in multiple threads. + CreateStub(); + for (size_t i = 0; i < kNumClientThreads; ++i) { + client_threads_.emplace_back( + std::thread(&ClientChannelStressTest::KeepSendingRequests, this)); + } + } + + void Shutdown() { + shutdown_ = true; + for (size_t i = 0; i < client_threads_.size(); ++i) { + client_threads_[i].join(); + } + for (size_t i = 0; i < balancers_.size(); ++i) { + balancers_[i]->Shutdown(); + balancer_servers_[i].Shutdown(); + } + for (size_t i = 0; i < backends_.size(); ++i) { + backend_servers_[i].Shutdown(); + } + grpc_fake_resolver_response_generator_unref(response_generator_); + } + + std::atomic_bool shutdown_{false}; + const grpc::string server_host_ = "localhost"; + std::shared_ptr<Channel> channel_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::mutex stub_mutex_; + std::vector<std::unique_ptr<BackendServiceImpl>> backends_; + std::vector<std::unique_ptr<BalancerServiceImpl>> balancers_; + std::vector<ServerThread<BackendServiceImpl>> backend_servers_; + std::vector<ServerThread<BalancerServiceImpl>> balancer_servers_; + grpc_fake_resolver_response_generator* response_generator_; + std::vector<std::thread> client_threads_; +}; + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc_init(); + grpc_test_init(argc, argv); + grpc::testing::ClientChannelStressTest test; + test.Run(); + grpc_shutdown(); + return 0; +} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 6cd9a04056..e97178180e 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1207,12 +1207,37 @@ "grpc", "grpc_test_util" ], - "headers": [], + "headers": [ + "test/core/handshake/server_ssl_common.h" + ], "is_filegroup": false, "language": "c", "name": "handshake_server", "src": [ - "test/core/handshake/server_ssl.cc" + "test/core/handshake/server_ssl.cc", + "test/core/handshake/server_ssl_common.cc", + "test/core/handshake/server_ssl_common.h" + ], + "third_party": false, + "type": "target" + }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [ + "test/core/handshake/server_ssl_common.h" + ], + "is_filegroup": false, + "language": "c", + "name": "handshake_server_with_readahead_handshaker", + "src": [ + "test/core/handshake/readahead_handshaker_server_ssl.cc", + "test/core/handshake/server_ssl_common.cc", + "test/core/handshake/server_ssl_common.h" ], "third_party": false, "type": "target" @@ -2895,6 +2920,29 @@ "grpc++_test_util", "grpc_test_util" ], + "headers": [ + "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h", + "src/proto/grpc/lb/v1/load_balancer.pb.h", + "src/proto/grpc/lb/v1/load_balancer_mock.grpc.pb.h" + ], + "is_filegroup": false, + "language": "c++", + "name": "client_channel_stress_test", + "src": [ + "test/cpp/client/client_channel_stress_test.cc" + ], + "third_party": false, + "type": "target" + }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc++", + "grpc++_test_util", + "grpc_test_util" + ], "headers": [], "is_filegroup": false, "language": "c++", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 5df5a7477b..4a5817cad1 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1507,6 +1507,26 @@ "args": [], "benchmark": false, "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "gtest": false, + "language": "c", + "name": "handshake_server_with_readahead_handshaker", + "platforms": [ + "linux" + ], + "uses_polling": true + }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ "linux", "mac", "posix", @@ -3371,6 +3391,30 @@ "ci_platforms": [ "linux", "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c++", + "name": "client_channel_stress_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", "posix" ], "cpu_cost": 0.1, |