Merge branch 'master' into noquestions

pull/22866/head
Yash Tibrewal 5 years ago
commit 8acfeef374
  1. 2
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 2
      .github/ISSUE_TEMPLATE/cleanup_request.md
  3. 2
      .github/ISSUE_TEMPLATE/feature_request.md
  4. 2
      .github/pull_request_template.md
  5. 4
      BUILD
  6. 22
      CMakeLists.txt
  7. 64
      Makefile
  8. 28
      build_autogenerated.yaml
  9. 4
      build_handwritten.yaml
  10. 3
      doc/g_stands_for.md
  11. 49
      examples/python/data_transmission/BUILD
  12. 39
      examples/python/data_transmission/alts_client.py
  13. 39
      examples/python/data_transmission/alts_server.py
  14. 5
      examples/python/data_transmission/client.py
  15. 1
      examples/python/data_transmission/server.py
  16. 2
      gRPC-C++.podspec
  17. 2
      gRPC-Core.podspec
  18. 2
      gRPC-ProtoRPC.podspec
  19. 2
      gRPC-RxLibrary.podspec
  20. 2
      gRPC.podspec
  21. 2
      grpc.gemspec
  22. 67
      include/grpcpp/impl/codegen/call_op_set.h
  23. 8
      include/grpcpp/impl/codegen/interceptor_common.h
  24. 6
      package.xml
  25. 20
      src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
  26. 21
      src/core/ext/filters/client_channel/xds/xds_api.cc
  27. 4
      src/core/lib/gpr/time.cc
  28. 2
      src/core/lib/iomgr/iomgr_posix_cfstream.cc
  29. 2
      src/core/lib/surface/version.cc
  30. 2
      src/cpp/common/version_cc.cc
  31. 4
      src/csharp/Grpc.Core.Api/VersionInfo.cs
  32. 2
      src/csharp/build/dependencies.props
  33. 2
      src/csharp/build_unitypackage.bat
  34. 2
      src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec
  35. 2
      src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
  36. 2
      src/objective-c/GRPCClient/version.h
  37. 12
      src/objective-c/README-CFSTREAM.md
  38. 2
      src/objective-c/tests/version.h
  39. 2
      src/php/composer.json
  40. 2
      src/php/ext/grpc/version.h
  41. 37
      src/python/grpcio/grpc/__init__.py
  42. 53
      src/python/grpcio/grpc/_cython/_cygrpc/aio/common.pyx.pxi
  43. 10
      src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pxd.pxi
  44. 126
      src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pyx.pxi
  45. 6
      src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd.pxi
  46. 29
      src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
  47. 15
      src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
  48. 2
      src/python/grpcio/grpc/_grpcio_metadata.py
  49. 4
      src/python/grpcio/grpc/experimental/aio/__init__.py
  50. 11
      src/python/grpcio/grpc/experimental/aio/_call.py
  51. 36
      src/python/grpcio/grpc/experimental/aio/_channel.py
  52. 217
      src/python/grpcio/grpc/experimental/aio/_interceptor.py
  53. 2
      src/python/grpcio/grpc_version.py
  54. 2
      src/python/grpcio_channelz/grpc_version.py
  55. 2
      src/python/grpcio_health_checking/grpc_version.py
  56. 2
      src/python/grpcio_reflection/grpc_version.py
  57. 2
      src/python/grpcio_status/grpc_version.py
  58. 2
      src/python/grpcio_testing/grpc_version.py
  59. 2
      src/python/grpcio_tests/grpc_version.py
  60. 11
      src/python/grpcio_tests/tests/interop/client.py
  61. 13
      src/python/grpcio_tests/tests/interop/server.py
  62. 2
      src/python/grpcio_tests/tests/unit/_api_test.py
  63. 2
      src/python/grpcio_tests/tests_aio/interop/client.py
  64. 5
      src/python/grpcio_tests/tests_aio/interop/server.py
  65. 1
      src/python/grpcio_tests/tests_aio/tests.json
  66. 6
      src/python/grpcio_tests/tests_aio/unit/_test_server.py
  67. 531
      src/python/grpcio_tests/tests_aio/unit/client_stream_unary_interceptor_test.py
  68. 179
      src/python/grpcio_tests/tests_aio/unit/compatibility_test.py
  69. 2
      src/ruby/lib/grpc/version.rb
  70. 2
      src/ruby/tools/version.rb
  71. 2
      templates/grpc.gemspec.template
  72. 1
      test/core/bad_ssl/generate_tests.bzl
  73. 1
      test/core/bad_ssl/servers/cert.cc
  74. 26
      test/core/channel/channelz_test.cc
  75. 4
      test/core/end2end/data/ssl_test_data.h
  76. 1
      test/core/end2end/fixtures/h2_fakesec.cc
  77. 3
      test/core/security/BUILD
  78. 1
      test/core/surface/BUILD
  79. 6
      test/core/util/test_config.cc
  80. 179
      test/cpp/end2end/client_interceptors_end2end_test.cc
  81. 24
      test/cpp/end2end/grpclb_end2end_test.cc
  82. 57
      test/cpp/end2end/interceptors_util.cc
  83. 18
      test/cpp/end2end/interceptors_util.h
  84. 816
      test/cpp/end2end/xds_end2end_test.cc
  85. 1
      test/cpp/util/BUILD
  86. 2
      tools/distrib/python/grpcio_tools/grpc_version.py
  87. 2
      tools/doxygen/Doxyfile.c++
  88. 2
      tools/doxygen/Doxyfile.c++.internal
  89. 2
      tools/doxygen/Doxyfile.objc
  90. 2
      tools/doxygen/Doxyfile.objc.internal
  91. 4
      tools/run_tests/run_interop_tests.py
  92. 6
      tools/run_tests/run_xds_tests.py

@ -2,7 +2,7 @@
name: Report a bug
about: Create a report to help us improve
labels: kind/bug, priority/P2
assignees: veblush
assignees: markdroth
---

@ -2,7 +2,7 @@
name: Request a cleanup
about: Suggest a cleanup in our repository
labels: kind/internal cleanup, priority/P2
assignees: veblush
assignees: markdroth
---

@ -2,7 +2,7 @@
name: Request a feature
about: Suggest an idea for this project
labels: kind/enhancement, priority/P2
assignees: veblush
assignees: markdroth
---

@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
-->
@veblush
@markdroth

@ -75,11 +75,11 @@ config_setting(
python_config_settings()
# This should be updated along with build.yaml
g_stands_for = "gringotts"
g_stands_for = "gradius"
core_version = "10.0.0"
version = "1.29.0-dev"
version = "1.30.0-dev"
GPR_PUBLIC_HDRS = [
"include/grpc/support/alloc.h",

@ -25,12 +25,12 @@
cmake_minimum_required(VERSION 3.5.1)
set(PACKAGE_NAME "grpc")
set(PACKAGE_VERSION "1.29.0-dev")
set(PACKAGE_VERSION "1.30.0-dev")
set(gRPC_CORE_VERSION "10.0.0")
set(gRPC_CORE_SOVERSION "10")
set(gRPC_CPP_VERSION "1.29.0-dev")
set(gRPC_CPP_VERSION "1.30.0-dev")
set(gRPC_CPP_SOVERSION "1")
set(gRPC_CSHARP_VERSION "2.29.0-dev")
set(gRPC_CSHARP_VERSION "2.30.0-dev")
set(gRPC_CSHARP_SOVERSION "2")
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}")
@ -6767,10 +6767,6 @@ endif()
if(gRPC_BUILD_TESTS)
add_executable(sequential_connectivity_test
test/core/end2end/data/client_certs.cc
test/core/end2end/data/server1_cert.cc
test/core/end2end/data/server1_key.cc
test/core/end2end/data/test_root_cert.cc
test/core/surface/sequential_connectivity_test.cc
)
@ -11073,10 +11069,6 @@ endif()
if(gRPC_BUILD_TESTS)
add_executable(grpc_tls_credentials_options_test
test/core/end2end/data/client_certs.cc
test/core/end2end/data/server1_cert.cc
test/core/end2end/data/server1_key.cc
test/core/end2end/data/test_root_cert.cc
test/core/security/grpc_tls_credentials_options_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
@ -14067,10 +14059,6 @@ endif()
if(gRPC_BUILD_TESTS)
add_executable(tls_security_connector_test
test/core/end2end/data/client_certs.cc
test/core/end2end/data/server1_cert.cc
test/core/end2end/data/server1_key.cc
test/core/end2end/data/test_root_cert.cc
test/core/security/tls_security_connector_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
@ -14962,10 +14950,6 @@ endif()
if(gRPC_BUILD_TESTS)
add_executable(ssl_server_fuzzer_one_entry
test/core/end2end/data/client_certs.cc
test/core/end2end/data/server1_cert.cc
test/core/end2end/data/server1_key.cc
test/core/end2end/data/test_root_cert.cc
test/core/security/ssl_server_fuzzer.cc
test/core/util/one_corpus_entry_fuzzer.cc
third_party/googletest/googletest/src/gtest-all.cc

@ -470,8 +470,8 @@ Q = @
endif
CORE_VERSION = 10.0.0
CPP_VERSION = 1.29.0-dev
CSHARP_VERSION = 2.29.0-dev
CPP_VERSION = 1.30.0-dev
CSHARP_VERSION = 2.30.0-dev
CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@ -9999,10 +9999,6 @@ endif
SEQUENTIAL_CONNECTIVITY_TEST_SRC = \
test/core/end2end/data/client_certs.cc \
test/core/end2end/data/server1_cert.cc \
test/core/end2end/data/server1_key.cc \
test/core/end2end/data/test_root_cert.cc \
test/core/surface/sequential_connectivity_test.cc \
SEQUENTIAL_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SEQUENTIAL_CONNECTIVITY_TEST_SRC))))
@ -10023,14 +10019,6 @@ $(BINDIR)/$(CONFIG)/sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_TEST
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/surface/sequential_connectivity_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
deps_sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS:.o=.dep)
@ -14701,10 +14689,6 @@ endif
GRPC_TLS_CREDENTIALS_OPTIONS_TEST_SRC = \
test/core/end2end/data/client_certs.cc \
test/core/end2end/data/server1_cert.cc \
test/core/end2end/data/server1_key.cc \
test/core/end2end/data/test_root_cert.cc \
test/core/security/grpc_tls_credentials_options_test.cc \
GRPC_TLS_CREDENTIALS_OPTIONS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_TLS_CREDENTIALS_OPTIONS_TEST_SRC))))
@ -14736,14 +14720,6 @@ endif
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/security/grpc_tls_credentials_options_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
deps_grpc_tls_credentials_options_test: $(GRPC_TLS_CREDENTIALS_OPTIONS_TEST_OBJS:.o=.dep)
@ -17864,10 +17840,6 @@ endif
SSL_SERVER_FUZZER_SRC = \
test/core/end2end/data/client_certs.cc \
test/core/end2end/data/server1_cert.cc \
test/core/end2end/data/server1_key.cc \
test/core/end2end/data/test_root_cert.cc \
test/core/security/ssl_server_fuzzer.cc \
test/core/util/fuzzer_corpus_test.cc \
@ -17900,14 +17872,6 @@ endif
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/security/ssl_server_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/util/fuzzer_corpus_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
@ -18507,10 +18471,6 @@ endif
TLS_SECURITY_CONNECTOR_TEST_SRC = \
test/core/end2end/data/client_certs.cc \
test/core/end2end/data/server1_cert.cc \
test/core/end2end/data/server1_key.cc \
test/core/end2end/data/test_root_cert.cc \
test/core/security/tls_security_connector_test.cc \
TLS_SECURITY_CONNECTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TLS_SECURITY_CONNECTOR_TEST_SRC))))
@ -18542,14 +18502,6 @@ endif
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/security/tls_security_connector_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
deps_tls_security_connector_test: $(TLS_SECURITY_CONNECTOR_TEST_OBJS:.o=.dep)
@ -19884,10 +19836,6 @@ endif
SSL_SERVER_FUZZER_ONE_ENTRY_SRC = \
test/core/end2end/data/client_certs.cc \
test/core/end2end/data/server1_cert.cc \
test/core/end2end/data/server1_key.cc \
test/core/end2end/data/test_root_cert.cc \
test/core/security/ssl_server_fuzzer.cc \
test/core/util/one_corpus_entry_fuzzer.cc \
@ -19920,14 +19868,6 @@ endif
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/security/ssl_server_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a

@ -4086,13 +4086,8 @@ targets:
build: test
run: false
language: c
headers:
- test/core/end2end/data/ssl_test_data.h
headers: []
src:
- test/core/end2end/data/client_certs.cc
- test/core/end2end/data/server1_cert.cc
- test/core/end2end/data/server1_key.cc
- test/core/end2end/data/test_root_cert.cc
- test/core/surface/sequential_connectivity_test.cc
deps:
- grpc_test_util
@ -5989,13 +5984,8 @@ targets:
gtest: true
build: test
language: c++
headers:
- test/core/end2end/data/ssl_test_data.h
headers: []
src:
- test/core/end2end/data/client_certs.cc
- test/core/end2end/data/server1_cert.cc
- test/core/end2end/data/server1_key.cc
- test/core/end2end/data/test_root_cert.cc
- test/core/security/grpc_tls_credentials_options_test.cc
deps:
- grpc_test_util
@ -7128,13 +7118,8 @@ targets:
- name: ssl_server_fuzzer
build: fuzzer
language: c++
headers:
- test/core/end2end/data/ssl_test_data.h
headers: []
src:
- test/core/end2end/data/client_certs.cc
- test/core/end2end/data/server1_cert.cc
- test/core/end2end/data/server1_key.cc
- test/core/end2end/data/test_root_cert.cc
- test/core/security/ssl_server_fuzzer.cc
- test/core/util/fuzzer_corpus_test.cc
deps:
@ -7362,13 +7347,8 @@ targets:
gtest: true
build: test
language: c++
headers:
- test/core/end2end/data/ssl_test_data.h
headers: []
src:
- test/core/end2end/data/client_certs.cc
- test/core/end2end/data/server1_cert.cc
- test/core/end2end/data/server1_key.cc
- test/core/end2end/data/test_root_cert.cc
- test/core/security/tls_security_connector_test.cc
deps:
- grpc_test_util

