Merge github.com:grpc/grpc into grpc_millis

pull/11866/head
Craig Tiller 8 years ago
commit da8a169928
  1. 4
      BUILD
  2. 84
      CMakeLists.txt
  3. 90
      Makefile
  4. 5
      WORKSPACE
  5. 2
      binding.gyp
  6. 43
      build.yaml
  7. 2
      config.m4
  8. 2
      config.w32
  9. 8
      doc/environment_variables.md
  10. 7
      gRPC-Core.podspec
  11. 1
      grpc.def
  12. 12
      grpc.gemspec
  13. 8
      grpc.gyp
  14. 4
      include/grpc++/impl/codegen/sync_stream.h
  15. 3
      include/grpc/grpc.h
  16. 7
      include/grpc/impl/codegen/slice.h
  17. 4
      package.xml
  18. 12
      src/core/ext/census/context.c
  19. 24
      src/core/ext/census/grpc_filter.c
  20. 3
      src/core/ext/census/mlog.c
  21. 22
      src/core/ext/census/resource.c
  22. 6
      src/core/ext/filters/client_channel/channel_connectivity.c
  23. 10
      src/core/ext/filters/client_channel/client_channel.c
  24. 36
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c
  25. 2
      src/core/ext/filters/max_age/max_age_filter.c
  26. 11
      src/core/ext/transport/chttp2/transport/writing.c
  27. 75
      src/core/ext/transport/cronet/transport/cronet_transport.c
  28. 26
      src/core/lib/iomgr/call_combiner.h
  29. 45
      src/core/lib/iomgr/ev_epoll1_linux.c
  30. 1940
      src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
  31. 28
      src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h
  32. 1181
      src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
  33. 28
      src/core/lib/iomgr/ev_epoll_thread_pool_linux.h
  34. 4
      src/core/lib/iomgr/ev_posix.c
  35. 8
      src/core/lib/iomgr/iomgr.c
  36. 5
      src/core/lib/iomgr/tcp_posix.c
  37. 10
      src/core/lib/security/transport/client_auth_filter.c
  38. 1
      src/core/lib/security/transport/server_auth_filter.c
  39. 13
      src/core/lib/support/string.c
  40. 3
      src/core/lib/support/string.h
  41. 6
      src/core/lib/surface/call.c
  42. 10
      src/core/lib/surface/call.h
  43. 2
      src/core/lib/surface/call_log_batch.c
  44. 2
      src/core/lib/transport/metadata_batch.c
  45. 1
      src/core/lib/transport/metadata_batch.h
  46. 25
      src/core/lib/transport/static_metadata.c
  47. 2
      src/core/lib/transport/static_metadata.h
  48. 14
      src/core/tsi/test_creds/BUILD
  49. 202
      src/cpp/client/channel_cc.cc
  50. 9
      src/cpp/server/server_cc.cc
  51. 2
      src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
  52. 2
      src/objective-c/!ProtoCompiler.podspec
  53. 2
      src/python/grpcio/grpc_core_dependencies.py
  54. 289
      src/python/grpcio_testing/grpc_testing/__init__.py
  55. 68
      src/python/grpcio_testing/grpc_testing/_common.py
  56. 20
      src/python/grpcio_testing/grpc_testing/_server/__init__.py
  57. 215
      src/python/grpcio_testing/grpc_testing/_server/_handler.py
  58. 153
      src/python/grpcio_testing/grpc_testing/_server/_rpc.py
  59. 149
      src/python/grpcio_testing/grpc_testing/_server/_server.py
  60. 93
      src/python/grpcio_testing/grpc_testing/_server/_server_rpc.py
  61. 88
      src/python/grpcio_testing/grpc_testing/_server/_service.py
  62. 74
      src/python/grpcio_testing/grpc_testing/_server/_servicer_context.py
  63. 66
      src/python/grpcio_tests/tests/testing/_server_application.py
  64. 169
      src/python/grpcio_tests/tests/testing/_server_test.py
  65. 1
      src/python/grpcio_tests/tests/tests.json
  66. 565
      src/ruby/.rubocop_todo.yml
  67. 2
      src/ruby/end2end/grpc_class_init_client.rb
  68. 2
      src/ruby/ext/grpc/rb_grpc_imports.generated.c
  69. 3
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  70. 1
      templates/gRPC-Core.podspec.template
  71. 8
      templates/grpc.gemspec.template
  72. 2
      templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template
  73. 9
      test/core/end2end/tests/cancel_after_accept.c
  74. 6
      test/core/end2end/tests/cancel_after_client_done.c
  75. 9
      test/core/end2end/tests/cancel_after_round_trip.c
  76. 6
      test/core/end2end/tests/cancel_before_invoke.c
  77. 6
      test/core/end2end/tests/cancel_in_a_vacuum.c
  78. 6
      test/core/end2end/tests/cancel_with_status.c
  79. 16
      test/core/support/string_test.c
  80. 52
      test/core/tsi/BUILD
  81. 148
      test/core/tsi/fake_transport_security_test.c
  82. 558
      test/core/tsi/ssl_transport_security_test.c
  83. 550
      test/core/tsi/transport_security_test_lib.c
  84. 165
      test/core/tsi/transport_security_test_lib.h
  85. 2
      test/cpp/end2end/BUILD
  86. 134
      test/cpp/end2end/async_end2end_test.cc
  87. 7
      test/cpp/end2end/client_lb_end2end_test.cc
  88. 26
      test/cpp/end2end/end2end_test.cc
  89. 32
      third_party/gtest.BUILD
  90. 5
      tools/codegen/core/gen_hpack_tables.c
  91. 64
      tools/codegen/core/gen_static_metadata.py
  92. 2
      tools/doxygen/Doxyfile.c++.internal
  93. 4
      tools/doxygen/Doxyfile.core.internal
  94. 2
      tools/gce/create_linux_performance_worker.sh
  95. 3
      tools/internal_ci/helper_scripts/prepare_build_macos_rc
  96. 2
      tools/internal_ci/macos/grpc_basictests_dbg.cfg
  97. 2
      tools/internal_ci/macos/grpc_basictests_opt.cfg
  98. 57
      tools/run_tests/generated/sources_and_headers.json
  99. 40
      tools/run_tests/generated/tests.json
  100. 359
      tools/run_tests/run_performance_tests.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -584,8 +584,6 @@ grpc_cc_library(
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/error.c",
"src/core/lib/iomgr/ev_epoll1_linux.c",
"src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c",
"src/core/lib/iomgr/ev_epoll_thread_pool_linux.c",
"src/core/lib/iomgr/ev_epollex_linux.c",
"src/core/lib/iomgr/ev_epollsig_linux.c",
"src/core/lib/iomgr/ev_poll_posix.c",
@ -717,8 +715,6 @@ grpc_cc_library(
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_epoll1_linux.h",
"src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h",
"src/core/lib/iomgr/ev_epoll_thread_pool_linux.h",
"src/core/lib/iomgr/ev_epollex_linux.h",
"src/core/lib/iomgr/ev_epollsig_linux.h",
"src/core/lib/iomgr/ev_poll_posix.h",

@ -422,6 +422,9 @@ add_dependencies(buildtests_c ev_epollsig_linux_test)
endif()
add_dependencies(buildtests_c fake_resolver_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c fake_transport_security_test)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c fd_conservation_posix_test)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@ -530,6 +533,9 @@ add_dependencies(buildtests_c sockaddr_utils_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c socket_utils_test)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c ssl_transport_security_test)
endif()
add_dependencies(buildtests_c status_conversion_test)
add_dependencies(buildtests_c stream_compression_test)
add_dependencies(buildtests_c stream_owned_slice_test)
@ -976,8 +982,6 @@ add_library(grpc
src/core/lib/iomgr/endpoint_pair_windows.c
src/core/lib/iomgr/error.c
src/core/lib/iomgr/ev_epoll1_linux.c
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
src/core/lib/iomgr/ev_epollex_linux.c
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
@ -1329,8 +1333,6 @@ add_library(grpc_cronet
src/core/lib/iomgr/endpoint_pair_windows.c
src/core/lib/iomgr/error.c
src/core/lib/iomgr/ev_epoll1_linux.c
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
src/core/lib/iomgr/ev_epollex_linux.c
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
@ -1650,8 +1652,6 @@ add_library(grpc_test_util
src/core/lib/iomgr/endpoint_pair_windows.c
src/core/lib/iomgr/error.c
src/core/lib/iomgr/ev_epoll1_linux.c
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
src/core/lib/iomgr/ev_epollex_linux.c
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
@ -1915,8 +1915,6 @@ add_library(grpc_test_util_unsecure
src/core/lib/iomgr/endpoint_pair_windows.c
src/core/lib/iomgr/error.c
src/core/lib/iomgr/ev_epoll1_linux.c
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
src/core/lib/iomgr/ev_epollex_linux.c
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
@ -2166,8 +2164,6 @@ add_library(grpc_unsecure
src/core/lib/iomgr/endpoint_pair_windows.c
src/core/lib/iomgr/error.c
src/core/lib/iomgr/ev_epoll1_linux.c
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
src/core/lib/iomgr/ev_epollex_linux.c
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
@ -2869,8 +2865,6 @@ add_library(grpc++_cronet
src/core/lib/iomgr/endpoint_pair_windows.c
src/core/lib/iomgr/error.c
src/core/lib/iomgr/ev_epoll1_linux.c
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
src/core/lib/iomgr/ev_epollex_linux.c
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
@ -6008,6 +6002,39 @@ endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(fake_transport_security_test
test/core/tsi/fake_transport_security_test.c
test/core/tsi/transport_security_test_lib.c
)
target_include_directories(fake_transport_security_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_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(fake_transport_security_test
${_gRPC_ALLTARGETS_LIBRARIES}
gpr_test_util
gpr
grpc
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(fd_conservation_posix_test
test/core/iomgr/fd_conservation_posix_test.c
)
@ -8721,6 +8748,39 @@ target_link_libraries(socket_utils_test
gpr
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(ssl_transport_security_test
test/core/tsi/ssl_transport_security_test.c
test/core/tsi/transport_security_test_lib.c
)
target_include_directories(ssl_transport_security_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_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(ssl_transport_security_test
${_gRPC_ALLTARGETS_LIBRARIES}
gpr_test_util
gpr
grpc
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)

@ -977,6 +977,7 @@ endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
error_test: $(BINDIR)/$(CONFIG)/error_test
ev_epollsig_linux_test: $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test
fake_resolver_test: $(BINDIR)/$(CONFIG)/fake_resolver_test
fake_transport_security_test: $(BINDIR)/$(CONFIG)/fake_transport_security_test
fd_conservation_posix_test: $(BINDIR)/$(CONFIG)/fd_conservation_posix_test
fd_posix_test: $(BINDIR)/$(CONFIG)/fd_posix_test
fling_client: $(BINDIR)/$(CONFIG)/fling_client
@ -1075,6 +1076,7 @@ sockaddr_resolver_test: $(BINDIR)/$(CONFIG)/sockaddr_resolver_test
sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test
socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test
ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer
ssl_transport_security_test: $(BINDIR)/$(CONFIG)/ssl_transport_security_test
status_conversion_test: $(BINDIR)/$(CONFIG)/status_conversion_test
stream_compression_test: $(BINDIR)/$(CONFIG)/stream_compression_test
stream_owned_slice_test: $(BINDIR)/$(CONFIG)/stream_owned_slice_test
@ -1367,6 +1369,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/error_test \
$(BINDIR)/$(CONFIG)/ev_epollsig_linux_test \
$(BINDIR)/$(CONFIG)/fake_resolver_test \
$(BINDIR)/$(CONFIG)/fake_transport_security_test \
$(BINDIR)/$(CONFIG)/fd_conservation_posix_test \
$(BINDIR)/$(CONFIG)/fd_posix_test \
$(BINDIR)/$(CONFIG)/fling_client \
@ -1448,6 +1451,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/sockaddr_resolver_test \
$(BINDIR)/$(CONFIG)/sockaddr_utils_test \
$(BINDIR)/$(CONFIG)/socket_utils_test \
$(BINDIR)/$(CONFIG)/ssl_transport_security_test \
$(BINDIR)/$(CONFIG)/status_conversion_test \
$(BINDIR)/$(CONFIG)/stream_compression_test \
$(BINDIR)/$(CONFIG)/stream_owned_slice_test \
@ -1790,6 +1794,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test || ( echo test ev_epollsig_linux_test failed ; exit 1 )
$(E) "[RUN] Testing fake_resolver_test"
$(Q) $(BINDIR)/$(CONFIG)/fake_resolver_test || ( echo test fake_resolver_test failed ; exit 1 )
$(E) "[RUN] Testing fake_transport_security_test"
$(Q) $(BINDIR)/$(CONFIG)/fake_transport_security_test || ( echo test fake_transport_security_test failed ; exit 1 )
$(E) "[RUN] Testing fd_conservation_posix_test"
$(Q) $(BINDIR)/$(CONFIG)/fd_conservation_posix_test || ( echo test fd_conservation_posix_test failed ; exit 1 )
$(E) "[RUN] Testing fd_posix_test"
@ -1936,6 +1942,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/sockaddr_utils_test || ( echo test sockaddr_utils_test failed ; exit 1 )
$(E) "[RUN] Testing socket_utils_test"
$(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 )
$(E) "[RUN] Testing ssl_transport_security_test"
$(Q) $(BINDIR)/$(CONFIG)/ssl_transport_security_test || ( echo test ssl_transport_security_test failed ; exit 1 )
$(E) "[RUN] Testing status_conversion_test"
$(Q) $(BINDIR)/$(CONFIG)/status_conversion_test || ( echo test status_conversion_test failed ; exit 1 )
$(E) "[RUN] Testing stream_compression_test"
@ -2921,8 +2929,6 @@ LIBGRPC_SRC = \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -3272,8 +3278,6 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -3590,8 +3594,6 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -3844,8 +3846,6 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -4071,8 +4071,6 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -4757,8 +4755,6 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -9645,6 +9641,41 @@ endif
endif
FAKE_TRANSPORT_SECURITY_TEST_SRC = \
test/core/tsi/fake_transport_security_test.c \
test/core/tsi/transport_security_test_lib.c \
FAKE_TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FAKE_TRANSPORT_SECURITY_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/fake_transport_security_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/fake_transport_security_test: $(FAKE_TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(FAKE_TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/fake_transport_security_test
endif
$(OBJDIR)/$(CONFIG)/test/core/tsi/fake_transport_security_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
$(OBJDIR)/$(CONFIG)/test/core/tsi/transport_security_test_lib.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
deps_fake_transport_security_test: $(FAKE_TRANSPORT_SECURITY_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(FAKE_TRANSPORT_SECURITY_TEST_OBJS:.o=.dep)
endif
endif
FD_CONSERVATION_POSIX_TEST_SRC = \
test/core/iomgr/fd_conservation_posix_test.c \
@ -12781,6 +12812,41 @@ endif
endif
SSL_TRANSPORT_SECURITY_TEST_SRC = \
test/core/tsi/ssl_transport_security_test.c \
test/core/tsi/transport_security_test_lib.c \
SSL_TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SSL_TRANSPORT_SECURITY_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/ssl_transport_security_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/ssl_transport_security_test: $(SSL_TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(SSL_TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/ssl_transport_security_test
endif
$(OBJDIR)/$(CONFIG)/test/core/tsi/ssl_transport_security_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
$(OBJDIR)/$(CONFIG)/test/core/tsi/transport_security_test_lib.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
deps_ssl_transport_security_test: $(SSL_TRANSPORT_SECURITY_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(SSL_TRANSPORT_SECURITY_TEST_OBJS:.o=.dep)
endif
endif
STATUS_CONVERSION_TEST_SRC = \
test/core/transport/status_conversion_test.c \

@ -38,6 +38,11 @@ bind(
actual = "@submodule_gtest//:gtest",
)
bind(
name = "gmock",
actual = "@submodule_gtest//:gmock",
)
bind(
name = "benchmark",
actual = "@submodule_benchmark//:benchmark",

@ -681,8 +681,6 @@
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll1_linux.c',
'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c',
'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c',
'src/core/lib/iomgr/ev_epollex_linux.c',
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',

@ -208,8 +208,6 @@ filegroups:
- src/core/lib/iomgr/endpoint_pair_windows.c
- src/core/lib/iomgr/error.c
- src/core/lib/iomgr/ev_epoll1_linux.c
- src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
- src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
- src/core/lib/iomgr/ev_epollex_linux.c
- src/core/lib/iomgr/ev_epollsig_linux.c
- src/core/lib/iomgr/ev_poll_posix.c
@ -361,8 +359,6 @@ filegroups:
- src/core/lib/iomgr/error.h
- src/core/lib/iomgr/error_internal.h
- src/core/lib/iomgr/ev_epoll1_linux.h
- src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h
- src/core/lib/iomgr/ev_epoll_thread_pool_linux.h
- src/core/lib/iomgr/ev_epollex_linux.h
- src/core/lib/iomgr/ev_epollsig_linux.h
- src/core/lib/iomgr/ev_poll_posix.h
@ -752,6 +748,7 @@ filegroups:
- test/core/util/trickle_endpoint.c
deps:
- gpr_test_util
- gpr
uses:
- grpc_base
- grpc_client_channel
@ -926,6 +923,14 @@ filegroups:
- third_party/nanopb/pb_common.h
- third_party/nanopb/pb_decode.h
- third_party/nanopb/pb_encode.h
- name: transport_security_test_lib
build: test
headers:
- test/core/tsi/transport_security_test_lib.h
src:
- test/core/tsi/transport_security_test_lib.c
deps:
- grpc
- name: tsi
headers:
- src/core/tsi/fake_transport_security.h
@ -2046,6 +2051,21 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: fake_transport_security_test
build: test
language: c
src:
- test/core/tsi/fake_transport_security_test.c
deps:
- gpr_test_util
- gpr
- grpc
filegroups:
- transport_security_test_lib
platforms:
- linux
- posix
- mac
- name: fd_conservation_posix_test
build: test
language: c
@ -3109,6 +3129,21 @@ targets:
corpus_dirs:
- test/core/security/corpus/ssl_server_corpus
maxlen: 2048
- name: ssl_transport_security_test
build: test
language: c
src:
- test/core/tsi/ssl_transport_security_test.c
deps:
- gpr_test_util
- gpr
- grpc
filegroups:
- transport_security_test_lib
platforms:
- linux
- posix
- mac
- name: status_conversion_test
build: test
language: c

@ -110,8 +110,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \

@ -87,8 +87,6 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\iomgr\\endpoint_pair_windows.c " +
"src\\core\\lib\\iomgr\\error.c " +
"src\\core\\lib\\iomgr\\ev_epoll1_linux.c " +
"src\\core\\lib\\iomgr\\ev_epoll_limited_pollers_linux.c " +
"src\\core\\lib\\iomgr\\ev_epoll_thread_pool_linux.c " +
"src\\core\\lib\\iomgr\\ev_epollex_linux.c " +
"src\\core\\lib\\iomgr\\ev_epollsig_linux.c " +
"src\\core\\lib\\iomgr\\ev_poll_posix.c " +

@ -114,3 +114,11 @@ some configuration as environment variables that can be set.
- native (default)- a DNS resolver based around getaddrinfo(), creates a new thread to
perform name resolution
- ares - a DNS resolver based around the c-ares library
* GRPC_DISABLE_CHANNEL_CONNECTIVITY_WATCHER
The channel connectivity watcher uses one extra thread to check the channel
state every 500 ms on the client side. It can help reconnect disconnected
client channels (mostly due to idleness), so that the next RPC on this channel
won't fail. Set to 1 to turn off this watcher and save a thread. Please note
this is a temporary work-around, it will be removed in the future once we have
support for automatically reestablishing failed connections.

@ -341,8 +341,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error.h',
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h',
'src/core/lib/iomgr/ev_epoll_thread_pool_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.h',
'src/core/lib/iomgr/ev_epollsig_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h',
@ -494,8 +492,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll1_linux.c',
'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c',
'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c',
'src/core/lib/iomgr/ev_epollex_linux.c',
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',
@ -841,8 +837,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error.h',
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h',
'src/core/lib/iomgr/ev_epoll_thread_pool_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.h',
'src/core/lib/iomgr/ev_epollsig_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h',
@ -997,6 +991,7 @@ Pod::Spec.new do |s|
'test/core/end2end/end2end_tests.{c,h}',
'test/core/end2end/end2end_test_utils.c',
'test/core/end2end/tests/*.{c,h}',
'test/core/end2end/fixtures/*.h',
'test/core/end2end/data/*.{c,h}',
'test/core/util/debugger_macros.{c,h}',
'test/core/util/test_config.{c,h}',

@ -70,6 +70,7 @@ EXPORTS
grpc_channel_check_connectivity_state
grpc_channel_num_external_connectivity_watchers
grpc_channel_watch_connectivity_state
grpc_channel_support_connectivity_watcher
grpc_channel_create_call
grpc_channel_ping
grpc_channel_register_call

@ -33,12 +33,12 @@ Gem::Specification.new do |s|
s.add_development_dependency 'bundler', '~> 1.9'
s.add_development_dependency 'facter', '~> 2.4'
s.add_development_dependency 'logging', '~> 2.0'
s.add_development_dependency 'simplecov', '~> 0.9'
s.add_development_dependency 'rake', '~> 10.4'
s.add_development_dependency 'simplecov', '~> 0.14.1'
s.add_development_dependency 'rake', '~> 12.0'
s.add_development_dependency 'rake-compiler', '~> 1.0'
s.add_development_dependency 'rake-compiler-dock', '~> 0.5.1'
s.add_development_dependency 'rspec', '~> 3.2'
s.add_development_dependency 'rubocop', '~> 0.30.0'
s.add_development_dependency 'rspec', '~> 3.6'
s.add_development_dependency 'rubocop', '~> 0.49.1'
s.add_development_dependency 'signet', '~> 0.7.0'
s.extensions = %w(src/ruby/ext/grpc/extconf.rb)
@ -273,8 +273,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/error.h )
s.files += %w( src/core/lib/iomgr/error_internal.h )
s.files += %w( src/core/lib/iomgr/ev_epoll1_linux.h )
s.files += %w( src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h )
s.files += %w( src/core/lib/iomgr/ev_epoll_thread_pool_linux.h )
s.files += %w( src/core/lib/iomgr/ev_epollex_linux.h )
s.files += %w( src/core/lib/iomgr/ev_epollsig_linux.h )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.h )
@ -430,8 +428,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c )
s.files += %w( src/core/lib/iomgr/error.c )
s.files += %w( src/core/lib/iomgr/ev_epoll1_linux.c )
s.files += %w( src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c )
s.files += %w( src/core/lib/iomgr/ev_epoll_thread_pool_linux.c )
s.files += %w( src/core/lib/iomgr/ev_epollex_linux.c )
s.files += %w( src/core/lib/iomgr/ev_epollsig_linux.c )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.c )

@ -247,8 +247,6 @@
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll1_linux.c',
'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c',
'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c',
'src/core/lib/iomgr/ev_epollex_linux.c',
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',
@ -549,8 +547,6 @@
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll1_linux.c',
'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c',
'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c',
'src/core/lib/iomgr/ev_epollex_linux.c',
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',
@ -756,8 +752,6 @@
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll1_linux.c',
'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c',
'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c',
'src/core/lib/iomgr/ev_epollex_linux.c',
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',
@ -948,8 +942,6 @@
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll1_linux.c',
'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c',
'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c',
'src/core/lib/iomgr/ev_epollex_linux.c',
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',

@ -244,7 +244,7 @@ class ClientWriterInterface : public ClientStreamingInterface,
public WriterInterface<W> {
public:
/// Half close writing from the client. (signal that the stream of messages
/// coming from the clinet is complete).
/// coming from the client is complete).
/// Blocks until currently-pending writes are completed.
/// Thread safe with respect to \a ReaderInterface::Read operations only
///
@ -375,7 +375,7 @@ class ClientReaderWriterInterface : public ClientStreamingInterface,
virtual void WaitForInitialMetadata() = 0;
/// Half close writing from the client. (signal that the stream of messages
/// coming from the clinet is complete).
/// coming from the client is complete).
/// Blocks until currently-pending writes are completed.
/// Thread-safe with respect to \a ReaderInterface::Read
///

@ -178,6 +178,9 @@ GRPCAPI void grpc_channel_watch_connectivity_state(
grpc_channel *channel, grpc_connectivity_state last_observed_state,
gpr_timespec deadline, grpc_completion_queue *cq, void *tag);
/** Check whether a grpc channel supports connectivity watcher */
GRPCAPI int grpc_channel_support_connectivity_watcher(grpc_channel *channel);
/** Create a call given a grpc_channel, in order to call 'method'. All
completions are sent to 'completion_queue'. 'method' and 'host' need only
live through the invocation of this function.

@ -62,7 +62,12 @@ typedef struct grpc_slice_refcount {
struct grpc_slice_refcount *sub_refcount;
} grpc_slice_refcount;
#define GRPC_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1)
/* Inlined half of grpc_slice is allowed to expand the size of the overall type
by this many bytes */
#define GRPC_SLICE_INLINE_EXTRA_SIZE sizeof(void *)
#define GRPC_SLICE_INLINED_SIZE \
(sizeof(size_t) + sizeof(uint8_t *) - 1 + GRPC_SLICE_INLINE_EXTRA_SIZE)
/** A grpc_slice s, if initialized, represents the byte range
s.bytes[0..s.length-1].

@ -283,8 +283,6 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/error.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/error_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll1_linux.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_thread_pool_linux.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollex_linux.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollsig_linux.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" />
@ -440,8 +438,6 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/error.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll1_linux.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_thread_pool_linux.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollex_linux.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollsig_linux.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.c" role="src" />

@ -141,7 +141,7 @@ static char *decode_tag(struct raw_tag *tag, char *header, int offset) {
// Make a copy (in 'to') of an existing tag_set.
static void tag_set_copy(struct tag_set *to, const struct tag_set *from) {
memcpy(to, from, sizeof(struct tag_set));
to->kvm = gpr_malloc(to->kvm_size);
to->kvm = (char *)gpr_malloc(to->kvm_size);
memcpy(to->kvm, from->kvm, from->kvm_used);
}
@ -184,7 +184,7 @@ static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag,
if (tags->kvm_used + tag_size > tags->kvm_size) {
// allocate new memory if needed
tags->kvm_size += 2 * CENSUS_MAX_TAG_KV_LEN + TAG_HEADER_SIZE;
char *new_kvm = gpr_malloc(tags->kvm_size);
char *new_kvm = (char *)gpr_malloc(tags->kvm_size);
if (tags->kvm_used > 0) memcpy(new_kvm, tags->kvm, tags->kvm_used);
gpr_free(tags->kvm);
tags->kvm = new_kvm;
@ -274,7 +274,8 @@ static void tag_set_flatten(struct tag_set *tags) {
census_context *census_context_create(const census_context *base,
const census_tag *tags, int ntags,
census_context_status const **status) {
census_context *context = gpr_malloc(sizeof(census_context));
census_context *context =
(census_context *)gpr_malloc(sizeof(census_context));
// If we are given a base, copy it into our new tag set. Otherwise set it
// to zero/NULL everything.
if (base == NULL) {
@ -459,7 +460,7 @@ static void tag_set_decode(struct tag_set *tags, const char *buffer,
}
tags->kvm_used = size - header_size;
tags->kvm_size = tags->kvm_used + CENSUS_MAX_TAG_KV_LEN;
tags->kvm = gpr_malloc(tags->kvm_size);
tags->kvm = (char *)gpr_malloc(tags->kvm_size);
if (tag_header_size != TAG_HEADER_SIZE) {
// something new in the tag information. I don't understand it, so
// don't copy it over.
@ -481,7 +482,8 @@ static void tag_set_decode(struct tag_set *tags, const char *buffer,
}
census_context *census_context_decode(const char *buffer, size_t size) {
census_context *context = gpr_malloc(sizeof(census_context));
census_context *context =
(census_context *)gpr_malloc(sizeof(census_context));
memset(&context->tags[LOCAL_TAGS], 0, sizeof(struct tag_set));
if (buffer == NULL) {
memset(&context->tags[PROPAGATED_TAGS], 0, sizeof(struct tag_set));

@ -60,8 +60,8 @@ static void extract_and_annotate_method_tag(grpc_metadata_batch *md,
static void client_mutate_op(grpc_call_element *elem,
grpc_transport_stream_op_batch *op) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
call_data *calld = (call_data *)elem->call_data;
channel_data *chand = (channel_data *)elem->channel_data;
if (op->send_initial_metadata) {
extract_and_annotate_method_tag(
op->payload->send_initial_metadata.send_initial_metadata, calld, chand);
@ -78,9 +78,9 @@ static void client_start_transport_op(grpc_exec_ctx *exec_ctx,
static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr,
grpc_error *error) {
GPR_TIMER_BEGIN("census-server:server_on_done_recv", 0);
grpc_call_element *elem = ptr;
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_call_element *elem = (grpc_call_element *)ptr;
call_data *calld = (call_data *)elem->call_data;
channel_data *chand = (channel_data *)elem->channel_data;
if (error == GRPC_ERROR_NONE) {
extract_and_annotate_method_tag(calld->recv_initial_metadata, calld, chand);
}
@ -90,7 +90,7 @@ static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr,
static void server_mutate_op(grpc_call_element *elem,
grpc_transport_stream_op_batch *op) {
call_data *calld = elem->call_data;
call_data *calld = (call_data *)elem->call_data;
if (op->recv_initial_metadata) {
/* substitute our callback for the op callback */
calld->recv_initial_metadata =
@ -117,7 +117,7 @@ static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_element_args *args) {
call_data *d = elem->call_data;
call_data *d = (call_data *)elem->call_data;
GPR_ASSERT(d != NULL);
memset(d, 0, sizeof(*d));
d->start_ts = args->start_time;
@ -128,7 +128,7 @@ static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_final_info *final_info,
grpc_closure *ignored) {
call_data *d = elem->call_data;
call_data *d = (call_data *)elem->call_data;
GPR_ASSERT(d != NULL);
/* TODO(hongyu): record rpc client stats and census_rpc_end_op here */
}
@ -136,7 +136,7 @@ static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_element_args *args) {
call_data *d = elem->call_data;
call_data *d = (call_data *)elem->call_data;
GPR_ASSERT(d != NULL);
memset(d, 0, sizeof(*d));
d->start_ts = args->start_time;
@ -150,7 +150,7 @@ static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_final_info *final_info,
grpc_closure *ignored) {
call_data *d = elem->call_data;
call_data *d = (call_data *)elem->call_data;
GPR_ASSERT(d != NULL);
/* TODO(hongyu): record rpc server stats and census_tracing_end_op here */
}
@ -158,14 +158,14 @@ static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_channel_element_args *args) {
channel_data *chand = elem->channel_data;
channel_data *chand = (channel_data *)elem->channel_data;
GPR_ASSERT(chand != NULL);
return GRPC_ERROR_NONE;
}
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
channel_data *chand = elem->channel_data;
channel_data *chand = (channel_data *)elem->channel_data;
GPR_ASSERT(chand != NULL);
}

@ -467,7 +467,8 @@ void census_log_initialize(size_t size_in_mb, int discard_old_records) {
g_log.blocks = (cl_block*)gpr_malloc_aligned(
g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE_LOG);
memset(g_log.blocks, 0, g_log.num_blocks * sizeof(cl_block));
g_log.buffer = gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
g_log.buffer =
(char*)gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
memset(g_log.buffer, 0, g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
cl_block_list_initialize(&g_log.free_block_list);
cl_block_list_initialize(&g_log.dirty_block_list);

@ -87,7 +87,7 @@ static bool validate_string(pb_istream_t *stream, const pb_field_t *field,
gpr_log(GPR_INFO, "Zero-length Resource name.");
return false;
}
vresource->name = gpr_malloc(stream->bytes_left + 1);
vresource->name = (char *)gpr_malloc(stream->bytes_left + 1);
vresource->name[stream->bytes_left] = '\0';
if (!pb_read(stream, (uint8_t *)vresource->name, stream->bytes_left)) {
return false;
@ -106,7 +106,7 @@ static bool validate_string(pb_istream_t *stream, const pb_field_t *field,
if (stream->bytes_left == 0) {
return true;
}
vresource->description = gpr_malloc(stream->bytes_left + 1);
vresource->description = (char *)gpr_malloc(stream->bytes_left + 1);
vresource->description[stream->bytes_left] = '\0';
if (!pb_read(stream, (uint8_t *)vresource->description,
stream->bytes_left)) {
@ -134,7 +134,8 @@ static bool validate_units_helper(pb_istream_t *stream, int *count,
// Have to allocate a new array of values. Normal case is 0 or 1, so
// this should normally not be an issue.
google_census_Resource_BasicUnit *new_bup =
gpr_malloc((size_t)*count * sizeof(google_census_Resource_BasicUnit));
(google_census_Resource_BasicUnit *)gpr_malloc(
(size_t)*count * sizeof(google_census_Resource_BasicUnit));
if (*count != 1) {
memcpy(new_bup, *bup,
(size_t)(*count - 1) * sizeof(google_census_Resource_BasicUnit));
@ -207,7 +208,8 @@ size_t allocate_resource(void) {
// Expand resources if needed.
if (n_resources == n_defined_resources) {
size_t new_n_resources = n_resources ? n_resources * 2 : 2;
resource **new_resources = gpr_malloc(new_n_resources * sizeof(resource *));
resource **new_resources =
(resource **)gpr_malloc(new_n_resources * sizeof(resource *));
if (n_resources != 0) {
memcpy(new_resources, resources, n_resources * sizeof(resource *));
}
@ -226,7 +228,7 @@ size_t allocate_resource(void) {
}
}
GPR_ASSERT(id < n_resources && resources[id] == NULL);
resources[id] = gpr_malloc(sizeof(resource));
resources[id] = (resource *)gpr_malloc(sizeof(resource));
memset(resources[id], 0, sizeof(resource));
n_defined_resources++;
next_id = (id + 1) % n_resources;
@ -276,22 +278,24 @@ int32_t define_resource(const resource *base) {
gpr_mu_lock(&resource_lock);
size_t id = allocate_resource();
size_t len = strlen(base->name) + 1;
resources[id]->name = gpr_malloc(len);
resources[id]->name = (char *)gpr_malloc(len);
memcpy(resources[id]->name, base->name, len);
if (base->description) {
len = strlen(base->description) + 1;
resources[id]->description = gpr_malloc(len);
resources[id]->description = (char *)gpr_malloc(len);
memcpy(resources[id]->description, base->description, len);
}
resources[id]->prefix = base->prefix;
resources[id]->n_numerators = base->n_numerators;
len = (size_t)base->n_numerators * sizeof(*base->numerators);
resources[id]->numerators = gpr_malloc(len);
resources[id]->numerators =
(google_census_Resource_BasicUnit *)gpr_malloc(len);
memcpy(resources[id]->numerators, base->numerators, len);
resources[id]->n_denominators = base->n_denominators;
if (base->n_denominators != 0) {
len = (size_t)base->n_denominators * sizeof(*base->denominators);
resources[id]->denominators = gpr_malloc(len);
resources[id]->denominators =
(google_census_Resource_BasicUnit *)gpr_malloc(len);
memcpy(resources[id]->denominators, base->denominators, len);
}
gpr_mu_unlock(&resource_lock);

@ -191,6 +191,12 @@ static void watcher_timer_init(grpc_exec_ctx *exec_ctx, void *arg,
gpr_free(wa);
}
int grpc_channel_support_connectivity_watcher(grpc_channel *channel) {
grpc_channel_element *client_channel_elem =
grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
return client_channel_elem->filter != &grpc_client_channel_filter ? 0 : 1;
}
void grpc_channel_watch_connectivity_state(
grpc_channel *channel, grpc_connectivity_state last_observed_state,
gpr_timespec deadline, grpc_completion_queue *cq, void *tag) {

@ -1085,10 +1085,9 @@ static void pick_after_resolver_result_cancel_locked(grpc_exec_ctx *exec_ctx,
// it's safe to call subchannel_ready_locked() here -- we are
// essentially calling it here instead of calling it in
// pick_after_resolver_result_done_locked().
subchannel_ready_locked(
exec_ctx, elem,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Pick cancelled",
&error, 1));
subchannel_ready_locked(exec_ctx, elem,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Pick cancelled", &error, 1));
}
static void pick_after_resolver_result_done_locked(grpc_exec_ctx *exec_ctx,
@ -1107,8 +1106,6 @@ static void pick_after_resolver_result_done_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem = args->elem;
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner,
NULL);
if (error != GRPC_ERROR_NONE) {
if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver failed to return data",
@ -1179,7 +1176,6 @@ static void pick_callback_done_locked(grpc_exec_ctx *exec_ctx, void *arg,
gpr_log(GPR_DEBUG, "chand=%p calld=%p: pick completed asynchronously",
chand, calld);
}
grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner, NULL);
GPR_ASSERT(calld->lb_policy != NULL);
GRPC_LB_POLICY_UNREF(exec_ctx, calld->lb_policy, "pick_subchannel");
calld->lb_policy = NULL;

@ -32,6 +32,7 @@
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
@ -125,7 +126,6 @@ static const grpc_resolver_vtable fake_resolver_vtable = {
struct grpc_fake_resolver_response_generator {
fake_resolver* resolver; // Set by the fake_resolver constructor to itself.
grpc_channel_args* next_response;
gpr_refcount refcount;
};
@ -151,19 +151,26 @@ void grpc_fake_resolver_response_generator_unref(
}
}
static void set_response_cb(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
grpc_fake_resolver_response_generator* generator =
(grpc_fake_resolver_response_generator*)arg;
typedef struct set_response_closure_arg {
grpc_closure set_response_closure;
grpc_fake_resolver_response_generator* generator;
grpc_channel_args* next_response;
} set_response_closure_arg;
static void set_response_closure_fn(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
set_response_closure_arg* closure_arg = arg;
grpc_fake_resolver_response_generator* generator = closure_arg->generator;
fake_resolver* r = generator->resolver;
if (r->next_results != NULL) {
grpc_channel_args_destroy(exec_ctx, r->next_results);
}
r->next_results = generator->next_response;
r->next_results = closure_arg->next_response;
if (r->results_upon_error != NULL) {
grpc_channel_args_destroy(exec_ctx, r->results_upon_error);
}
r->results_upon_error = grpc_channel_args_copy(generator->next_response);
r->results_upon_error = grpc_channel_args_copy(closure_arg->next_response);
gpr_free(closure_arg);
fake_resolver_maybe_finish_next_locked(exec_ctx, r);
}
@ -171,12 +178,15 @@ void grpc_fake_resolver_response_generator_set_response(
grpc_exec_ctx* exec_ctx, grpc_fake_resolver_response_generator* generator,
grpc_channel_args* next_response) {
GPR_ASSERT(generator->resolver != NULL);
generator->next_response = grpc_channel_args_copy(next_response);
GRPC_CLOSURE_SCHED(
exec_ctx, GRPC_CLOSURE_CREATE(set_response_cb, generator,
grpc_combiner_scheduler(
generator->resolver->base.combiner)),
GRPC_ERROR_NONE);
set_response_closure_arg* closure_arg = gpr_zalloc(sizeof(*closure_arg));
closure_arg->generator = generator;
closure_arg->next_response = grpc_channel_args_copy(next_response);
GRPC_CLOSURE_SCHED(exec_ctx,
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
set_response_closure_fn, closure_arg,
grpc_combiner_scheduler(
generator->resolver->base.combiner)),
GRPC_ERROR_NONE);
}
static void* response_generator_arg_copy(void* p) {

@ -275,7 +275,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
const grpc_call_final_info* final_info,
grpc_closure* ignored) {
channel_data* chand = elem->channel_data;
channel_data* chand = (channel_data*)elem->channel_data;
decrease_call_count(exec_ctx, chand);
}

@ -153,17 +153,8 @@ static uint32_t target_write_size(grpc_chttp2_transport *t) {
}
// Returns true if initial_metadata contains only default headers.
//
// TODO(roth): The fact that we hard-code these particular headers here
// is fairly ugly. Need some better way to know which headers are
// default, maybe via a bit in the static metadata table?
static bool is_default_initial_metadata(grpc_metadata_batch *initial_metadata) {
int num_default_fields =
(initial_metadata->idx.named.status != NULL) +
(initial_metadata->idx.named.content_type != NULL) +
(initial_metadata->idx.named.grpc_encoding != NULL) +
(initial_metadata->idx.named.grpc_accept_encoding != NULL);
return (size_t)num_default_fields == initial_metadata->list.count;
return initial_metadata->list.default_count == initial_metadata->list.count;
}
grpc_chttp2_begin_write_result grpc_chttp2_begin_write(

@ -187,9 +187,34 @@ struct stream_obj {
/* Mutex to protect storage */
gpr_mu mu;
/* Refcount object of the stream */
grpc_stream_refcount *refcount;
};
typedef struct stream_obj stream_obj;
#ifndef NDEBUG
#define GRPC_CRONET_STREAM_REF(stream, reason) \
grpc_cronet_stream_ref((stream), (reason))
#define GRPC_CRONET_STREAM_UNREF(exec_ctx, stream, reason) \
grpc_cronet_stream_unref((exec_ctx), (stream), (reason))
void grpc_cronet_stream_ref(stream_obj *s, const char *reason) {
grpc_stream_ref(s->refcount, reason);
}
void grpc_cronet_stream_unref(grpc_exec_ctx *exec_ctx, stream_obj *s,
const char *reason) {
grpc_stream_unref(exec_ctx, s->refcount, reason);
}
#else
#define GRPC_CRONET_STREAM_REF(stream, reason) grpc_cronet_stream_ref((stream))
#define GRPC_CRONET_STREAM_UNREF(exec_ctx, stream, reason) \
grpc_cronet_stream_unref((exec_ctx), (stream))
void grpc_cronet_stream_ref(stream_obj *s) { grpc_stream_ref(s->refcount); }
void grpc_cronet_stream_unref(grpc_exec_ctx *exec_ctx, stream_obj *s) {
grpc_stream_unref(exec_ctx, s->refcount);
}
#endif
static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
struct op_and_state *oas);
@ -346,13 +371,12 @@ static void remove_from_storage(struct stream_obj *s,
This can get executed from the Cronet network thread via cronet callback
or on the application supplied thread via the perform_stream_op function.
*/
static void execute_from_storage(stream_obj *s) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
static void execute_from_storage(grpc_exec_ctx *exec_ctx, stream_obj *s) {
gpr_mu_lock(&s->mu);
for (struct op_and_state *curr = s->storage.head; curr != NULL;) {
CRONET_LOG(GPR_DEBUG, "calling op at %p. done = %d", curr, curr->done);
GPR_ASSERT(curr->done == 0);
enum e_op_result result = execute_stream_op(&exec_ctx, curr);
enum e_op_result result = execute_stream_op(exec_ctx, curr);
CRONET_LOG(GPR_DEBUG, "execute_stream_op[%p] returns %s", curr,
op_result_string(result));
/* if this op is done, then remove it and free memory */
@ -369,7 +393,6 @@ static void execute_from_storage(stream_obj *s) {
}
}
gpr_mu_unlock(&s->mu);
grpc_exec_ctx_finish(&exec_ctx);
}
/*
@ -377,6 +400,8 @@ static void execute_from_storage(stream_obj *s) {
*/
static void on_failed(bidirectional_stream *stream, int net_error) {
CRONET_LOG(GPR_DEBUG, "on_failed(%p, %d)", stream, net_error);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
stream_obj *s = (stream_obj *)stream->annotation;
gpr_mu_lock(&s->mu);
bidirectional_stream_destroy(s->cbs);
@ -392,7 +417,9 @@ static void on_failed(bidirectional_stream *stream, int net_error) {
}
null_and_maybe_free_read_buffer(s);
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
execute_from_storage(&exec_ctx, s);
GRPC_CRONET_STREAM_UNREF(&exec_ctx, s, "cronet transport");
grpc_exec_ctx_finish(&exec_ctx);
}
/*
@ -400,6 +427,8 @@ static void on_failed(bidirectional_stream *stream, int net_error) {
*/
static void on_canceled(bidirectional_stream *stream) {
CRONET_LOG(GPR_DEBUG, "on_canceled(%p)", stream);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
stream_obj *s = (stream_obj *)stream->annotation;
gpr_mu_lock(&s->mu);
bidirectional_stream_destroy(s->cbs);
@ -415,7 +444,9 @@ static void on_canceled(bidirectional_stream *stream) {
}
null_and_maybe_free_read_buffer(s);
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
execute_from_storage(&exec_ctx, s);
GRPC_CRONET_STREAM_UNREF(&exec_ctx, s, "cronet transport");
grpc_exec_ctx_finish(&exec_ctx);
}
/*
@ -423,6 +454,8 @@ static void on_canceled(bidirectional_stream *stream) {
*/
static void on_succeeded(bidirectional_stream *stream) {
CRONET_LOG(GPR_DEBUG, "on_succeeded(%p)", stream);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
stream_obj *s = (stream_obj *)stream->annotation;
gpr_mu_lock(&s->mu);
bidirectional_stream_destroy(s->cbs);
@ -430,7 +463,9 @@ static void on_succeeded(bidirectional_stream *stream) {
s->cbs = NULL;
null_and_maybe_free_read_buffer(s);
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
execute_from_storage(&exec_ctx, s);
GRPC_CRONET_STREAM_UNREF(&exec_ctx, s, "cronet transport");
grpc_exec_ctx_finish(&exec_ctx);
}
/*
@ -438,6 +473,7 @@ static void on_succeeded(bidirectional_stream *stream) {
*/
static void on_stream_ready(bidirectional_stream *stream) {
CRONET_LOG(GPR_DEBUG, "W: on_stream_ready(%p)", stream);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
stream_obj *s = (stream_obj *)stream->annotation;
grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
gpr_mu_lock(&s->mu);
@ -457,7 +493,8 @@ static void on_stream_ready(bidirectional_stream *stream) {
}
}
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
execute_from_storage(&exec_ctx, s);
grpc_exec_ctx_finish(&exec_ctx);
}
/*
@ -513,14 +550,15 @@ static void on_response_headers_received(
s->state.pending_read_from_cronet = true;
}
gpr_mu_unlock(&s->mu);
execute_from_storage(&exec_ctx, s);
grpc_exec_ctx_finish(&exec_ctx);
execute_from_storage(s);
}
/*
Cronet callback
*/
static void on_write_completed(bidirectional_stream *stream, const char *data) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
stream_obj *s = (stream_obj *)stream->annotation;
CRONET_LOG(GPR_DEBUG, "W: on_write_completed(%p, %s)", stream, data);
gpr_mu_lock(&s->mu);
@ -530,7 +568,8 @@ static void on_write_completed(bidirectional_stream *stream, const char *data) {
}
s->state.state_callback_received[OP_SEND_MESSAGE] = true;
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
execute_from_storage(&exec_ctx, s);
grpc_exec_ctx_finish(&exec_ctx);
}
/*
@ -538,6 +577,7 @@ static void on_write_completed(bidirectional_stream *stream, const char *data) {
*/
static void on_read_completed(bidirectional_stream *stream, char *data,
int count) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
stream_obj *s = (stream_obj *)stream->annotation;
CRONET_LOG(GPR_DEBUG, "R: on_read_completed(%p, %p, %d)", stream, data,
count);
@ -563,14 +603,15 @@ static void on_read_completed(bidirectional_stream *stream, char *data,
gpr_mu_unlock(&s->mu);
} else {
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
execute_from_storage(&exec_ctx, s);
}
} else {
null_and_maybe_free_read_buffer(s);
s->state.rs.read_stream_closed = true;
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
execute_from_storage(&exec_ctx, s);
}
grpc_exec_ctx_finish(&exec_ctx);
}
/*
@ -625,12 +666,11 @@ static void on_response_trailers_received(
s->state.state_op_done[OP_SEND_TRAILING_METADATA] = true;
gpr_mu_unlock(&s->mu);
grpc_exec_ctx_finish(&exec_ctx);
} else {
gpr_mu_unlock(&s->mu);
grpc_exec_ctx_finish(&exec_ctx);
execute_from_storage(s);
execute_from_storage(&exec_ctx, s);
}
grpc_exec_ctx_finish(&exec_ctx);
}
/*
@ -1313,6 +1353,9 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_stream_refcount *refcount,
const void *server_data, gpr_arena *arena) {
stream_obj *s = (stream_obj *)gs;
s->refcount = refcount;
GRPC_CRONET_STREAM_REF(s, "cronet transport");
memset(&s->storage, 0, sizeof(s->storage));
s->storage.head = NULL;
memset(&s->state, 0, sizeof(s->state));
@ -1370,7 +1413,7 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
}
stream_obj *s = (stream_obj *)gs;
add_to_storage(s, op);
execute_from_storage(s);
execute_from_storage(exec_ctx, s);
}
static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,

@ -87,20 +87,28 @@ void grpc_call_combiner_stop(grpc_exec_ctx* exec_ctx,
const char* reason);
#endif
/// Tells \a call_combiner to schedule \a closure when
/// Registers \a closure to be invoked by \a call_combiner when
/// grpc_call_combiner_cancel() is called.
///
/// If grpc_call_combiner_cancel() was previously called, \a closure will be
/// scheduled immediately.
/// Once a closure is registered, it will always be scheduled exactly
/// once; this allows the closure to hold references that will be freed
/// regardless of whether or not the call was cancelled. If a cancellation
/// does occur, the closure will be scheduled with the cancellation error;
/// otherwise, it will be scheduled with GRPC_ERROR_NONE.
///
/// The closure will be scheduled in the following cases:
/// - If grpc_call_combiner_cancel() was called prior to registering the
/// closure, it will be scheduled immediately with the cancelation error.
/// - If grpc_call_combiner_cancel() is called after registering the
/// closure, the closure will be scheduled with the cancellation error.
/// - If grpc_call_combiner_set_notify_on_cancel() is called again to
/// register a new cancellation closure, the previous cancellation
/// closure will be scheduled with GRPC_ERROR_NONE.
///
/// If \a closure is NULL, then no closure will be invoked on
/// cancellation; this effectively unregisters the previously set closure.
///
/// If a closure was set via a previous call to
/// grpc_call_combiner_set_notify_on_cancel(), the previous closure will be
/// scheduled immediately with GRPC_ERROR_NONE. This ensures that
/// \a closure will be scheduled exactly once, which allows callers to clean
/// up resources they may be holding for the callback.
/// However, most filters will not need to explicitly unregister their
/// callbacks, as this is done automatically when the call is destroyed.
void grpc_call_combiner_set_notify_on_cancel(grpc_exec_ctx* exec_ctx,
grpc_call_combiner* call_combiner,
grpc_closure* closure);

@ -695,22 +695,30 @@ static bool begin_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
gpr_mu_unlock(&pollset->mu);
goto retry_lock_neighbourhood;
}
pollset->seen_inactive = false;
if (neighbourhood->active_root == NULL) {
neighbourhood->active_root = pollset->next = pollset->prev = pollset;
/* TODO: sreek. Why would this worker state be other than UNKICKED
* here ? (since the worker isn't added to the pollset yet, there is no
* way it can be "found" by other threads to get kicked). */
/* If there is no designated poller, make this the designated poller */
if (worker->kick_state == UNKICKED &&
gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) {
SET_KICK_STATE(worker, DESIGNATED_POLLER);
/* In the brief time we released the pollset locks above, the worker MAY
have been kicked. In this case, the worker should get out of this
pollset ASAP and hence this should neither add the pollset to
neighbourhood nor mark the pollset as active.
On a side note, the only way a worker's kick state could have changed
at this point is if it were "kicked specifically". Since the worker has
not added itself to the pollset yet (by calling worker_insert()), it is
not visible in the "kick any" path yet */
if (worker->kick_state == UNKICKED) {
pollset->seen_inactive = false;
if (neighbourhood->active_root == NULL) {
neighbourhood->active_root = pollset->next = pollset->prev = pollset;
/* Make this the designated poller if there isn't one already */
if (worker->kick_state == UNKICKED &&
gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) {
SET_KICK_STATE(worker, DESIGNATED_POLLER);
}
} else {
pollset->next = neighbourhood->active_root;
pollset->prev = pollset->next->prev;
pollset->next->prev = pollset->prev->next = pollset;
}
} else {
pollset->next = neighbourhood->active_root;
pollset->prev = pollset->next->prev;
pollset->next->prev = pollset->prev->next = pollset;
}
}
if (is_reassigning) {
@ -998,6 +1006,7 @@ static grpc_error *pollset_kick(grpc_pollset *pollset,
gpr_log(GPR_ERROR, "%s", tmp);
gpr_free(tmp);
}
if (specific_worker == NULL) {
if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
grpc_pollset_worker *root_worker = pollset->root_worker;
@ -1073,7 +1082,11 @@ static grpc_error *pollset_kick(grpc_pollset *pollset,
}
goto done;
}
} else if (specific_worker->kick_state == KICKED) {
GPR_UNREACHABLE_CODE(goto done);
}
if (specific_worker->kick_state == KICKED) {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. specific worker already kicked");
}

File diff suppressed because it is too large Load Diff

@ -1,28 +0,0 @@
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLL_LIMITED_POLLERS_LINUX_H
#define GRPC_CORE_LIB_IOMGR_EV_EPOLL_LIMITED_POLLERS_LINUX_H
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/port.h"
const grpc_event_engine_vtable *grpc_init_epoll_limited_pollers_linux(
bool explicitly_requested);
#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLL_LIMITED_POLLERS_LINUX_H */

File diff suppressed because it is too large Load Diff

@ -1,28 +0,0 @@
/*
*
* 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.
*
*/
#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLL_THREAD_POOL_LINUX_H
#define GRPC_CORE_LIB_IOMGR_EV_EPOLL_THREAD_POOL_LINUX_H
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/port.h"
const grpc_event_engine_vtable *grpc_init_epoll_thread_pool_linux(
bool requested_explicitly);
#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLL_THREAD_POOL_LINUX_H */

@ -31,8 +31,6 @@
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/ev_epoll1_linux.h"
#include "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h"
#include "src/core/lib/iomgr/ev_epoll_thread_pool_linux.h"
#include "src/core/lib/iomgr/ev_epollex_linux.h"
#include "src/core/lib/iomgr/ev_epollsig_linux.h"
#include "src/core/lib/iomgr/ev_poll_posix.h"
@ -66,8 +64,6 @@ typedef struct {
static const event_engine_factory g_factories[] = {
{"epoll1", grpc_init_epoll1_linux},
{"epollsig", grpc_init_epollsig_linux},
{"epoll-threadpool", grpc_init_epoll_thread_pool_linux},
{"epoll-limited", grpc_init_epoll_limited_pollers_linux},
{"poll", grpc_init_poll_posix},
{"poll-cv", grpc_init_poll_cv_posix},
{"epollex", grpc_init_epollex_linux},

@ -165,13 +165,7 @@ void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) {
bool grpc_iomgr_abort_on_leaks(void) {
char *env = gpr_getenv("GRPC_ABORT_ON_LEAKS");
if (env == NULL) return false;
static const char *truthy[] = {"yes", "Yes", "YES", "true",
"True", "TRUE", "1"};
bool should_we = false;
for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
if (0 == strcmp(env, truthy[i])) should_we = true;
}
bool should_we = gpr_is_true(env);
gpr_free(env);
return should_we;
}

@ -67,7 +67,6 @@ typedef struct {
grpc_fd *em_fd;
int fd;
bool finished_edge;
msg_iovlen_type iov_size; /* Number of slices to allocate per read attempt */
double target_length;
double bytes_read_this_round;
gpr_refcount refcount;
@ -240,7 +239,6 @@ static void tcp_do_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
size_t i;
GPR_ASSERT(!tcp->finished_edge);
GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC);
GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC);
GPR_TIMER_BEGIN("tcp_continue_read", 0);
@ -252,7 +250,7 @@ static void tcp_do_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = tcp->iov_size;
msg.msg_iovlen = (msg_iovlen_type)tcp->incoming_buffer->count;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
@ -621,7 +619,6 @@ grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_fd *em_fd,
tcp->min_read_chunk_size = tcp_min_read_chunk_size;
tcp->max_read_chunk_size = tcp_max_read_chunk_size;
tcp->bytes_read_this_round = 0;
tcp->iov_size = 1;
tcp->finished_edge = true;
/* paired with unref in grpc_tcp_destroy */
gpr_ref_init(&tcp->refcount, 1);

@ -95,7 +95,6 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *arg,
grpc_transport_stream_op_batch *batch = (grpc_transport_stream_op_batch *)arg;
grpc_call_element *elem = batch->handler_private.extra_arg;
call_data *calld = elem->call_data;
grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner, NULL);
reset_auth_metadata_context(&calld->auth_md_context);
grpc_error *error = GRPC_ERROR_REF(input_error);
if (error == GRPC_ERROR_NONE) {
@ -228,7 +227,6 @@ static void on_host_checked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_transport_stream_op_batch *batch = (grpc_transport_stream_op_batch *)arg;
grpc_call_element *elem = batch->handler_private.extra_arg;
call_data *calld = elem->call_data;
grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner, NULL);
if (error == GRPC_ERROR_NONE) {
send_security_metadata(exec_ctx, elem, batch);
} else {
@ -318,14 +316,6 @@ static void auth_start_transport_stream_op_batch(
on_host_checked(exec_ctx, batch, error);
GRPC_ERROR_UNREF(error);
} else {
// FIXME: if grpc_channel_security_connector_check_call_host() invokes
// the callback in this thread before returning, then we'll call
// grpc_call_combiner_set_notify_on_cancel() to set it "back" to NULL
// *before* we call this to set it to the cancel function.
// Can't just do this before calling
// grpc_channel_security_connector_check_call_host(), because then the
// cancellation might be invoked before we actually send the request.
// May need to fix the credentials plugin API to deal with this.
// Async return; register cancellation closure with call combiner.
GRPC_CALL_STACK_REF(calld->owning_call, "cancel_check_call_host");
grpc_call_combiner_set_notify_on_cancel(

@ -97,7 +97,6 @@ static void on_md_processing_done_inner(grpc_exec_ctx *exec_ctx,
grpc_error *error) {
call_data *calld = elem->call_data;
grpc_transport_stream_op_batch *batch = calld->recv_initial_metadata_batch;
grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner, NULL);
/* TODO(jboeuf): Implement support for response_md. */
if (response_md != NULL && num_response_md > 0) {
gpr_log(GPR_INFO,

@ -298,3 +298,16 @@ void *gpr_memrchr(const void *s, int c, size_t n) {
}
return NULL;
}
bool gpr_is_true(const char *s) {
if (s == NULL) {
return false;
}
static const char *truthy[] = {"yes", "true", "1"};
for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
if (0 == gpr_stricmp(s, truthy[i])) {
return true;
}
}
return false;
}

@ -19,6 +19,7 @@
#ifndef GRPC_CORE_LIB_SUPPORT_STRING_H
#define GRPC_CORE_LIB_SUPPORT_STRING_H
#include <stdbool.h>
#include <stddef.h>
#include <grpc/support/port_platform.h>
@ -106,6 +107,8 @@ int gpr_stricmp(const char *a, const char *b);
void *gpr_memrchr(const void *s, int c, size_t n);
/** Return true if lower(s) equals "true", "yes" or "1", otherwise false. */
bool gpr_is_true(const char *s);
#ifdef __cplusplus
}
#endif

@ -594,6 +594,12 @@ void grpc_call_unref(grpc_call *c) {
if (cancel) {
cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE,
GRPC_ERROR_CANCELLED);
} else {
// Unset the call combiner cancellation closure. This has the
// effect of scheduling the previously set cancellation closure, if
// any, so that it can release any internal references it may be
// holding to the call stack.
grpc_call_combiner_set_notify_on_cancel(&exec_ctx, &c->call_combiner, NULL);
}
GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
grpc_exec_ctx_finish(&exec_ctx);

@ -19,6 +19,10 @@
#ifndef GRPC_CORE_LIB_SURFACE_CALL_H
#define GRPC_CORE_LIB_SURFACE_CALL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/surface/api_trace.h"
@ -26,10 +30,6 @@
#include <grpc/grpc.h>
#include <grpc/impl/codegen/compression_types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*grpc_ioreq_completion_func)(grpc_exec_ctx *exec_ctx,
grpc_call *call, int success,
void *user_data);
@ -89,7 +89,7 @@ grpc_call_error grpc_call_start_batch_and_execute(grpc_exec_ctx *exec_ctx,
/* Given the top call_element, get the call object. */
grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element);
void grpc_call_log_batch(char *file, int line, gpr_log_severity severity,
void grpc_call_log_batch(const char *file, int line, gpr_log_severity severity,
grpc_call *call, const grpc_op *ops, size_t nops,
void *tag);

@ -103,7 +103,7 @@ char *grpc_op_string(const grpc_op *op) {
return out;
}
void grpc_call_log_batch(char *file, int line, gpr_log_severity severity,
void grpc_call_log_batch(const char *file, int line, gpr_log_severity severity,
grpc_call *call, const grpc_op *ops, size_t nops,
void *tag) {
char *tmp;

@ -105,6 +105,7 @@ static grpc_error *maybe_link_callout(grpc_metadata_batch *batch,
return GRPC_ERROR_NONE;
}
if (batch->idx.array[idx] == NULL) {
if (grpc_static_callout_is_default[idx]) ++batch->list.default_count;
batch->idx.array[idx] = storage;
return GRPC_ERROR_NONE;
}
@ -120,6 +121,7 @@ static void maybe_unlink_callout(grpc_metadata_batch *batch,
if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
return;
}
if (grpc_static_callout_is_default[idx]) --batch->list.default_count;
GPR_ASSERT(batch->idx.array[idx] != NULL);
batch->idx.array[idx] = NULL;
}

@ -41,6 +41,7 @@ typedef struct grpc_linked_mdelem {
typedef struct grpc_mdelem_list {
size_t count;
size_t default_count; // Number of default keys.
grpc_linked_mdelem *head;
grpc_linked_mdelem *tail;
} grpc_mdelem_list;

@ -823,6 +823,31 @@ grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {
{.refcount = &grpc_static_metadata_refcounts[97],
.data.refcounted = {g_bytes + 1040, 13}}},
};
bool grpc_static_callout_is_default[GRPC_BATCH_CALLOUTS_COUNT] = {
true, // :path
true, // :method
true, // :status
true, // :authority
true, // :scheme
true, // te
true, // grpc-message
true, // grpc-status
true, // grpc-payload-bin
true, // grpc-encoding
true, // grpc-accept-encoding
true, // grpc-server-stats-bin
true, // grpc-tags-bin
true, // grpc-trace-bin
true, // content-type
true, // content-encoding
true, // accept-encoding
true, // grpc-internal-encoding-request
true, // grpc-internal-stream-encoding-request
true, // user-agent
true, // host
true, // lb-token
};
const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 76, 77, 78,
79, 80, 81, 82};

@ -571,6 +571,8 @@ typedef union {
GRPC_BATCH_CALLOUTS_COUNT) \
: GRPC_BATCH_CALLOUTS_COUNT)
extern bool grpc_static_callout_is_default[GRPC_BATCH_CALLOUTS_COUNT];
extern const uint8_t grpc_static_accept_encoding_metadata[8];
#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \
(GRPC_MAKE_MDELEM( \

@ -15,7 +15,15 @@
licenses(["notice"]) # Apache v2
exports_files([
"ca.pem",
"server1.key",
"server1.pem",
"ca.pem",
"server1.key",
"server1.pem",
"server0.key",
"server0.pem",
"client.key",
"client.pem",
"badserver.key",
"badserver.pem",
"badclient.key",
"badclient.pem",
])

@ -18,7 +18,10 @@
#include <grpc++/channel.h>
#include <chrono>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <grpc++/client_context.h>
#include <grpc++/completion_queue.h>
@ -35,17 +38,197 @@
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h"
namespace grpc {
namespace {
int kConnectivityCheckIntervalMsec = 500;
void WatchStateChange(void* arg);
class TagSaver final : public CompletionQueueTag {
public:
explicit TagSaver(void* tag) : tag_(tag) {}
~TagSaver() override {}
bool FinalizeResult(void** tag, bool* status) override {
*tag = tag_;
delete this;
return true;
}
private:
void* tag_;
};
// Constantly watches channel connectivity status to reconnect a transiently
// disconnected channel. This is a temporary work-around before we have retry
// support.
class ChannelConnectivityWatcher : private GrpcLibraryCodegen {
public:
static void StartWatching(grpc_channel* channel) {
if (!IsDisabled()) {
std::unique_lock<std::mutex> lock(g_watcher_mu_);
if (g_watcher_ == nullptr) {
g_watcher_ = new ChannelConnectivityWatcher();
}
g_watcher_->StartWatchingLocked(channel);
}
}
static void StopWatching() {
if (!IsDisabled()) {
std::unique_lock<std::mutex> lock(g_watcher_mu_);
if (g_watcher_->StopWatchingLocked()) {
delete g_watcher_;
g_watcher_ = nullptr;
}
}
}
private:
ChannelConnectivityWatcher() : channel_count_(0), shutdown_(false) {
gpr_ref_init(&ref_, 0);
gpr_thd_options options = gpr_thd_options_default();
gpr_thd_options_set_joinable(&options);
gpr_thd_new(&thd_id_, &WatchStateChange, this, &options);
}
static bool IsDisabled() {
char* env = gpr_getenv("GRPC_DISABLE_CHANNEL_CONNECTIVITY_WATCHER");
bool disabled = gpr_is_true(env);
gpr_free(env);
return disabled;
}
void WatchStateChangeImpl() {
bool ok = false;
void* tag = NULL;
CompletionQueue::NextStatus status = CompletionQueue::GOT_EVENT;
while (true) {
{
std::unique_lock<std::mutex> lock(shutdown_mu_);
if (shutdown_) {
// Drain cq_ if the watcher is shutting down
status = cq_.AsyncNext(&tag, &ok, gpr_inf_future(GPR_CLOCK_REALTIME));
} else {
status = cq_.AsyncNext(&tag, &ok, gpr_inf_past(GPR_CLOCK_REALTIME));
// Make sure we've seen 2 TIMEOUTs before going to sleep
if (status == CompletionQueue::TIMEOUT) {
status = cq_.AsyncNext(&tag, &ok, gpr_inf_past(GPR_CLOCK_REALTIME));
if (status == CompletionQueue::TIMEOUT) {
shutdown_cv_.wait_for(lock, std::chrono::milliseconds(
kConnectivityCheckIntervalMsec));
continue;
}
}
}
}
ChannelState* channel_state = static_cast<ChannelState*>(tag);
channel_state->state =
grpc_channel_check_connectivity_state(channel_state->channel, false);
if (channel_state->state == GRPC_CHANNEL_SHUTDOWN) {
void* shutdown_tag = NULL;
channel_state->shutdown_cq.Next(&shutdown_tag, &ok);
delete channel_state;
if (gpr_unref(&ref_)) {
break;
}
} else {
TagSaver* tag_saver = new TagSaver(channel_state);
grpc_channel_watch_connectivity_state(
channel_state->channel, channel_state->state,
gpr_inf_future(GPR_CLOCK_REALTIME), cq_.cq(), tag_saver);
}
}
}
void StartWatchingLocked(grpc_channel* channel) {
if (thd_id_ != 0) {
gpr_ref(&ref_);
++channel_count_;
ChannelState* channel_state = new ChannelState(channel);
// The first grpc_channel_watch_connectivity_state() is not used to
// monitor the channel state change, but to hold a reference of the
// c channel. So that WatchStateChangeImpl() can observe state ==
// GRPC_CHANNEL_SHUTDOWN before the channel gets destroyed.
grpc_channel_watch_connectivity_state(
channel_state->channel, channel_state->state,
gpr_inf_future(GPR_CLOCK_REALTIME), channel_state->shutdown_cq.cq(),
new TagSaver(nullptr));
grpc_channel_watch_connectivity_state(
channel_state->channel, channel_state->state,
gpr_inf_future(GPR_CLOCK_REALTIME), cq_.cq(),
new TagSaver(channel_state));
}
}
bool StopWatchingLocked() {
if (--channel_count_ == 0) {
{
std::unique_lock<std::mutex> lock(shutdown_mu_);
shutdown_ = true;
shutdown_cv_.notify_one();
}
gpr_thd_join(thd_id_);
return true;
}
return false;
}
friend void WatchStateChange(void* arg);
struct ChannelState {
explicit ChannelState(grpc_channel* channel)
: channel(channel), state(GRPC_CHANNEL_IDLE){};
grpc_channel* channel;
grpc_connectivity_state state;
CompletionQueue shutdown_cq;
};
gpr_thd_id thd_id_;
CompletionQueue cq_;
gpr_refcount ref_;
int channel_count_;
std::mutex shutdown_mu_;
std::condition_variable shutdown_cv_; // protected by shutdown_mu_
bool shutdown_; // protected by shutdown_mu_
static std::mutex g_watcher_mu_;
static ChannelConnectivityWatcher* g_watcher_; // protected by g_watcher_mu_
};
std::mutex ChannelConnectivityWatcher::g_watcher_mu_;
ChannelConnectivityWatcher* ChannelConnectivityWatcher::g_watcher_ = nullptr;
void WatchStateChange(void* arg) {
ChannelConnectivityWatcher* watcher =
static_cast<ChannelConnectivityWatcher*>(arg);
watcher->WatchStateChangeImpl();
}
} // namespace
static internal::GrpcLibraryInitializer g_gli_initializer;
Channel::Channel(const grpc::string& host, grpc_channel* channel)
: host_(host), c_channel_(channel) {
g_gli_initializer.summon();
if (grpc_channel_support_connectivity_watcher(channel)) {
ChannelConnectivityWatcher::StartWatching(channel);
}
}
Channel::~Channel() { grpc_channel_destroy(c_channel_); }
Channel::~Channel() {
const bool stop_watching =
grpc_channel_support_connectivity_watcher(c_channel_);
grpc_channel_destroy(c_channel_);
if (stop_watching) {
ChannelConnectivityWatcher::StopWatching();
}
}
namespace {
@ -130,23 +313,6 @@ grpc_connectivity_state Channel::GetState(bool try_to_connect) {
return grpc_channel_check_connectivity_state(c_channel_, try_to_connect);
}
namespace {
class TagSaver final : public CompletionQueueTag {
public:
explicit TagSaver(void* tag) : tag_(tag) {}
~TagSaver() override {}
bool FinalizeResult(void** tag, bool* status) override {
*tag = tag_;
delete this;
return true;
}
private:
void* tag_;
};
} // namespace
void Channel::NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
gpr_timespec deadline,
CompletionQueue* cq, void* tag) {

@ -17,6 +17,7 @@
#include <grpc++/server.h>
#include <cstdlib>
#include <sstream>
#include <utility>
@ -38,6 +39,7 @@
#include "src/core/ext/transport/inproc/inproc_transport.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/surface/call.h"
#include "src/cpp/client/create_channel_internal.h"
#include "src/cpp/server/health/default_health_check_service.h"
#include "src/cpp/thread_manager/thread_manager.h"
@ -607,7 +609,12 @@ void Server::PerformOpsOnCall(CallOpSetInterface* ops, Call* call) {
grpc_op cops[MAX_OPS];
ops->FillOps(call->call(), cops, &nops);
auto result = grpc_call_start_batch(call->call(), cops, nops, ops, nullptr);
GPR_ASSERT(GRPC_CALL_OK == result);
if (result != GRPC_CALL_OK) {
gpr_log(GPR_ERROR, "Fatal: grpc_call_start_batch returned %d", result);
grpc_call_log_batch(__FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR,
call->call(), cops, nops, ops);
abort();
}
}
ServerInterface::BaseAsyncRequest::BaseAsyncRequest(

@ -101,7 +101,7 @@ Pod::Spec.new do |s|
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
s.dependency '!ProtoCompiler', '3.3.0'
s.dependency '!ProtoCompiler', '3.4.0'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'

@ -36,7 +36,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler'
v = '3.3.0'
v = '3.4.0'
s.version = v
s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
s.description = <<-DESC

@ -86,8 +86,6 @@ CORE_SOURCE_FILES = [
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll1_linux.c',
'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c',
'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c',
'src/core/lib/iomgr/ev_epollex_linux.c',
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',

@ -293,6 +293,278 @@ class Channel(six.with_metaclass(abc.ABCMeta), grpc.Channel):
raise NotImplementedError()
class UnaryUnaryServerRpc(six.with_metaclass(abc.ABCMeta)):
"""Fixture for a unary-unary RPC serviced by a system under test.
Enables users to "play client" for the RPC.
"""
@abc.abstractmethod
def initial_metadata(self):
"""Accesses the initial metadata emitted by the system under test.
This method blocks until the system under test has added initial
metadata to the RPC (or has provided one or more response messages or
has terminated the RPC, either of which will cause gRPC Python to
synthesize initial metadata for the RPC).
Returns:
The initial metadata for the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def cancel(self):
"""Cancels the RPC."""
raise NotImplementedError()
@abc.abstractmethod
def termination(self):
"""Blocks until the system under test has terminated the RPC.
Returns:
A (response, trailing_metadata, code, details) sequence with the RPC's
response, trailing metadata, code, and details.
"""
raise NotImplementedError()
class UnaryStreamServerRpc(six.with_metaclass(abc.ABCMeta)):
"""Fixture for a unary-stream RPC serviced by a system under test.
Enables users to "play client" for the RPC.
"""
@abc.abstractmethod
def initial_metadata(self):
"""Accesses the initial metadata emitted by the system under test.
This method blocks until the system under test has added initial
metadata to the RPC (or has provided one or more response messages or
has terminated the RPC, either of which will cause gRPC Python to
synthesize initial metadata for the RPC).
Returns:
The initial metadata for the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def take_response(self):
"""Draws one of the responses added to the RPC by the system under test.
Successive calls to this method return responses in the same order in
which the system under test added them to the RPC.
Returns:
A response message added to the RPC by the system under test.
"""
raise NotImplementedError()
@abc.abstractmethod
def cancel(self):
"""Cancels the RPC."""
raise NotImplementedError()
@abc.abstractmethod
def termination(self):
"""Blocks until the system under test has terminated the RPC.
Returns:
A (trailing_metadata, code, details) sequence with the RPC's trailing
metadata, code, and details.
"""
raise NotImplementedError()
class StreamUnaryServerRpc(six.with_metaclass(abc.ABCMeta)):
"""Fixture for a stream-unary RPC serviced by a system under test.
Enables users to "play client" for the RPC.
"""
@abc.abstractmethod
def initial_metadata(self):
"""Accesses the initial metadata emitted by the system under test.
This method blocks until the system under test has added initial
metadata to the RPC (or has provided one or more response messages or
has terminated the RPC, either of which will cause gRPC Python to
synthesize initial metadata for the RPC).
Returns:
The initial metadata for the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def send_request(self, request):
"""Sends a request to the system under test.
Args:
request: A request message for the RPC to be "sent" to the system
under test.
"""
raise NotImplementedError()
@abc.abstractmethod
def requests_closed(self):
"""Indicates the end of the RPC's request stream."""
raise NotImplementedError()
@abc.abstractmethod
def cancel(self):
"""Cancels the RPC."""
raise NotImplementedError()
@abc.abstractmethod
def termination(self):
"""Blocks until the system under test has terminated the RPC.
Returns:
A (response, trailing_metadata, code, details) sequence with the RPC's
response, trailing metadata, code, and details.
"""
raise NotImplementedError()
class StreamStreamServerRpc(six.with_metaclass(abc.ABCMeta)):
"""Fixture for a stream-stream RPC serviced by a system under test.
Enables users to "play client" for the RPC.
"""
@abc.abstractmethod
def initial_metadata(self):
"""Accesses the initial metadata emitted by the system under test.
This method blocks until the system under test has added initial
metadata to the RPC (or has provided one or more response messages or
has terminated the RPC, either of which will cause gRPC Python to
synthesize initial metadata for the RPC).
Returns:
The initial metadata for the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def send_request(self, request):
"""Sends a request to the system under test.
Args:
request: A request message for the RPC to be "sent" to the system
under test.
"""
raise NotImplementedError()
@abc.abstractmethod
def requests_closed(self):
"""Indicates the end of the RPC's request stream."""
raise NotImplementedError()
@abc.abstractmethod
def take_response(self):
"""Draws one of the responses added to the RPC by the system under test.
Successive calls to this method return responses in the same order in
which the system under test added them to the RPC.
Returns:
A response message added to the RPC by the system under test.
"""
raise NotImplementedError()
@abc.abstractmethod
def cancel(self):
"""Cancels the RPC."""
raise NotImplementedError()
@abc.abstractmethod
def termination(self):
"""Blocks until the system under test has terminated the RPC.
Returns:
A (trailing_metadata, code, details) sequence with the RPC's trailing
metadata, code, and details.
"""
raise NotImplementedError()
class Server(six.with_metaclass(abc.ABCMeta)):
"""A server with which to test a system that services RPCs."""
@abc.abstractmethod
def invoke_unary_unary(
self, method_descriptor, invocation_metadata, request, timeout):
"""Invokes an RPC to be serviced by the system under test.
Args:
method_descriptor: A descriptor.MethodDescriptor describing a unary-unary
RPC method.
invocation_metadata: The RPC's invocation metadata.
request: The RPC's request.
timeout: A duration of time in seconds for the RPC or None to
indicate that the RPC has no time limit.
Returns:
A UnaryUnaryServerRpc with which to "play client" for the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def invoke_unary_stream(
self, method_descriptor, invocation_metadata, request, timeout):
"""Invokes an RPC to be serviced by the system under test.
Args:
method_descriptor: A descriptor.MethodDescriptor describing a unary-stream
RPC method.
invocation_metadata: The RPC's invocation metadata.
request: The RPC's request.
timeout: A duration of time in seconds for the RPC or None to
indicate that the RPC has no time limit.
Returns:
A UnaryStreamServerRpc with which to "play client" for the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def invoke_stream_unary(
self, method_descriptor, invocation_metadata, timeout):
"""Invokes an RPC to be serviced by the system under test.
Args:
method_descriptor: A descriptor.MethodDescriptor describing a stream-unary
RPC method.
invocation_metadata: The RPC's invocation metadata.
timeout: A duration of time in seconds for the RPC or None to
indicate that the RPC has no time limit.
Returns:
A StreamUnaryServerRpc with which to "play client" for the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def invoke_stream_stream(
self, method_descriptor, invocation_metadata, timeout):
"""Invokes an RPC to be serviced by the system under test.
Args:
method_descriptor: A descriptor.MethodDescriptor describing a stream-stream
RPC method.
invocation_metadata: The RPC's invocation metadata.
timeout: A duration of time in seconds for the RPC or None to
indicate that the RPC has no time limit.
Returns:
A StreamStreamServerRpc with which to "play client" for the RPC.
"""
raise NotImplementedError()
class Time(six.with_metaclass(abc.ABCMeta)):
"""A simulation of time.
@ -406,3 +678,20 @@ def channel(service_descriptors, time):
"""
from grpc_testing import _channel
return _channel.testing_channel(service_descriptors, time)
def server_from_dictionary(descriptors_to_servicers, time):
"""Creates a Server for use in tests of a gRPC Python-using system.
Args:
descriptors_to_servicers: A dictionary from descriptor.ServiceDescriptors
defining RPC services to servicer objects (usually instances of classes
that implement "Servicer" interfaces defined in generated "_pb2_grpc"
modules) implementing those services.
time: A Time to be used for tests.
Returns:
A Server for use in tests.
"""
from grpc_testing import _server
return _server.server_from_dictionary(descriptors_to_servicers, time)

@ -37,6 +37,16 @@ def fuss_with_metadata(metadata):
return _fuss(tuple(metadata))
def rpc_names(service_descriptors):
rpc_names_to_descriptors = {}
for service_descriptor in service_descriptors:
for method_descriptor in service_descriptor.methods_by_name.values():
rpc_name = '/{}/{}'.format(
service_descriptor.full_name, method_descriptor.name)
rpc_names_to_descriptors[rpc_name] = method_descriptor
return rpc_names_to_descriptors
class ChannelRpcRead(
collections.namedtuple(
'ChannelRpcRead',
@ -90,3 +100,61 @@ class ChannelHandler(six.with_metaclass(abc.ABCMeta)):
self, method_full_rpc_name, invocation_metadata, requests,
requests_closed, timeout):
raise NotImplementedError()
class ServerRpcRead(
collections.namedtuple('ServerRpcRead',
('request', 'requests_closed', 'terminated',))):
pass
REQUESTS_CLOSED = ServerRpcRead(None, True, False)
TERMINATED = ServerRpcRead(None, False, True)
class ServerRpcHandler(six.with_metaclass(abc.ABCMeta)):
@abc.abstractmethod
def send_initial_metadata(self, initial_metadata):
raise NotImplementedError()
@abc.abstractmethod
def take_request(self):
raise NotImplementedError()
@abc.abstractmethod
def add_response(self, response):
raise NotImplementedError()
@abc.abstractmethod
def send_termination(self, trailing_metadata, code, details):
raise NotImplementedError()
@abc.abstractmethod
def add_termination_callback(self, callback):
raise NotImplementedError()
class Serverish(six.with_metaclass(abc.ABCMeta)):
@abc.abstractmethod
def invoke_unary_unary(
self, method_descriptor, handler, invocation_metadata, request,
deadline):
raise NotImplementedError()
@abc.abstractmethod
def invoke_unary_stream(
self, method_descriptor, handler, invocation_metadata, request,
deadline):
raise NotImplementedError()
@abc.abstractmethod
def invoke_stream_unary(
self, method_descriptor, handler, invocation_metadata, deadline):
raise NotImplementedError()
@abc.abstractmethod
def invoke_stream_stream(
self, method_descriptor, handler, invocation_metadata, deadline):
raise NotImplementedError()

@ -0,0 +1,20 @@
# 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.
from grpc_testing._server import _server
def server_from_dictionary(descriptors_to_servicers, time):
return _server.server_from_descriptor_to_servicers(
descriptors_to_servicers, time)

@ -0,0 +1,215 @@
# 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.
import abc
import threading
import grpc
from grpc_testing import _common
_CLIENT_INACTIVE = object()
class Handler(_common.ServerRpcHandler):
@abc.abstractmethod
def initial_metadata(self):
raise NotImplementedError()
@abc.abstractmethod
def add_request(self, request):
raise NotImplementedError()
@abc.abstractmethod
def take_response(self):
raise NotImplementedError()
@abc.abstractmethod
def requests_closed(self):
raise NotImplementedError()
@abc.abstractmethod
def cancel(self):
raise NotImplementedError()
@abc.abstractmethod
def unary_response_termination(self):
raise NotImplementedError()
@abc.abstractmethod
def stream_response_termination(self):
raise NotImplementedError()
class _Handler(Handler):
def __init__(self, requests_closed):
self._condition = threading.Condition()
self._requests = []
self._requests_closed = requests_closed
self._initial_metadata = None
self._responses = []
self._trailing_metadata = None
self._code = None
self._details = None
self._unary_response = None
self._expiration_future = None
self._termination_callbacks = []
def send_initial_metadata(self, initial_metadata):
with self._condition:
self._initial_metadata = initial_metadata
self._condition.notify_all()
def take_request(self):
with self._condition:
while True:
if self._code is None:
if self._requests:
request = self._requests.pop(0)
self._condition.notify_all()
return _common.ServerRpcRead(request, False, False)
elif self._requests_closed:
return _common.REQUESTS_CLOSED
else:
self._condition.wait()
else:
return _common.TERMINATED
def is_active(self):
with self._condition:
return self._code is None
def add_response(self, response):
with self._condition:
self._responses.append(response)
self._condition.notify_all()
def send_termination(self, trailing_metadata, code, details):
with self._condition:
self._trailing_metadata = trailing_metadata
self._code = code
self._details = details
if self._expiration_future is not None:
self._expiration_future.cancel()
self._condition.notify_all()
def add_termination_callback(self, termination_callback):
with self._condition:
if self._code is None:
self._termination_callbacks.append(termination_callback)
return True
else:
return False
def initial_metadata(self):
with self._condition:
while True:
if self._initial_metadata is None:
if self._code is None:
self._condition.wait()
else:
raise ValueError(
'No initial metadata despite status code!')
else:
return self._initial_metadata
def add_request(self, request):
with self._condition:
self._requests.append(request)
self._condition.notify_all()
def take_response(self):
with self._condition:
while True:
if self._responses:
response = self._responses.pop(0)
self._condition.notify_all()
return response
elif self._code is None:
self._condition.wait()
else:
raise ValueError('No more responses!')
def requests_closed(self):
with self._condition:
self._requests_closed = True
self._condition.notify_all()
def cancel(self):
with self._condition:
if self._code is None:
self._code = _CLIENT_INACTIVE
termination_callbacks = self._termination_callbacks
self._termination_callbacks = None
if self._expiration_future is not None:
self._expiration_future.cancel()
self._condition.notify_all()
for termination_callback in termination_callbacks:
termination_callback()
def unary_response_termination(self):
with self._condition:
while True:
if self._code is _CLIENT_INACTIVE:
raise ValueError('Huh? Cancelled but wanting status?')
elif self._code is None:
self._condition.wait()
else:
if self._unary_response is None:
if self._responses:
self._unary_response = self._responses.pop(0)
return (
self._unary_response, self._trailing_metadata,
self._code, self._details,)
def stream_response_termination(self):
with self._condition:
while True:
if self._code is _CLIENT_INACTIVE:
raise ValueError('Huh? Cancelled but wanting status?')
elif self._code is None:
self._condition.wait()
else:
return self._trailing_metadata, self._code, self._details,
def expire(self):
with self._condition:
if self._code is None:
if self._initial_metadata is None:
self._initial_metadata = _common.FUSSED_EMPTY_METADATA
self._trailing_metadata = _common.FUSSED_EMPTY_METADATA
self._code = grpc.StatusCode.DEADLINE_EXCEEDED
self._details = 'Took too much time!'
termination_callbacks = self._termination_callbacks
self._termination_callbacks = None
self._condition.notify_all()
for termination_callback in termination_callbacks:
termination_callback()
def set_expiration_future(self, expiration_future):
with self._condition:
self._expiration_future = expiration_future
def handler_without_deadline(requests_closed):
return _Handler(requests_closed)
def handler_with_deadline(requests_closed, time, deadline):
handler = _Handler(requests_closed)
expiration_future = time.call_at(handler.expire, deadline)
handler.set_expiration_future(expiration_future)
return handler

@ -0,0 +1,153 @@
# 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.
import logging
import threading
import grpc
from grpc_testing import _common
class Rpc(object):
def __init__(self, handler, invocation_metadata):
self._condition = threading.Condition()
self._handler = handler
self._invocation_metadata = invocation_metadata
self._initial_metadata_sent = False
self._pending_trailing_metadata = None
self._pending_code = None
self._pending_details = None
self._callbacks = []
self._active = True
self._rpc_errors = []
def _ensure_initial_metadata_sent(self):
if not self._initial_metadata_sent:
self._handler.send_initial_metadata(_common.FUSSED_EMPTY_METADATA)
self._initial_metadata_sent = True
def _call_back(self):
callbacks = tuple(self._callbacks)
self._callbacks = None
def call_back():
for callback in callbacks:
try:
callback()
except Exception: # pylint: disable=broad-except
logging.exception('Exception calling server-side callback!')
callback_calling_thread = threading.Thread(target=call_back)
callback_calling_thread.start()
def _terminate(self, trailing_metadata, code, details):
if self._active:
self._active = False
self._handler.send_termination(trailing_metadata, code, details)
self._call_back()
self._condition.notify_all()
def _complete(self):
if self._pending_trailing_metadata is None:
trailing_metadata = _common.FUSSED_EMPTY_METADATA
else:
trailing_metadata = self._pending_trailing_metadata
if self._pending_code is None:
code = grpc.StatusCode.OK
else:
code = self._pending_code
details = '' if self._pending_details is None else self._pending_details
self._terminate(trailing_metadata, code, details)
def _abort(self, code, details):
self._terminate(_common.FUSSED_EMPTY_METADATA, code, details)
def add_rpc_error(self, rpc_error):
with self._condition:
self._rpc_errors.append(rpc_error)
def application_cancel(self):
with self._condition:
self._abort(
grpc.StatusCode.CANCELLED,
'Cancelled by server-side application!')
def application_exception_abort(self, exception):
with self._condition:
if exception not in self._rpc_errors:
logging.exception('Exception calling application!')
self._abort(
grpc.StatusCode.UNKNOWN,
'Exception calling application: {}'.format(exception))
def extrinsic_abort(self):
with self._condition:
if self._active:
self._active = False
self._call_back()
self._condition.notify_all()
def unary_response_complete(self, response):
with self._condition:
self._ensure_initial_metadata_sent()
self._handler.add_response(response)
self._complete()
def stream_response(self, response):
with self._condition:
self._ensure_initial_metadata_sent()
self._handler.add_response(response)
def stream_response_complete(self):
with self._condition:
self._ensure_initial_metadata_sent()
self._complete()
def send_initial_metadata(self, initial_metadata):
with self._condition:
if self._initial_metadata_sent:
return False
else:
self._handler.send_initial_metadata(initial_metadata)
self._initial_metadata_sent = True
return True
def is_active(self):
with self._condition:
return self._active
def add_callback(self, callback):
with self._condition:
if self._callbacks is None:
return False
else:
self._callbacks.append(callback)
return True
def invocation_metadata(self):
with self._condition:
return self._invocation_metadata
def set_trailing_metadata(self, trailing_metadata):
with self._condition:
self._pending_trailing_metadata = trailing_metadata
def set_code(self, code):
with self._condition:
self._pending_code = code
def set_details(self, details):
with self._condition:
self._pending_details = details

@ -0,0 +1,149 @@
# 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.
import threading
import grpc_testing
from grpc_testing import _common
from grpc_testing._server import _handler
from grpc_testing._server import _rpc
from grpc_testing._server import _server_rpc
from grpc_testing._server import _service
from grpc_testing._server import _servicer_context
def _implementation(descriptors_to_servicers, method_descriptor):
servicer = descriptors_to_servicers[method_descriptor.containing_service]
return getattr(servicer, method_descriptor.name)
def _unary_unary_service(request):
def service(implementation, rpc, servicer_context):
_service.unary_unary(
implementation, rpc, request, servicer_context)
return service
def _unary_stream_service(request):
def service(implementation, rpc, servicer_context):
_service.unary_stream(
implementation, rpc, request, servicer_context)
return service
def _stream_unary_service(handler):
def service(implementation, rpc, servicer_context):
_service.stream_unary(implementation, rpc, handler, servicer_context)
return service
def _stream_stream_service(handler):
def service(implementation, rpc, servicer_context):
_service.stream_stream(implementation, rpc, handler, servicer_context)
return service
class _Serverish(_common.Serverish):
def __init__(self, descriptors_to_servicers, time):
self._descriptors_to_servicers = descriptors_to_servicers
self._time = time
def _invoke(
self, service_behavior, method_descriptor, handler,
invocation_metadata, deadline):
implementation = _implementation(
self._descriptors_to_servicers, method_descriptor)
rpc = _rpc.Rpc(handler, invocation_metadata)
if handler.add_termination_callback(rpc.extrinsic_abort):
servicer_context = _servicer_context.ServicerContext(
rpc, self._time, deadline)
service_thread = threading.Thread(
target=service_behavior,
args=(implementation, rpc, servicer_context,))
service_thread.start()
def invoke_unary_unary(
self, method_descriptor, handler, invocation_metadata, request,
deadline):
self._invoke(
_unary_unary_service(request), method_descriptor, handler,
invocation_metadata, deadline)
def invoke_unary_stream(
self, method_descriptor, handler, invocation_metadata, request,
deadline):
self._invoke(
_unary_stream_service(request), method_descriptor, handler,
invocation_metadata, deadline)
def invoke_stream_unary(
self, method_descriptor, handler, invocation_metadata, deadline):
self._invoke(
_stream_unary_service(handler), method_descriptor, handler,
invocation_metadata, deadline)
def invoke_stream_stream(
self, method_descriptor, handler, invocation_metadata, deadline):
self._invoke(
_stream_stream_service(handler), method_descriptor, handler,
invocation_metadata, deadline)
def _deadline_and_handler(requests_closed, time, timeout):
if timeout is None:
return None, _handler.handler_without_deadline(requests_closed)
else:
deadline = time.time() + timeout
handler = _handler.handler_with_deadline(requests_closed, time, deadline)
return deadline, handler
class _Server(grpc_testing.Server):
def __init__(self, serverish, time):
self._serverish = serverish
self._time = time
def invoke_unary_unary(
self, method_descriptor, invocation_metadata, request, timeout):
deadline, handler = _deadline_and_handler(True, self._time, timeout)
self._serverish.invoke_unary_unary(
method_descriptor, handler, invocation_metadata, request, deadline)
return _server_rpc.UnaryUnaryServerRpc(handler)
def invoke_unary_stream(
self, method_descriptor, invocation_metadata, request, timeout):
deadline, handler = _deadline_and_handler(True, self._time, timeout)
self._serverish.invoke_unary_stream(
method_descriptor, handler, invocation_metadata, request, deadline)
return _server_rpc.UnaryStreamServerRpc(handler)
def invoke_stream_unary(
self, method_descriptor, invocation_metadata, timeout):
deadline, handler = _deadline_and_handler(False, self._time, timeout)
self._serverish.invoke_stream_unary(
method_descriptor, handler, invocation_metadata, deadline)
return _server_rpc.StreamUnaryServerRpc(handler)
def invoke_stream_stream(
self, method_descriptor, invocation_metadata, timeout):
deadline, handler = _deadline_and_handler(False, self._time, timeout)
self._serverish.invoke_stream_stream(
method_descriptor, handler, invocation_metadata, deadline)
return _server_rpc.StreamStreamServerRpc(handler)
def server_from_descriptor_to_servicers(descriptors_to_servicers, time):
return _Server(_Serverish(descriptors_to_servicers, time), time)

@ -0,0 +1,93 @@
# 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.
import grpc_testing
class UnaryUnaryServerRpc(grpc_testing.UnaryUnaryServerRpc):
def __init__(self, handler):
self._handler = handler
def initial_metadata(self):
return self._handler.initial_metadata()
def cancel(self):
self._handler.cancel()
def termination(self):
return self._handler.unary_response_termination()
class UnaryStreamServerRpc(grpc_testing.UnaryStreamServerRpc):
def __init__(self, handler):
self._handler = handler
def initial_metadata(self):
return self._handler.initial_metadata()
def take_response(self):
return self._handler.take_response()
def cancel(self):
self._handler.cancel()
def termination(self):
return self._handler.stream_response_termination()
class StreamUnaryServerRpc(grpc_testing.StreamUnaryServerRpc):
def __init__(self, handler):
self._handler = handler
def initial_metadata(self):
return self._handler.initial_metadata()
def send_request(self, request):
self._handler.add_request(request)
def requests_closed(self):
self._handler.requests_closed()
def cancel(self):
self._handler.cancel()
def termination(self):
return self._handler.unary_response_termination()
class StreamStreamServerRpc(grpc_testing.StreamStreamServerRpc):
def __init__(self, handler):
self._handler = handler
def initial_metadata(self):
return self._handler.initial_metadata()
def send_request(self, request):
self._handler.add_request(request)
def requests_closed(self):
self._handler.requests_closed()
def take_response(self):
return self._handler.take_response()
def cancel(self):
self._handler.cancel()
def termination(self):
return self._handler.stream_response_termination()

@ -0,0 +1,88 @@
# 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.
import grpc
class _RequestIterator(object):
def __init__(self, rpc, handler):
self._rpc = rpc
self._handler = handler
def _next(self):
read = self._handler.take_request()
if read.requests_closed:
raise StopIteration()
elif read.terminated:
rpc_error = grpc.RpcError()
self._rpc.add_rpc_error(rpc_error)
raise rpc_error
else:
return read.request
def __iter__(self):
return self
def __next__(self):
return self._next()
def next(self):
return self._next()
def _unary_response(argument, implementation, rpc, servicer_context):
try:
response = implementation(argument, servicer_context)
except Exception as exception: # pylint: disable=broad-except
rpc.application_exception_abort(exception)
else:
rpc.unary_response_complete(response)
def _stream_response(argument, implementation, rpc, servicer_context):
try:
response_iterator = implementation(argument, servicer_context)
except Exception as exception: # pylint: disable=broad-except
rpc.application_exception_abort(exception)
else:
while True:
try:
response = next(response_iterator)
except StopIteration:
rpc.stream_response_complete()
break
except Exception as exception: # pylint: disable=broad-except
rpc.application_exception_abort(exception)
break
else:
rpc.stream_response(response)
def unary_unary(implementation, rpc, request, servicer_context):
_unary_response(request, implementation, rpc, servicer_context)
def unary_stream(implementation, rpc, request, servicer_context):
_stream_response(request, implementation, rpc, servicer_context)
def stream_unary(implementation, rpc, handler, servicer_context):
_unary_response(
_RequestIterator(rpc, handler), implementation, rpc, servicer_context)
def stream_stream(implementation, rpc, handler, servicer_context):
_stream_response(
_RequestIterator(rpc, handler), implementation, rpc, servicer_context)

@ -0,0 +1,74 @@
# 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.
import grpc
from grpc_testing import _common
class ServicerContext(grpc.ServicerContext):
def __init__(self, rpc, time, deadline):
self._rpc = rpc
self._time = time
self._deadline = deadline
def is_active(self):
return self._rpc.is_active()
def time_remaining(self):
if self._rpc.is_active():
if self._deadline is None:
return None
else:
return max(0.0, self._deadline - self._time.time())
else:
return 0.0
def cancel(self):
self._rpc.application_cancel()
def add_callback(self, callback):
return self._rpc.add_callback(callback)
def invocation_metadata(self):
return self._rpc.invocation_metadata()
def peer(self):
raise NotImplementedError()
def peer_identities(self):
raise NotImplementedError()
def peer_identity_key(self):
raise NotImplementedError()
def auth_context(self):
raise NotImplementedError()
def send_initial_metadata(self, initial_metadata):
initial_metadata_sent = self._rpc.send_initial_metadata(
_common.fuss_with_metadata(initial_metadata))
if not initial_metadata_sent:
raise ValueError(
'ServicerContext.send_initial_metadata called too late!')
def set_trailing_metadata(self, trailing_metadata):
self._rpc.set_trailing_metadata(
_common.fuss_with_metadata(trailing_metadata))
def set_code(self, code):
self._rpc.set_code(code)
def set_details(self, details):
self._rpc.set_details(details)

@ -0,0 +1,66 @@
# 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.
"""An example gRPC Python-using server-side application."""
import grpc
# requests_pb2 is a semantic dependency of this module.
from tests.testing import _application_common
from tests.testing.proto import requests_pb2 # pylint: disable=unused-import
from tests.testing.proto import services_pb2
from tests.testing.proto import services_pb2_grpc
class FirstServiceServicer(services_pb2_grpc.FirstServiceServicer):
"""Services RPCs."""
def UnUn(self, request, context):
if _application_common.UNARY_UNARY_REQUEST == request:
return _application_common.UNARY_UNARY_RESPONSE
else:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details('Something is wrong with your request!')
return services_pb2.Down()
def UnStre(self, request, context):
if _application_common.UNARY_STREAM_REQUEST != request:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details('Something is wrong with your request!')
return
yield services_pb2.Strange()
def StreUn(self, request_iterator, context):
context.send_initial_metadata((
('server_application_metadata_key', 'Hi there!',),))
for request in request_iterator:
if request != _application_common.STREAM_UNARY_REQUEST:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details('Something is wrong with your request!')
return services_pb2.Strange()
elif not context.is_active():
return services_pb2.Strange()
else:
return _application_common.STREAM_UNARY_RESPONSE
def StreStre(self, request_iterator, context):
for request in request_iterator:
if request != _application_common.STREAM_STREAM_REQUEST:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details('Something is wrong with your request!')
return
elif not context.is_active():
return
else:
yield _application_common.STREAM_STREAM_RESPONSE
yield _application_common.STREAM_STREAM_RESPONSE

@ -0,0 +1,169 @@
# 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.
import time
import unittest
import grpc
import grpc_testing
from tests.testing import _application_common
from tests.testing import _application_testing_common
from tests.testing import _server_application
from tests.testing.proto import services_pb2
# TODO(https://github.com/google/protobuf/issues/3452): Drop this skip.
@unittest.skipIf(
services_pb2.DESCRIPTOR.services_by_name.get('FirstService') is None,
'Fix protobuf issue 3452!')
class FirstServiceServicerTest(unittest.TestCase):
def setUp(self):
self._real_time = grpc_testing.strict_real_time()
self._fake_time = grpc_testing.strict_fake_time(time.time())
servicer = _server_application.FirstServiceServicer()
descriptors_to_servicers = {
_application_testing_common.FIRST_SERVICE: servicer
}
self._real_time_server = grpc_testing.server_from_dictionary(
descriptors_to_servicers, self._real_time)
self._fake_time_server = grpc_testing.server_from_dictionary(
descriptors_to_servicers, self._fake_time)
def test_successful_unary_unary(self):
rpc = self._real_time_server.invoke_unary_unary(
_application_testing_common.FIRST_SERVICE_UNUN, (),
_application_common.UNARY_UNARY_REQUEST, None)
initial_metadata = rpc.initial_metadata()
response, trailing_metadata, code, details = rpc.termination()
self.assertEqual(_application_common.UNARY_UNARY_RESPONSE, response)
self.assertIs(code, grpc.StatusCode.OK)
def test_successful_unary_stream(self):
rpc = self._real_time_server.invoke_unary_stream(
_application_testing_common.FIRST_SERVICE_UNSTRE, (),
_application_common.UNARY_STREAM_REQUEST, None)
initial_metadata = rpc.initial_metadata()
trailing_metadata, code, details = rpc.termination()
self.assertIs(code, grpc.StatusCode.OK)
def test_successful_stream_unary(self):
rpc = self._real_time_server.invoke_stream_unary(
_application_testing_common.FIRST_SERVICE_STREUN, (), None)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
rpc.requests_closed()
initial_metadata = rpc.initial_metadata()
response, trailing_metadata, code, details = rpc.termination()
self.assertEqual(_application_common.STREAM_UNARY_RESPONSE, response)
self.assertIs(code, grpc.StatusCode.OK)
def test_successful_stream_stream(self):
rpc = self._real_time_server.invoke_stream_stream(
_application_testing_common.FIRST_SERVICE_STRESTRE, (), None)
rpc.send_request(_application_common.STREAM_STREAM_REQUEST)
initial_metadata = rpc.initial_metadata()
responses = [
rpc.take_response(),
rpc.take_response(),
]
rpc.send_request(_application_common.STREAM_STREAM_REQUEST)
rpc.send_request(_application_common.STREAM_STREAM_REQUEST)
responses.extend([
rpc.take_response(),
rpc.take_response(),
rpc.take_response(),
rpc.take_response(),
])
rpc.requests_closed()
trailing_metadata, code, details = rpc.termination()
for response in responses:
self.assertEqual(_application_common.STREAM_STREAM_RESPONSE,
response)
self.assertIs(code, grpc.StatusCode.OK)
def test_server_rpc_idempotence(self):
rpc = self._real_time_server.invoke_unary_unary(
_application_testing_common.FIRST_SERVICE_UNUN, (),
_application_common.UNARY_UNARY_REQUEST, None)
first_initial_metadata = rpc.initial_metadata()
second_initial_metadata = rpc.initial_metadata()
third_initial_metadata = rpc.initial_metadata()
first_termination = rpc.termination()
second_termination = rpc.termination()
third_termination = rpc.termination()
for later_initial_metadata in (second_initial_metadata,
third_initial_metadata,):
self.assertEqual(first_initial_metadata, later_initial_metadata)
response = first_termination[0]
terminal_metadata = first_termination[1]
code = first_termination[2]
details = first_termination[3]
for later_termination in (second_termination, third_termination,):
self.assertEqual(response, later_termination[0])
self.assertEqual(terminal_metadata, later_termination[1])
self.assertIs(code, later_termination[2])
self.assertEqual(details, later_termination[3])
self.assertEqual(_application_common.UNARY_UNARY_RESPONSE, response)
self.assertIs(code, grpc.StatusCode.OK)
def test_misbehaving_client_unary_unary(self):
rpc = self._real_time_server.invoke_unary_unary(
_application_testing_common.FIRST_SERVICE_UNUN, (),
_application_common.ERRONEOUS_UNARY_UNARY_REQUEST, None)
initial_metadata = rpc.initial_metadata()
response, trailing_metadata, code, details = rpc.termination()
self.assertIsNot(code, grpc.StatusCode.OK)
def test_infinite_request_stream_real_time(self):
rpc = self._real_time_server.invoke_stream_unary(
_application_testing_common.FIRST_SERVICE_STREUN, (),
_application_common.INFINITE_REQUEST_STREAM_TIMEOUT)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
initial_metadata = rpc.initial_metadata()
self._real_time.sleep_for(
_application_common.INFINITE_REQUEST_STREAM_TIMEOUT * 2)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
response, trailing_metadata, code, details = rpc.termination()
self.assertIs(code, grpc.StatusCode.DEADLINE_EXCEEDED)
def test_infinite_request_stream_fake_time(self):
rpc = self._fake_time_server.invoke_stream_unary(
_application_testing_common.FIRST_SERVICE_STREUN, (),
_application_common.INFINITE_REQUEST_STREAM_TIMEOUT)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
initial_metadata = rpc.initial_metadata()
self._fake_time.sleep_for(
_application_common.INFINITE_REQUEST_STREAM_TIMEOUT * 2)
rpc.send_request(_application_common.STREAM_UNARY_REQUEST)
response, trailing_metadata, code, details = rpc.termination()
self.assertIs(code, grpc.StatusCode.DEADLINE_EXCEEDED)
if __name__ == '__main__':
unittest.main(verbosity=2)

@ -10,6 +10,7 @@
"protoc_plugin.beta_python_plugin_test.PythonPluginTest",
"reflection._reflection_servicer_test.ReflectionServicerTest",
"testing._client_test.ClientTest",
"testing._server_test.FirstServiceServicerTest",
"testing._time_test.StrictFakeTimeTest",
"testing._time_test.StrictRealTimeTest",
"unit._api_test.AllTest",

@ -1,44 +1,569 @@
# This configuration was generated by `rubocop --auto-gen-config`
# on 2015-05-22 13:23:34 -0700 using RuboCop version 0.30.1.
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2017-09-04 17:00:36 +0200 using RuboCop version 0.49.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 30
Metrics/AbcSize:
Max: 38
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentOneStep, IndentationWidth.
# SupportedStyles: case, end
Layout/CaseIndentation:
Exclude:
- 'tools/platform_check.rb'
# Offense count: 1
# Cop supports --auto-correct.
Layout/CommentIndentation:
Exclude:
- 'qps/client.rb'
# Offense count: 1
# Cop supports --auto-correct.
Layout/EmptyLineAfterMagicComment:
Exclude:
- 'tools/grpc-tools.gemspec'
# Offense count: 33
# Cop supports --auto-correct.
# Configuration parameters: AllowAdjacentOneLineDefs, NumberOfEmptyLines.
Layout/EmptyLineBetweenDefs:
Exclude:
- 'qps/client.rb'
- 'qps/histogram.rb'
- 'qps/proxy-worker.rb'
- 'qps/server.rb'
- 'qps/worker.rb'
# Offense count: 1
# Cop supports --auto-correct.
Layout/EmptyLines:
Exclude:
- 'qps/qps-common.rb'
# Offense count: 8
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines
Layout/EmptyLinesAroundClassBody:
Exclude:
- 'pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb'
- 'pb/grpc/testing/metrics_services_pb.rb'
- 'pb/src/proto/grpc/testing/test_services_pb.rb'
- 'qps/src/proto/grpc/testing/proxy-service_services_pb.rb'
- 'qps/src/proto/grpc/testing/services_services_pb.rb'
# Offense count: 28
# Cop supports --auto-correct.
# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment.
Layout/ExtraSpacing:
Enabled: false
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: normal, rails
Layout/IndentationConsistency:
Exclude:
- 'pb/grpc/health/checker.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: Width, IgnoredPatterns.
Layout/IndentationWidth:
Exclude:
- 'pb/grpc/health/checker.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: symmetrical, new_line, same_line
Layout/MultilineHashBraceLayout:
Exclude:
- 'spec/generic/active_call_spec.rb'
# Offense count: 70
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: symmetrical, new_line, same_line
Layout/MultilineMethodCallBraceLayout:
Enabled: false
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
# SupportedStyles: aligned, indented, indented_relative_to_receiver
Layout/MultilineMethodCallIndentation:
Exclude:
- 'spec/generic/rpc_desc_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: symmetrical, new_line, same_line
Layout/MultilineMethodDefinitionBraceLayout:
Exclude:
- 'spec/generic/client_stub_spec.rb'
# Offense count: 5
# Cop supports --auto-correct.
Layout/SpaceAfterColon:
Exclude:
- 'lib/grpc/generic/rpc_server.rb'
# Offense count: 7
# Cop supports --auto-correct.
Layout/SpaceAfterComma:
Exclude:
- 'qps/client.rb'
# Offense count: 27
# Cop supports --auto-correct.
# Configuration parameters: AllowForAlignment.
Layout/SpaceAroundOperators:
Exclude:
- 'qps/client.rb'
- 'qps/histogram.rb'
- 'qps/proxy-worker.rb'
- 'qps/server.rb'
- 'spec/generic/active_call_spec.rb'
- 'spec/generic/rpc_server_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters.
# SupportedStyles: space, no_space
# SupportedStylesForEmptyBraces: space, no_space
Layout/SpaceInsideBlockBraces:
Exclude:
- 'stress/stress_client.rb'
# Offense count: 4
# Cop supports --auto-correct.
Layout/SpaceInsideBrackets:
Exclude:
- 'tools/bin/grpc_tools_ruby_protoc'
- 'tools/bin/grpc_tools_ruby_protoc_plugin'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces.
# SupportedStyles: space, no_space, compact
# SupportedStylesForEmptyBraces: space, no_space
Layout/SpaceInsideHashLiteralBraces:
Exclude:
- 'qps/server.rb'
# Offense count: 6
# Cop supports --auto-correct.
Layout/SpaceInsidePercentLiteralDelimiters:
Exclude:
- 'spec/generic/client_stub_spec.rb'
- 'tools/grpc-tools.gemspec'
# Offense count: 3
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 200
# Cop supports --auto-correct.
Layout/Tab:
Exclude:
- 'pb/grpc/health/checker.rb'
- 'qps/client.rb'
# Offense count: 1
# Cop supports --auto-correct.
Layout/TrailingWhitespace:
Exclude:
- 'qps/worker.rb'
# Offense count: 1
Lint/IneffectiveAccessModifier:
Exclude:
- 'lib/grpc/generic/active_call.rb'
# Offense count: 4
# Cop supports --auto-correct.
Lint/PercentStringArray:
Exclude:
- 'spec/client_server_spec.rb'
- 'spec/generic/active_call_spec.rb'
- 'spec/generic/client_stub_spec.rb'
# Offense count: 4
Lint/ScriptPermission:
Exclude:
- 'qps/client.rb'
- 'qps/histogram.rb'
- 'qps/qps-common.rb'
- 'qps/server.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
Lint/UnusedBlockArgument:
Exclude:
- 'qps/client.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
Lint/UnusedMethodArgument:
Exclude:
- 'qps/client.rb'
# Offense count: 1
# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
Lint/UselessAccessModifier:
Exclude:
- 'lib/grpc/logconfig.rb'
# Offense count: 1
Lint/UselessAssignment:
Exclude:
- 'qps/client.rb'
# Offense count: 35
# Offense count: 4
Lint/Void:
Exclude:
- 'stress/metrics_server.rb'
- 'stress/stress_client.rb'
# Offense count: 53
Metrics/AbcSize:
Max: 57
# Offense count: 81
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/BlockLength:
Max: 715
# Offense count: 82
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Metrics/LineLength:
Max: 141
# Offense count: 82
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 36
Max: 54
# Offense count: 7
# Offense count: 5
# Configuration parameters: CountKeywordArgs.
Metrics/ParameterLists:
Max: 8
Max: 7
# Offense count: 1
# Cop supports --auto-correct.
Performance/RedundantBlockCall:
Exclude:
- 'spec/generic/client_stub_spec.rb'
# Offense count: 5
# Cop supports --auto-correct.
# Configuration parameters: MaxKeyValuePairs.
Performance/RedundantMerge:
Exclude:
- 'spec/generic/active_call_spec.rb'
- 'spec/generic/client_stub_spec.rb'
# Offense count: 8
# Cop supports --auto-correct.
Performance/TimesMap:
Exclude:
- 'spec/channel_spec.rb'
- 'spec/client_server_spec.rb'
- 'spec/server_spec.rb'
# Offense count: 7
Style/AccessorMethodName:
Exclude:
- 'qps/server.rb'
- 'stress/metrics_server.rb'
- 'stress/stress_client.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: prefer_alias, prefer_alias_method
Style/Alias:
Exclude:
- 'lib/grpc/generic/rpc_server.rb'
- 'lib/grpc/notifier.rb'
# Offense count: 7
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods.
# SupportedStyles: line_count_based, semantic, braces_for_chaining
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
# FunctionalMethods: let, let!, subject, watch
# IgnoredMethods: lambda, proc, it
Style/BlockDelimiters:
Exclude:
- 'qps/client.rb'
- 'qps/proxy-worker.rb'
- 'qps/server.rb'
- 'qps/worker.rb'
# Offense count: 2
# Cop supports --auto-correct.
Style/ClassMethods:
Exclude:
- 'tools/platform_check.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, SingleLineConditionsOnly, IncludeTernaryExpressions.
# SupportedStyles: assign_to_condition, assign_inside_condition
Style/ConditionalAssignment:
Exclude:
- 'lib/grpc/generic/rpc_server.rb'
- 'lib/grpc/generic/service.rb'
# Offense count: 19
Style/Documentation:
Exclude:
- 'spec/**/*'
- 'test/**/*'
- 'pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb'
- 'pb/grpc/testing/metrics_services_pb.rb'
- 'pb/src/proto/grpc/testing/test_pb.rb'
- 'qps/client.rb'
- 'qps/histogram.rb'
- 'qps/proxy-worker.rb'
- 'qps/server.rb'
- 'qps/src/proto/grpc/testing/proxy-service_services_pb.rb'
- 'qps/src/proto/grpc/testing/services_pb.rb'
- 'qps/src/proto/grpc/testing/services_services_pb.rb'
- 'qps/worker.rb'
- 'stress/metrics_server.rb'
- 'stress/stress_client.rb'
- 'tools/platform_check.rb'
# Offense count: 9
# Offense count: 8
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: compact, expanded
Style/EmptyMethod:
Exclude:
- 'bin/noproto_server.rb'
- 'lib/grpc/logconfig.rb'
- 'spec/generic/rpc_desc_spec.rb'
# Offense count: 2
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
Style/FileName:
Exclude:
- 'qps/src/proto/grpc/testing/proxy-service_pb.rb'
- 'qps/src/proto/grpc/testing/proxy-service_services_pb.rb'
# Offense count: 12
# Configuration parameters: AllowedVariables.
Style/GlobalVars:
Enabled: false
Exclude:
- 'ext/grpc/extconf.rb'
# Offense count: 3
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Exclude:
- 'lib/grpc/generic/bidi_call.rb'
- 'lib/grpc/generic/rpc_server.rb'
- 'qps/client.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
Style/HashSyntax:
Exclude:
- 'stress/metrics_server.rb'
# Offense count: 1
Style/IfInsideElse:
Exclude:
- 'lib/grpc/generic/rpc_desc.rb'
# Offense count: 4
# Cop supports --auto-correct.
# Configuration parameters: MaxLineLength.
Style/IfUnlessModifier:
Exclude:
- 'ext/grpc/extconf.rb'
- 'qps/histogram.rb'
- 'stress/stress_client.rb'
# Offense count: 1
# Cop supports --auto-correct.
Style/MethodCallWithoutArgsParentheses:
Exclude:
- 'qps/client.rb'
# Offense count: 3
# Cop supports --auto-correct.
Style/MultilineIfModifier:
Exclude:
- 'lib/grpc/generic/bidi_call.rb'
- 'lib/grpc/generic/client_stub.rb'
- 'spec/spec_helper.rb'
# Offense count: 7
# Cop supports --auto-correct.
Style/MutableConstant:
Exclude:
- 'ext/grpc/extconf.rb'
- 'lib/grpc/version.rb'
- 'spec/compression_options_spec.rb'
- 'spec/generic/active_call_spec.rb'
- 'tools/version.rb'
# Offense count: 1
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
Style/Next:
# Cop supports --auto-correct.
Style/NegatedWhile:
Exclude:
- 'qps/client.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
# SupportedStyles: predicate, comparison
Style/NumericPredicate:
Exclude:
- 'spec/**/*'
- 'ext/grpc/extconf.rb'
# Offense count: 7
# Cop supports --auto-correct.
Style/ParallelAssignment:
Exclude:
- 'bin/math_server.rb'
- 'lib/grpc/generic/rpc_server.rb'
- 'spec/generic/client_stub_spec.rb'
- 'spec/generic/rpc_desc_spec.rb'
- 'spec/generic/rpc_server_pool_spec.rb'
- 'spec/generic/rpc_server_spec.rb'
# Offense count: 8
# Cop supports --auto-correct.
# Configuration parameters: PreferredDelimiters.
Style/PercentLiteralDelimiters:
Exclude:
- 'end2end/grpc_class_init_driver.rb'
- 'spec/client_server_spec.rb'
- 'spec/generic/active_call_spec.rb'
- 'spec/generic/client_stub_spec.rb'
- 'tools/grpc-tools.gemspec'
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: compact, exploded
Style/RaiseArgs:
Exclude:
- 'stress/metrics_server.rb'
# Offense count: 4
# Cop supports --auto-correct.
Style/RedundantParentheses:
Exclude:
- 'lib/grpc/generic/rpc_server.rb'
- 'qps/client.rb'
- 'qps/proxy-worker.rb'
- 'spec/generic/rpc_desc_spec.rb'
# Offense count: 5
# Cop supports --auto-correct.
# Configuration parameters: AllowMultipleReturnValues.
Style/RedundantReturn:
Exclude:
- 'end2end/grpc_class_init_client.rb'
# Offense count: 77
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: only_raise, only_fail, semantic
Style/SignalException:
Enabled: false
# Offense count: 2
# Configuration parameters: Methods.
Style/SingleLineBlockParams:
Enabled: false
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: use_perl_names, use_english_names
Style/SpecialGlobalVars:
Exclude:
- 'ext/grpc/extconf.rb'
- 'stress/stress_client.rb'
# Offense count: 189
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiterals:
Exclude:
- 'pb/grpc/testing/metrics_pb.rb'
- 'pb/src/proto/grpc/testing/empty_pb.rb'
- 'pb/src/proto/grpc/testing/messages_pb.rb'
- 'qps/proxy-worker.rb'
- 'qps/server.rb'
- 'qps/src/proto/grpc/testing/control_pb.rb'
- 'qps/src/proto/grpc/testing/messages_pb.rb'
- 'qps/src/proto/grpc/testing/payloads_pb.rb'
- 'qps/src/proto/grpc/testing/proxy-service_pb.rb'
- 'qps/src/proto/grpc/testing/stats_pb.rb'
- 'qps/worker.rb'
# Offense count: 1
Style/StructInheritance:
Enabled: false
Exclude:
- 'lib/grpc/generic/rpc_desc.rb'
# Offense count: 10
# Cop supports --auto-correct.
# Configuration parameters: MinSize, SupportedStyles.
# SupportedStyles: percent, brackets
Style/SymbolArray:
EnforcedStyle: brackets
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: IgnoredMethods.
# IgnoredMethods: respond_to, define_method
Style/SymbolProc:
Exclude:
- 'qps/client.rb'
- 'stress/stress_client.rb'
# Offense count: 6
# Cop supports --auto-correct.
# Configuration parameters: AllowNamedUnderscoreVariables.
Style/TrailingUnderscoreVariable:
Exclude:
- 'spec/channel_credentials_spec.rb'
- 'spec/server_credentials_spec.rb'
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
# Whitelist: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym
Style/TrivialAccessors:
Exclude:
- 'qps/histogram.rb'
# Offense count: 3
# Cop supports --auto-correct.
Style/UnneededInterpolation:
Exclude:
- 'pb/grpc/health/checker.rb'
# Offense count: 1
# Cop supports --auto-correct.
Style/YodaCondition:
Exclude:
- 'stress/stress_client.rb'
# Offense count: 2
# Cop supports --auto-correct.
Style/ZeroLengthPredicate:
Exclude:
- 'lib/grpc/generic/rpc_server.rb'

@ -41,7 +41,7 @@ def run_gc_stress_test(test_proc)
GC.enable
construct_many(test_proc)
GC.start(full_mark: true, immediate_sweep: true)
GC.start
construct_many(test_proc)
end

@ -93,6 +93,7 @@ grpc_alarm_destroy_type grpc_alarm_destroy_import;
grpc_channel_check_connectivity_state_type grpc_channel_check_connectivity_state_import;
grpc_channel_num_external_connectivity_watchers_type grpc_channel_num_external_connectivity_watchers_import;
grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import;
grpc_channel_support_connectivity_watcher_type grpc_channel_support_connectivity_watcher_import;
grpc_channel_create_call_type grpc_channel_create_call_import;
grpc_channel_ping_type grpc_channel_ping_import;
grpc_channel_register_call_type grpc_channel_register_call_import;
@ -399,6 +400,7 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_channel_check_connectivity_state_import = (grpc_channel_check_connectivity_state_type) GetProcAddress(library, "grpc_channel_check_connectivity_state");
grpc_channel_num_external_connectivity_watchers_import = (grpc_channel_num_external_connectivity_watchers_type) GetProcAddress(library, "grpc_channel_num_external_connectivity_watchers");
grpc_channel_watch_connectivity_state_import = (grpc_channel_watch_connectivity_state_type) GetProcAddress(library, "grpc_channel_watch_connectivity_state");
grpc_channel_support_connectivity_watcher_import = (grpc_channel_support_connectivity_watcher_type) GetProcAddress(library, "grpc_channel_support_connectivity_watcher");
grpc_channel_create_call_import = (grpc_channel_create_call_type) GetProcAddress(library, "grpc_channel_create_call");
grpc_channel_ping_import = (grpc_channel_ping_type) GetProcAddress(library, "grpc_channel_ping");
grpc_channel_register_call_import = (grpc_channel_register_call_type) GetProcAddress(library, "grpc_channel_register_call");

@ -260,6 +260,9 @@ extern grpc_channel_num_external_connectivity_watchers_type grpc_channel_num_ext
typedef void(*grpc_channel_watch_connectivity_state_type)(grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag);
extern grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import;
#define grpc_channel_watch_connectivity_state grpc_channel_watch_connectivity_state_import
typedef int(*grpc_channel_support_connectivity_watcher_type)(grpc_channel *channel);
extern grpc_channel_support_connectivity_watcher_type grpc_channel_support_connectivity_watcher_import;
#define grpc_channel_support_connectivity_watcher grpc_channel_support_connectivity_watcher_import
typedef grpc_call *(*grpc_channel_create_call_type)(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved);
extern grpc_channel_create_call_type grpc_channel_create_call_import;
#define grpc_channel_create_call grpc_channel_create_call_import

@ -171,6 +171,7 @@
'test/core/end2end/end2end_tests.{c,h}',
'test/core/end2end/end2end_test_utils.c',
'test/core/end2end/tests/*.{c,h}',
'test/core/end2end/fixtures/*.h',
'test/core/end2end/data/*.{c,h}',
'test/core/util/debugger_macros.{c,h}',
'test/core/util/test_config.{c,h}',

@ -35,12 +35,12 @@
s.add_development_dependency 'bundler', '~> 1.9'
s.add_development_dependency 'facter', '~> 2.4'
s.add_development_dependency 'logging', '~> 2.0'
s.add_development_dependency 'simplecov', '~> 0.9'
s.add_development_dependency 'rake', '~> 10.4'
s.add_development_dependency 'simplecov', '~> 0.14.1'
s.add_development_dependency 'rake', '~> 12.0'
s.add_development_dependency 'rake-compiler', '~> 1.0'
s.add_development_dependency 'rake-compiler-dock', '~> 0.5.1'
s.add_development_dependency 'rspec', '~> 3.2'
s.add_development_dependency 'rubocop', '~> 0.30.0'
s.add_development_dependency 'rspec', '~> 3.6'
s.add_development_dependency 'rubocop', '~> 0.49.1'
s.add_development_dependency 'signet', '~> 0.7.0'
s.extensions = %w(src/ruby/ext/grpc/extconf.rb)

@ -103,7 +103,7 @@
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
s.dependency '!ProtoCompiler', '3.3.0'
s.dependency '!ProtoCompiler', '3.4.0'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'

@ -39,10 +39,13 @@ static void *tag(intptr_t t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
cancellation_mode mode,
bool use_service_config,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
gpr_log(GPR_INFO, "Running test: %s/%s/%s/%s", test_name, config.name,
mode.name, use_service_config ? "service_config" : "client_api");
f = config.create_fixture(client_args, server_args);
config.init_server(&f, server_args);
config.init_client(&f, client_args);
@ -135,8 +138,8 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
args = grpc_channel_args_copy_and_add(args, &arg, 1);
}
grpc_end2end_test_fixture f =
begin_test(config, "cancel_after_accept", args, NULL);
grpc_end2end_test_fixture f = begin_test(config, "cancel_after_accept", mode,
use_service_config, args, NULL);
cq_verifier *cqv = cq_verifier_create(f.cq);
gpr_timespec deadline = use_service_config

@ -33,10 +33,12 @@ static void *tag(intptr_t t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
cancellation_mode mode,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
gpr_log(GPR_INFO, "Running test: %s/%s/%s", test_name, config.name,
mode.name);
f = config.create_fixture(client_args, server_args);
config.init_server(&f, server_args);
config.init_client(&f, client_args);
@ -93,7 +95,7 @@ static void test_cancel_after_accept_and_writes_closed(
grpc_call *c;
grpc_call *s;
grpc_end2end_test_fixture f = begin_test(
config, "test_cancel_after_accept_and_writes_closed", NULL, NULL);
config, "test_cancel_after_accept_and_writes_closed", mode, NULL, NULL);
cq_verifier *cqv = cq_verifier_create(f.cq);
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;

@ -39,10 +39,13 @@ static void *tag(intptr_t t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
cancellation_mode mode,
bool use_service_config,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
gpr_log(GPR_INFO, "Running test: %s/%s/%s/%s", test_name, config.name,
mode.name, use_service_config ? "service_config" : "client_api");
f = config.create_fixture(client_args, server_args);
config.init_server(&f, server_args);
config.init_client(&f, client_args);
@ -137,8 +140,8 @@ static void test_cancel_after_round_trip(grpc_end2end_test_config config,
args = grpc_channel_args_copy_and_add(args, &arg, 1);
}
grpc_end2end_test_fixture f =
begin_test(config, "cancel_after_round_trip", args, NULL);
grpc_end2end_test_fixture f = begin_test(
config, "cancel_after_round_trip", mode, use_service_config, args, NULL);
cq_verifier *cqv = cq_verifier_create(f.cq);
gpr_timespec deadline = use_service_config

@ -32,10 +32,12 @@ static void *tag(intptr_t t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
size_t num_ops,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
gpr_log(GPR_INFO, "Running test: %s/%s [%" PRIdPTR " ops]", test_name,
config.name, num_ops);
f = config.create_fixture(client_args, server_args);
config.init_server(&f, server_args);
config.init_client(&f, client_args);
@ -91,7 +93,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config,
grpc_op *op;
grpc_call *c;
grpc_end2end_test_fixture f =
begin_test(config, "cancel_before_invoke", NULL, NULL);
begin_test(config, "cancel_before_invoke", test_ops, NULL, NULL);
cq_verifier *cqv = cq_verifier_create(f.cq);
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;

@ -33,10 +33,12 @@ static void *tag(intptr_t t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
cancellation_mode mode,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
gpr_log(GPR_INFO, "Running test: %s/%s/%s", test_name, config.name,
mode.name);
f = config.create_fixture(client_args, server_args);
config.init_server(&f, server_args);
config.init_client(&f, client_args);
@ -90,7 +92,7 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config,
cancellation_mode mode) {
grpc_call *c;
grpc_end2end_test_fixture f =
begin_test(config, "test_cancel_in_a_vacuum", NULL, NULL);
begin_test(config, "test_cancel_in_a_vacuum", mode, NULL, NULL);
cq_verifier *v_client = cq_verifier_create(f.cq);
gpr_timespec deadline = five_seconds_from_now();

@ -35,10 +35,12 @@ static void *tag(intptr_t t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
size_t num_ops,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
gpr_log(GPR_INFO, "Running test: %s/%s [%" PRIdPTR " ops]", test_name,
config.name, num_ops);
f = config.create_fixture(client_args, server_args);
config.init_server(&f, server_args);
config.init_client(&f, client_args);
@ -165,7 +167,7 @@ static void test_invoke_simple_request(grpc_end2end_test_config config,
size_t num_ops) {
grpc_end2end_test_fixture f;
f = begin_test(config, "test_invoke_simple_request", NULL, NULL);
f = begin_test(config, "test_invoke_simple_request", num_ops, NULL, NULL);
simple_request_body(config, f, num_ops);
end_test(&f);
config.tear_down_data(&f);

@ -279,6 +279,21 @@ static void test_memrchr(void) {
GPR_ASSERT(0 == strcmp((const char *)gpr_memrchr("hello", 'l', 5), "lo"));
}
static void test_is_true(void) {
LOG_TEST_NAME("test_is_true");
GPR_ASSERT(true == gpr_is_true("True"));
GPR_ASSERT(true == gpr_is_true("true"));
GPR_ASSERT(true == gpr_is_true("TRUE"));
GPR_ASSERT(true == gpr_is_true("Yes"));
GPR_ASSERT(true == gpr_is_true("yes"));
GPR_ASSERT(true == gpr_is_true("YES"));
GPR_ASSERT(true == gpr_is_true("1"));
GPR_ASSERT(false == gpr_is_true(NULL));
GPR_ASSERT(false == gpr_is_true(""));
GPR_ASSERT(false == gpr_is_true("0"));
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_strdup();
@ -292,5 +307,6 @@ int main(int argc, char **argv) {
test_leftpad();
test_stricmp();
test_memrchr();
test_is_true();
return 0;
}

@ -18,13 +18,63 @@ licenses(["notice"]) # Apache v2
grpc_package(name = "test/core/tsi")
grpc_cc_library(
name = "transport_security_test_lib",
srcs = ["transport_security_test_lib.c"],
hdrs = ["transport_security_test_lib.h"],
deps = [
"//:grpc",
"//:tsi",
],
)
grpc_cc_test(
name = "fake_transport_security_test",
srcs = ["fake_transport_security_test.c"],
language = "C",
deps = [
":transport_security_test_lib",
"//:grpc",
"//:gpr",
"//:tsi",
"//test/core/util:gpr_test_util",
],
)
grpc_cc_test(
name = "ssl_transport_security_test",
srcs = ["ssl_transport_security_test.c"],
data = [
"//src/core/tsi/test_creds:badclient.key",
"//src/core/tsi/test_creds:badclient.pem",
"//src/core/tsi/test_creds:badserver.key",
"//src/core/tsi/test_creds:badserver.pem",
"//src/core/tsi/test_creds:ca.pem",
"//src/core/tsi/test_creds:client.key",
"//src/core/tsi/test_creds:client.pem",
"//src/core/tsi/test_creds:server0.key",
"//src/core/tsi/test_creds:server0.pem",
"//src/core/tsi/test_creds:server1.key",
"//src/core/tsi/test_creds:server1.pem",
],
language = "C",
deps = [
":transport_security_test_lib",
"//:grpc",
"//:gpr",
"//:tsi",
"//test/core/util:gpr_test_util",
],
)
grpc_cc_test(
name = "transport_security_test",
srcs = ["transport_security_test.c"],
language = "C",
deps = [
"//:gpr",
"//:grpc",
"//:gpr",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],

@ -0,0 +1,148 @@
/*
*
* 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 <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "src/core/lib/security/transport/security_connector.h"
#include "src/core/tsi/fake_transport_security.h"
#include "test/core/tsi/transport_security_test_lib.h"
#include "test/core/util/test_config.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
typedef struct fake_tsi_test_fixture {
tsi_test_fixture base;
} fake_tsi_test_fixture;
static void fake_test_setup_handshakers(tsi_test_fixture *fixture) {
fixture->client_handshaker =
tsi_create_fake_handshaker(true /* is_client. */);
fixture->server_handshaker =
tsi_create_fake_handshaker(false /* is_client. */);
}
static void validate_handshaker_peers(tsi_handshaker_result *result) {
GPR_ASSERT(result != NULL);
tsi_peer peer;
GPR_ASSERT(tsi_handshaker_result_extract_peer(result, &peer) == TSI_OK);
const tsi_peer_property *property =
tsi_peer_get_property_by_name(&peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY);
GPR_ASSERT(property != NULL);
GPR_ASSERT(memcmp(property->value.data, TSI_FAKE_CERTIFICATE_TYPE,
property->value.length) == 0);
tsi_peer_destruct(&peer);
}
static void fake_test_check_handshaker_peers(tsi_test_fixture *fixture) {
validate_handshaker_peers(fixture->client_result);
validate_handshaker_peers(fixture->server_result);
}
static void fake_test_destruct(tsi_test_fixture *fixture) {}
static const struct tsi_test_fixture_vtable vtable = {
fake_test_setup_handshakers, fake_test_check_handshaker_peers,
fake_test_destruct};
static tsi_test_fixture *fake_tsi_test_fixture_create() {
fake_tsi_test_fixture *fake_fixture = gpr_zalloc(sizeof(*fake_fixture));
tsi_test_fixture_init(&fake_fixture->base);
fake_fixture->base.vtable = &vtable;
return &fake_fixture->base;
}
void fake_tsi_test_do_handshake_tiny_handshake_buffer() {
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void fake_tsi_test_do_handshake_small_handshake_buffer() {
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
fixture->handshake_buffer_size = TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void fake_tsi_test_do_handshake() {
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void fake_tsi_test_do_round_trip_for_all_configs() {
unsigned int *bit_array =
gpr_zalloc(sizeof(unsigned int) * TSI_TEST_NUM_OF_ARGUMENTS);
const unsigned int mask = 1U << (TSI_TEST_NUM_OF_ARGUMENTS - 1);
for (unsigned int val = 0; val < TSI_TEST_NUM_OF_COMBINATIONS; val++) {
unsigned int v = val;
for (unsigned int ind = 0; ind < TSI_TEST_NUM_OF_ARGUMENTS; ind++) {
bit_array[ind] = (v & mask) ? 1 : 0;
v <<= 1;
}
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
fake_tsi_test_fixture *fake_fixture = (fake_tsi_test_fixture *)fixture;
tsi_test_frame_protector_config_destroy(fake_fixture->base.config);
fake_fixture->base.config = tsi_test_frame_protector_config_create(
bit_array[0], bit_array[1], bit_array[2], bit_array[3], bit_array[4],
bit_array[5], bit_array[6], bit_array[7]);
tsi_test_do_round_trip(&fake_fixture->base);
tsi_test_fixture_destroy(fixture);
}
gpr_free(bit_array);
}
void fake_tsi_test_do_round_trip_odd_buffer_size() {
const size_t odd_sizes[] = {1025, 2051, 4103, 8207, 16409};
const size_t size = sizeof(odd_sizes) / sizeof(size_t);
for (size_t ind1 = 0; ind1 < size; ind1++) {
for (size_t ind2 = 0; ind2 < size; ind2++) {
for (size_t ind3 = 0; ind3 < size; ind3++) {
for (size_t ind4 = 0; ind4 < size; ind4++) {
for (size_t ind5 = 0; ind5 < size; ind5++) {
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
fake_tsi_test_fixture *fake_fixture =
(fake_tsi_test_fixture *)fixture;
tsi_test_frame_protector_config_set_buffer_size(
fake_fixture->base.config, odd_sizes[ind1], odd_sizes[ind2],
odd_sizes[ind3], odd_sizes[ind4], odd_sizes[ind5]);
tsi_test_do_round_trip(&fake_fixture->base);
tsi_test_fixture_destroy(fixture);
}
}
}
}
}
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
fake_tsi_test_do_handshake_tiny_handshake_buffer();
fake_tsi_test_do_handshake_small_handshake_buffer();
fake_tsi_test_do_handshake();
fake_tsi_test_do_round_trip_for_all_configs();
fake_tsi_test_do_round_trip_odd_buffer_size();
grpc_shutdown();
return 0;
}

@ -0,0 +1,558 @@
/*
*
* 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 <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/transport/security_connector.h"
#include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security_adapter.h"
#include "test/core/tsi/transport_security_test_lib.h"
#include "test/core/util/test_config.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#define SSL_TSI_TEST_ALPN1 "foo"
#define SSL_TSI_TEST_ALPN2 "toto"
#define SSL_TSI_TEST_ALPN3 "baz"
#define SSL_TSI_TEST_ALPN_NUM 2
#define SSL_TSI_TEST_SERVER_KEY_CERT_PAIRS_NUM 2
#define SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM 1
#define SSL_TSI_TEST_CREDENTIALS_DIR "src/core/tsi/test_creds/"
typedef enum AlpnMode {
NO_ALPN,
ALPN_CLIENT_NO_SERVER,
ALPN_SERVER_NO_CLIENT,
ALPN_CLIENT_SERVER_OK,
ALPN_CLIENT_SERVER_MISMATCH
} AlpnMode;
typedef struct ssl_alpn_lib {
AlpnMode alpn_mode;
char **server_alpn_protocols;
char **client_alpn_protocols;
uint16_t num_server_alpn_protocols;
uint16_t num_client_alpn_protocols;
} ssl_alpn_lib;
typedef struct ssl_key_cert_lib {
bool use_bad_server_cert;
bool use_bad_client_cert;
char *root_cert;
tsi_ssl_pem_key_cert_pair *server_pem_key_cert_pairs;
tsi_ssl_pem_key_cert_pair *bad_server_pem_key_cert_pairs;
tsi_ssl_pem_key_cert_pair client_pem_key_cert_pair;
tsi_ssl_pem_key_cert_pair bad_client_pem_key_cert_pair;
uint16_t server_num_key_cert_pairs;
uint16_t bad_server_num_key_cert_pairs;
} ssl_key_cert_lib;
typedef struct ssl_tsi_test_fixture {
tsi_test_fixture base;
ssl_key_cert_lib *key_cert_lib;
ssl_alpn_lib *alpn_lib;
bool force_client_auth;
char *server_name_indication;
tsi_ssl_server_handshaker_factory *server_handshaker_factory;
tsi_ssl_client_handshaker_factory *client_handshaker_factory;
} ssl_tsi_test_fixture;
static void ssl_test_setup_handshakers(tsi_test_fixture *fixture) {
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
GPR_ASSERT(ssl_fixture != NULL);
GPR_ASSERT(ssl_fixture->key_cert_lib != NULL);
GPR_ASSERT(ssl_fixture->alpn_lib != NULL);
ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib;
ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib;
/* Create client handshaker factory. */
tsi_ssl_pem_key_cert_pair *client_key_cert_pair = NULL;
if (ssl_fixture->force_client_auth) {
client_key_cert_pair = key_cert_lib->use_bad_client_cert
? &key_cert_lib->bad_client_pem_key_cert_pair
: &key_cert_lib->client_pem_key_cert_pair;
}
char **client_alpn_protocols = NULL;
uint16_t num_client_alpn_protocols = 0;
if (alpn_lib->alpn_mode == ALPN_CLIENT_NO_SERVER ||
alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ||
alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) {
client_alpn_protocols = alpn_lib->client_alpn_protocols;
num_client_alpn_protocols = alpn_lib->num_client_alpn_protocols;
}
GPR_ASSERT(tsi_create_ssl_client_handshaker_factory(
client_key_cert_pair, key_cert_lib->root_cert, NULL,
(const char **)client_alpn_protocols,
num_client_alpn_protocols,
&ssl_fixture->client_handshaker_factory) == TSI_OK);
/* Create server handshaker factory. */
char **server_alpn_protocols = NULL;
uint16_t num_server_alpn_protocols = 0;
if (alpn_lib->alpn_mode == ALPN_SERVER_NO_CLIENT ||
alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ||
alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) {
server_alpn_protocols = alpn_lib->server_alpn_protocols;
num_server_alpn_protocols = alpn_lib->num_server_alpn_protocols;
if (alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) {
num_server_alpn_protocols--;
}
}
GPR_ASSERT(tsi_create_ssl_server_handshaker_factory(
key_cert_lib->use_bad_server_cert
? key_cert_lib->bad_server_pem_key_cert_pairs
: key_cert_lib->server_pem_key_cert_pairs,
key_cert_lib->use_bad_server_cert
? key_cert_lib->bad_server_num_key_cert_pairs
: key_cert_lib->server_num_key_cert_pairs,
key_cert_lib->root_cert, ssl_fixture->force_client_auth, NULL,
(const char **)server_alpn_protocols,
num_server_alpn_protocols,
&ssl_fixture->server_handshaker_factory) == TSI_OK);
/* Create server and client handshakers. */
tsi_handshaker *client_handshaker = NULL;
GPR_ASSERT(tsi_ssl_client_handshaker_factory_create_handshaker(
ssl_fixture->client_handshaker_factory,
ssl_fixture->server_name_indication,
&client_handshaker) == TSI_OK);
ssl_fixture->base.client_handshaker =
tsi_create_adapter_handshaker(client_handshaker);
tsi_handshaker *server_handshaker = NULL;
GPR_ASSERT(tsi_ssl_server_handshaker_factory_create_handshaker(
ssl_fixture->server_handshaker_factory, &server_handshaker) ==
TSI_OK);
ssl_fixture->base.server_handshaker =
tsi_create_adapter_handshaker(server_handshaker);
}
static void check_alpn(ssl_tsi_test_fixture *ssl_fixture,
const tsi_peer *peer) {
GPR_ASSERT(ssl_fixture != NULL);
GPR_ASSERT(ssl_fixture->alpn_lib != NULL);
ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib;
const tsi_peer_property *alpn_property =
tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL);
if (alpn_lib->alpn_mode != ALPN_CLIENT_SERVER_OK) {
GPR_ASSERT(alpn_property == NULL);
} else {
GPR_ASSERT(alpn_property != NULL);
const char *expected_match = "baz";
GPR_ASSERT(memcmp(alpn_property->value.data, expected_match,
alpn_property->value.length) == 0);
}
}
static const tsi_peer_property *
check_basic_authenticated_peer_and_get_common_name(const tsi_peer *peer) {
const tsi_peer_property *cert_type_property =
tsi_peer_get_property_by_name(peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY);
GPR_ASSERT(cert_type_property != NULL);
GPR_ASSERT(memcmp(cert_type_property->value.data, TSI_X509_CERTIFICATE_TYPE,
cert_type_property->value.length) == 0);
const tsi_peer_property *property = tsi_peer_get_property_by_name(
peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY);
GPR_ASSERT(property != NULL);
return property;
}
void check_server0_peer(tsi_peer *peer) {
const tsi_peer_property *property =
check_basic_authenticated_peer_and_get_common_name(peer);
const char *expected_match = "*.test.google.com.au";
GPR_ASSERT(memcmp(property->value.data, expected_match,
property->value.length) == 0);
GPR_ASSERT(tsi_peer_get_property_by_name(
peer, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) ==
NULL);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.google.com.au") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.com.au") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.blah") == 0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.bar.test.google.com.au") ==
0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "test.google.com.au") == 0);
tsi_peer_destruct(peer);
}
static bool check_subject_alt_name(tsi_peer *peer, const char *name) {
for (size_t i = 0; i < peer->property_count; i++) {
const tsi_peer_property *prop = &peer->properties[i];
if (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) ==
0) {
if (memcmp(prop->value.data, name, prop->value.length) == 0) {
return true;
}
}
}
return false;
}
void check_server1_peer(tsi_peer *peer) {
const tsi_peer_property *property =
check_basic_authenticated_peer_and_get_common_name(peer);
const char *expected_match = "*.test.google.com";
GPR_ASSERT(memcmp(property->value.data, expected_match,
property->value.length) == 0);
GPR_ASSERT(check_subject_alt_name(peer, "*.test.google.fr") == 1);
GPR_ASSERT(check_subject_alt_name(peer, "waterzooi.test.google.be") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.google.fr") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.fr") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "waterzooi.test.google.be") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.youtube.com") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.foo.test.google.com") == 0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "test.google.fr") == 0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "tartines.test.google.be") == 0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "tartines.youtube.com") == 0);
tsi_peer_destruct(peer);
}
static void check_client_peer(ssl_tsi_test_fixture *ssl_fixture,
tsi_peer *peer) {
GPR_ASSERT(ssl_fixture != NULL);
GPR_ASSERT(ssl_fixture->alpn_lib != NULL);
ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib;
if (!ssl_fixture->force_client_auth) {
GPR_ASSERT(peer->property_count ==
(alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ? 1 : 0));
} else {
const tsi_peer_property *property =
check_basic_authenticated_peer_and_get_common_name(peer);
const char *expected_match = "testclient";
GPR_ASSERT(memcmp(property->value.data, expected_match,
property->value.length) == 0);
}
tsi_peer_destruct(peer);
}
static void ssl_test_check_handshaker_peers(tsi_test_fixture *fixture) {
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
GPR_ASSERT(ssl_fixture != NULL);
GPR_ASSERT(ssl_fixture->key_cert_lib != NULL);
ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib;
tsi_peer peer;
bool expect_success =
!(key_cert_lib->use_bad_server_cert ||
(key_cert_lib->use_bad_client_cert && ssl_fixture->force_client_auth));
if (expect_success) {
GPR_ASSERT(tsi_handshaker_result_extract_peer(
ssl_fixture->base.client_result, &peer) == TSI_OK);
check_alpn(ssl_fixture, &peer);
if (ssl_fixture->server_name_indication != NULL) {
check_server1_peer(&peer);
} else {
check_server0_peer(&peer);
}
} else {
GPR_ASSERT(ssl_fixture->base.client_result == NULL);
}
if (expect_success) {
GPR_ASSERT(tsi_handshaker_result_extract_peer(
ssl_fixture->base.server_result, &peer) == TSI_OK);
check_alpn(ssl_fixture, &peer);
check_client_peer(ssl_fixture, &peer);
} else {
GPR_ASSERT(ssl_fixture->base.server_result == NULL);
}
}
static void ssl_test_pem_key_cert_pair_destroy(tsi_ssl_pem_key_cert_pair kp) {
gpr_free((void *)kp.private_key);
gpr_free((void *)kp.cert_chain);
}
static void ssl_test_destruct(tsi_test_fixture *fixture) {
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
if (ssl_fixture == NULL) {
return;
}
/* Destroy ssl_alpn_lib. */
ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib;
for (size_t i = 0; i < alpn_lib->num_server_alpn_protocols; i++) {
gpr_free(alpn_lib->server_alpn_protocols[i]);
}
gpr_free(alpn_lib->server_alpn_protocols);
for (size_t i = 0; i < alpn_lib->num_client_alpn_protocols; i++) {
gpr_free(alpn_lib->client_alpn_protocols[i]);
}
gpr_free(alpn_lib->client_alpn_protocols);
gpr_free(alpn_lib);
/* Destroy ssl_key_cert_lib. */
ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib;
for (size_t i = 0; i < key_cert_lib->server_num_key_cert_pairs; i++) {
ssl_test_pem_key_cert_pair_destroy(
key_cert_lib->server_pem_key_cert_pairs[i]);
}
gpr_free(key_cert_lib->server_pem_key_cert_pairs);
for (size_t i = 0; i < key_cert_lib->bad_server_num_key_cert_pairs; i++) {
ssl_test_pem_key_cert_pair_destroy(
key_cert_lib->bad_server_pem_key_cert_pairs[i]);
}
gpr_free(key_cert_lib->bad_server_pem_key_cert_pairs);
ssl_test_pem_key_cert_pair_destroy(key_cert_lib->client_pem_key_cert_pair);
ssl_test_pem_key_cert_pair_destroy(
key_cert_lib->bad_client_pem_key_cert_pair);
gpr_free(key_cert_lib->root_cert);
gpr_free(key_cert_lib);
/* Destroy others. */
tsi_ssl_server_handshaker_factory_destroy(
ssl_fixture->server_handshaker_factory);
tsi_ssl_client_handshaker_factory_destroy(
ssl_fixture->client_handshaker_factory);
}
static const struct tsi_test_fixture_vtable vtable = {
ssl_test_setup_handshakers, ssl_test_check_handshaker_peers,
ssl_test_destruct};
static char *load_file(const char *dir_path, const char *file_name) {
char *file_path =
gpr_zalloc(sizeof(char) * (strlen(dir_path) + strlen(file_name) + 1));
memcpy(file_path, dir_path, strlen(dir_path));
memcpy(file_path + strlen(dir_path), file_name, strlen(file_name));
grpc_slice slice;
GPR_ASSERT(grpc_load_file(file_path, 1, &slice) == GRPC_ERROR_NONE);
char *data = grpc_slice_to_c_string(slice);
grpc_slice_unref(slice);
gpr_free(file_path);
return data;
}
static tsi_test_fixture *ssl_tsi_test_fixture_create() {
ssl_tsi_test_fixture *ssl_fixture = gpr_zalloc(sizeof(*ssl_fixture));
tsi_test_fixture_init(&ssl_fixture->base);
ssl_fixture->base.test_unused_bytes = false;
ssl_fixture->base.vtable = &vtable;
/* Create ssl_key_cert_lib. */
ssl_key_cert_lib *key_cert_lib = gpr_zalloc(sizeof(*key_cert_lib));
key_cert_lib->use_bad_server_cert = false;
key_cert_lib->use_bad_client_cert = false;
key_cert_lib->server_num_key_cert_pairs =
SSL_TSI_TEST_SERVER_KEY_CERT_PAIRS_NUM;
key_cert_lib->bad_server_num_key_cert_pairs =
SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM;
key_cert_lib->server_pem_key_cert_pairs =
gpr_malloc(sizeof(tsi_ssl_pem_key_cert_pair) *
key_cert_lib->server_num_key_cert_pairs);
key_cert_lib->bad_server_pem_key_cert_pairs =
gpr_malloc(sizeof(tsi_ssl_pem_key_cert_pair) *
key_cert_lib->bad_server_num_key_cert_pairs);
key_cert_lib->server_pem_key_cert_pairs[0].private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.key");
key_cert_lib->server_pem_key_cert_pairs[0].cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.pem");
key_cert_lib->server_pem_key_cert_pairs[1].private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server1.key");
key_cert_lib->server_pem_key_cert_pairs[1].cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server1.pem");
key_cert_lib->bad_server_pem_key_cert_pairs[0].private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badserver.key");
key_cert_lib->bad_server_pem_key_cert_pairs[0].cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badserver.pem");
key_cert_lib->client_pem_key_cert_pair.private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.key");
key_cert_lib->client_pem_key_cert_pair.cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.pem");
key_cert_lib->bad_client_pem_key_cert_pair.private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badclient.key");
key_cert_lib->bad_client_pem_key_cert_pair.cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badclient.pem");
key_cert_lib->root_cert = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "ca.pem");
ssl_fixture->key_cert_lib = key_cert_lib;
/* Create ssl_alpn_lib. */
ssl_alpn_lib *alpn_lib = gpr_zalloc(sizeof(*alpn_lib));
alpn_lib->server_alpn_protocols =
gpr_zalloc(sizeof(char *) * SSL_TSI_TEST_ALPN_NUM);
alpn_lib->client_alpn_protocols =
gpr_zalloc(sizeof(char *) * SSL_TSI_TEST_ALPN_NUM);
alpn_lib->server_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN1);
alpn_lib->server_alpn_protocols[1] = gpr_strdup(SSL_TSI_TEST_ALPN3);
alpn_lib->client_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN2);
alpn_lib->client_alpn_protocols[1] = gpr_strdup(SSL_TSI_TEST_ALPN3);
alpn_lib->num_server_alpn_protocols = SSL_TSI_TEST_ALPN_NUM;
alpn_lib->num_client_alpn_protocols = SSL_TSI_TEST_ALPN_NUM;
alpn_lib->alpn_mode = NO_ALPN;
ssl_fixture->alpn_lib = alpn_lib;
ssl_fixture->base.vtable = &vtable;
ssl_fixture->server_name_indication = NULL;
ssl_fixture->force_client_auth = false;
return &ssl_fixture->base;
}
void ssl_tsi_test_do_handshake_tiny_handshake_buffer() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_small_handshake_buffer() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
fixture->handshake_buffer_size = TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_client_authentication() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->force_client_auth = true;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain() {
/* server1 cert contains "waterzooi.test.google.be" in SAN. */
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->server_name_indication = "waterzooi.test.google.be";
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_server_name_indication_wild_star_domain() {
/* server1 cert contains "*.test.google.fr" in SAN. */
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->server_name_indication = "juju.test.google.fr";
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_bad_server_cert() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->key_cert_lib->use_bad_server_cert = true;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_bad_client_cert() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->key_cert_lib->use_bad_client_cert = true;
ssl_fixture->force_client_auth = true;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_alpn_client_no_server() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_NO_SERVER;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_alpn_server_no_client() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->alpn_lib->alpn_mode = ALPN_SERVER_NO_CLIENT;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_alpn_client_server_mismatch() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_SERVER_MISMATCH;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_alpn_client_server_ok() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_SERVER_OK;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_round_trip_for_all_configs() {
unsigned int *bit_array =
gpr_zalloc(sizeof(unsigned int) * TSI_TEST_NUM_OF_ARGUMENTS);
const unsigned int mask = 1U << (TSI_TEST_NUM_OF_ARGUMENTS - 1);
for (unsigned int val = 0; val < TSI_TEST_NUM_OF_COMBINATIONS; val++) {
unsigned int v = val;
for (unsigned int ind = 0; ind < TSI_TEST_NUM_OF_ARGUMENTS; ind++) {
bit_array[ind] = (v & mask) ? 1 : 0;
v <<= 1;
}
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
tsi_test_frame_protector_config_destroy(ssl_fixture->base.config);
ssl_fixture->base.config = tsi_test_frame_protector_config_create(
bit_array[0], bit_array[1], bit_array[2], bit_array[3], bit_array[4],
bit_array[5], bit_array[6], bit_array[7]);
tsi_test_do_round_trip(&ssl_fixture->base);
tsi_test_fixture_destroy(fixture);
}
gpr_free(bit_array);
}
void ssl_tsi_test_do_round_trip_odd_buffer_size() {
const size_t odd_sizes[] = {1025, 2051, 4103, 8207, 16409};
const size_t size = sizeof(odd_sizes) / sizeof(size_t);
for (size_t ind1 = 0; ind1 < size; ind1++) {
for (size_t ind2 = 0; ind2 < size; ind2++) {
for (size_t ind3 = 0; ind3 < size; ind3++) {
for (size_t ind4 = 0; ind4 < size; ind4++) {
for (size_t ind5 = 0; ind5 < size; ind5++) {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
tsi_test_frame_protector_config_set_buffer_size(
ssl_fixture->base.config, odd_sizes[ind1], odd_sizes[ind2],
odd_sizes[ind3], odd_sizes[ind4], odd_sizes[ind5]);
tsi_test_do_round_trip(&ssl_fixture->base);
tsi_test_fixture_destroy(fixture);
}
}
}
}
}
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
ssl_tsi_test_do_handshake_tiny_handshake_buffer();
ssl_tsi_test_do_handshake_small_handshake_buffer();
ssl_tsi_test_do_handshake();
ssl_tsi_test_do_handshake_with_client_authentication();
ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain();
ssl_tsi_test_do_handshake_with_server_name_indication_wild_star_domain();
ssl_tsi_test_do_handshake_with_bad_server_cert();
ssl_tsi_test_do_handshake_with_bad_client_cert();
ssl_tsi_test_do_handshake_alpn_client_no_server();
ssl_tsi_test_do_handshake_alpn_server_no_client();
ssl_tsi_test_do_handshake_alpn_client_server_mismatch();
ssl_tsi_test_do_handshake_alpn_client_server_ok();
ssl_tsi_test_do_round_trip_for_all_configs();
ssl_tsi_test_do_round_trip_odd_buffer_size();
grpc_shutdown();
return 0;
}

@ -0,0 +1,550 @@
/*
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/security/transport/tsi_error.h"
#include "test/core/tsi/transport_security_test_lib.h"
typedef struct handshaker_args {
tsi_test_fixture *fixture;
unsigned char *handshake_buffer;
size_t handshake_buffer_size;
bool is_client;
bool transferred_data;
bool appended_unused_bytes;
grpc_error *error;
} handshaker_args;
static handshaker_args *handshaker_args_create(tsi_test_fixture *fixture,
bool is_client) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->config != NULL);
handshaker_args *args = gpr_zalloc(sizeof(*args));
args->fixture = fixture;
args->handshake_buffer_size = fixture->handshake_buffer_size;
args->handshake_buffer = gpr_zalloc(args->handshake_buffer_size);
args->is_client = is_client;
args->error = GRPC_ERROR_NONE;
return args;
}
static void handshaker_args_destroy(handshaker_args *args) {
gpr_free(args->handshake_buffer);
GRPC_ERROR_UNREF(args->error);
gpr_free(args);
}
static void do_handshaker_next(handshaker_args *args);
static void setup_handshakers(tsi_test_fixture *fixture) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->vtable != NULL);
GPR_ASSERT(fixture->vtable->setup_handshakers != NULL);
fixture->vtable->setup_handshakers(fixture);
}
static void check_unused_bytes(tsi_test_fixture *fixture) {
tsi_handshaker_result *result_with_unused_bytes =
fixture->has_client_finished_first ? fixture->server_result
: fixture->client_result;
tsi_handshaker_result *result_without_unused_bytes =
fixture->has_client_finished_first ? fixture->client_result
: fixture->server_result;
const unsigned char *bytes = NULL;
size_t bytes_size = 0;
GPR_ASSERT(tsi_handshaker_result_get_unused_bytes(
result_with_unused_bytes, &bytes, &bytes_size) == TSI_OK);
GPR_ASSERT(bytes_size == strlen(TSI_TEST_UNUSED_BYTES));
GPR_ASSERT(memcmp(bytes, TSI_TEST_UNUSED_BYTES, bytes_size) == 0);
GPR_ASSERT(tsi_handshaker_result_get_unused_bytes(
result_without_unused_bytes, &bytes, &bytes_size) == TSI_OK);
GPR_ASSERT(bytes_size == 0);
GPR_ASSERT(bytes == NULL);
}
static void check_handshake_results(tsi_test_fixture *fixture) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->vtable != NULL);
GPR_ASSERT(fixture->vtable->check_handshaker_peers != NULL);
/* Check handshaker peers. */
fixture->vtable->check_handshaker_peers(fixture);
/* Check unused bytes. */
if (fixture->test_unused_bytes) {
if (fixture->server_result != NULL && fixture->client_result != NULL) {
check_unused_bytes(fixture);
}
fixture->bytes_written_to_server_channel = 0;
fixture->bytes_written_to_client_channel = 0;
fixture->bytes_read_from_client_channel = 0;
fixture->bytes_read_from_server_channel = 0;
}
}
static void send_bytes_to_peer(tsi_test_fixture *fixture,
const unsigned char *buf, size_t buf_size,
bool is_client) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(buf != NULL);
uint8_t *channel =
is_client ? fixture->server_channel : fixture->client_channel;
GPR_ASSERT(channel != NULL);
size_t *bytes_written = is_client ? &fixture->bytes_written_to_server_channel
: &fixture->bytes_written_to_client_channel;
GPR_ASSERT(bytes_written != NULL);
GPR_ASSERT(*bytes_written + buf_size <= TSI_TEST_DEFAULT_CHANNEL_SIZE);
/* Write data to channel. */
memcpy(channel + *bytes_written, buf, buf_size);
*bytes_written += buf_size;
}
static void maybe_append_unused_bytes(handshaker_args *args) {
GPR_ASSERT(args != NULL);
GPR_ASSERT(args->fixture != NULL);
tsi_test_fixture *fixture = args->fixture;
if (fixture->test_unused_bytes && !args->appended_unused_bytes) {
args->appended_unused_bytes = true;
send_bytes_to_peer(fixture, (const unsigned char *)TSI_TEST_UNUSED_BYTES,
strlen(TSI_TEST_UNUSED_BYTES), args->is_client);
if (fixture->client_result != NULL && fixture->server_result == NULL) {
fixture->has_client_finished_first = true;
}
}
}
static void receive_bytes_from_peer(tsi_test_fixture *fixture,
unsigned char **buf, size_t *buf_size,
bool is_client) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(*buf != NULL);
GPR_ASSERT(buf_size != NULL);
uint8_t *channel =
is_client ? fixture->client_channel : fixture->server_channel;
GPR_ASSERT(channel != NULL);
size_t *bytes_read = is_client ? &fixture->bytes_read_from_client_channel
: &fixture->bytes_read_from_server_channel;
size_t *bytes_written = is_client ? &fixture->bytes_written_to_client_channel
: &fixture->bytes_written_to_server_channel;
GPR_ASSERT(bytes_read != NULL);
GPR_ASSERT(bytes_written != NULL);
size_t to_read = *buf_size < *bytes_written - *bytes_read
? *buf_size
: *bytes_written - *bytes_read;
/* Read data from channel. */
memcpy(*buf, channel + *bytes_read, to_read);
*buf_size = to_read;
*bytes_read += to_read;
}
static void send_message_to_peer(tsi_test_fixture *fixture,
tsi_frame_protector *protector,
bool is_client) {
/* Initialization. */
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->config != NULL);
GPR_ASSERT(protector != NULL);
tsi_test_frame_protector_config *config = fixture->config;
unsigned char *protected_buffer = gpr_zalloc(config->protected_buffer_size);
size_t message_size =
is_client ? config->client_message_size : config->server_message_size;
uint8_t *message =
is_client ? config->client_message : config->server_message;
GPR_ASSERT(message != NULL);
const unsigned char *message_bytes = (const unsigned char *)message;
tsi_result result = TSI_OK;
/* Do protect and send protected data to peer. */
while (message_size > 0 && result == TSI_OK) {
size_t protected_buffer_size_to_send = config->protected_buffer_size;
size_t processed_message_size = message_size;
/* Do protect. */
result = tsi_frame_protector_protect(
protector, message_bytes, &processed_message_size, protected_buffer,
&protected_buffer_size_to_send);
GPR_ASSERT(result == TSI_OK);
/* Send protected data to peer. */
send_bytes_to_peer(fixture, protected_buffer, protected_buffer_size_to_send,
is_client);
message_bytes += processed_message_size;
message_size -= processed_message_size;
/* Flush if we're done. */
if (message_size == 0) {
size_t still_pending_size;
do {
protected_buffer_size_to_send = config->protected_buffer_size;
result = tsi_frame_protector_protect_flush(
protector, protected_buffer, &protected_buffer_size_to_send,
&still_pending_size);
GPR_ASSERT(result == TSI_OK);
send_bytes_to_peer(fixture, protected_buffer,
protected_buffer_size_to_send, is_client);
} while (still_pending_size > 0 && result == TSI_OK);
GPR_ASSERT(result == TSI_OK);
}
}
GPR_ASSERT(result == TSI_OK);
gpr_free(protected_buffer);
}
static void receive_message_from_peer(tsi_test_fixture *fixture,
tsi_frame_protector *protector,
unsigned char *message,
size_t *bytes_received, bool is_client) {
/* Initialization. */
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(protector != NULL);
GPR_ASSERT(message != NULL);
GPR_ASSERT(bytes_received != NULL);
GPR_ASSERT(fixture->config != NULL);
tsi_test_frame_protector_config *config = fixture->config;
size_t read_offset = 0;
size_t message_offset = 0;
size_t read_from_peer_size = 0;
tsi_result result = TSI_OK;
bool done = false;
unsigned char *read_buffer = gpr_zalloc(config->read_buffer_allocated_size);
unsigned char *message_buffer =
gpr_zalloc(config->message_buffer_allocated_size);
/* Do unprotect on data received from peer. */
while (!done && result == TSI_OK) {
/* Receive data from peer. */
if (read_from_peer_size == 0) {
read_from_peer_size = config->read_buffer_allocated_size;
receive_bytes_from_peer(fixture, &read_buffer, &read_from_peer_size,
is_client);
read_offset = 0;
}
if (read_from_peer_size == 0) {
done = true;
}
/* Do unprotect. */
size_t message_buffer_size;
do {
message_buffer_size = config->message_buffer_allocated_size;
size_t processed_size = read_from_peer_size;
result = tsi_frame_protector_unprotect(
protector, read_buffer + read_offset, &processed_size, message_buffer,
&message_buffer_size);
GPR_ASSERT(result == TSI_OK);
if (message_buffer_size > 0) {
memcpy(message + message_offset, message_buffer, message_buffer_size);
message_offset += message_buffer_size;
}
read_offset += processed_size;
read_from_peer_size -= processed_size;
} while ((read_from_peer_size > 0 || message_buffer_size > 0) &&
result == TSI_OK);
GPR_ASSERT(result == TSI_OK);
}
GPR_ASSERT(result == TSI_OK);
*bytes_received = message_offset;
gpr_free(read_buffer);
gpr_free(message_buffer);
}
grpc_error *on_handshake_next_done(tsi_result result, void *user_data,
const unsigned char *bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result *handshaker_result) {
handshaker_args *args = (handshaker_args *)user_data;
GPR_ASSERT(args != NULL);
GPR_ASSERT(args->fixture != NULL);
tsi_test_fixture *fixture = args->fixture;
grpc_error *error = GRPC_ERROR_NONE;
/* Read more data if we need to. */
if (result == TSI_INCOMPLETE_DATA) {
GPR_ASSERT(bytes_to_send_size == 0);
return error;
}
if (result != TSI_OK) {
return grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result);
}
/* Update handshaker result. */
if (handshaker_result != NULL) {
tsi_handshaker_result **result_to_write =
args->is_client ? &fixture->client_result : &fixture->server_result;
GPR_ASSERT(*result_to_write == NULL);
*result_to_write = handshaker_result;
}
/* Send data to peer, if needed. */
if (bytes_to_send_size > 0) {
send_bytes_to_peer(args->fixture, bytes_to_send, bytes_to_send_size,
args->is_client);
args->transferred_data = true;
}
if (handshaker_result != NULL) {
maybe_append_unused_bytes(args);
}
return error;
}
static void on_handshake_next_done_wrapper(
tsi_result result, void *user_data, const unsigned char *bytes_to_send,
size_t bytes_to_send_size, tsi_handshaker_result *handshaker_result) {
handshaker_args *args = (handshaker_args *)user_data;
args->error = on_handshake_next_done(result, user_data, bytes_to_send,
bytes_to_send_size, handshaker_result);
}
static bool is_handshake_finished_properly(handshaker_args *args) {
GPR_ASSERT(args != NULL);
GPR_ASSERT(args->fixture != NULL);
tsi_test_fixture *fixture = args->fixture;
if ((args->is_client && fixture->client_result != NULL) ||
(!args->is_client && fixture->server_result != NULL)) {
return true;
}
return false;
}
static void do_handshaker_next(handshaker_args *args) {
/* Initialization. */
GPR_ASSERT(args != NULL);
GPR_ASSERT(args->fixture != NULL);
tsi_test_fixture *fixture = args->fixture;
tsi_handshaker *handshaker =
args->is_client ? fixture->client_handshaker : fixture->server_handshaker;
if (is_handshake_finished_properly(args)) {
return;
}
tsi_handshaker_result *handshaker_result = NULL;
unsigned char *bytes_to_send = NULL;
size_t bytes_to_send_size = 0;
/* Receive data from peer, if available. */
size_t buf_size = args->handshake_buffer_size;
receive_bytes_from_peer(args->fixture, &args->handshake_buffer, &buf_size,
args->is_client);
if (buf_size > 0) {
args->transferred_data = true;
}
/* Peform handshaker next. */
tsi_result result = tsi_handshaker_next(
handshaker, args->handshake_buffer, buf_size,
(const unsigned char **)&bytes_to_send, &bytes_to_send_size,
&handshaker_result, &on_handshake_next_done_wrapper, args);
if (result != TSI_ASYNC) {
args->error = on_handshake_next_done(result, args, bytes_to_send,
bytes_to_send_size, handshaker_result);
}
}
void tsi_test_do_handshake(tsi_test_fixture *fixture) {
/* Initializaiton. */
setup_handshakers(fixture);
handshaker_args *client_args =
handshaker_args_create(fixture, true /* is_client */);
handshaker_args *server_args =
handshaker_args_create(fixture, false /* is_client */);
/* Do handshake. */
do {
client_args->transferred_data = false;
server_args->transferred_data = false;
do_handshaker_next(client_args);
if (client_args->error != GRPC_ERROR_NONE) {
break;
}
do_handshaker_next(server_args);
if (server_args->error != GRPC_ERROR_NONE) {
break;
}
GPR_ASSERT(client_args->transferred_data || server_args->transferred_data);
} while (fixture->client_result == NULL || fixture->server_result == NULL);
/* Verify handshake results. */
check_handshake_results(fixture);
/* Cleanup. */
handshaker_args_destroy(client_args);
handshaker_args_destroy(server_args);
}
void tsi_test_do_round_trip(tsi_test_fixture *fixture) {
/* Initialization. */
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->config != NULL);
tsi_test_frame_protector_config *config = fixture->config;
tsi_frame_protector *client_frame_protector = NULL;
tsi_frame_protector *server_frame_protector = NULL;
/* Perform handshake. */
tsi_test_do_handshake(fixture);
/* Create frame protectors.*/
size_t client_max_output_protected_frame_size =
config->client_max_output_protected_frame_size;
GPR_ASSERT(tsi_handshaker_result_create_frame_protector(
fixture->client_result,
client_max_output_protected_frame_size == 0
? NULL
: &client_max_output_protected_frame_size,
&client_frame_protector) == TSI_OK);
size_t server_max_output_protected_frame_size =
config->server_max_output_protected_frame_size;
GPR_ASSERT(tsi_handshaker_result_create_frame_protector(
fixture->server_result,
server_max_output_protected_frame_size == 0
? NULL
: &server_max_output_protected_frame_size,
&server_frame_protector) == TSI_OK);
/* Client sends a message to server. */
send_message_to_peer(fixture, client_frame_protector, true /* is_client */);
unsigned char *server_received_message =
gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE);
size_t server_received_message_size = 0;
receive_message_from_peer(
fixture, server_frame_protector, server_received_message,
&server_received_message_size, false /* is_client */);
GPR_ASSERT(config->client_message_size == server_received_message_size);
GPR_ASSERT(memcmp(config->client_message, server_received_message,
server_received_message_size) == 0);
/* Server sends a message to client. */
send_message_to_peer(fixture, server_frame_protector, false /* is_client */);
unsigned char *client_received_message =
gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE);
size_t client_received_message_size = 0;
receive_message_from_peer(
fixture, client_frame_protector, client_received_message,
&client_received_message_size, true /* is_client */);
GPR_ASSERT(config->server_message_size == client_received_message_size);
GPR_ASSERT(memcmp(config->server_message, client_received_message,
client_received_message_size) == 0);
/* Destroy server and client frame protectors. */
tsi_frame_protector_destroy(client_frame_protector);
tsi_frame_protector_destroy(server_frame_protector);
gpr_free(server_received_message);
gpr_free(client_received_message);
}
static unsigned char *generate_random_message(size_t size) {
size_t i;
unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890";
unsigned char *output = gpr_zalloc(sizeof(unsigned char) * size);
for (i = 0; i < size - 1; ++i) {
output[i] = chars[rand() % (int)(sizeof(chars) - 1)];
}
return output;
}
tsi_test_frame_protector_config *tsi_test_frame_protector_config_create(
bool use_default_read_buffer_allocated_size,
bool use_default_message_buffer_allocated_size,
bool use_default_protected_buffer_size, bool use_default_client_message,
bool use_default_server_message,
bool use_default_client_max_output_protected_frame_size,
bool use_default_server_max_output_protected_frame_size,
bool use_default_handshake_buffer_size) {
tsi_test_frame_protector_config *config = gpr_zalloc(sizeof(*config));
/* Set the value for read_buffer_allocated_size. */
config->read_buffer_allocated_size =
use_default_read_buffer_allocated_size
? TSI_TEST_DEFAULT_BUFFER_SIZE
: TSI_TEST_SMALL_READ_BUFFER_ALLOCATED_SIZE;
/* Set the value for message_buffer_allocated_size. */
config->message_buffer_allocated_size =
use_default_message_buffer_allocated_size
? TSI_TEST_DEFAULT_BUFFER_SIZE
: TSI_TEST_SMALL_MESSAGE_BUFFER_ALLOCATED_SIZE;
/* Set the value for protected_buffer_size. */
config->protected_buffer_size = use_default_protected_buffer_size
? TSI_TEST_DEFAULT_PROTECTED_BUFFER_SIZE
: TSI_TEST_SMALL_PROTECTED_BUFFER_SIZE;
/* Set the value for client message. */
config->client_message_size = use_default_client_message
? TSI_TEST_BIG_MESSAGE_SIZE
: TSI_TEST_SMALL_MESSAGE_SIZE;
config->client_message =
use_default_client_message
? generate_random_message(TSI_TEST_BIG_MESSAGE_SIZE)
: generate_random_message(TSI_TEST_SMALL_MESSAGE_SIZE);
/* Set the value for server message. */
config->server_message_size = use_default_server_message
? TSI_TEST_BIG_MESSAGE_SIZE
: TSI_TEST_SMALL_MESSAGE_SIZE;
config->server_message =
use_default_server_message
? generate_random_message(TSI_TEST_BIG_MESSAGE_SIZE)
: generate_random_message(TSI_TEST_SMALL_MESSAGE_SIZE);
/* Set the value for client max_output_protected_frame_size.
If it is 0, we pass NULL to tsi_handshaker_result_create_frame_protector(),
which then uses default protected frame size for it. */
config->client_max_output_protected_frame_size =
use_default_client_max_output_protected_frame_size
? 0
: TSI_TEST_SMALL_CLIENT_MAX_OUTPUT_PROTECTED_FRAME_SIZE;
/* Set the value for server max_output_protected_frame_size.
If it is 0, we pass NULL to tsi_handshaker_result_create_frame_protector(),
which then uses default protected frame size for it. */
config->server_max_output_protected_frame_size =
use_default_server_max_output_protected_frame_size
? 0
: TSI_TEST_SMALL_SERVER_MAX_OUTPUT_PROTECTED_FRAME_SIZE;
return config;
}
void tsi_test_frame_protector_config_set_buffer_size(
tsi_test_frame_protector_config *config, size_t read_buffer_allocated_size,
size_t message_buffer_allocated_size, size_t protected_buffer_size,
size_t client_max_output_protected_frame_size,
size_t server_max_output_protected_frame_size) {
GPR_ASSERT(config != NULL);
config->read_buffer_allocated_size = read_buffer_allocated_size;
config->message_buffer_allocated_size = message_buffer_allocated_size;
config->protected_buffer_size = protected_buffer_size;
config->client_max_output_protected_frame_size =
client_max_output_protected_frame_size;
config->server_max_output_protected_frame_size =
server_max_output_protected_frame_size;
}
void tsi_test_frame_protector_config_destroy(
tsi_test_frame_protector_config *config) {
GPR_ASSERT(config != NULL);
gpr_free(config->client_message);
gpr_free(config->server_message);
gpr_free(config);
}
void tsi_test_fixture_init(tsi_test_fixture *fixture) {
fixture->config = tsi_test_frame_protector_config_create(
true, true, true, true, true, true, true, true);
fixture->handshake_buffer_size = TSI_TEST_DEFAULT_BUFFER_SIZE;
fixture->client_channel = gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE);
fixture->server_channel = gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE);
fixture->bytes_written_to_client_channel = 0;
fixture->bytes_written_to_server_channel = 0;
fixture->bytes_read_from_client_channel = 0;
fixture->bytes_read_from_server_channel = 0;
fixture->test_unused_bytes = true;
fixture->has_client_finished_first = false;
}
void tsi_test_fixture_destroy(tsi_test_fixture *fixture) {
GPR_ASSERT(fixture != NULL);
tsi_test_frame_protector_config_destroy(fixture->config);
tsi_handshaker_destroy(fixture->client_handshaker);
tsi_handshaker_destroy(fixture->server_handshaker);
tsi_handshaker_result_destroy(fixture->client_result);
tsi_handshaker_result_destroy(fixture->server_result);
gpr_free(fixture->client_channel);
gpr_free(fixture->server_channel);
GPR_ASSERT(fixture->vtable != NULL);
GPR_ASSERT(fixture->vtable->destruct != NULL);
fixture->vtable->destruct(fixture);
gpr_free(fixture);
}

@ -0,0 +1,165 @@
/*
*
* 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.
*
*/
#ifndef GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H_
#define GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H_
#include "src/core/tsi/transport_security_interface.h"
#define TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE 32
#define TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE 128
#define TSI_TEST_SMALL_READ_BUFFER_ALLOCATED_SIZE 41
#define TSI_TEST_SMALL_PROTECTED_BUFFER_SIZE 37
#define TSI_TEST_SMALL_MESSAGE_BUFFER_ALLOCATED_SIZE 42
#define TSI_TEST_SMALL_CLIENT_MAX_OUTPUT_PROTECTED_FRAME_SIZE 39
#define TSI_TEST_SMALL_SERVER_MAX_OUTPUT_PROTECTED_FRAME_SIZE 43
#define TSI_TEST_DEFAULT_BUFFER_SIZE 4096
#define TSI_TEST_DEFAULT_PROTECTED_BUFFER_SIZE 16384
#define TSI_TEST_DEFAULT_CHANNEL_SIZE 32768
#define TSI_TEST_BIG_MESSAGE_SIZE 17000
#define TSI_TEST_SMALL_MESSAGE_SIZE 10
#define TSI_TEST_NUM_OF_ARGUMENTS 8
#define TSI_TEST_NUM_OF_COMBINATIONS 256
#define TSI_TEST_UNUSED_BYTES "HELLO GOOGLE"
/* --- tsi_test_fixture object ---
The tests for specific TSI implementations should create their own
custom "subclass" of this fixture, which wraps all information
that will be used to test correctness of TSI handshakes and frame
protect/unprotect operations with respect to TSI implementations. */
typedef struct tsi_test_fixture tsi_test_fixture;
/* --- tsi_test_frame_protector_config object ---
This object is used to configure different parameters of TSI frame protector
APIs. */
typedef struct tsi_test_frame_protector_config tsi_test_frame_protector_config;
/* V-table for tsi_test_fixture operations that are implemented differently in
different TSI implementations. */
typedef struct tsi_test_fixture_vtable {
void (*setup_handshakers)(tsi_test_fixture *fixture);
void (*check_handshaker_peers)(tsi_test_fixture *fixture);
void (*destruct)(tsi_test_fixture *fixture);
} tranport_security_test_vtable;
struct tsi_test_fixture {
const struct tsi_test_fixture_vtable *vtable;
/* client/server TSI handshaker used to perform TSI handshakes, and will get
instantiated during the call to setup_handshakers. */
tsi_handshaker *client_handshaker;
tsi_handshaker *server_handshaker;
/* client/server TSI handshaker results used to store the result of TSI
handshake. If the handshake fails, the result will store NULL upon
finishing the handshake. */
tsi_handshaker_result *client_result;
tsi_handshaker_result *server_result;
/* size of buffer used to store data received from the peer. */
size_t handshake_buffer_size;
/* simulated channels between client and server. If the server (client)
wants to send data to the client (server), he will write data to
client_channel (server_channel), which will be read by client (server). */
uint8_t *client_channel;
uint8_t *server_channel;
/* size of data written to the client/server channel. */
size_t bytes_written_to_client_channel;
size_t bytes_written_to_server_channel;
/* size of data read from the client/server channel */
size_t bytes_read_from_client_channel;
size_t bytes_read_from_server_channel;
/* tsi_test_frame_protector_config instance */
tsi_test_frame_protector_config *config;
/* a flag indicating if client has finished TSI handshake first (i.e., before
server).
The flag should be referred if and only if TSI handshake finishes
successfully. */
bool has_client_finished_first;
/* a flag indicating whether to test tsi_handshaker_result_get_unused_bytes()
for TSI implementation. This field is true by default, and false
for SSL TSI implementation due to grpc issue #12164
(https://github.com/grpc/grpc/issues/12164).
*/
bool test_unused_bytes;
};
struct tsi_test_frame_protector_config {
/* size of buffer used to store protected frames to be unprotected. */
size_t read_buffer_allocated_size;
/* size of buffer used to store bytes resulted from unprotect operations. */
size_t message_buffer_allocated_size;
/* size of buffer used to store frames resulted from protect operations. */
size_t protected_buffer_size;
/* size of client/server maximum frame size. */
size_t client_max_output_protected_frame_size;
size_t server_max_output_protected_frame_size;
/* pointer that points to client/server message to be protected. */
uint8_t *client_message;
uint8_t *server_message;
/* size of client/server message. */
size_t client_message_size;
size_t server_message_size;
};
/* This method creates a tsi_test_frame_protector_config instance. Each
parameter of this function is a boolean value indicating whether to set the
corresponding parameter with a default value or not. If it's false, it will
be set with a specific value which is usually much smaller than the default.
Both values are defined with #define directive. */
tsi_test_frame_protector_config *tsi_test_frame_protector_config_create(
bool use_default_read_buffer_allocated_size,
bool use_default_message_buffer_allocated_size,
bool use_default_protected_buffer_size, bool use_default_client_message,
bool use_default_server_message,
bool use_default_client_max_output_protected_frame_size,
bool use_default_server_max_output_protected_frame_size,
bool use_default_handshake_buffer_size);
/* This method sets different buffer and frame sizes of a
tsi_test_frame_protector_config instance with user provided values. */
void tsi_test_frame_protector_config_set_buffer_size(
tsi_test_frame_protector_config *config, size_t read_buffer_allocated_size,
size_t message_buffer_allocated_size, size_t protected_buffer_size,
size_t client_max_output_protected_frame_size,
size_t server_max_output_protected_frame_size);
/* This method destroys a tsi_test_frame_protector_config instance. */
void tsi_test_frame_protector_config_destroy(
tsi_test_frame_protector_config *config);
/* This method initializes members of tsi_test_fixture instance.
Note that the struct instance should be allocated before making
this call. */
void tsi_test_fixture_init(tsi_test_fixture *fixture);
/* This method destroys a tsi_test_fixture instance. Note that the
fixture intance must be dynamically allocated and will be freed by
this function. */
void tsi_test_fixture_destroy(tsi_test_fixture *fixture);
/* This method performs a full TSI handshake between a client and a server.
Note that the test library will implement the new TSI handshaker API to
perform handshakes. */
void tsi_test_do_handshake(tsi_test_fixture *fixture);
/* This method performs a round trip test between the client and the server.
That is, the client sends a protected message to a server who receives the
message, and unprotects it. The same operation is triggered again with
the client and server switching its role. */
void tsi_test_do_round_trip(tsi_test_fixture *fixture);
#endif // GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H_

@ -193,6 +193,7 @@ grpc_cc_test(
"//test/cpp/util:test_util",
],
external_deps = [
"gmock",
"gtest",
],
)
@ -235,6 +236,7 @@ grpc_cc_test(
"//test/cpp/util:test_util",
],
external_deps = [
"gmock",
"gtest",
],
)

@ -260,11 +260,31 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
server_address_ << "localhost:" << port_;
// Setup server
BuildAndStartServer();
gpr_tls_set(&g_is_async_end2end_test, 1);
}
void TearDown() override {
server_->Shutdown();
void* ignored_tag;
bool ignored_ok;
cq_->Shutdown();
while (cq_->Next(&ignored_tag, &ignored_ok))
;
stub_.reset();
poll_overrider_.reset();
gpr_tls_set(&g_is_async_end2end_test, 0);
grpc_recycle_unused_port(port_);
}
void BuildAndStartServer() {
ServerBuilder builder;
auto server_creds = GetCredentialsProvider()->GetServerCredentials(
GetParam().credentials_type);
builder.AddListeningPort(server_address_.str(), server_creds);
builder.RegisterService(&service_);
service_.reset(new grpc::testing::EchoTestService::AsyncService());
builder.RegisterService(service_.get());
if (GetParam().health_check_service) {
builder.RegisterService(&health_check_);
}
@ -276,20 +296,6 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
new ServerBuilderSyncPluginDisabler());
builder.SetOption(move(sync_plugin_disabler));
server_ = builder.BuildAndStart();
gpr_tls_set(&g_is_async_end2end_test, 1);
}
void TearDown() override {
server_->Shutdown();
void* ignored_tag;
bool ignored_ok;
cq_->Shutdown();
while (cq_->Next(&ignored_tag, &ignored_ok))
;
poll_overrider_.reset();
gpr_tls_set(&g_is_async_end2end_test, 0);
grpc_recycle_unused_port(port_);
}
void ResetStub() {
@ -319,8 +325,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
service_->RequestEcho(&srv_ctx, &recv_request, &response_writer,
cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
@ -341,7 +347,7 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
std::unique_ptr<ServerCompletionQueue> cq_;
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
std::unique_ptr<Server> server_;
grpc::testing::EchoTestService::AsyncService service_;
std::unique_ptr<grpc::testing::EchoTestService::AsyncService> service_;
HealthCheck health_check_;
std::ostringstream server_address_;
int port_;
@ -359,6 +365,26 @@ TEST_P(AsyncEnd2endTest, SequentialRpcs) {
SendRpc(10);
}
TEST_P(AsyncEnd2endTest, ReconnectChannel) {
if (GetParam().inproc) {
return;
}
ResetStub();
SendRpc(1);
server_->Shutdown();
void* ignored_tag;
bool ignored_ok;
cq_->Shutdown();
while (cq_->Next(&ignored_tag, &ignored_ok))
;
BuildAndStartServer();
// It needs more than kConnectivityCheckIntervalMsec time to reconnect the
// channel.
gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_millis(1600, GPR_TIMESPAN)));
SendRpc(1);
}
// We do not need to protect notify because the use is synchronized.
void ServerWait(Server* server, int* notify) {
server->Wait();
@ -407,8 +433,8 @@ TEST_P(AsyncEnd2endTest, AsyncNextRpc) {
Verifier(GetParam().disable_blocking).Verify(cq_.get(), time_now);
Verifier(GetParam().disable_blocking).Verify(cq_.get(), time_now);
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
Verifier(GetParam().disable_blocking)
.Expect(2, true)
@ -444,8 +470,8 @@ TEST_P(AsyncEnd2endTest, SimpleClientStreaming) {
std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream(
stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1)));
service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
Verifier(GetParam().disable_blocking)
.Expect(2, true)
@ -506,8 +532,8 @@ TEST_P(AsyncEnd2endTest, SimpleClientStreamingWithCoalescingApi) {
std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream(
stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1)));
service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
cli_stream->Write(send_request, tag(3));
@ -579,8 +605,8 @@ TEST_P(AsyncEnd2endTest, SimpleServerStreaming) {
std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream(
stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1)));
service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
cq_.get(), cq_.get(), tag(2));
service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking)
.Expect(1, true)
@ -635,8 +661,8 @@ TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWAF) {
std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream(
stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1)));
service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
cq_.get(), cq_.get(), tag(2));
service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking)
.Expect(1, true)
@ -687,8 +713,8 @@ TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWL) {
std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream(
stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1)));
service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
cq_.get(), cq_.get(), tag(2));
service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking)
.Expect(1, true)
@ -741,8 +767,8 @@ TEST_P(AsyncEnd2endTest, SimpleBidiStreaming) {
std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>>
cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1)));
service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
Verifier(GetParam().disable_blocking)
.Expect(1, true)
@ -801,8 +827,8 @@ TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWAF) {
std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>>
cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1)));
service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
cli_stream->WriteLast(send_request, WriteOptions(), tag(3));
@ -869,8 +895,8 @@ TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWL) {
std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>>
cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1)));
service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
cli_stream->WriteLast(send_request, WriteOptions(), tag(3));
@ -946,8 +972,8 @@ TEST_P(AsyncEnd2endTest, ClientInitialMetadataRpc) {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
auto client_initial_metadata = srv_ctx.client_metadata();
@ -991,8 +1017,8 @@ TEST_P(AsyncEnd2endTest, ServerInitialMetadataRpc) {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
srv_ctx.AddInitialMetadata(meta1.first, meta1.second);
@ -1041,8 +1067,8 @@ TEST_P(AsyncEnd2endTest, ServerTrailingMetadataRpc) {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
response_writer.SendInitialMetadata(tag(3));
@ -1104,8 +1130,8 @@ TEST_P(AsyncEnd2endTest, MetadataRpc) {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
auto client_initial_metadata = srv_ctx.client_metadata();
@ -1168,8 +1194,8 @@ TEST_P(AsyncEnd2endTest, ServerCheckCancellation) {
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
srv_ctx.AsyncNotifyWhenDone(tag(5));
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
@ -1203,8 +1229,8 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) {
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
srv_ctx.AsyncNotifyWhenDone(tag(5));
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
@ -1295,8 +1321,8 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
// On the server, request to be notified of 'RequestStream' calls
// and receive the 'RequestStream' call just made by the client
srv_ctx.AsyncNotifyWhenDone(tag(11));
service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
// Client sends 3 messages (tags 3, 4 and 5)
@ -1426,8 +1452,8 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
// On the server, request to be notified of 'ResponseStream' calls and
// receive the call just made by the client
srv_ctx.AsyncNotifyWhenDone(tag(11));
service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
cq_.get(), cq_.get(), tag(2));
service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
@ -1562,8 +1588,8 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
// On the server, request to be notified of the 'BidiStream' call and
// receive the call just made by the client
srv_ctx.AsyncNotifyWhenDone(tag(11));
service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
// Client sends the first and the only message

@ -180,16 +180,18 @@ class ClientLbEnd2endTest : public ::testing::Test {
std::unique_ptr<Server> server_;
MyTestServiceImpl service_;
std::unique_ptr<std::thread> thread_;
bool server_ready_ = false;
explicit ServerData(const grpc::string& server_host, int port = 0) {
port_ = port > 0 ? port : grpc_pick_unused_port_or_die();
gpr_log(GPR_INFO, "starting server on port %d", port_);
std::mutex mu;
std::unique_lock<std::mutex> lock(mu);
std::condition_variable cond;
thread_.reset(new std::thread(
std::bind(&ServerData::Start, this, server_host, &mu, &cond)));
std::unique_lock<std::mutex> lock(mu);
cond.wait(lock);
cond.wait(lock, [this] { return server_ready_; });
server_ready_ = false;
gpr_log(GPR_INFO, "server startup complete");
}
@ -203,6 +205,7 @@ class ClientLbEnd2endTest : public ::testing::Test {
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
std::lock_guard<std::mutex> lock(*mu);
server_ready_ = true;
cond->notify_one();
}

@ -238,6 +238,18 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> {
int port = grpc_pick_unused_port_or_die();
server_address_ << "127.0.0.1:" << port;
// Setup server
BuildAndStartServer(processor);
}
void RestartServer(const std::shared_ptr<AuthMetadataProcessor>& processor) {
if (is_server_started_) {
server_->Shutdown();
BuildAndStartServer(processor);
}
}
void BuildAndStartServer(
const std::shared_ptr<AuthMetadataProcessor>& processor) {
ServerBuilder builder;
ConfigureServerBuilder(&builder);
auto server_creds = GetCredentialsProvider()->GetServerCredentials(
@ -685,6 +697,20 @@ TEST_P(End2endTest, MultipleRpcs) {
}
}
TEST_P(End2endTest, ReconnectChannel) {
if (GetParam().inproc) {
return;
}
ResetStub();
SendRpc(stub_.get(), 1, false);
RestartServer(std::shared_ptr<AuthMetadataProcessor>());
// It needs more than kConnectivityCheckIntervalMsec time to reconnect the
// channel.
gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_millis(1600, GPR_TIMESPAN)));
SendRpc(stub_.get(), 1, false);
}
TEST_P(End2endTest, RequestStreamOneRequest) {
ResetStub();
EchoRequest request;

@ -2,14 +2,38 @@ cc_library(
name = "gtest",
srcs = [
"googletest/src/gtest-all.cc",
"googlemock/src/gmock-all.cc"
],
hdrs = glob(["googletest/include/**/*.h", "googletest/src/*.cc", "googletest/src/*.h", "googlemock/include/**/*.h", "googlemock/src/*.cc", "googlemock/src/*.h"]),
hdrs = glob([
"googletest/include/**/*.h",
"googletest/src/*.cc",
"googletest/src/*.h",
]),
includes = [
"googletest",
"googletest/include",
"googlemock",
"googlemock/include",
],
linkstatic = 1,
visibility = [
"//visibility:public",
],
)
cc_library(
name = "gmock",
srcs = [
"googlemock/src/gmock-all.cc"
],
hdrs = glob([
"googlemock/include/**/*.h",
"googlemock/src/*.cc",
"googlemock/src/*.h"
]),
includes = [
"googlemock",
"googlemock/include",
],
deps = [
":gtest",
],
linkstatic = 1,
visibility = [

@ -189,7 +189,10 @@ static unsigned state_index(unsigned bitofs, symset syms, unsigned *isnew) {
return i;
}
GPR_ASSERT(nhuffstates != MAXHUFFSTATES);
i = nhuffstates++;
i = nhuffstates;
nhuffstates++;
huffstates[i].bitofs = bitofs;
huffstates[i].syms = syms;
huffstates[i].next = nibblelut_empty();

@ -132,29 +132,33 @@ CONFIG = [
('www-authenticate', ''),
]
# Entries marked with is_default=True are ignored when counting
# non-default initial metadata that prevents the chttp2 server from
# sending a Trailers-Only response.
METADATA_BATCH_CALLOUTS = [
':path',
':method',
':status',
':authority',
':scheme',
'te',
'grpc-message',
'grpc-status',
'grpc-payload-bin',
'grpc-encoding',
'grpc-accept-encoding',
'grpc-server-stats-bin',
'grpc-tags-bin',
'grpc-trace-bin',
'content-type',
'content-encoding',
'accept-encoding',
'grpc-internal-encoding-request',
'grpc-internal-stream-encoding-request',
'user-agent',
'host',
'lb-token',
# (name, is_default)
(':path', True),
(':method', True),
(':status', True),
(':authority', True),
(':scheme', True),
('te', True),
('grpc-message', True),
('grpc-status', True),
('grpc-payload-bin', True),
('grpc-encoding', True),
('grpc-accept-encoding', True),
('grpc-server-stats-bin', True),
('grpc-tags-bin', True),
('grpc-trace-bin', True),
('content-type', True),
('content-encoding', True),
('accept-encoding', True),
('grpc-internal-encoding-request', True),
('grpc-internal-stream-encoding-request', True),
('user-agent', True),
('host', True),
('lb-token', True),
]
COMPRESSION_ALGORITHMS = [
@ -235,7 +239,7 @@ all_elems = list()
static_userdata = {}
# put metadata batch callouts first, to make the check of if a static metadata
# string is a callout trivial
for elem in METADATA_BATCH_CALLOUTS:
for elem, _ in METADATA_BATCH_CALLOUTS:
if elem not in all_strs:
all_strs.append(elem)
for elem in CONFIG:
@ -372,7 +376,7 @@ def slice_def(i):
# validate configuration
for elem in METADATA_BATCH_CALLOUTS:
for elem, _ in METADATA_BATCH_CALLOUTS:
assert elem in all_strs
print >> H, '#define GRPC_STATIC_MDSTR_COUNT %d' % len(all_strs)
@ -540,7 +544,7 @@ for a, b in all_elems:
print >> C, '};'
print >> H, 'typedef enum {'
for elem in METADATA_BATCH_CALLOUTS:
for elem, _ in METADATA_BATCH_CALLOUTS:
print >> H, ' %s,' % mangle(elem, 'batch').upper()
print >> H, ' GRPC_BATCH_CALLOUTS_COUNT'
print >> H, '} grpc_metadata_batch_callouts_index;'
@ -548,7 +552,7 @@ print >> H
print >> H, 'typedef union {'
print >> H, ' struct grpc_linked_mdelem *array[GRPC_BATCH_CALLOUTS_COUNT];'
print >> H, ' struct {'
for elem in METADATA_BATCH_CALLOUTS:
for elem, _ in METADATA_BATCH_CALLOUTS:
print >> H, ' struct grpc_linked_mdelem *%s;' % mangle(elem, '').lower()
print >> H, ' } named;'
print >> H, '} grpc_metadata_batch_callouts;'
@ -556,6 +560,14 @@ print >> H
print >> H, '#define GRPC_BATCH_INDEX_OF(slice) \\'
print >> H, ' (GRPC_IS_STATIC_METADATA_STRING((slice)) ? (grpc_metadata_batch_callouts_index)GPR_CLAMP(GRPC_STATIC_METADATA_INDEX((slice)), 0, GRPC_BATCH_CALLOUTS_COUNT) : GRPC_BATCH_CALLOUTS_COUNT)'
print >> H
print >> H, ('extern bool grpc_static_callout_is_default['
'GRPC_BATCH_CALLOUTS_COUNT];')
print >> H
print >> C, 'bool grpc_static_callout_is_default[GRPC_BATCH_CALLOUTS_COUNT] = {'
for elem, is_default in METADATA_BATCH_CALLOUTS:
print >> C, ' %s, // %s' % (str(is_default).lower(), elem)
print >> C, '};'
print >> C
print >> H, 'extern const uint8_t grpc_static_accept_encoding_metadata[%d];' % (
1 << len(COMPRESSION_ALGORITHMS))

@ -957,8 +957,6 @@ src/core/lib/iomgr/endpoint_pair.h \
src/core/lib/iomgr/error.h \
src/core/lib/iomgr/error_internal.h \
src/core/lib/iomgr/ev_epoll1_linux.h \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.h \
src/core/lib/iomgr/ev_epollex_linux.h \
src/core/lib/iomgr/ev_epollsig_linux.h \
src/core/lib/iomgr/ev_poll_posix.h \

@ -1110,10 +1110,6 @@ src/core/lib/iomgr/error.h \
src/core/lib/iomgr/error_internal.h \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll1_linux.h \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.h \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollex_linux.h \
src/core/lib/iomgr/ev_epollsig_linux.c \

@ -34,7 +34,7 @@ gcloud compute instances create $INSTANCE_NAME \
--zone "$ZONE" \
--machine-type $MACHINE_TYPE \
--image-project ubuntu-os-cloud \
--image-family ubuntu-1610 \
--image-family ubuntu-1704 \
--boot-disk-size 300 \
--scopes https://www.googleapis.com/auth/bigquery

@ -54,8 +54,7 @@ pod repo update # needed by python
brew install coreutils # we need grealpath
pip install virtualenv --user python
pip install -U six tox setuptools --user python
export PYTHONPATH=/Library/Python/2.7/site-packages
source ~/.bashrc
export PYTHONPATH=/Library/Python/3.4/site-packages
# python 3.4
wget -q https://www.python.org/ftp/python/3.4.4/python-3.4.4-macosx10.6.pkg

@ -27,5 +27,5 @@ action {
env_vars {
key: "RUN_TESTS_FLAGS"
value: "-f basictests macos dbg --internal_ci -j 1 --inner_jobs 4 --bq_result_table aggregate_results"
value: "-f basictests macos dbg --internal_ci -j 1 --inner_jobs 4"
}

@ -27,5 +27,5 @@ action {
env_vars {
key: "RUN_TESTS_FLAGS"
value: "-f basictests macos opt --internal_ci -j 1 --inner_jobs 4 --bq_result_table aggregate_results"
value: "-f basictests macos opt --internal_ci -j 1 --inner_jobs 4"
}

@ -553,6 +553,23 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"transport_security_test_lib"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "fake_transport_security_test",
"src": [
"test/core/tsi/fake_transport_security_test.c"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -2165,6 +2182,23 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"transport_security_test_lib"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "ssl_transport_security_test",
"src": [
"test/core/tsi/ssl_transport_security_test.c"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -7836,8 +7870,6 @@
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/error.c",
"src/core/lib/iomgr/ev_epoll1_linux.c",
"src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c",
"src/core/lib/iomgr/ev_epoll_thread_pool_linux.c",
"src/core/lib/iomgr/ev_epollex_linux.c",
"src/core/lib/iomgr/ev_epollsig_linux.c",
"src/core/lib/iomgr/ev_poll_posix.c",
@ -7990,8 +8022,6 @@
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_epoll1_linux.h",
"src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h",
"src/core/lib/iomgr/ev_epoll_thread_pool_linux.h",
"src/core/lib/iomgr/ev_epollex_linux.h",
"src/core/lib/iomgr/ev_epollsig_linux.h",
"src/core/lib/iomgr/ev_poll_posix.h",
@ -8124,8 +8154,6 @@
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_epoll1_linux.h",
"src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h",
"src/core/lib/iomgr/ev_epoll_thread_pool_linux.h",
"src/core/lib/iomgr/ev_epollex_linux.h",
"src/core/lib/iomgr/ev_epollsig_linux.h",
"src/core/lib/iomgr/ev_poll_posix.h",
@ -9111,6 +9139,23 @@
"third_party": false,
"type": "filegroup"
},
{
"deps": [
"grpc"
],
"headers": [
"test/core/tsi/transport_security_test_lib.h"
],
"is_filegroup": true,
"language": "c",
"name": "transport_security_test_lib",
"src": [
"test/core/tsi/transport_security_test_lib.c",
"test/core/tsi/transport_security_test_lib.h"
],
"third_party": false,
"type": "filegroup"
},
{
"deps": [
"gpr",

@ -665,6 +665,26 @@
"windows"
]
},
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "fake_transport_security_test",
"platforms": [
"linux",
"mac",
"posix"
]
},
{
"args": [],
"ci_platforms": [
@ -2273,6 +2293,26 @@
"posix"
]
},
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "ssl_transport_security_test",
"platforms": [
"linux",
"mac",
"posix"
]
},
{
"args": [],
"ci_platforms": [

@ -281,18 +281,18 @@ def create_qpsworkers(languages, worker_hosts, perf_cmd=None):
for worker_idx, worker in enumerate(workers)]
def perf_report_processor_job(worker_host, perf_base_name, output_filename):
def perf_report_processor_job(worker_host, perf_base_name, output_filename, flame_graph_reports):
print('Creating perf report collection job for %s' % worker_host)
cmd = ''
if worker_host != 'localhost':
user_at_host = "%s@%s" % (_REMOTE_HOST_USERNAME, worker_host)
cmd = "USER_AT_HOST=%s OUTPUT_FILENAME=%s OUTPUT_DIR=%s PERF_BASE_NAME=%s\
tools/run_tests/performance/process_remote_perf_flamegraphs.sh" \
% (user_at_host, output_filename, args.flame_graph_reports, perf_base_name)
% (user_at_host, output_filename, flame_graph_reports, perf_base_name)
else:
cmd = "OUTPUT_FILENAME=%s OUTPUT_DIR=%s PERF_BASE_NAME=%s\
tools/run_tests/performance/process_local_perf_flamegraphs.sh" \
% (output_filename, args.flame_graph_reports, perf_base_name)
% (output_filename, flame_graph_reports, perf_base_name)
return jobset.JobSpec(cmdline=cmd,
timeout_seconds=3*60,
@ -332,7 +332,7 @@ def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*',
for language in languages:
for scenario_json in language.scenarios():
if re.search(args.regex, scenario_json['name']):
if re.search(regex, scenario_json['name']):
categories = scenario_json.get('CATEGORIES', ['scalable', 'smoketest'])
if category in categories or category == 'all':
workers = workers_by_lang[str(language)][:]
@ -376,7 +376,7 @@ def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*',
return scenarios
def finish_qps_workers(jobs):
def finish_qps_workers(jobs, qpsworker_jobs):
"""Waits for given jobs to finish and eventually kills them."""
retries = 0
num_killed = 0
@ -399,10 +399,10 @@ profile_output_files = []
# Collect perf text reports and flamegraphs if perf_cmd was used
# Note the base names of perf text reports are used when creating and processing
# perf data. The scenario name uniqifies the output name in the final
# perf reports directory.
# perf reports directory.
# Alos, the perf profiles need to be fetched and processed after each scenario
# in order to avoid clobbering the output files.
def run_collect_perf_profile_jobs(hosts_and_base_names, scenario_name):
def run_collect_perf_profile_jobs(hosts_and_base_names, scenario_name, flame_graph_reports):
perf_report_jobs = []
global profile_output_files
for host_and_port in hosts_and_base_names:
@ -411,181 +411,184 @@ def run_collect_perf_profile_jobs(hosts_and_base_names, scenario_name):
# from the base filename, create .svg output filename
host = host_and_port.split(':')[0]
profile_output_files.append('%s.svg' % output_filename)
perf_report_jobs.append(perf_report_processor_job(host, perf_base_name, output_filename))
perf_report_jobs.append(perf_report_processor_job(host, perf_base_name, output_filename, flame_graph_reports))
jobset.message('START', 'Collecting perf reports from qps workers', do_newline=True)
failures, _ = jobset.run(perf_report_jobs, newline_on_success=True, maxjobs=1, clear_alarms=False)
jobset.message('END', 'Collecting perf reports from qps workers', do_newline=True)
return failures
def main():
argp = argparse.ArgumentParser(description='Run performance tests.')
argp.add_argument('-l', '--language',
choices=['all'] + sorted(scenario_config.LANGUAGES.keys()),
nargs='+',
required=True,
help='Languages to benchmark.')
argp.add_argument('--remote_driver_host',
default=None,
help='Run QPS driver on given host. By default, QPS driver is run locally.')
argp.add_argument('--remote_worker_host',
nargs='+',
default=[],
help='Worker hosts where to start QPS workers.')
argp.add_argument('--dry_run',
default=False,
action='store_const',
const=True,
help='Just list scenarios to be run, but don\'t run them.')
argp.add_argument('-r', '--regex', default='.*', type=str,
help='Regex to select scenarios to run.')
argp.add_argument('--bq_result_table', default=None, type=str,
help='Bigquery "dataset.table" to upload results to.')
argp.add_argument('--category',
choices=['smoketest','all','scalable','sweep'],
default='all',
help='Select a category of tests to run.')
argp.add_argument('--netperf',
default=False,
action='store_const',
const=True,
help='Run netperf benchmark as one of the scenarios.')
argp.add_argument('--server_cpu_load',
default=0, type=int,
help='Select a targeted server cpu load to run. 0 means ignore this flag')
argp.add_argument('-x', '--xml_report', default='report.xml', type=str,
help='Name of XML report file to generate.')
argp.add_argument('--perf_args',
help=('Example usage: "--perf_args=record -F 99 -g". '
'Wrap QPS workers in a perf command '
'with the arguments to perf specified here. '
'".svg" flame graph profiles will be '
'created for each Qps Worker on each scenario. '
'Files will output to "<repo_root>/<args.flame_graph_reports>" '
'directory. Output files from running the worker '
'under perf are saved in the repo root where its ran. '
'Note that the perf "-g" flag is necessary for '
'flame graphs generation to work (assuming the binary '
'being profiled uses frame pointers, check out '
'"--call-graph dwarf" option using libunwind otherwise.) '
'Also note that the entire "--perf_args=<arg(s)>" must '
'be wrapped in quotes as in the example usage. '
'If the "--perg_args" is unspecified, "perf" will '
'not be used at all. '
'See http://www.brendangregg.com/perf.html '
'for more general perf examples.'))
argp.add_argument('--skip_generate_flamegraphs',
default=False,
action='store_const',
const=True,
help=('Turn flame graph generation off. '
'May be useful if "perf_args" arguments do not make sense for '
'generating flamegraphs (e.g., "--perf_args=stat ...")'))
argp.add_argument('-f', '--flame_graph_reports', default='perf_reports', type=str,
help='Name of directory to output flame graph profiles to, if any are created.')
args = argp.parse_args()
languages = set(scenario_config.LANGUAGES[l]
for l in itertools.chain.from_iterable(
six.iterkeys(scenario_config.LANGUAGES) if x == 'all'
else [x] for x in args.language))
# Put together set of remote hosts where to run and build
remote_hosts = set()
if args.remote_worker_host:
for host in args.remote_worker_host:
remote_hosts.add(host)
if args.remote_driver_host:
remote_hosts.add(args.remote_driver_host)
if not args.dry_run:
if remote_hosts:
archive_repo(languages=[str(l) for l in languages])
prepare_remote_hosts(remote_hosts, prepare_local=True)
else:
prepare_remote_hosts([], prepare_local=True)
build_local = False
if not args.remote_driver_host:
build_local = True
if not args.dry_run:
build_on_remote_hosts(remote_hosts, languages=[str(l) for l in languages], build_local=build_local)
perf_cmd = None
if args.perf_args:
print('Running workers under perf profiler')
# Expect /usr/bin/perf to be installed here, as is usual
perf_cmd = ['/usr/bin/perf']
perf_cmd.extend(re.split('\s+', args.perf_args))
qpsworker_jobs = create_qpsworkers(languages, args.remote_worker_host, perf_cmd=perf_cmd)
# get list of worker addresses for each language.
workers_by_lang = dict([(str(language), []) for language in languages])
for job in qpsworker_jobs:
workers_by_lang[str(job.language)].append(job)
scenarios = create_scenarios(languages,
workers_by_lang=workers_by_lang,
remote_host=args.remote_driver_host,
regex=args.regex,
category=args.category,
bq_result_table=args.bq_result_table,
netperf=args.netperf,
netperf_hosts=args.remote_worker_host,
server_cpu_load=args.server_cpu_load)
if not scenarios:
raise Exception('No scenarios to run')
total_scenario_failures = 0
qps_workers_killed = 0
merged_resultset = {}
perf_report_failures = 0
for scenario in scenarios:
if args.dry_run:
print(scenario.name)
else:
scenario_failures = 0
try:
for worker in scenario.workers:
worker.start()
jobs = [scenario.jobspec]
if scenario.workers:
jobs.append(create_quit_jobspec(scenario.workers, remote_host=args.remote_driver_host))
scenario_failures, resultset = jobset.run(jobs, newline_on_success=True, maxjobs=1, clear_alarms=False)
total_scenario_failures += scenario_failures
merged_resultset = dict(itertools.chain(six.iteritems(merged_resultset),
six.iteritems(resultset)))
finally:
# Consider qps workers that need to be killed as failures
qps_workers_killed += finish_qps_workers(scenario.workers, qpsworker_jobs)
if perf_cmd and scenario_failures == 0 and not args.skip_generate_flamegraphs:
workers_and_base_names = {}
for worker in scenario.workers:
if not worker.perf_file_base_name:
raise Exception('using perf buf perf report filename is unspecified')
workers_and_base_names[worker.host_and_port] = worker.perf_file_base_name
perf_report_failures += run_collect_perf_profile_jobs(workers_and_base_names, scenario.name, args.flame_graph_reports)
# Still write the index.html even if some scenarios failed.
# 'profile_output_files' will only have names for scenarios that passed
if perf_cmd and not args.skip_generate_flamegraphs:
# write the index fil to the output dir, with all profiles from all scenarios/workers
report_utils.render_perf_profiling_results('%s/index.html' % args.flame_graph_reports, profile_output_files)
report_utils.render_junit_xml_report(merged_resultset, args.xml_report,
suite_name='benchmarks')
if total_scenario_failures > 0 or qps_workers_killed > 0:
print('%s scenarios failed and %s qps worker jobs killed' % (total_scenario_failures, qps_workers_killed))
sys.exit(1)
argp = argparse.ArgumentParser(description='Run performance tests.')
argp.add_argument('-l', '--language',
choices=['all'] + sorted(scenario_config.LANGUAGES.keys()),
nargs='+',
required=True,
help='Languages to benchmark.')
argp.add_argument('--remote_driver_host',
default=None,
help='Run QPS driver on given host. By default, QPS driver is run locally.')
argp.add_argument('--remote_worker_host',
nargs='+',
default=[],
help='Worker hosts where to start QPS workers.')
argp.add_argument('--dry_run',
default=False,
action='store_const',
const=True,
help='Just list scenarios to be run, but don\'t run them.')
argp.add_argument('-r', '--regex', default='.*', type=str,
help='Regex to select scenarios to run.')
argp.add_argument('--bq_result_table', default=None, type=str,
help='Bigquery "dataset.table" to upload results to.')
argp.add_argument('--category',
choices=['smoketest','all','scalable','sweep'],
default='all',
help='Select a category of tests to run.')
argp.add_argument('--netperf',
default=False,
action='store_const',
const=True,
help='Run netperf benchmark as one of the scenarios.')
argp.add_argument('--server_cpu_load',
default=0, type=int,
help='Select a targeted server cpu load to run. 0 means ignore this flag')
argp.add_argument('-x', '--xml_report', default='report.xml', type=str,
help='Name of XML report file to generate.')
argp.add_argument('--perf_args',
help=('Example usage: "--perf_args=record -F 99 -g". '
'Wrap QPS workers in a perf command '
'with the arguments to perf specified here. '
'".svg" flame graph profiles will be '
'created for each Qps Worker on each scenario. '
'Files will output to "<repo_root>/<args.flame_graph_reports>" '
'directory. Output files from running the worker '
'under perf are saved in the repo root where its ran. '
'Note that the perf "-g" flag is necessary for '
'flame graphs generation to work (assuming the binary '
'being profiled uses frame pointers, check out '
'"--call-graph dwarf" option using libunwind otherwise.) '
'Also note that the entire "--perf_args=<arg(s)>" must '
'be wrapped in quotes as in the example usage. '
'If the "--perg_args" is unspecified, "perf" will '
'not be used at all. '
'See http://www.brendangregg.com/perf.html '
'for more general perf examples.'))
argp.add_argument('--skip_generate_flamegraphs',
default=False,
action='store_const',
const=True,
help=('Turn flame graph generation off. '
'May be useful if "perf_args" arguments do not make sense for '
'generating flamegraphs (e.g., "--perf_args=stat ...")'))
argp.add_argument('-f', '--flame_graph_reports', default='perf_reports', type=str,
help='Name of directory to output flame graph profiles to, if any are created.')
args = argp.parse_args()
languages = set(scenario_config.LANGUAGES[l]
for l in itertools.chain.from_iterable(
six.iterkeys(scenario_config.LANGUAGES) if x == 'all'
else [x] for x in args.language))
# Put together set of remote hosts where to run and build
remote_hosts = set()
if args.remote_worker_host:
for host in args.remote_worker_host:
remote_hosts.add(host)
if args.remote_driver_host:
remote_hosts.add(args.remote_driver_host)
if not args.dry_run:
if remote_hosts:
archive_repo(languages=[str(l) for l in languages])
prepare_remote_hosts(remote_hosts, prepare_local=True)
else:
prepare_remote_hosts([], prepare_local=True)
build_local = False
if not args.remote_driver_host:
build_local = True
if not args.dry_run:
build_on_remote_hosts(remote_hosts, languages=[str(l) for l in languages], build_local=build_local)
perf_cmd = None
if args.perf_args:
print('Running workers under perf profiler')
# Expect /usr/bin/perf to be installed here, as is usual
perf_cmd = ['/usr/bin/perf']
perf_cmd.extend(re.split('\s+', args.perf_args))
qpsworker_jobs = create_qpsworkers(languages, args.remote_worker_host, perf_cmd=perf_cmd)
# get list of worker addresses for each language.
workers_by_lang = dict([(str(language), []) for language in languages])
for job in qpsworker_jobs:
workers_by_lang[str(job.language)].append(job)
scenarios = create_scenarios(languages,
workers_by_lang=workers_by_lang,
remote_host=args.remote_driver_host,
regex=args.regex,
category=args.category,
bq_result_table=args.bq_result_table,
netperf=args.netperf,
netperf_hosts=args.remote_worker_host,
server_cpu_load=args.server_cpu_load)
if not scenarios:
raise Exception('No scenarios to run')
total_scenario_failures = 0
qps_workers_killed = 0
merged_resultset = {}
perf_report_failures = 0
for scenario in scenarios:
if args.dry_run:
print(scenario.name)
else:
scenario_failures = 0
try:
for worker in scenario.workers:
worker.start()
jobs = [scenario.jobspec]
if scenario.workers:
jobs.append(create_quit_jobspec(scenario.workers, remote_host=args.remote_driver_host))
scenario_failures, resultset = jobset.run(jobs, newline_on_success=True, maxjobs=1, clear_alarms=False)
total_scenario_failures += scenario_failures
merged_resultset = dict(itertools.chain(six.iteritems(merged_resultset),
six.iteritems(resultset)))
finally:
# Consider qps workers that need to be killed as failures
qps_workers_killed += finish_qps_workers(scenario.workers)
if perf_cmd and scenario_failures == 0 and not args.skip_generate_flamegraphs:
workers_and_base_names = {}
for worker in scenario.workers:
if not worker.perf_file_base_name:
raise Exception('using perf buf perf report filename is unspecified')
workers_and_base_names[worker.host_and_port] = worker.perf_file_base_name
perf_report_failures += run_collect_perf_profile_jobs(workers_and_base_names, scenario.name)
# Still write the index.html even if some scenarios failed.
# 'profile_output_files' will only have names for scenarios that passed
if perf_cmd and not args.skip_generate_flamegraphs:
# write the index fil to the output dir, with all profiles from all scenarios/workers
report_utils.render_perf_profiling_results('%s/index.html' % args.flame_graph_reports, profile_output_files)
report_utils.render_junit_xml_report(merged_resultset, args.xml_report,
suite_name='benchmarks')
if total_scenario_failures > 0 or qps_workers_killed > 0:
print('%s scenarios failed and %s qps worker jobs killed' % (total_scenario_failures, qps_workers_killed))
sys.exit(1)
if perf_report_failures > 0:
print('%s perf profile collection jobs failed' % perf_report_failures)
sys.exit(1)
if perf_report_failures > 0:
print('%s perf profile collection jobs failed' % perf_report_failures)
sys.exit(1)
if __name__ == "__main__":
main()

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save