aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar ncteisen <ncteisen@gmail.com>2017-11-14 17:09:48 -0800
committerGravatar ncteisen <ncteisen@gmail.com>2017-11-14 17:09:48 -0800
commitb60615895512e2e969d31dbaf7f9eed584b453e0 (patch)
tree69079043b19931d89d8ea275af2af81e0a7a426b
parent88a7a9f82e3a78f28b3e6eb1fba474051d72173b (diff)
parent070f0c4b677c89052fa92bd24e9541ac1c0ef827 (diff)
Merge branch 'master' of https://github.com/grpc/grpc into inheritance-in-core
-rw-r--r--BUILD88
-rw-r--r--CMakeLists.txt87
-rw-r--r--Makefile98
-rw-r--r--bazel/grpc_build_system.bzl4
-rw-r--r--build.yaml35
-rw-r--r--include/grpc++/impl/codegen/completion_queue.h32
-rw-r--r--src/compiler/protobuf_plugin.h1
-rw-r--r--src/compiler/python_generator_helpers.h2
-rw-r--r--src/core/lib/security/transport/security_handshaker.cc45
-rw-r--r--src/core/lib/support/cpu_linux.cc10
-rw-r--r--src/proto/grpc/testing/BUILD1
-rw-r--r--src/proto/grpc/testing/services.proto1
-rw-r--r--test/core/handshake/BUILD31
-rw-r--r--test/core/handshake/readahead_handshaker_server_ssl.cc103
-rw-r--r--test/core/handshake/server_ssl.cc201
-rw-r--r--test/core/handshake/server_ssl_common.cc238
-rw-r--r--test/core/handshake/server_ssl_common.h36
-rw-r--r--test/core/util/BUILD1
-rw-r--r--test/cpp/client/BUILD51
-rw-r--r--test/cpp/client/client_channel_stress_test.cc329
-rw-r--r--tools/run_tests/generated/sources_and_headers.json52
-rw-r--r--tools/run_tests/generated/tests.json44
22 files changed, 1213 insertions, 277 deletions
diff --git a/BUILD b/BUILD
index ba927582c1..bf4b4fcf15 100644
--- a/BUILD
+++ b/BUILD
@@ -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 4c632c14ce..21a4a4f773 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -463,6 +463,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)
@@ -676,6 +679,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()
@@ -7265,6 +7269,7 @@ if(_gRPC_PLATFORM_LINUX)
add_executable(handshake_server
test/core/handshake/server_ssl.cc
+ test/core/handshake/server_ssl_common.cc
)
@@ -7294,6 +7299,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
@@ -10059,6 +10098,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
diff --git a/Makefile b/Makefile
index d17afad155..591da10fd2 100644
--- a/Makefile
+++ b/Makefile
@@ -1021,6 +1021,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
@@ -1115,6 +1116,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
@@ -1411,6 +1413,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 \
@@ -1556,6 +1559,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 \
@@ -1681,6 +1685,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 \
@@ -1881,6 +1886,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"
@@ -2065,6 +2072,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"
@@ -2504,12 +2513,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) $<
@@ -11087,6 +11096,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)
@@ -11108,6 +11118,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)
@@ -11117,6 +11129,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 \
@@ -14373,6 +14420,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 d0c2bec106..864429f856 100644
--- a/build.yaml
+++ b/build.yaml
@@ -2522,8 +2522,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
@@ -3818,6 +3839,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 a1a5020b42..1cbf128161 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -1222,12 +1222,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"
@@ -2910,6 +2935,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 70b452453d..dfd7bfafe6 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -1531,6 +1531,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",
@@ -3395,6 +3415,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,