@ -14,8 +14,8 @@ settings:
'#10': See the expand_version.py for all the quirks here
core_version: 10.0.0
csharp_major_version: 2
g_stands_for: gringotts
version: 1.29.0-dev
g_stands_for: gradius
version: 1.30.0-dev
targets:
- name: check_epollexclusive
build: tool

@ -28,4 +28,5 @@
- 1.26 'g' stands for ['gon'](https://github.com/grpc/grpc/tree/v1.26.x)
- 1.27 'g' stands for ['guantao'](https://github.com/grpc/grpc/tree/v1.27.x)
- 1.28 'g' stands for ['galactic'](https://github.com/grpc/grpc/tree/v1.28.x)
- 1.29 'g' stands for ['gringotts'](https://github.com/grpc/grpc/tree/master)
- 1.29 'g' stands for ['gringotts'](https://github.com/grpc/grpc/tree/v1.29.x)
- 1.30 'g' stands for ['gradius'](https://github.com/grpc/grpc/tree/master)

@ -0,0 +1,49 @@
# Copyright 2020 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
licenses(["notice"]) # 3-clause BSD
load("@grpc_python_dependencies//:requirements.bzl", "requirement")
py_binary(
name = "alts_server",
srcs = [
"alts_server.py",
"demo_pb2.py",
"demo_pb2_grpc.py",
"server.py",
],
main = "alts_server.py",
python_version = "PY3",
srcs_version = "PY2AND3",
deps = [
"//src/python/grpcio/grpc:grpcio",
],
)
py_binary(
name = "alts_client",
srcs = [
"alts_client.py",
"client.py",
"demo_pb2.py",
"demo_pb2_grpc.py",
],
main = "alts_client.py",
python_version = "PY3",
srcs_version = "PY2AND3",
deps = [
"//src/python/grpcio/grpc:grpcio",
],
)

@ -0,0 +1,39 @@
# Copyright 2020 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.
"""The example of using ALTS credentials to setup gRPC client.
The example would only successfully run in GCP environment."""
import grpc
import demo_pb2_grpc
from client import (bidirectional_streaming_method, client_streaming_method,
server_streaming_method, simple_method)
SERVER_ADDRESS = "localhost:23333"
def main():
with grpc.secure_channel(
SERVER_ADDRESS,
credentials=grpc.alts_channel_credentials()) as channel:
stub = demo_pb2_grpc.GRPCDemoStub(channel)
simple_method(stub)
client_streaming_method(stub)
server_streaming_method(stub)
bidirectional_streaming_method(stub)
if __name__ == '__main__':
main()

@ -0,0 +1,39 @@
# Copyright 2020 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.
"""The example of using ALTS credentials to setup gRPC server in python.
The example would only successfully run in GCP environment."""
from concurrent import futures
import grpc
import demo_pb2_grpc
from server import DemoServer
SERVER_ADDRESS = 'localhost:23333'
def main():
svr = grpc.server(futures.ThreadPoolExecutor())
demo_pb2_grpc.add_GRPCDemoServicer_to_server(DemoServer(), svr)
svr.add_secure_port(SERVER_ADDRESS,
server_credentials=grpc.alts_server_credentials())
print("------------------start Python GRPC server with ALTS encryption")
svr.start()
svr.wait_for_termination()
if __name__ == '__main__':
main()

@ -19,6 +19,11 @@ import grpc
import demo_pb2_grpc
import demo_pb2
__all__ = [
'simple_method', 'client_streaming_method', 'server_streaming_method',
'bidirectional_streaming_method'
]
SERVER_ADDRESS = "localhost:23333"
CLIENT_ID = 1

@ -20,6 +20,7 @@ import grpc
import demo_pb2_grpc
import demo_pb2
__all__ = 'DemoServer'
SERVER_ADDRESS = 'localhost:23333'
SERVER_ID = 1

@ -22,7 +22,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-C++'
# TODO (mxyan): use version that match gRPC version when pod is stabilized
version = '1.29.0-dev'
version = '1.30.0-dev'
s.version = version
s.summary = 'gRPC C++ library'
s.homepage = 'https://grpc.io'

@ -21,7 +21,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-Core'
version = '1.29.0-dev'
version = '1.30.0-dev'
s.version = version
s.summary = 'Core cross-platform gRPC library, written in C'
s.homepage = 'https://grpc.io'

@ -21,7 +21,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-ProtoRPC'
version = '1.29.0-dev'
version = '1.30.0-dev'
s.version = version
s.summary = 'RPC library for Protocol Buffers, based on gRPC'
s.homepage = 'https://grpc.io'

@ -21,7 +21,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-RxLibrary'
version = '1.29.0-dev'
version = '1.30.0-dev'
s.version = version
s.summary = 'Reactive Extensions library for iOS/OSX.'
s.homepage = 'https://grpc.io'

@ -20,7 +20,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
version = '1.29.0-dev'
version = '1.30.0-dev'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'https://grpc.io'

@ -7,7 +7,7 @@ Gem::Specification.new do |s|
s.name = 'grpc'
s.version = GRPC::VERSION
s.authors = ['gRPC Authors']
s.email = 'temiola@google.com'
s.email = 'grpc-io@googlegroups.com'
s.homepage = 'https://github.com/google/grpc/tree/master/src/ruby'
s.summary = 'GRPC system in Ruby'
s.description = 'Send RPCs from Ruby using GRPC'

@ -421,17 +421,12 @@ Status CallOpSendMessage::SendMessagePtr(const M* message) {
template <class R>
class CallOpRecvMessage {
public:
CallOpRecvMessage()
: got_message(false),
message_(nullptr),
allow_not_getting_message_(false) {}
void RecvMessage(R* message) { message_ = message; }
// Do not change status if no message is received.
void AllowNoMessage() { allow_not_getting_message_ = true; }
bool got_message;
bool got_message = false;
protected:
void AddOp(grpc_op* ops, size_t* nops) {
@ -444,7 +439,7 @@ class CallOpRecvMessage {
}
void FinishOp(bool* status) {
if (message_ == nullptr || hijacked_) return;
if (message_ == nullptr) return;
if (recv_buf_.Valid()) {
if (*status) {
got_message = *status =
@ -455,18 +450,24 @@ class CallOpRecvMessage {
got_message = false;
recv_buf_.Clear();
}
} else if (hijacked_) {
if (hijacked_recv_message_failed_) {
FinishOpRecvMessageFailureHandler(status);
} else {
got_message = false;
if (!allow_not_getting_message_) {
*status = false;
// The op was hijacked and it was successful. There is no further action
// to be performed since the message is already in its non-serialized
// form.
}
} else {
FinishOpRecvMessageFailureHandler(status);
}
}
void SetInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
if (message_ == nullptr) return;
interceptor_methods->SetRecvMessage(message_, &got_message);
interceptor_methods->SetRecvMessage(message_,
&hijacked_recv_message_failed_);
}
void SetFinishInterceptionHookPoint(
@ -485,10 +486,19 @@ class CallOpRecvMessage {
}
private:
R* message_;
// Sets got_message and \a status for a failed recv message op
void FinishOpRecvMessageFailureHandler(bool* status) {
got_message = false;
if (!allow_not_getting_message_) {
*status = false;
}
}
R* message_ = nullptr;
ByteBuffer recv_buf_;
bool allow_not_getting_message_;
bool allow_not_getting_message_ = false;
bool hijacked_ = false;
bool hijacked_recv_message_failed_ = false;
};
class DeserializeFunc {
@ -513,9 +523,6 @@ class DeserializeFuncType final : public DeserializeFunc {
class CallOpGenericRecvMessage {
public:
CallOpGenericRecvMessage()
: got_message(false), allow_not_getting_message_(false) {}
template <class R>
void RecvMessage(R* message) {
// Use an explicit base class pointer to avoid resolution error in the
@ -528,7 +535,7 @@ class CallOpGenericRecvMessage {
// Do not change status if no message is received.
void AllowNoMessage() { allow_not_getting_message_ = true; }
bool got_message;
bool got_message = false;
protected:
void AddOp(grpc_op* ops, size_t* nops) {
@ -551,6 +558,14 @@ class CallOpGenericRecvMessage {
got_message = false;
recv_buf_.Clear();
}
} else if (hijacked_) {
if (hijacked_recv_message_failed_) {
FinishOpRecvMessageFailureHandler(status);
} else {
// The op was hijacked and it was successful. There is no further action
// to be performed since the message is already in its non-serialized
// form.
}
} else {
got_message = false;
if (!allow_not_getting_message_) {
@ -562,7 +577,8 @@ class CallOpGenericRecvMessage {
void SetInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
if (!deserialize_) return;
interceptor_methods->SetRecvMessage(message_, &got_message);
interceptor_methods->SetRecvMessage(message_,
&hijacked_recv_message_failed_);
}
void SetFinishInterceptionHookPoint(
@ -582,11 +598,20 @@ class CallOpGenericRecvMessage {
}
private:
void* message_;
bool hijacked_ = false;
// Sets got_message and \a status for a failed recv message op
void FinishOpRecvMessageFailureHandler(bool* status) {
got_message = false;
if (!allow_not_getting_message_) {
*status = false;
}
}
void* message_ = nullptr;
std::unique_ptr<DeserializeFunc> deserialize_;
ByteBuffer recv_buf_;
bool allow_not_getting_message_;
bool allow_not_getting_message_ = false;
bool hijacked_ = false;
bool hijacked_recv_message_failed_ = false;
};
class CallOpClientSendClose {

@ -166,9 +166,9 @@ class InterceptorBatchMethodsImpl
send_trailing_metadata_ = metadata;
}
void SetRecvMessage(void* message, bool* got_message) {
void SetRecvMessage(void* message, bool* hijacked_recv_message_failed) {
recv_message_ = message;
got_message_ = got_message;
hijacked_recv_message_failed_ = hijacked_recv_message_failed;
}
void SetRecvInitialMetadata(MetadataMap* map) {
@ -195,7 +195,7 @@ class InterceptorBatchMethodsImpl
void FailHijackedRecvMessage() override {
GPR_CODEGEN_ASSERT(hooks_[static_cast<size_t>(
experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)]);
*got_message_ = false;
*hijacked_recv_message_failed_ = true;
}
// Clears all state
@ -407,7 +407,7 @@ class InterceptorBatchMethodsImpl
std::multimap<grpc::string, grpc::string>* send_trailing_metadata_ = nullptr;
void* recv_message_ = nullptr;
bool* got_message_ = nullptr;
bool* hijacked_recv_message_failed_ = nullptr;
MetadataMap* recv_initial_metadata_ = nullptr;

@ -13,8 +13,8 @@
<date>2019-09-24</date>
<time>16:06:07</time>
<version>
<release>1.29.0dev</release>
<api>1.29.0dev</api>
<release>1.30.0dev</release>
<api>1.30.0dev</api>
</version>
<stability>
<release>beta</release>
@ -22,7 +22,7 @@
</stability>
<license>Apache 2.0</license>
<notes>
- gRPC Core 1.29.0 update
- gRPC Core 1.30.0 update
</notes>
<contents>
<dir baseinstalldir="/" name="/">

@ -278,19 +278,29 @@ void WeightedTargetLb::UpdateLocked(UpdateArgs args) {
child->DeactivateLocked();
}
}
// Add or update the targets in the new config.
HierarchicalAddressMap address_map =
MakeHierarchicalAddressMap(args.addresses);
// Create any children that don't already exist.
// Note that we add all children before updating any of them, because
// an update may trigger a child to immediately update its
// connectivity state (e.g., reporting TRANSIENT_FAILURE immediately when
// receiving an empty address list), and we don't want to return an
// overall state with incomplete data.
for (const auto& p : config_->target_map()) {
const std::string& name = p.first;
const WeightedTargetLbConfig::ChildConfig& config = p.second;
auto it = targets_.find(name);
if (it == targets_.end()) {
it = targets_.emplace(std::make_pair(name, nullptr)).first;
it->second = MakeOrphanable<WeightedChild>(
Ref(DEBUG_LOCATION, "WeightedChild"), it->first);
}
it->second->UpdateLocked(config, std::move(address_map[name]), args.args);
}
// Update all children.
HierarchicalAddressMap address_map =
MakeHierarchicalAddressMap(args.addresses);
for (const auto& p : config_->target_map()) {
const std::string& name = p.first;
const WeightedTargetLbConfig::ChildConfig& config = p.second;
targets_[name]->UpdateLocked(config, std::move(address_map[name]),
args.args);
}
}

@ -1145,7 +1145,7 @@ grpc_error* LdsResponseParse(XdsClient* client, TraceFlag* tracer,
envoy_api_v2_Listener_api_listener(listener);
if (api_listener == nullptr) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Listener doesn't have ApiListener.");
"Listener has no ApiListener.");
}
const upb_strview encoded_api_listener = google_protobuf_Any_value(
envoy_config_listener_v2_ApiListener_api_listener(api_listener));
@ -1174,10 +1174,22 @@ grpc_error* LdsResponseParse(XdsClient* client, TraceFlag* tracer,
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"HttpConnectionManager neither has inlined route_config nor RDS.");
}
// Get the route_config_name.
const envoy_config_filter_network_http_connection_manager_v2_Rds* rds =
envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_rds(
http_connection_manager);
// Check that the ConfigSource specifies ADS.
const envoy_api_v2_core_ConfigSource* config_source =
envoy_config_filter_network_http_connection_manager_v2_Rds_config_source(
rds);
if (config_source == nullptr) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"HttpConnectionManager missing config_source for RDS.");
}
if (!envoy_api_v2_core_ConfigSource_has_ads(config_source)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"HttpConnectionManager ConfigSource for RDS does not specify ADS.");
}
// Get the route_config_name.
const upb_strview route_config_name =
envoy_config_filter_network_http_connection_manager_v2_Rds_route_config_name(
rds);
@ -1278,7 +1290,8 @@ grpc_error* CdsResponseParse(
const envoy_api_v2_core_ConfigSource* eds_config =
envoy_api_v2_Cluster_EdsClusterConfig_eds_config(eds_cluster_config);
if (!envoy_api_v2_core_ConfigSource_has_ads(eds_config)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("ConfigSource is not ADS.");
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"EDS ConfigSource is not ADS.");
}
// Record EDS service_name (if any).
upb_strview service_name =
@ -1299,7 +1312,7 @@ grpc_error* CdsResponseParse(
if (lrs_server != nullptr) {
if (!envoy_api_v2_core_ConfigSource_has_self(lrs_server)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"ConfigSource is not self.");
"LRS ConfigSource is not self.");
}
cds_update.lrs_load_reporting_server_name.emplace("");
}

@ -254,6 +254,10 @@ gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) {
return gpr_time_add(gpr_now(clock_type), t);
}
// If the given input hits this code, the same result is not guaranteed for
// the same input because it relies on `gpr_now` to calculate the difference
// between two different clocks. Please be careful when you want to use this
// function in unit tests. (e.g. https://github.com/grpc/grpc/pull/22655)
return gpr_time_add(gpr_now(clock_type),
gpr_time_sub(t, gpr_now(t.clock_type)));
}

@ -25,7 +25,7 @@
/// platforms), the users can disable CFStream with environment variable
/// "grpc_cfstream=0". This will let gRPC to fallback to use POSIX sockets. In
/// addition, the users may choose to use an alternative CFRunLoop based pollset
/// "ev_apple" by setting environment variable "grpc_cfstream_run_loop=1". This
/// "ev_apple" by setting environment variable "GRPC_CFSTREAM_RUN_LOOP=1". This
/// pollset resolves a bug from Apple when CFStream streams dispatch events to
/// dispatch queues. The caveat of this pollset is that users may not be able to
/// run a gRPC server in the same process.

@ -25,4 +25,4 @@
const char* grpc_version_string(void) { return "10.0.0"; }
const char* grpc_g_stands_for(void) { return "gringotts"; }
const char* grpc_g_stands_for(void) { return "gradius"; }

@ -22,5 +22,5 @@
#include <grpcpp/grpcpp.h>
namespace grpc {
grpc::string Version() { return "1.29.0-dev"; }
grpc::string Version() { return "1.30.0-dev"; }
} // namespace grpc

@ -33,11 +33,11 @@ namespace Grpc.Core
/// <summary>
/// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
/// </summary>
public const string CurrentAssemblyFileVersion = "2.29.0.0";
public const string CurrentAssemblyFileVersion = "2.30.0.0";
/// <summary>
/// Current version of gRPC C#
/// </summary>
public const string CurrentVersion = "2.29.0-dev";
public const string CurrentVersion = "2.30.0-dev";
}
}

@ -1,7 +1,7 @@
<!-- This file is generated -->
<Project>
<PropertyGroup>
<GrpcCsharpVersion>2.29.0-dev</GrpcCsharpVersion>
<GrpcCsharpVersion>2.30.0-dev</GrpcCsharpVersion>
<GoogleProtobufVersion>3.11.4</GoogleProtobufVersion>
</PropertyGroup>
</Project>

@ -13,7 +13,7 @@
@rem limitations under the License.
@rem Current package versions
set VERSION=2.29.0-dev
set VERSION=2.30.0-dev
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe

@ -42,7 +42,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-gRPCCppPlugin'
v = '1.29.0-dev'
v = '1.30.0-dev'
s.version = v
s.summary = 'The gRPC ProtoC plugin generates C++ files from .proto services.'
s.description = <<-DESC

@ -42,7 +42,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-gRPCPlugin'
v = '1.29.0-dev'
v = '1.30.0-dev'
s.version = v
s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
s.description = <<-DESC

@ -22,4 +22,4 @@
// instead. This file can be regenerated from the template by running
// `tools/buildgen/generate_projects.sh`.
#define GRPC_OBJC_VERSION_STRING @"1.29.0-dev"
#define GRPC_OBJC_VERSION_STRING @"1.30.0-dev"

@ -23,8 +23,18 @@ platforms, you can turn it on with macro `GRPC_CFSTREAM=1` for the pod 'gRPC-Cor
case of problem and you want to disable CFStream on iOS, you can set environment variable
"grpc\_cfstream=0".
## Caveats
It is known to us that the CFStream API has some bug (FB6162039) which will cause gRPC's CFStream
networking layer to stall occasionally. The issue mostly occur on MacOS systems (including iOS
simulators on MacOS); iOS may be affected too but we have not seen issue there. gRPC provides a
workaround to this problem with an alternative poller based on CFRunLoop. The poller can be enabled
by setting environment variable `GRPC_CFSTREAM_RUN_LOOP=1`. Note that the poller is a client side
only poller that does not support running a server on it. That means if an app opts in to the
CFRunLoop-based poller, the app cannot host a gRPC server (gRPC Objective-C does not support running
a server but other languages running on iOS do support it).
## Notes
- Currently we do not support platforms other than iOS, although it is likely that this integration
can run on MacOS targets with Apple's compiler.
- Let us know if you meet any issue by filing issue and ping @muxi.
- Let us know if you meet any issue by filing issue and ping @stanleycheung.

@ -22,5 +22,5 @@
// instead. This file can be regenerated from the template by running
// `tools/buildgen/generate_projects.sh`.
#define GRPC_OBJC_VERSION_STRING @"1.29.0-dev"
#define GRPC_OBJC_VERSION_STRING @"1.30.0-dev"
#define GRPC_C_VERSION_STRING @"10.0.0"

@ -2,7 +2,7 @@
"name": "grpc/grpc-dev",
"description": "gRPC library for PHP - for Development use only",
"license": "Apache-2.0",
"version": "1.29.0",
"version": "1.30.0",
"require": {
"php": ">=5.5.0",
"google/protobuf": "^v3.3.0"

@ -20,6 +20,6 @@
#ifndef VERSION_H
#define VERSION_H
#define PHP_GRPC_VERSION "1.29.0dev"
#define PHP_GRPC_VERSION "1.30.0dev"
#endif /* VERSION_H */

@ -1833,6 +1833,41 @@ def local_server_credentials(local_connect_type=LocalConnectionType.LOCAL_TCP):
_cygrpc.server_credentials_local(local_connect_type.value))
def alts_channel_credentials(service_accounts=None):
"""Creates a ChannelCredentials for use with an ALTS-enabled Channel.
This is an EXPERIMENTAL API.
ALTS credentials API can only be used in GCP environment as it relies on
handshaker service being available. For more info about ALTS see
https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security
Args:
service_accounts: A list of server identities accepted by the client.
If target service accounts are provided and none of them matches the
peer identity of the server, handshake will fail. The arg can be empty
if the client does not have any information about trusted server
identity.
Returns:
A ChannelCredentials for use with an ALTS-enabled Channel
"""
return ChannelCredentials(
_cygrpc.channel_credentials_alts(service_accounts or []))
def alts_server_credentials():
"""Creates a ServerCredentials for use with an ALTS-enabled connection.
This is an EXPERIMENTAL API.
ALTS credentials API can only be used in GCP environment as it relies on
handshaker service being available. For more info about ALTS see
https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security
Returns:
A ServerCredentials for use with an ALTS-enabled Server
"""
return ServerCredentials(_cygrpc.server_credentials_alts())
def channel_ready_future(channel):
"""Creates a Future that tracks when a Channel is ready.
@ -2036,6 +2071,8 @@ __all__ = (
'composite_channel_credentials',
'local_channel_credentials',
'local_server_credentials',
'alts_channel_credentials',
'alts_server_credentials',
'ssl_server_credentials',
'ssl_server_certificate_configuration',
'dynamic_ssl_server_credentials',

@ -112,3 +112,56 @@ def schedule_coro_threadsafe(object coro, object loop):
)
else:
raise
def async_generator_to_generator(object agen, object loop):
"""Converts an async generator into generator."""
try:
while True:
future = asyncio.run_coroutine_threadsafe(
agen.__anext__(),
loop
)
response = future.result()
if response is EOF:
break
else:
yield response
except StopAsyncIteration:
# If StopAsyncIteration is raised, end this generator.
pass
async def generator_to_async_generator(object gen, object loop, object thread_pool):
"""Converts a generator into async generator.
The generator might block, so we need to delegate the iteration to thread
pool. Also, we can't simply delegate __next__ to the thread pool, otherwise
we will see following error:
TypeError: StopIteration interacts badly with generators and cannot be
raised into a Future
"""
queue = asyncio.Queue(maxsize=1, loop=loop)
def yield_to_queue():
try:
for item in gen:
asyncio.run_coroutine_threadsafe(queue.put(item), loop).result()
finally:
asyncio.run_coroutine_threadsafe(queue.put(EOF), loop).result()
future = loop.run_in_executor(
thread_pool,
yield_to_queue,
)
while True:
response = await queue.get()
if response is EOF:
break
else:
yield response
# Port the exception if there is any
await future

@ -48,6 +48,12 @@ cdef class _ServicerContext:
cdef object _response_serializer # Callable[[Any], bytes]
cdef class _SyncServicerContext:
cdef _ServicerContext _context
cdef list _callbacks
cdef object _loop # asyncio.AbstractEventLoop
cdef class _MessageReceiver:
cdef _ServicerContext _servicer_context
cdef object _agen
@ -71,5 +77,7 @@ cdef class AioServer:
cdef object _shutdown_completed # asyncio.Future
cdef CallbackWrapper _shutdown_callback_wrapper
cdef object _crash_exception # Exception
cdef set _ongoing_rpc_tasks
cdef tuple _interceptors
cdef object _thread_pool # concurrent.futures.ThreadPoolExecutor
cdef thread_pool(self)

@ -211,6 +211,53 @@ cdef class _ServicerContext:
self._rpc_state.disable_next_compression = True
cdef class _SyncServicerContext:
"""Sync servicer context for sync handler compatibility."""
def __cinit__(self,
_ServicerContext context):
self._context = context
self._callbacks = []
self._loop = context._loop
def abort(self,
object code,
str details='',
tuple trailing_metadata=_IMMUTABLE_EMPTY_METADATA):
future = asyncio.run_coroutine_threadsafe(
self._context.abort(code, details, trailing_metadata),
self._loop)
# Abort should raise an AbortError
future.exception()
def send_initial_metadata(self, tuple metadata):
future = asyncio.run_coroutine_threadsafe(
self._context.send_initial_metadata(metadata),
self._loop)
future.result()
def set_trailing_metadata(self, tuple metadata):
self._context.set_trailing_metadata(metadata)
def invocation_metadata(self):
return self._context.invocation_metadata()
def set_code(self, object code):
self._context.set_code(code)
def set_details(self, str details):
self._context.set_details(details)
def set_compression(self, object compression):
self._context.set_compression(compression)
def disable_next_message_compression(self):
self._context.disable_next_message_compression()
def add_callback(self, object callback):
self._callbacks.append(callback)
async def _run_interceptor(object interceptors, object query_handler,
object handler_call_details):
interceptor = next(interceptors, None)
@ -222,6 +269,11 @@ async def _run_interceptor(object interceptors, object query_handler,
return query_handler(handler_call_details)
def _is_async_handler(object handler):
"""Inspect if a method handler is async or sync."""
return inspect.isawaitable(handler) or inspect.iscoroutinefunction(handler) or inspect.isasyncgenfunction(handler)
async def _find_method_handler(str method, tuple metadata, list generic_handlers,
tuple interceptors):
def query_handlers(handler_call_details):
@ -254,11 +306,27 @@ async def _finish_handler_with_unary_response(RPCState rpc_state,
stream-unary handlers.
"""
# Executes application logic
cdef object response_message
cdef _SyncServicerContext sync_servicer_context
cdef object response_message = await unary_handler(
if _is_async_handler(unary_handler):
# Run async method handlers in this coroutine
response_message = await unary_handler(
request,
servicer_context,
)
else:
# Run sync method handlers in the thread pool
sync_servicer_context = _SyncServicerContext(servicer_context)
response_message = await loop.run_in_executor(
rpc_state.server.thread_pool(),
unary_handler,
request,
sync_servicer_context,
)
# Support sync-stack callback
for callback in sync_servicer_context._callbacks:
callback()
# Raises exception if aborted
rpc_state.raise_for_termination()
@ -307,18 +375,31 @@ async def _finish_handler_with_stream_responses(RPCState rpc_state,
"""
cdef object async_response_generator
cdef object response_message
if inspect.iscoroutinefunction(stream_handler):
# Case 1: Coroutine async handler - using reader-writer API
# The handler uses reader / writer API, returns None.
await stream_handler(
request,
servicer_context,
)
else:
if inspect.isasyncgenfunction(stream_handler):
# Case 2: Async handler - async generator
# The handler uses async generator API
async_response_generator = stream_handler(
request,
servicer_context,
)
else:
# Case 3: Sync handler - normal generator
# NOTE(lidiz) Streaming handler in sync stack is either a generator
# function or a function returns a generator.
sync_servicer_context = _SyncServicerContext(servicer_context)
gen = stream_handler(request, sync_servicer_context)
async_response_generator = generator_to_async_generator(gen,
loop,
rpc_state.server.thread_pool())
# Consumes messages from the generator
async for response_message in async_response_generator:
@ -438,6 +519,9 @@ cdef class _MessageReceiver:
self._agen = self._async_message_receiver()
return self._agen
async def __anext__(self):
return await self.__aiter__().__anext__()
async def _handle_stream_unary_rpc(object method_handler,
RPCState rpc_state,
@ -451,13 +535,20 @@ async def _handle_stream_unary_rpc(object method_handler,
)
# Prepares the request generator
cdef object request_async_iterator = _MessageReceiver(servicer_context)
cdef object request_iterator
if _is_async_handler(method_handler.stream_unary):
request_iterator = _MessageReceiver(servicer_context)
else:
request_iterator = async_generator_to_generator(
_MessageReceiver(servicer_context),
loop
)
# Finishes the application handler
await _finish_handler_with_unary_response(
rpc_state,
method_handler.stream_unary,
request_async_iterator,
request_iterator,
servicer_context,
method_handler.response_serializer,
loop
@ -476,13 +567,20 @@ async def _handle_stream_stream_rpc(object method_handler,
)
# Prepares the request generator
cdef object request_async_iterator = _MessageReceiver(servicer_context)
cdef object request_iterator
if _is_async_handler(method_handler.stream_stream):
request_iterator = _MessageReceiver(servicer_context)
else:
request_iterator = async_generator_to_generator(
_MessageReceiver(servicer_context),
loop
)
# Finishes the application handler
await _finish_handler_with_stream_responses(
rpc_state,
method_handler.stream_stream,
request_async_iterator,
request_iterator,
servicer_context,
loop,
)
@ -648,7 +746,6 @@ cdef class AioServer:
self._generic_handlers = []
self.add_generic_rpc_handlers(generic_handlers)
self._serving_task = None
self._ongoing_rpc_tasks = set()
self._shutdown_lock = asyncio.Lock(loop=self._loop)
self._shutdown_completed = self._loop.create_future()
@ -658,17 +755,18 @@ cdef class AioServer:
SERVER_SHUTDOWN_FAILURE_HANDLER)
self._crash_exception = None
self._interceptors = ()
if interceptors:
self._interceptors = interceptors
else:
self._interceptors = ()
self._thread_pool = thread_pool
if maximum_concurrent_rpcs:
raise NotImplementedError()
if thread_pool:
raise NotImplementedError()
def add_generic_rpc_handlers(self, generic_rpc_handlers):
for h in generic_rpc_handlers:
self._generic_handlers.append(h)
def add_generic_rpc_handlers(self, object generic_rpc_handlers):
self._generic_handlers.extend(generic_rpc_handlers)
def add_insecure_port(self, address):
return self._server.add_http2_port(address)
@ -846,3 +944,7 @@ cdef class AioServer:
self._status
)
shutdown_grpc_aio()
cdef thread_pool(self):
"""Access the thread pool instance."""
return self._thread_pool

@ -102,3 +102,9 @@ cdef class ServerCredentials:
cdef class LocalChannelCredentials(ChannelCredentials):
cdef grpc_local_connect_type _local_connect_type
cdef class ALTSChannelCredentials(ChannelCredentials):
cdef grpc_alts_credentials_options *c_options
cdef grpc_channel_credentials *c(self) except *

@ -351,3 +351,32 @@ def server_credentials_local(grpc_local_connect_type local_connect_type):
cdef ServerCredentials credentials = ServerCredentials()
credentials.c_credentials = grpc_local_server_credentials_create(local_connect_type)
return credentials
cdef class ALTSChannelCredentials(ChannelCredentials):
def __cinit__(self, list service_accounts):
self.c_options = grpc_alts_credentials_client_options_create()
cdef str account
for account in service_accounts:
grpc_alts_credentials_client_options_add_target_service_account(self.c_options, account)
def __dealloc__(self):
if self.c_options != NULL:
grpc_alts_credentials_options_destroy(self.c_options)
cdef grpc_channel_credentials *c(self) except *:
return grpc_alts_credentials_create(self.c_options)
def channel_credentials_alts(list service_accounts):
return ALTSChannelCredentials(service_accounts)
def server_credentials_alts():
cdef ServerCredentials credentials = ServerCredentials()
cdef grpc_alts_credentials_options* c_options = grpc_alts_credentials_server_options_create()
credentials.c_credentials = grpc_alts_server_credentials_create(c_options)
# Options can be destroyed as deep copy was performed.
grpc_alts_credentials_options_destroy(c_options)
return credentials

@ -606,6 +606,21 @@ cdef extern from "grpc/grpc_security.h":
grpc_server_credentials *grpc_local_server_credentials_create(
grpc_local_connect_type type)
ctypedef struct grpc_alts_credentials_options:
# We don't care about the internals (and in fact don't know them)
pass
grpc_channel_credentials *grpc_alts_credentials_create(
const grpc_alts_credentials_options *options)
grpc_server_credentials *grpc_alts_server_credentials_create(
const grpc_alts_credentials_options *options)
grpc_alts_credentials_options* grpc_alts_credentials_client_options_create()
grpc_alts_credentials_options* grpc_alts_credentials_server_options_create()
void grpc_alts_credentials_options_destroy(grpc_alts_credentials_options *options)
void grpc_alts_credentials_client_options_add_target_service_account(grpc_alts_credentials_options *options, const char *service_account)
cdef extern from "grpc/compression.h":

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!!
__version__ = """1.29.0.dev0"""
__version__ = """1.30.0.dev0"""

@ -33,7 +33,8 @@ from ._call import AioRpcError
from ._interceptor import (ClientCallDetails, ClientInterceptor,
InterceptedUnaryUnaryCall,
UnaryUnaryClientInterceptor,
UnaryStreamClientInterceptor, ServerInterceptor)
UnaryStreamClientInterceptor,
StreamUnaryClientInterceptor, ServerInterceptor)
from ._server import server
from ._base_server import Server, ServicerContext
from ._typing import ChannelArgumentType
@ -61,6 +62,7 @@ __all__ = (
'ClientInterceptor',
'UnaryStreamClientInterceptor',
'UnaryUnaryClientInterceptor',
'StreamUnaryClientInterceptor',
'InterceptedUnaryUnaryCall',
'ServerInterceptor',
'insecure_channel',

@ -35,6 +35,7 @@ _LOCAL_CANCELLATION_DETAILS = 'Locally cancelled by application!'
_GC_CANCELLATION_DETAILS = 'Cancelled upon garbage collection!'
_RPC_ALREADY_FINISHED_DETAILS = 'RPC already finished.'
_RPC_HALF_CLOSED_DETAILS = 'RPC is half closed after calling "done_writing".'
_API_STYLE_ERROR = 'The iterator and read/write APIs may not be mixed on a single RPC.'
_OK_CALL_REPRESENTATION = ('<{} of RPC that terminated with:\n'
'\tstatus = {}\n'
@ -302,8 +303,7 @@ class _StreamResponseMixin(Call):
if self._response_style is _APIStyle.UNKNOWN:
self._response_style = style
elif self._response_style is not style:
raise cygrpc.UsageError(
'Please don\'t mix two styles of API for streaming responses')
raise cygrpc.UsageError(_API_STYLE_ERROR)
def cancel(self) -> bool:
if super().cancel():
@ -381,8 +381,7 @@ class _StreamRequestMixin(Call):
def _raise_for_different_style(self, style: _APIStyle):
if self._request_style is not style:
raise cygrpc.UsageError(
'Please don\'t mix two styles of API for streaming requests')
raise cygrpc.UsageError(_API_STYLE_ERROR)
def cancel(self) -> bool:
if super().cancel():
@ -399,7 +398,8 @@ class _StreamRequestMixin(Call):
request_iterator: RequestIterableType
) -> None:
try:
if inspect.isasyncgen(request_iterator):
if inspect.isasyncgen(request_iterator) or hasattr(
request_iterator, '__aiter__'):
async for request in request_iterator:
await self._write(request)
else:
@ -426,7 +426,6 @@ class _StreamRequestMixin(Call):
serialized_request = _common.serialize(request,
self._request_serializer)
try:
await self._cython_call.send_serialized_message(serialized_request)
except asyncio.CancelledError:

@ -25,9 +25,11 @@ from . import _base_call, _base_channel
from ._call import (StreamStreamCall, StreamUnaryCall, UnaryStreamCall,
UnaryUnaryCall)
from ._interceptor import (InterceptedUnaryUnaryCall,
InterceptedUnaryStreamCall, ClientInterceptor,
InterceptedUnaryStreamCall,
InterceptedStreamUnaryCall, ClientInterceptor,
UnaryUnaryClientInterceptor,
UnaryStreamClientInterceptor)
UnaryStreamClientInterceptor,
StreamUnaryClientInterceptor)
from ._typing import (ChannelArgumentType, DeserializingFunction, MetadataType,
SerializingFunction, RequestIterableType)
from ._utils import _timeout_to_deadline
@ -167,10 +169,17 @@ class StreamUnaryMultiCallable(_BaseMultiCallable,
deadline = _timeout_to_deadline(timeout)
if not self._interceptors:
call = StreamUnaryCall(request_iterator, deadline, metadata,
credentials, wait_for_ready, self._channel,
self._method, self._request_serializer,
self._response_deserializer, self._loop)
else:
call = InterceptedStreamUnaryCall(
self._interceptors, request_iterator, deadline, metadata,
credentials, wait_for_ready, self._channel, self._method,
self._request_serializer, self._response_deserializer,
self._loop)
return call
@ -204,6 +213,7 @@ class Channel(_base_channel.Channel):
_channel: cygrpc.AioChannel
_unary_unary_interceptors: List[UnaryUnaryClientInterceptor]
_unary_stream_interceptors: List[UnaryStreamClientInterceptor]
_stream_unary_interceptors: List[StreamUnaryClientInterceptor]
def __init__(self, target: str, options: ChannelArgumentType,
credentials: Optional[grpc.ChannelCredentials],
@ -222,12 +232,15 @@ class Channel(_base_channel.Channel):
"""
self._unary_unary_interceptors = []
self._unary_stream_interceptors = []
self._stream_unary_interceptors = []
if interceptors:
attrs_and_interceptor_classes = ((self._unary_unary_interceptors,
UnaryUnaryClientInterceptor),
(self._unary_stream_interceptors,
UnaryStreamClientInterceptor))
UnaryStreamClientInterceptor),
(self._stream_unary_interceptors,
StreamUnaryClientInterceptor))
# pylint: disable=cell-var-from-loop
for attr, interceptor_class in attrs_and_interceptor_classes:
@ -238,14 +251,17 @@ class Channel(_base_channel.Channel):
invalid_interceptors = set(interceptors) - set(
self._unary_unary_interceptors) - set(
self._unary_stream_interceptors)
self._unary_stream_interceptors) - set(
self._stream_unary_interceptors)
if invalid_interceptors:
raise ValueError(
"Interceptor must be "+\
"UnaryUnaryClientInterceptors or "+\
"UnaryStreamClientInterceptors. The following are invalid: {}"\
.format(invalid_interceptors))
"Interceptor must be " +
"{} or ".format(UnaryUnaryClientInterceptor.__name__) +
"{} or ".format(UnaryStreamClientInterceptor.__name__) +
"{}. ".format(StreamUnaryClientInterceptor.__name__) +
"The following are invalid: {}".format(invalid_interceptors)
)
self._loop = asyncio.get_event_loop()
self._channel = cygrpc.AioChannel(
@ -383,7 +399,9 @@ class Channel(_base_channel.Channel):
) -> StreamUnaryMultiCallable:
return StreamUnaryMultiCallable(self._channel, _common.encode(method),
request_serializer,
response_deserializer, None, self._loop)
response_deserializer,
self._stream_unary_interceptors,
self._loop)
def stream_stream(
self,

@ -22,10 +22,13 @@ import grpc
from grpc._cython import cygrpc
from . import _base_call
from ._call import UnaryUnaryCall, UnaryStreamCall, AioRpcError
from ._call import UnaryUnaryCall, UnaryStreamCall, StreamUnaryCall, AioRpcError
from ._call import _RPC_ALREADY_FINISHED_DETAILS, _RPC_HALF_CLOSED_DETAILS
from ._call import _API_STYLE_ERROR
from ._utils import _timeout_to_deadline
from ._typing import (RequestType, SerializingFunction, DeserializingFunction,
MetadataType, ResponseType, DoneCallbackType)
MetadataType, ResponseType, DoneCallbackType,
RequestIterableType)
_LOCAL_CANCELLATION_DETAILS = 'Locally cancelled by application!'
@ -101,7 +104,7 @@ class UnaryUnaryClientInterceptor(ClientInterceptor, metaclass=ABCMeta):
Args:
continuation: A coroutine that proceeds with the invocation by
executing the next interceptor in chain or invoking the
executing the next interceptor in the chain or invoking the
actual RPC on the underlying Channel. It is the interceptor's
responsibility to call it if it decides to move the RPC forward.
The interceptor can use
@ -132,13 +135,17 @@ class UnaryStreamClientInterceptor(ClientInterceptor, metaclass=ABCMeta):
) -> Union[AsyncIterable[ResponseType], UnaryStreamCall]:
"""Intercepts a unary-stream invocation asynchronously.
The function could return the call object or an asynchronous
iterator, in case of being an asyncrhonous iterator this will
become the source of the reads done by the caller.
Args:
continuation: A coroutine that proceeds with the invocation by
executing the next interceptor in chain or invoking the
executing the next interceptor in the chain or invoking the
actual RPC on the underlying Channel. It is the interceptor's
responsibility to call it if it decides to move the RPC forward.
The interceptor can use
`call = await continuation(client_call_details, request, response_iterator))`
`call = await continuation(client_call_details, request)`
to continue with the RPC. `continuation` returns the call to the
RPC.
client_call_details: A ClientCallDetails object describing the
@ -154,6 +161,47 @@ class UnaryStreamClientInterceptor(ClientInterceptor, metaclass=ABCMeta):
"""
class StreamUnaryClientInterceptor(ClientInterceptor, metaclass=ABCMeta):
"""Affords intercepting stream-unary invocations."""
@abstractmethod
async def intercept_stream_unary(
self,
continuation: Callable[[ClientCallDetails, RequestType],
UnaryStreamCall],
client_call_details: ClientCallDetails,
request_iterator: RequestIterableType,
) -> StreamUnaryCall:
"""Intercepts a stream-unary invocation asynchronously.
Within the interceptor the usage of the call methods like `write` or
even awaiting the call should be done carefully, since the caller
could be expecting an untouched call, for example for start writing
messages to it.
Args:
continuation: A coroutine that proceeds with the invocation by
executing the next interceptor in the chain or invoking the
actual RPC on the underlying Channel. It is the interceptor's
responsibility to call it if it decides to move the RPC forward.
The interceptor can use
`call = await continuation(client_call_details, request_iterator)`
to continue with the RPC. `continuation` returns the call to the
RPC.
client_call_details: A ClientCallDetails object describing the
outgoing RPC.
request_iterator: The request iterator that will produce requests
for the RPC.
Returns:
The RPC Call.
Raises:
AioRpcError: Indicating that the RPC terminated with non-OK status.
asyncio.CancelledError: Indicating that the RPC was canceled.
"""
class InterceptedCall:
"""Base implementation for all intecepted call arities.
@ -332,7 +380,16 @@ class InterceptedCall:
return await call.wait_for_connection()
class InterceptedUnaryUnaryCall(InterceptedCall, _base_call.UnaryUnaryCall):
class _InterceptedUnaryResponseMixin:
def __await__(self):
call = yield from self._interceptors_task.__await__()
response = yield from call.__await__()
return response
class InterceptedUnaryUnaryCall(_InterceptedUnaryResponseMixin, InterceptedCall,
_base_call.UnaryUnaryCall):
"""Used for running a `UnaryUnaryCall` wrapped by interceptors.
For the `__await__` method is it is proxied to the intercepted call only when
@ -402,11 +459,6 @@ class InterceptedUnaryUnaryCall(InterceptedCall, _base_call.UnaryUnaryCall):
return await _run_interceptor(iter(interceptors), client_call_details,
request)
def __await__(self):
call = yield from self._interceptors_task.__await__()
response = yield from call.__await__()
return response
def time_remaining(self) -> Optional[float]:
raise NotImplementedError()
@ -504,6 +556,149 @@ class InterceptedUnaryStreamCall(InterceptedCall, _base_call.UnaryStreamCall):
raise NotImplementedError()
class InterceptedStreamUnaryCall(_InterceptedUnaryResponseMixin,
InterceptedCall, _base_call.StreamUnaryCall):
"""Used for running a `StreamUnaryCall` wrapped by interceptors.
For the `__await__` method is it is proxied to the intercepted call only when
the interceptor task is finished.
"""
_loop: asyncio.AbstractEventLoop
_channel: cygrpc.AioChannel
_write_to_iterator_async_gen: Optional[AsyncIterable[RequestType]]
_write_to_iterator_queue: Optional[asyncio.Queue]
_FINISH_ITERATOR_SENTINEL = object()
# pylint: disable=too-many-arguments
def __init__(self, interceptors: Sequence[StreamUnaryClientInterceptor],
request_iterator: Optional[RequestIterableType],
timeout: Optional[float], metadata: MetadataType,
credentials: Optional[grpc.CallCredentials],
wait_for_ready: Optional[bool], channel: cygrpc.AioChannel,
method: bytes, request_serializer: SerializingFunction,
response_deserializer: DeserializingFunction,
loop: asyncio.AbstractEventLoop) -> None:
self._loop = loop
self._channel = channel
if request_iterator is None:
# We provide our own request iterator which is a proxy
# of the futures writes that will be done by the caller.
self._write_to_iterator_queue = asyncio.Queue(maxsize=1)
self._write_to_iterator_async_gen = self._proxy_writes_as_request_iterator(
)
request_iterator = self._write_to_iterator_async_gen
else:
self._write_to_iterator_queue = None
interceptors_task = loop.create_task(
self._invoke(interceptors, method, timeout, metadata, credentials,
wait_for_ready, request_iterator, request_serializer,
response_deserializer))
super().__init__(interceptors_task)
# pylint: disable=too-many-arguments
async def _invoke(
self, interceptors: Sequence[StreamUnaryClientInterceptor],
method: bytes, timeout: Optional[float],
metadata: Optional[MetadataType],
credentials: Optional[grpc.CallCredentials],
wait_for_ready: Optional[bool],
request_iterator: RequestIterableType,
request_serializer: SerializingFunction,
response_deserializer: DeserializingFunction) -> StreamUnaryCall:
"""Run the RPC call wrapped in interceptors"""
async def _run_interceptor(
interceptors: Iterator[UnaryUnaryClientInterceptor],
client_call_details: ClientCallDetails,
request_iterator: RequestIterableType
) -> _base_call.StreamUnaryCall:
interceptor = next(interceptors, None)
if interceptor:
continuation = functools.partial(_run_interceptor, interceptors)
return await interceptor.intercept_stream_unary(
continuation, client_call_details, request_iterator)
else:
return StreamUnaryCall(
request_iterator,
_timeout_to_deadline(client_call_details.timeout),
client_call_details.metadata,
client_call_details.credentials,
client_call_details.wait_for_ready, self._channel,
client_call_details.method, request_serializer,
response_deserializer, self._loop)
client_call_details = ClientCallDetails(method, timeout, metadata,
credentials, wait_for_ready)
return await _run_interceptor(iter(interceptors), client_call_details,
request_iterator)
def time_remaining(self) -> Optional[float]:
raise NotImplementedError()
async def _proxy_writes_as_request_iterator(self):
await self._interceptors_task
while True:
value = await self._write_to_iterator_queue.get()
if value is InterceptedStreamUnaryCall._FINISH_ITERATOR_SENTINEL:
break
yield value
async def write(self, request: RequestType) -> None:
# If no queue was created it means that requests
# should be expected through an iterators provided
# by the caller.
if self._write_to_iterator_queue is None:
raise cygrpc.UsageError(_API_STYLE_ERROR)
try:
call = await self._interceptors_task
except (asyncio.CancelledError, AioRpcError):
raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
if call.done():
raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
elif call._done_writing_flag:
raise asyncio.InvalidStateError(_RPC_HALF_CLOSED_DETAILS)
# Write might never end up since the call could abrubtly finish,
# we give up on the first awaitable object that finishes..
_, _ = await asyncio.wait(
(self._write_to_iterator_queue.put(request), call),
return_when=asyncio.FIRST_COMPLETED)
if call.done():
raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
async def done_writing(self) -> None:
"""Signal peer that client is done writing.
This method is idempotent.
"""
# If no queue was created it means that requests
# should be expected through an iterators provided
# by the caller.
if self._write_to_iterator_queue is None:
raise cygrpc.UsageError(_API_STYLE_ERROR)
try:
call = await self._interceptors_task
except asyncio.CancelledError:
raise asyncio.InvalidStateError(_RPC_ALREADY_FINISHED_DETAILS)
# Write might never end up since the call could abrubtly finish,
# we give up on the first awaitable object that finishes.
_, _ = await asyncio.wait((self._write_to_iterator_queue.put(
InterceptedStreamUnaryCall._FINISH_ITERATOR_SENTINEL), call),
return_when=asyncio.FIRST_COMPLETED)
class UnaryUnaryCallResponse(_base_call.UnaryUnaryCall):
"""Final UnaryUnaryCall class finished with a response."""
_response: ResponseType

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
VERSION = '1.29.0.dev0'
VERSION = '1.30.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_channelz/grpc_version.py.template`!!!
VERSION = '1.29.0.dev0'
VERSION = '1.30.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
VERSION = '1.29.0.dev0'
VERSION = '1.30.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
VERSION = '1.29.0.dev0'
VERSION = '1.30.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_status/grpc_version.py.template`!!!
VERSION = '1.29.0.dev0'
VERSION = '1.30.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!!
VERSION = '1.29.0.dev0'
VERSION = '1.30.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
VERSION = '1.29.0.dev0'
VERSION = '1.30.0.dev0'

@ -43,6 +43,10 @@ def parse_interop_client_args():
default=False,
type=resources.parse_bool,
help='require a secure connection')
parser.add_argument('--use_alts',
default=False,
type=resources.parse_bool,
help='require an ALTS secure connection')
parser.add_argument('--use_test_ca',
default=False,
type=resources.parse_bool,
@ -85,6 +89,8 @@ def _create_call_credentials(args):
def get_secure_channel_parameters(args):
call_credentials = _create_call_credentials(args)
channel_opts = None
if args.use_tls:
if args.use_test_ca:
root_certificates = resources.test_root_certificates()
else:
@ -95,12 +101,13 @@ def get_secure_channel_parameters(args):
channel_credentials = grpc.composite_channel_credentials(
channel_credentials, call_credentials)
channel_opts = None
if args.server_host_override:
channel_opts = ((
'grpc.ssl_target_name_override',
args.server_host_override,
),)
elif args.use_alts:
channel_credentials = grpc.alts_channel_credentials()
return channel_credentials, channel_opts
@ -108,7 +115,7 @@ def get_secure_channel_parameters(args):
def _create_channel(args):
target = '{}:{}'.format(args.server_host, args.server_port)
if args.use_tls:
if args.use_tls or args.use_alts:
channel_credentials, options = get_secure_channel_parameters(args)
return grpc.secure_channel(target, channel_credentials, options)
else:

@ -38,13 +38,20 @@ def parse_interop_server_arguments():
default=False,
type=resources.parse_bool,
help='require a secure connection')
parser.add_argument('--use_alts',
default=False,
type=resources.parse_bool,
help='require an ALTS connection')
return parser.parse_args()
def get_server_credentials():
def get_server_credentials(use_tls):
if use_tls:
private_key = resources.private_key()
certificate_chain = resources.certificate_chain()
return grpc.ssl_server_credentials(((private_key, certificate_chain),))
else:
return grpc.alts_server_credentials()
def serve():
@ -53,8 +60,8 @@ def serve():
server = test_common.test_server()
test_pb2_grpc.add_TestServiceServicer_to_server(service.TestService(),
server)
if args.use_tls:
credentials = get_server_credentials()
if args.use_tls or args.use_alts:
credentials = get_server_credentials(args.use_tls)
server.add_secure_port('[::]:{}'.format(args.port), credentials)
else:
server.add_insecure_port('[::]:{}'.format(args.port))

@ -63,6 +63,8 @@ class AllTest(unittest.TestCase):
'LocalConnectionType',
'local_channel_credentials',
'local_server_credentials',
'alts_channel_credentials',
'alts_server_credentials',
'unary_unary_rpc_method_handler',
'unary_stream_rpc_method_handler',
'stream_unary_rpc_method_handler',

@ -30,7 +30,7 @@ _LOGGER.setLevel(logging.DEBUG)
def _create_channel(args):
target = f'{args.server_host}:{args.server_port}'
if args.use_tls:
if args.use_tls or args.use_alts:
channel_credentials, options = interop_client_lib.get_secure_channel_parameters(
args)
return aio.secure_channel(target, channel_credentials, options)

@ -30,9 +30,8 @@ _LOGGER.setLevel(logging.DEBUG)
async def serve():
args = interop_server_lib.parse_interop_server_arguments()
if args.use_tls:
credentials = interop_server_lib.get_server_credentials()
if args.use_tls or args.use_alts:
credentials = interop_server_lib.get_server_credentials(args.use_tls)
address, server = await _test_server.start_test_server(
port=args.port, secure=True, server_credentials=credentials)
else:

@ -14,6 +14,7 @@
"unit.channel_argument_test.TestChannelArgument",
"unit.channel_ready_test.TestChannelReady",
"unit.channel_test.TestChannel",
"unit.client_stream_unary_interceptor_test.TestStreamUnaryClientInterceptor",
"unit.client_unary_stream_interceptor_test.TestUnaryStreamClientInterceptor",
"unit.client_unary_unary_interceptor_test.TestInterceptedUnaryUnaryCall",
"unit.client_unary_unary_interceptor_test.TestUnaryUnaryClientInterceptor",

@ -47,7 +47,7 @@ async def _maybe_echo_status(request: messages_pb2.SimpleRequest,
request.response_status.message)
class _TestServiceServicer(test_pb2_grpc.TestServiceServicer):
class TestServiceServicer(test_pb2_grpc.TestServiceServicer):
async def UnaryCall(self, request, context):
await _maybe_echo_metadata(context)
@ -102,7 +102,7 @@ class _TestServiceServicer(test_pb2_grpc.TestServiceServicer):
response_parameters.size))
def _create_extra_generic_handler(servicer: _TestServiceServicer):
def _create_extra_generic_handler(servicer: TestServiceServicer):
# Add programatically extra methods not provided by the proto file
# that are used during the tests
rpc_method_handlers = {
@ -123,7 +123,7 @@ async def start_test_server(port=0,
interceptors=None):
server = aio.server(options=(('grpc.so_reuseport', 0),),
interceptors=interceptors)
servicer = _TestServiceServicer()
servicer = TestServiceServicer()
test_pb2_grpc.add_TestServiceServicer_to_server(servicer, server)
server.add_generic_rpc_handlers((_create_extra_generic_handler(servicer),))

@ -0,0 +1,531 @@
# Copyright 2020 The 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 asyncio
import logging
import unittest
import datetime
import grpc
from grpc.experimental import aio
from tests_aio.unit._constants import UNREACHABLE_TARGET
from tests_aio.unit._common import inject_callbacks
from tests_aio.unit._test_server import start_test_server
from tests_aio.unit._test_base import AioTestBase
from tests.unit.framework.common import test_constants
from src.proto.grpc.testing import messages_pb2, test_pb2_grpc
_SHORT_TIMEOUT_S = 1.0
_NUM_STREAM_REQUESTS = 5
_REQUEST_PAYLOAD_SIZE = 7
_RESPONSE_INTERVAL_US = int(_SHORT_TIMEOUT_S * 1000 * 1000)
class _CountingRequestIterator:
def __init__(self, request_iterator):
self.request_cnt = 0
self._request_iterator = request_iterator
async def _forward_requests(self):
async for request in self._request_iterator:
self.request_cnt += 1
yield request
def __aiter__(self):
return self._forward_requests()
class _StreamUnaryInterceptorEmpty(aio.StreamUnaryClientInterceptor):
async def intercept_stream_unary(self, continuation, client_call_details,
request_iterator):
return await continuation(client_call_details, request_iterator)
def assert_in_final_state(self, test: unittest.TestCase):
pass
class _StreamUnaryInterceptorWithRequestIterator(
aio.StreamUnaryClientInterceptor):
async def intercept_stream_unary(self, continuation, client_call_details,
request_iterator):
self.request_iterator = _CountingRequestIterator(request_iterator)
call = await continuation(client_call_details, self.request_iterator)
return call
def assert_in_final_state(self, test: unittest.TestCase):
test.assertEqual(_NUM_STREAM_REQUESTS,
self.request_iterator.request_cnt)
class TestStreamUnaryClientInterceptor(AioTestBase):
async def setUp(self):
self._server_target, self._server = await start_test_server()
async def tearDown(self):
await self._server.stop(None)
async def test_intercepts(self):
for interceptor_class in (_StreamUnaryInterceptorEmpty,
_StreamUnaryInterceptorWithRequestIterator):
with self.subTest(name=interceptor_class):
interceptor = interceptor_class()
channel = aio.insecure_channel(self._server_target,
interceptors=[interceptor])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' *
_REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(
payload=payload)
async def request_iterator():
for _ in range(_NUM_STREAM_REQUESTS):
yield request
call = stub.StreamingInputCall(request_iterator())
response = await call
self.assertEqual(_NUM_STREAM_REQUESTS * _REQUEST_PAYLOAD_SIZE,
response.aggregated_payload_size)
self.assertEqual(await call.code(), grpc.StatusCode.OK)
self.assertEqual(await call.initial_metadata(), ())
self.assertEqual(await call.trailing_metadata(), ())
self.assertEqual(await call.details(), '')
self.assertEqual(await call.debug_error_string(), '')
self.assertEqual(call.cancel(), False)
self.assertEqual(call.cancelled(), False)
self.assertEqual(call.done(), True)
interceptor.assert_in_final_state(self)
await channel.close()
async def test_intercepts_using_write(self):
for interceptor_class in (_StreamUnaryInterceptorEmpty,
_StreamUnaryInterceptorWithRequestIterator):
with self.subTest(name=interceptor_class):
interceptor = interceptor_class()
channel = aio.insecure_channel(self._server_target,
interceptors=[interceptor])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' *
_REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(
payload=payload)
call = stub.StreamingInputCall()
for _ in range(_NUM_STREAM_REQUESTS):
await call.write(request)
await call.done_writing()
response = await call
self.assertEqual(_NUM_STREAM_REQUESTS * _REQUEST_PAYLOAD_SIZE,
response.aggregated_payload_size)
self.assertEqual(await call.code(), grpc.StatusCode.OK)
self.assertEqual(await call.initial_metadata(), ())
self.assertEqual(await call.trailing_metadata(), ())
self.assertEqual(await call.details(), '')
self.assertEqual(await call.debug_error_string(), '')
self.assertEqual(call.cancel(), False)
self.assertEqual(call.cancelled(), False)
self.assertEqual(call.done(), True)
interceptor.assert_in_final_state(self)
await channel.close()
async def test_add_done_callback_interceptor_task_not_finished(self):
for interceptor_class in (_StreamUnaryInterceptorEmpty,
_StreamUnaryInterceptorWithRequestIterator):
with self.subTest(name=interceptor_class):
interceptor = interceptor_class()
channel = aio.insecure_channel(self._server_target,
interceptors=[interceptor])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' *
_REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(
payload=payload)
async def request_iterator():
for _ in range(_NUM_STREAM_REQUESTS):
yield request
call = stub.StreamingInputCall(request_iterator())
validation = inject_callbacks(call)
response = await call
await validation
await channel.close()
async def test_add_done_callback_interceptor_task_finished(self):
for interceptor_class in (_StreamUnaryInterceptorEmpty,
_StreamUnaryInterceptorWithRequestIterator):
with self.subTest(name=interceptor_class):
interceptor = interceptor_class()
channel = aio.insecure_channel(self._server_target,
interceptors=[interceptor])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' *
_REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(
payload=payload)
async def request_iterator():
for _ in range(_NUM_STREAM_REQUESTS):
yield request
call = stub.StreamingInputCall(request_iterator())
response = await call
validation = inject_callbacks(call)
await validation
await channel.close()
async def test_multiple_interceptors_request_iterator(self):
for interceptor_class in (_StreamUnaryInterceptorEmpty,
_StreamUnaryInterceptorWithRequestIterator):
with self.subTest(name=interceptor_class):
interceptors = [interceptor_class(), interceptor_class()]
channel = aio.insecure_channel(self._server_target,
interceptors=interceptors)
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' *
_REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(
payload=payload)
async def request_iterator():
for _ in range(_NUM_STREAM_REQUESTS):
yield request
call = stub.StreamingInputCall(request_iterator())
response = await call
self.assertEqual(_NUM_STREAM_REQUESTS * _REQUEST_PAYLOAD_SIZE,
response.aggregated_payload_size)
self.assertEqual(await call.code(), grpc.StatusCode.OK)
self.assertEqual(await call.initial_metadata(), ())
self.assertEqual(await call.trailing_metadata(), ())
self.assertEqual(await call.details(), '')
self.assertEqual(await call.debug_error_string(), '')
self.assertEqual(call.cancel(), False)
self.assertEqual(call.cancelled(), False)
self.assertEqual(call.done(), True)
for interceptor in interceptors:
interceptor.assert_in_final_state(self)
await channel.close()
async def test_intercepts_request_iterator_rpc_error(self):
for interceptor_class in (_StreamUnaryInterceptorEmpty,
_StreamUnaryInterceptorWithRequestIterator):
with self.subTest(name=interceptor_class):
channel = aio.insecure_channel(
UNREACHABLE_TARGET, interceptors=[interceptor_class()])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' *
_REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(
payload=payload)
# When there is an error the request iterator is no longer
# consumed.
async def request_iterator():
for _ in range(_NUM_STREAM_REQUESTS):
yield request
call = stub.StreamingInputCall(request_iterator())
with self.assertRaises(aio.AioRpcError) as exception_context:
await call
self.assertEqual(grpc.StatusCode.UNAVAILABLE,
exception_context.exception.code())
self.assertTrue(call.done())
self.assertEqual(grpc.StatusCode.UNAVAILABLE, await call.code())
await channel.close()
async def test_intercepts_request_iterator_rpc_error_using_write(self):
for interceptor_class in (_StreamUnaryInterceptorEmpty,
_StreamUnaryInterceptorWithRequestIterator):
with self.subTest(name=interceptor_class):
channel = aio.insecure_channel(
UNREACHABLE_TARGET, interceptors=[interceptor_class()])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' *
_REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(
payload=payload)
call = stub.StreamingInputCall()
# When there is an error during the write, exception is raised.
with self.assertRaises(asyncio.InvalidStateError):
for _ in range(_NUM_STREAM_REQUESTS):
await call.write(request)
with self.assertRaises(aio.AioRpcError) as exception_context:
await call
self.assertEqual(grpc.StatusCode.UNAVAILABLE,
exception_context.exception.code())
self.assertTrue(call.done())
self.assertEqual(grpc.StatusCode.UNAVAILABLE, await call.code())
await channel.close()
async def test_cancel_before_rpc(self):
interceptor_reached = asyncio.Event()
wait_for_ever = self.loop.create_future()
class Interceptor(aio.StreamUnaryClientInterceptor):
async def intercept_stream_unary(self, continuation,
client_call_details,
request_iterator):
interceptor_reached.set()
await wait_for_ever
channel = aio.insecure_channel(self._server_target,
interceptors=[Interceptor()])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(payload=payload)
call = stub.StreamingInputCall()
self.assertFalse(call.cancelled())
self.assertFalse(call.done())
await interceptor_reached.wait()
self.assertTrue(call.cancel())
# When there is an error during the write, exception is raised.
with self.assertRaises(asyncio.InvalidStateError):
for _ in range(_NUM_STREAM_REQUESTS):
await call.write(request)
with self.assertRaises(asyncio.CancelledError):
await call
self.assertTrue(call.cancelled())
self.assertTrue(call.done())
self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
self.assertEqual(await call.initial_metadata(), None)
self.assertEqual(await call.trailing_metadata(), None)
await channel.close()
async def test_cancel_after_rpc(self):
interceptor_reached = asyncio.Event()
wait_for_ever = self.loop.create_future()
class Interceptor(aio.StreamUnaryClientInterceptor):
async def intercept_stream_unary(self, continuation,
client_call_details,
request_iterator):
call = await continuation(client_call_details, request_iterator)
interceptor_reached.set()
await wait_for_ever
channel = aio.insecure_channel(self._server_target,
interceptors=[Interceptor()])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(payload=payload)
call = stub.StreamingInputCall()
self.assertFalse(call.cancelled())
self.assertFalse(call.done())
await interceptor_reached.wait()
self.assertTrue(call.cancel())
# When there is an error during the write, exception is raised.
with self.assertRaises(asyncio.InvalidStateError):
for _ in range(_NUM_STREAM_REQUESTS):
await call.write(request)
with self.assertRaises(asyncio.CancelledError):
await call
self.assertTrue(call.cancelled())
self.assertTrue(call.done())
self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
self.assertEqual(await call.initial_metadata(), None)
self.assertEqual(await call.trailing_metadata(), None)
await channel.close()
async def test_cancel_while_writing(self):
# Test cancelation before making any write or after doing at least 1
for num_writes_before_cancel in (0, 1):
with self.subTest(name="Num writes before cancel: {}".format(
num_writes_before_cancel)):
channel = aio.insecure_channel(
UNREACHABLE_TARGET,
interceptors=[_StreamUnaryInterceptorWithRequestIterator()])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' *
_REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(
payload=payload)
call = stub.StreamingInputCall()
with self.assertRaises(asyncio.InvalidStateError):
for i in range(_NUM_STREAM_REQUESTS):
if i == num_writes_before_cancel:
self.assertTrue(call.cancel())
await call.write(request)
with self.assertRaises(asyncio.CancelledError):
await call
self.assertTrue(call.cancelled())
self.assertTrue(call.done())
self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
await channel.close()
async def test_cancel_by_the_interceptor(self):
class Interceptor(aio.StreamUnaryClientInterceptor):
async def intercept_stream_unary(self, continuation,
client_call_details,
request_iterator):
call = await continuation(client_call_details, request_iterator)
call.cancel()
return call
channel = aio.insecure_channel(UNREACHABLE_TARGET,
interceptors=[Interceptor()])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(payload=payload)
call = stub.StreamingInputCall()
with self.assertRaises(asyncio.InvalidStateError):
for i in range(_NUM_STREAM_REQUESTS):
await call.write(request)
with self.assertRaises(asyncio.CancelledError):
await call
self.assertTrue(call.cancelled())
self.assertTrue(call.done())
self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED)
await channel.close()
async def test_exception_raised_by_interceptor(self):
class InterceptorException(Exception):
pass
class Interceptor(aio.StreamUnaryClientInterceptor):
async def intercept_stream_unary(self, continuation,
client_call_details,
request_iterator):
raise InterceptorException
channel = aio.insecure_channel(UNREACHABLE_TARGET,
interceptors=[Interceptor()])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(payload=payload)
call = stub.StreamingInputCall()
with self.assertRaises(InterceptorException):
for i in range(_NUM_STREAM_REQUESTS):
await call.write(request)
with self.assertRaises(InterceptorException):
await call
await channel.close()
async def test_intercepts_prohibit_mixing_style(self):
channel = aio.insecure_channel(
self._server_target, interceptors=[_StreamUnaryInterceptorEmpty()])
stub = test_pb2_grpc.TestServiceStub(channel)
payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE)
request = messages_pb2.StreamingInputCallRequest(payload=payload)
async def request_iterator():
for _ in range(_NUM_STREAM_REQUESTS):
yield request
call = stub.StreamingInputCall(request_iterator())
with self.assertRaises(grpc._cython.cygrpc.UsageError):
await call.write(request)
with self.assertRaises(grpc._cython.cygrpc.UsageError):
await call.done_writing()
await channel.close()
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
unittest.main(verbosity=2)

@ -20,32 +20,63 @@ import random
import threading
import unittest
from concurrent.futures import ThreadPoolExecutor
from typing import Callable, Sequence, Tuple
from typing import Callable, Iterable, Sequence, Tuple
import grpc
from grpc.experimental import aio
from src.proto.grpc.testing import messages_pb2, test_pb2_grpc
from tests.unit.framework.common import test_constants
from tests_aio.unit import _common
from tests_aio.unit._test_base import AioTestBase
from tests_aio.unit._test_server import start_test_server
from tests_aio.unit._test_server import TestServiceServicer, start_test_server
_NUM_STREAM_RESPONSES = 5
_REQUEST_PAYLOAD_SIZE = 7
_RESPONSE_PAYLOAD_SIZE = 42
_REQUEST = b'\x03\x07'
_ADHOC_METHOD = '/test/AdHoc'
def _unique_options() -> Sequence[Tuple[str, float]]:
return (('iv', random.random()),)
class _AdhocGenericHandler(grpc.GenericRpcHandler):
_handler: grpc.RpcMethodHandler
def __init__(self):
self._handler = None
def set_adhoc_handler(self, handler: grpc.RpcMethodHandler):
self._handler = handler
def service(self, handler_call_details):
if handler_call_details.method == _ADHOC_METHOD:
return self._handler
else:
return None
@unittest.skipIf(
os.environ.get('GRPC_ASYNCIO_ENGINE', '').lower() != 'poller',
os.environ.get('GRPC_ASYNCIO_ENGINE', '').lower() == 'custom_io_manager',
'Compatible mode needs POLLER completion queue.')
class TestCompatibility(AioTestBase):
async def setUp(self):
address, self._async_server = await start_test_server()
self._async_server = aio.server(
options=(('grpc.so_reuseport', 0),),
migration_thread_pool=ThreadPoolExecutor())
test_pb2_grpc.add_TestServiceServicer_to_server(TestServiceServicer(),
self._async_server)
self._adhoc_handlers = _AdhocGenericHandler()
self._async_server.add_generic_rpc_handlers((self._adhoc_handlers,))
port = self._async_server.add_insecure_port('[::]:0')
address = 'localhost:%d' % port
await self._async_server.start()
# Create async stub
self._async_channel = aio.insecure_channel(address,
options=_unique_options())
@ -202,6 +233,146 @@ class TestCompatibility(AioTestBase):
await self._run_in_another_thread(sync_work)
await server.stop(None)
async def test_sync_unary_unary_success(self):
@grpc.unary_unary_rpc_method_handler
def echo_unary_unary(request: bytes, unused_context):
return request
self._adhoc_handlers.set_adhoc_handler(echo_unary_unary)
response = await self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST
)
self.assertEqual(_REQUEST, response)
async def test_sync_unary_unary_metadata(self):
metadata = (('unique', 'key-42'),)
@grpc.unary_unary_rpc_method_handler
def metadata_unary_unary(request: bytes, context: grpc.ServicerContext):
context.send_initial_metadata(metadata)
return request
self._adhoc_handlers.set_adhoc_handler(metadata_unary_unary)
call = self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST)
self.assertTrue(
_common.seen_metadata(metadata, await call.initial_metadata()))
async def test_sync_unary_unary_abort(self):
@grpc.unary_unary_rpc_method_handler
def abort_unary_unary(request: bytes, context: grpc.ServicerContext):
context.abort(grpc.StatusCode.INTERNAL, 'Test')
self._adhoc_handlers.set_adhoc_handler(abort_unary_unary)
with self.assertRaises(aio.AioRpcError) as exception_context:
await self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST)
self.assertEqual(grpc.StatusCode.INTERNAL,
exception_context.exception.code())
async def test_sync_unary_unary_set_code(self):
@grpc.unary_unary_rpc_method_handler
def set_code_unary_unary(request: bytes, context: grpc.ServicerContext):
context.set_code(grpc.StatusCode.INTERNAL)
self._adhoc_handlers.set_adhoc_handler(set_code_unary_unary)
with self.assertRaises(aio.AioRpcError) as exception_context:
await self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST)
self.assertEqual(grpc.StatusCode.INTERNAL,
exception_context.exception.code())
async def test_sync_unary_stream_success(self):
@grpc.unary_stream_rpc_method_handler
def echo_unary_stream(request: bytes, unused_context):
for _ in range(_NUM_STREAM_RESPONSES):
yield request
self._adhoc_handlers.set_adhoc_handler(echo_unary_stream)
call = self._async_channel.unary_stream(_ADHOC_METHOD)(_REQUEST)
async for response in call:
self.assertEqual(_REQUEST, response)
async def test_sync_unary_stream_error(self):
@grpc.unary_stream_rpc_method_handler
def error_unary_stream(request: bytes, unused_context):
for _ in range(_NUM_STREAM_RESPONSES):
yield request
raise RuntimeError('Test')
self._adhoc_handlers.set_adhoc_handler(error_unary_stream)
call = self._async_channel.unary_stream(_ADHOC_METHOD)(_REQUEST)
with self.assertRaises(aio.AioRpcError) as exception_context:
async for response in call:
self.assertEqual(_REQUEST, response)
self.assertEqual(grpc.StatusCode.UNKNOWN,
exception_context.exception.code())
async def test_sync_stream_unary_success(self):
@grpc.stream_unary_rpc_method_handler
def echo_stream_unary(request_iterator: Iterable[bytes],
unused_context):
self.assertEqual(len(list(request_iterator)), _NUM_STREAM_RESPONSES)
return _REQUEST
self._adhoc_handlers.set_adhoc_handler(echo_stream_unary)
request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES)
response = await self._async_channel.stream_unary(_ADHOC_METHOD)(
request_iterator)
self.assertEqual(_REQUEST, response)
async def test_sync_stream_unary_error(self):
@grpc.stream_unary_rpc_method_handler
def echo_stream_unary(request_iterator: Iterable[bytes],
unused_context):
self.assertEqual(len(list(request_iterator)), _NUM_STREAM_RESPONSES)
raise RuntimeError('Test')
self._adhoc_handlers.set_adhoc_handler(echo_stream_unary)
request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES)
with self.assertRaises(aio.AioRpcError) as exception_context:
response = await self._async_channel.stream_unary(_ADHOC_METHOD)(
request_iterator)
self.assertEqual(grpc.StatusCode.UNKNOWN,
exception_context.exception.code())
async def test_sync_stream_stream_success(self):
@grpc.stream_stream_rpc_method_handler
def echo_stream_stream(request_iterator: Iterable[bytes],
unused_context):
for request in request_iterator:
yield request
self._adhoc_handlers.set_adhoc_handler(echo_stream_stream)
request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES)
call = self._async_channel.stream_stream(_ADHOC_METHOD)(
request_iterator)
async for response in call:
self.assertEqual(_REQUEST, response)
async def test_sync_stream_stream_error(self):
@grpc.stream_stream_rpc_method_handler
def echo_stream_stream(request_iterator: Iterable[bytes],
unused_context):
for request in request_iterator:
yield request
raise RuntimeError('test')
self._adhoc_handlers.set_adhoc_handler(echo_stream_stream)
request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES)
call = self._async_channel.stream_stream(_ADHOC_METHOD)(
request_iterator)
with self.assertRaises(aio.AioRpcError) as exception_context:
async for response in call:
self.assertEqual(_REQUEST, response)
self.assertEqual(grpc.StatusCode.UNKNOWN,
exception_context.exception.code())
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)

@ -14,5 +14,5 @@
# GRPC contains the General RPC module.
module GRPC
VERSION = '1.29.0.dev'
VERSION = '1.30.0.dev'
end

@ -14,6 +14,6 @@
module GRPC
module Tools
VERSION = '1.29.0.dev'
VERSION = '1.30.0.dev'
end
end

@ -9,7 +9,7 @@
s.name = 'grpc'
s.version = GRPC::VERSION
s.authors = ['gRPC Authors']
s.email = 'temiola@google.com'
s.email = 'grpc-io@googlegroups.com'
s.homepage = 'https://github.com/google/grpc/tree/master/src/ruby'
s.summary = 'GRPC system in Ruby'
s.description = 'Send RPCs from Ruby using GRPC'

@ -29,7 +29,6 @@ def grpc_bad_ssl_tests():
deps = [
"//test/core/util:grpc_test_util",
"//:grpc",
"//test/core/end2end:ssl_test_data",
],
)
for t in BAD_SSL_TESTS:

@ -25,7 +25,6 @@
#include "src/core/lib/iomgr/load_file.h"
#include "test/core/bad_ssl/server_common.h"
#include "test/core/end2end/data/ssl_test_data.h"
/* This server will present an untrusted cert to the connecting client,
* causing the SSL handshake to fail */

@ -48,11 +48,11 @@ namespace testing {
class CallCountingHelperPeer {
public:
explicit CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {}
grpc_millis last_call_started_millis() const {
gpr_timespec last_call_started_time() const {
CallCountingHelper::CounterData data;
node_->CollectData(&data);
gpr_timespec ts = gpr_cycle_counter_to_time(data.last_call_started_cycle);
return grpc_timespec_to_millis_round_up(ts);
return gpr_cycle_counter_to_time(data.last_call_started_cycle);
}
private:
@ -243,9 +243,9 @@ void ValidateServer(ServerNode* server, const ValidateChannelDataArgs& args) {
gpr_free(core_api_json_str);
}
grpc_millis GetLastCallStartedMillis(CallCountingHelper* channel) {
gpr_timespec GetLastCallStartedTime(CallCountingHelper* channel) {
CallCountingHelperPeer peer(channel);
return peer.last_call_started_millis();
return peer.last_call_started_time();
}
void ChannelzSleep(int64_t sleep_us) {
@ -301,28 +301,28 @@ TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) {
ValidateChannel(channelz_channel, {3, 3, 3});
}
TEST_P(ChannelzChannelTest, LastCallStartedMillis) {
TEST_P(ChannelzChannelTest, LastCallStartedTime) {
grpc_core::ExecCtx exec_ctx;
CallCountingHelper counter;
// start a call to set the last call started timestamp
counter.RecordCallStarted();
grpc_millis millis1 = GetLastCallStartedMillis(&counter);
gpr_timespec time1 = GetLastCallStartedTime(&counter);
// time gone by should not affect the timestamp
ChannelzSleep(100);
grpc_millis millis2 = GetLastCallStartedMillis(&counter);
EXPECT_EQ(millis1, millis2);
gpr_timespec time2 = GetLastCallStartedTime(&counter);
EXPECT_EQ(gpr_time_cmp(time1, time2), 0);
// calls succeeded or failed should not affect the timestamp
ChannelzSleep(100);
counter.RecordCallFailed();
counter.RecordCallSucceeded();
grpc_millis millis3 = GetLastCallStartedMillis(&counter);
EXPECT_EQ(millis1, millis3);
gpr_timespec time3 = GetLastCallStartedTime(&counter);
EXPECT_EQ(gpr_time_cmp(time1, time3), 0);
// another call started should affect the timestamp
// sleep for extra long to avoid flakes (since we cache Now())
ChannelzSleep(5000);
counter.RecordCallStarted();
grpc_millis millis4 = GetLastCallStartedMillis(&counter);
EXPECT_NE(millis1, millis4);
gpr_timespec time4 = GetLastCallStartedTime(&counter);
EXPECT_NE(gpr_time_cmp(time1, time4), 0);
}
class ChannelzRegistryBasedTest : public ::testing::TestWithParam<size_t> {

@ -19,6 +19,10 @@
#ifndef GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H
#define GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H
// These credentials are hardcoded as char arrays and are hence considered to
// be deprecated. Please consider using credentials in
// "src/core/tsi/test_creds" instead.
extern const char test_root_cert[];
extern const char test_server1_cert[];
extern const char test_server1_key[];

@ -27,7 +27,6 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
#include "test/core/end2end/data/ssl_test_data.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"

@ -47,7 +47,6 @@ grpc_fuzzer(
deps = [
"//:gpr",
"//:grpc",
"//test/core/end2end:ssl_test_data",
"//test/core/util:grpc_test_util",
],
)
@ -268,7 +267,6 @@ grpc_cc_test(
"//:grpc_secure",
"//:tsi",
"//:tsi_interface",
"//test/core/end2end:ssl_test_data",
"//test/core/util:grpc_test_util",
],
)
@ -287,7 +285,6 @@ grpc_cc_test(
"//:gpr",
"//:grpc",
"//:grpc_secure",
"//test/core/end2end:ssl_test_data",
"//test/core/util:grpc_test_util",
],
)

@ -148,7 +148,6 @@ grpc_cc_test(
deps = [
"//:gpr",
"//:grpc",
"//test/core/end2end:ssl_test_data",
"//test/core/util:grpc_test_util",
],
)

@ -18,6 +18,7 @@
#include "test/core/util/test_config.h"
#include <grpc/impl/codegen/gpr_types.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
@ -402,13 +403,12 @@ TestEnvironment::TestEnvironment(int argc, char** argv) {
TestEnvironment::~TestEnvironment() {
// This will wait until gRPC shutdown has actually happened to make sure
// no gRPC resources (such as thread) are active. (timeout = 10s)
gpr_timespec timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_seconds(10, GPR_TIMESPAN));
gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10);
while (grpc_is_initialized()) {
grpc_maybe_wait_for_async_shutdown();
gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_millis(1, GPR_TIMESPAN)));
if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), timeout) > 0) {
if (gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) > 0) {
gpr_log(GPR_ERROR, "Timeout in waiting for gRPC shutdown");
break;
}

@ -43,6 +43,17 @@ namespace grpc {
namespace testing {
namespace {
enum class RPCType {
kSyncUnary,
kSyncClientStreaming,
kSyncServerStreaming,
kSyncBidiStreaming,
kAsyncCQUnary,
kAsyncCQClientStreaming,
kAsyncCQServerStreaming,
kAsyncCQBidiStreaming,
};
/* Hijacks Echo RPC and fills in the expected values */
class HijackingInterceptor : public experimental::Interceptor {
public:
@ -400,6 +411,7 @@ class ServerStreamingRpcHijackingInterceptor
public:
ServerStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) {
info_ = info;
got_failed_message_ = false;
}
virtual void Intercept(experimental::InterceptorBatchMethods* methods) {
@ -531,10 +543,22 @@ class LoggingInterceptor : public experimental::Interceptor {
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) {
EchoRequest req;
EXPECT_EQ(static_cast<const EchoRequest*>(methods->GetSendMessage())
->message()
.find("Hello"),
auto* send_msg = methods->GetSendMessage();
if (send_msg == nullptr) {
// We did not get the non-serialized form of the message. Get the
// serialized form.
auto* buffer = methods->GetSerializedSendMessage();
auto copied_buffer = *buffer;
EchoRequest req;
EXPECT_TRUE(
SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req)
.ok());
EXPECT_EQ(req.message(), "Hello");
} else {
EXPECT_EQ(
static_cast<const EchoRequest*>(send_msg)->message().find("Hello"),
0u);
}
auto* buffer = methods->GetSerializedSendMessage();
auto copied_buffer = *buffer;
EXPECT_TRUE(
@ -582,6 +606,27 @@ class LoggingInterceptor : public experimental::Interceptor {
methods->Proceed();
}
static void VerifyCall(RPCType type) {
switch (type) {
case RPCType::kSyncUnary:
case RPCType::kAsyncCQUnary:
VerifyUnaryCall();
break;
case RPCType::kSyncClientStreaming:
case RPCType::kAsyncCQClientStreaming:
VerifyClientStreamingCall();
break;
case RPCType::kSyncServerStreaming:
case RPCType::kAsyncCQServerStreaming:
VerifyServerStreamingCall();
break;
case RPCType::kSyncBidiStreaming:
case RPCType::kAsyncCQBidiStreaming:
VerifyBidiStreamingCall();
break;
}
}
static void VerifyCallCommon() {
EXPECT_TRUE(pre_send_initial_metadata_);
EXPECT_TRUE(pre_send_close_);
@ -638,9 +683,31 @@ class LoggingInterceptorFactory
}
};
class ClientInterceptorsEnd2endTest : public ::testing::Test {
class TestScenario {
public:
explicit TestScenario(const RPCType& type) : type_(type) {}
RPCType type() const { return type_; }
private:
RPCType type_;
};
std::vector<TestScenario> CreateTestScenarios() {
std::vector<TestScenario> scenarios;
scenarios.emplace_back(RPCType::kSyncUnary);
scenarios.emplace_back(RPCType::kSyncClientStreaming);
scenarios.emplace_back(RPCType::kSyncServerStreaming);
scenarios.emplace_back(RPCType::kSyncBidiStreaming);
scenarios.emplace_back(RPCType::kAsyncCQUnary);
scenarios.emplace_back(RPCType::kAsyncCQServerStreaming);
return scenarios;
}
class ParameterizedClientInterceptorsEnd2endTest
: public ::testing::TestWithParam<TestScenario> {
protected:
ClientInterceptorsEnd2endTest() {
ParameterizedClientInterceptorsEnd2endTest() {
int port = grpc_pick_unused_port_or_die();
ServerBuilder builder;
@ -650,14 +717,44 @@ class ClientInterceptorsEnd2endTest : public ::testing::Test {
server_ = builder.BuildAndStart();
}
~ClientInterceptorsEnd2endTest() { server_->Shutdown(); }
~ParameterizedClientInterceptorsEnd2endTest() { server_->Shutdown(); }
void SendRPC(const std::shared_ptr<Channel>& channel) {
switch (GetParam().type()) {
case RPCType::kSyncUnary:
MakeCall(channel);
break;
case RPCType::kSyncClientStreaming:
MakeClientStreamingCall(channel);
break;
case RPCType::kSyncServerStreaming:
MakeServerStreamingCall(channel);
break;
case RPCType::kSyncBidiStreaming:
MakeBidiStreamingCall(channel);
break;
case RPCType::kAsyncCQUnary:
MakeAsyncCQCall(channel);
break;
case RPCType::kAsyncCQClientStreaming:
// TODO(yashykt) : Fill this out
break;
case RPCType::kAsyncCQServerStreaming:
MakeAsyncCQServerStreamingCall(channel);
break;
case RPCType::kAsyncCQBidiStreaming:
// TODO(yashykt) : Fill this out
break;
}
}
std::string server_address_;
TestServiceImpl service_;
EchoTestServiceStreamingImpl service_;
std::unique_ptr<Server> server_;
};
TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLoggingTest) {
TEST_P(ParameterizedClientInterceptorsEnd2endTest,
ClientInterceptorLoggingTest) {
ChannelArguments args;
DummyInterceptor::Reset();
std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
@ -671,12 +768,36 @@ TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLoggingTest) {
}
auto channel = experimental::CreateCustomChannelWithInterceptors(
server_address_, InsecureChannelCredentials(), args, std::move(creators));
MakeCall(channel);
LoggingInterceptor::VerifyUnaryCall();
SendRPC(channel);
LoggingInterceptor::VerifyCall(GetParam().type());
// Make sure all 20 dummy interceptors were run
EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20);
}
INSTANTIATE_TEST_SUITE_P(ParameterizedClientInterceptorsEnd2end,
ParameterizedClientInterceptorsEnd2endTest,
::testing::ValuesIn(CreateTestScenarios()));
class ClientInterceptorsEnd2endTest
: public ::testing::TestWithParam<TestScenario> {
protected:
ClientInterceptorsEnd2endTest() {
int port = grpc_pick_unused_port_or_die();
ServerBuilder builder;
server_address_ = "localhost:" + std::to_string(port);
builder.AddListeningPort(server_address_, InsecureServerCredentials());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
}
~ClientInterceptorsEnd2endTest() { server_->Shutdown(); }
std::string server_address_;
TestServiceImpl service_;
std::unique_ptr<Server> server_;
};
TEST_F(ClientInterceptorsEnd2endTest,
LameChannelClientInterceptorHijackingTest) {
ChannelArguments args;
@ -757,7 +878,26 @@ TEST_F(ClientInterceptorsEnd2endTest,
EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 12);
}
TEST_F(ClientInterceptorsEnd2endTest,
class ClientInterceptorsCallbackEnd2endTest : public ::testing::Test {
protected:
ClientInterceptorsCallbackEnd2endTest() {
int port = grpc_pick_unused_port_or_die();
ServerBuilder builder;
server_address_ = "localhost:" + std::to_string(port);
builder.AddListeningPort(server_address_, InsecureServerCredentials());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
}
~ClientInterceptorsCallbackEnd2endTest() { server_->Shutdown(); }
std::string server_address_;
TestServiceImpl service_;
std::unique_ptr<Server> server_;
};
TEST_F(ClientInterceptorsCallbackEnd2endTest,
ClientInterceptorLoggingTestWithCallback) {
ChannelArguments args;
DummyInterceptor::Reset();
@ -778,7 +918,7 @@ TEST_F(ClientInterceptorsEnd2endTest,
EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20);
}
TEST_F(ClientInterceptorsEnd2endTest,
TEST_F(ClientInterceptorsCallbackEnd2endTest,
ClientInterceptorFactoryAllowsNullptrReturn) {
ChannelArguments args;
DummyInterceptor::Reset();
@ -903,6 +1043,21 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingHijackingTest) {
EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage());
}
TEST_F(ClientInterceptorsStreamingEnd2endTest,
AsyncCQServerStreamingHijackingTest) {
ChannelArguments args;
DummyInterceptor::Reset();
std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
creators;
creators.push_back(
std::unique_ptr<ServerStreamingRpcHijackingInterceptorFactory>(
new ServerStreamingRpcHijackingInterceptorFactory()));
auto channel = experimental::CreateCustomChannelWithInterceptors(
server_address_, InsecureChannelCredentials(), args, std::move(creators));
MakeAsyncCQServerStreamingCall(channel);
EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage());
}
TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingHijackingTest) {
ChannelArguments args;
DummyInterceptor::Reset();

@ -618,11 +618,17 @@ class GrpclbEnd2endTest : public ::testing::Test {
}
Status SendRpc(EchoResponse* response = nullptr, int timeout_ms = 1000,
bool wait_for_ready = false) {
bool wait_for_ready = false,
const Status& expected_status = Status::OK) {
const bool local_response = (response == nullptr);
if (local_response) response = new EchoResponse;
EchoRequest request;
request.set_message(kRequestMessage_);
if (!expected_status.ok()) {
auto* error = request.mutable_param()->mutable_expected_error();
error->set_code(expected_status.error_code());
error->set_error_message(expected_status.error_message());
}
ClientContext context;
context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms));
if (wait_for_ready) context.set_wait_for_ready(true);
@ -751,6 +757,22 @@ TEST_F(SingleBalancerTest, Vanilla) {
EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
}
TEST_F(SingleBalancerTest, ReturnServerStatus) {
SetNextResolutionAllBalancers();
ScheduleResponseForBalancer(
0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
0);
// We need to wait for all backends to come online.
WaitForAllBackends();
// Send a request that the backend will fail, and make sure we get
// back the right status.
Status expected(StatusCode::INVALID_ARGUMENT, "He's dead, Jim!");
Status actual = SendRpc(/*response=*/nullptr, /*timeout_ms=*/1000,
/*wait_for_ready=*/false, expected);
EXPECT_EQ(actual.error_code(), expected.error_code());
EXPECT_EQ(actual.error_message(), expected.error_message());
}
TEST_F(SingleBalancerTest, SelectGrpclbWithMigrationServiceConfig) {
SetNextResolutionAllBalancers(
"{\n"

@ -66,7 +66,6 @@ void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel) {
ctx.AddMetadata("testkey", "testvalue");
req.set_message("Hello");
EchoResponse resp;
string expected_resp = "";
auto reader = stub->ResponseStream(&ctx, req);
int count = 0;
while (reader->Read(&resp)) {
@ -84,6 +83,7 @@ void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) {
EchoRequest req;
EchoResponse resp;
ctx.AddMetadata("testkey", "testvalue");
req.mutable_param()->set_echo_metadata(true);
auto stream = stub->BidiStream(&ctx);
for (auto i = 0; i < kNumStreamingMessages; i++) {
req.set_message("Hello" + std::to_string(i));
@ -96,6 +96,60 @@ void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) {
EXPECT_EQ(s.ok(), true);
}
void MakeAsyncCQCall(const std::shared_ptr<Channel>& channel) {
auto stub = grpc::testing::EchoTestService::NewStub(channel);
CompletionQueue cq;
EchoRequest send_request;
EchoResponse recv_response;
Status recv_status;
ClientContext cli_ctx;
send_request.set_message("Hello");
cli_ctx.AddMetadata("testkey", "testvalue");
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub->AsyncEcho(&cli_ctx, send_request, &cq));
response_reader->Finish(&recv_response, &recv_status, tag(1));
Verifier().Expect(1, true).Verify(&cq);
EXPECT_EQ(send_request.message(), recv_response.message());
EXPECT_TRUE(recv_status.ok());
}
void MakeAsyncCQClientStreamingCall(const std::shared_ptr<Channel>& channel) {
// TODO(yashykt) : Fill this out
}
void MakeAsyncCQServerStreamingCall(const std::shared_ptr<Channel>& channel) {
auto stub = grpc::testing::EchoTestService::NewStub(channel);
CompletionQueue cq;
EchoRequest send_request;
EchoResponse recv_response;
Status recv_status;
ClientContext cli_ctx;
cli_ctx.AddMetadata("testkey", "testvalue");
send_request.set_message("Hello");
std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream(
stub->AsyncResponseStream(&cli_ctx, send_request, &cq, tag(1)));
Verifier().Expect(1, true).Verify(&cq);
// Read the expected number of messages
for (int i = 0; i < kNumStreamingMessages; i++) {
cli_stream->Read(&recv_response, tag(2));
Verifier().Expect(2, true).Verify(&cq);
ASSERT_EQ(recv_response.message(), send_request.message());
}
// The next read should fail
cli_stream->Read(&recv_response, tag(3));
Verifier().Expect(3, false).Verify(&cq);
// Get the status
cli_stream->Finish(&recv_status, tag(4));
Verifier().Expect(4, true).Verify(&cq);
EXPECT_TRUE(recv_status.ok());
}
void MakeAsyncCQBidiStreamingCall(const std::shared_ptr<Channel>& channel) {
// TODO(yashykt) : Fill this out
}
void MakeCallbackCall(const std::shared_ptr<Channel>& channel) {
auto stub = grpc::testing::EchoTestService::NewStub(channel);
ClientContext ctx;
@ -109,7 +163,6 @@ void MakeCallbackCall(const std::shared_ptr<Channel>& channel) {
EchoResponse resp;
stub->experimental_async()->Echo(&ctx, &req, &resp,
[&resp, &mu, &done, &cv](Status s) {
// gpr_log(GPR_ERROR, "got the callback");
EXPECT_EQ(s.ok(), true);
EXPECT_EQ(resp.message(), "Hello");
std::lock_guard<std::mutex> l(mu);

@ -102,6 +102,16 @@ class EchoTestServiceStreamingImpl : public EchoTestService::Service {
public:
~EchoTestServiceStreamingImpl() override {}
Status Echo(ServerContext* context, const EchoRequest* request,
EchoResponse* response) {
auto client_metadata = context->client_metadata();
for (const auto& pair : client_metadata) {
context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second));
}
response->set_message(request->message());
return Status::OK;
}
Status BidiStream(
ServerContext* context,
grpc::ServerReaderWriter<EchoResponse, EchoRequest>* stream) override {
@ -162,6 +172,14 @@ void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel);
void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel);
void MakeAsyncCQCall(const std::shared_ptr<Channel>& channel);
void MakeAsyncCQClientStreamingCall(const std::shared_ptr<Channel>& channel);
void MakeAsyncCQServerStreamingCall(const std::shared_ptr<Channel>& channel);
void MakeAsyncCQBidiStreamingCall(const std::shared_ptr<Channel>& channel);
void MakeCallbackCall(const std::shared_ptr<Channel>& channel);
bool CheckMetadata(const std::multimap<grpc::string_ref, grpc::string_ref>& map,

File diff suppressed because it is too large Load Diff

@ -202,7 +202,6 @@ grpc_cc_test(
"//src/proto/grpc/testing:echo_messages_proto",
"//src/proto/grpc/testing:echo_proto",
"//src/proto/grpc/testing:simple_messages_proto",
"//test/core/end2end:ssl_test_data",
"//test/core/util:grpc_test_util",
],
)

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!!
VERSION = '1.29.0.dev0'
VERSION = '1.30.0.dev0'

@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 1.29.0-dev
PROJECT_NUMBER = 1.30.0-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 1.29.0-dev
PROJECT_NUMBER = 1.30.0-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Objective-C"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 1.29.0-dev
PROJECT_NUMBER = 1.30.0-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Objective-C"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 1.29.0-dev
PROJECT_NUMBER = 1.30.0-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

@ -786,9 +786,9 @@ _LANGUAGES_WITH_HTTP2_CLIENTS_FOR_HTTP2_SERVER_TEST_CASES = [
'java', 'go', 'python', 'c++'
]
_LANGUAGES_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++']
_LANGUAGES_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++', 'python']
_SERVERS_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++']
_SERVERS_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++', 'python']
_TRANSPORT_SECURITY_OPTIONS = ['tls', 'alts', 'insecure']

@ -226,9 +226,9 @@ _BOOTSTRAP_TEMPLATE = """
# TODO(ericgribkoff) Add change_backend_service to this list once TD no longer
# sends an update with no localities when adding the MIG to the backend service
# can race with the URL map patch.
_TESTS_TO_FAIL_ON_RPC_FAILURE = [
'new_instance_group_receives_traffic', 'ping_pong', 'round_robin'
]
# TODO(ericgribkoff) Add new_instance_group_receives_traffic, ping_pong, and
# round_robin when empty update issue is resolved.
_TESTS_TO_FAIL_ON_RPC_FAILURE = []
_TESTS_USING_SECONDARY_IG = [
'secondary_locality_gets_no_requests_on_partial_primary_failure',
'secondary_locality_gets_requests_on_primary_failure'

Loading…
Cancel
Save