diff --git a/BUILD b/BUILD index b4b10b535e8..ad6903d6847 100644 --- a/BUILD +++ b/BUILD @@ -286,7 +286,7 @@ cc_library( "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", "src/core/ext/census/aggregation.h", "src/core/ext/census/census_interface.h", "src/core/ext/census/census_rpc_stats.h", @@ -440,7 +440,7 @@ cc_library( "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", "src/core/ext/lb_policy/round_robin/round_robin.c", "src/core/ext/resolver/dns/native/dns_resolver.c", @@ -463,6 +463,7 @@ cc_library( "include/grpc/grpc.h", "include/grpc/status.h", "include/grpc/impl/codegen/byte_buffer.h", + "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/grpc_types.h", @@ -617,7 +618,7 @@ cc_library( "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", "src/core/ext/census/aggregation.h", "src/core/ext/census/census_interface.h", "src/core/ext/census/census_rpc_stats.h", @@ -753,7 +754,7 @@ cc_library( "src/core/ext/resolver/dns/native/dns_resolver.c", "src/core/ext/resolver/sockaddr/sockaddr_resolver.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", "src/core/ext/lb_policy/round_robin/round_robin.c", "src/core/ext/census/context.c", @@ -774,6 +775,7 @@ cc_library( "include/grpc/grpc.h", "include/grpc/status.h", "include/grpc/impl/codegen/byte_buffer.h", + "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/grpc_types.h", @@ -946,6 +948,7 @@ cc_library( "include/grpc++/impl/codegen/sync_stream.h", "include/grpc++/impl/codegen/time.h", "include/grpc/impl/codegen/byte_buffer.h", + "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/grpc_types.h", @@ -1091,6 +1094,7 @@ cc_library( "include/grpc++/impl/codegen/sync_stream.h", "include/grpc++/impl/codegen/time.h", "include/grpc/impl/codegen/byte_buffer.h", + "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/grpc_types.h", @@ -1457,7 +1461,7 @@ objc_library( "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", "src/core/ext/lb_policy/round_robin/round_robin.c", "src/core/ext/resolver/dns/native/dns_resolver.c", @@ -1480,6 +1484,7 @@ objc_library( "include/grpc/grpc.h", "include/grpc/status.h", "include/grpc/impl/codegen/byte_buffer.h", + "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/grpc_types.h", @@ -1627,7 +1632,7 @@ objc_library( "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", "src/core/ext/census/aggregation.h", "src/core/ext/census/census_interface.h", "src/core/ext/census/census_rpc_stats.h", diff --git a/Makefile b/Makefile index 922e0b0568f..b9752a6ff7f 100644 --- a/Makefile +++ b/Makefile @@ -407,7 +407,7 @@ E = @echo Q = @ endif -VERSION = 0.14.0-dev +VERSION = 0.15.0-dev CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) @@ -1089,6 +1089,7 @@ connection_prefix_bad_client_test: $(BINDIR)/$(CONFIG)/connection_prefix_bad_cli head_of_line_blocking_bad_client_test: $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test headers_bad_client_test: $(BINDIR)/$(CONFIG)/headers_bad_client_test initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test +large_metadata_bad_client_test: $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test server_registered_method_bad_client_test: $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test simple_request_bad_client_test: $(BINDIR)/$(CONFIG)/simple_request_bad_client_test unknown_frame_bad_client_test: $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test @@ -1318,6 +1319,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \ $(BINDIR)/$(CONFIG)/headers_bad_client_test \ $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \ + $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test \ $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \ $(BINDIR)/$(CONFIG)/simple_request_bad_client_test \ $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \ @@ -1656,6 +1658,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/headers_bad_client_test || ( echo test headers_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing initial_settings_frame_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test || ( echo test initial_settings_frame_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing large_metadata_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test || ( echo test large_metadata_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing server_registered_method_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test || ( echo test server_registered_method_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing simple_request_bad_client_test" @@ -1870,15 +1874,15 @@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc: $(Q) echo "$(GRPCXX_UNSECURE_PC_FILE)" | tr , '\n' >$@ ifeq ($(NO_PROTOC),true) -$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc: protoc_dep_error -$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc: protoc_dep_error +$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: protoc_dep_error +$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: protoc_dep_error else -$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc: src/proto/grpc/lb/v0/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) +$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) --cpp_out=$(GENDIR) $< -$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v0/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) +$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $< @@ -2624,7 +2628,7 @@ LIBGRPC_SRC = \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ + src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ @@ -2650,6 +2654,7 @@ PUBLIC_HEADERS_C += \ include/grpc/grpc.h \ include/grpc/status.h \ include/grpc/impl/codegen/byte_buffer.h \ + include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ @@ -2946,7 +2951,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/resolver/dns/native/dns_resolver.c \ src/core/ext/resolver/sockaddr/sockaddr_resolver.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ + src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ @@ -2970,6 +2975,7 @@ PUBLIC_HEADERS_C += \ include/grpc/grpc.h \ include/grpc/status.h \ include/grpc/impl/codegen/byte_buffer.h \ + include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ @@ -3256,6 +3262,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ include/grpc/impl/codegen/byte_buffer.h \ + include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ @@ -3559,6 +3566,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ include/grpc/impl/codegen/byte_buffer.h \ + include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ @@ -10742,7 +10750,7 @@ endif GRPCLB_API_TEST_SRC = \ - $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc \ + $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \ test/cpp/grpclb/grpclb_api_test.cc \ GRPCLB_API_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPCLB_API_TEST_SRC)))) @@ -10774,7 +10782,7 @@ endif endif -$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v0/load_balancer.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a +$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v1/load_balancer.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a @@ -10785,7 +10793,7 @@ ifneq ($(NO_DEPS),true) -include $(GRPCLB_API_TEST_OBJS:.o=.dep) endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc +$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc HYBRID_END2END_TEST_SRC = \ @@ -13100,6 +13108,26 @@ ifneq ($(NO_DEPS),true) endif +LARGE_METADATA_BAD_CLIENT_TEST_SRC = \ + test/core/bad_client/tests/large_metadata.c \ + +LARGE_METADATA_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LARGE_METADATA_BAD_CLIENT_TEST_SRC)))) + + +$(BINDIR)/$(CONFIG)/large_metadata_bad_client_test: $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test + +$(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/large_metadata.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_large_metadata_bad_client_test: $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS:.o=.dep) + +ifneq ($(NO_DEPS),true) +-include $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS:.o=.dep) +endif + + SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/server_registered_method.c \ diff --git a/binding.gyp b/binding.gyp index 4314ab7243d..8bc2aee3d1a 100644 --- a/binding.gyp +++ b/binding.gyp @@ -710,7 +710,7 @@ 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_decode.c', 'third_party/nanopb/pb_encode.c', diff --git a/build.yaml b/build.yaml index 441752dc3dc..c9381e9bc5d 100644 --- a/build.yaml +++ b/build.yaml @@ -7,7 +7,7 @@ settings: '#3': Use "-preN" suffixes to identify pre-release versions '#4': Per-language overrides are possible with (eg) ruby_version tag here '#5': See the expand_version.py for all the quirks here - version: 0.14.0-dev + version: 0.15.0-dev filegroups: - name: census public_headers: @@ -351,6 +351,7 @@ filegroups: - name: grpc_codegen public_headers: - include/grpc/impl/codegen/byte_buffer.h + - include/grpc/impl/codegen/byte_buffer_reader.h - include/grpc/impl/codegen/compression_types.h - include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/grpc_types.h @@ -361,10 +362,10 @@ filegroups: - name: grpc_lb_policy_grpclb headers: - src/core/ext/lb_policy/grpclb/load_balancer_api.h - - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h + - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h src: - src/core/ext/lb_policy/grpclb/load_balancer_api.c - - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c + - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c uses: - grpc_base - grpc_client_config @@ -2642,7 +2643,7 @@ targets: build: test language: c++ src: - - src/proto/grpc/lb/v0/load_balancer.proto + - src/proto/grpc/lb/v1/load_balancer.proto - test/cpp/grpclb/grpclb_api_test.cc deps: - grpc++_test_util diff --git a/composer.json b/composer.json index 97b1a5cb49b..b77a59e351c 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc", "type": "library", "description": "gRPC library for PHP", - "version": "0.14.0", + "version": "0.15.0", "keywords": ["rpc"], "homepage": "http://grpc.io", "license": "BSD-3-Clause", diff --git a/config.m4 b/config.m4 index 74f9ad242ab..c8d2aae106c 100644 --- a/config.m4 +++ b/config.m4 @@ -229,7 +229,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ + src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ @@ -555,7 +555,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/client_config) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb) - PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/pick_first) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/round_robin) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/resolver/dns/native) diff --git a/examples/cpp/helloworld/Makefile b/examples/cpp/helloworld/Makefile index 470b83573e4..58a82dbb831 100644 --- a/examples/cpp/helloworld/Makefile +++ b/examples/cpp/helloworld/Makefile @@ -41,7 +41,7 @@ PROTOS_PATH = ../../protos vpath %.proto $(PROTOS_PATH) -all: system-check greeter_client greeter_server greeter_async_client greeter_async_server +all: system-check greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o $(CXX) $^ $(LDFLAGS) -o $@ @@ -52,6 +52,9 @@ greeter_server: helloworld.pb.o helloworld.grpc.pb.o greeter_server.o greeter_async_client: helloworld.pb.o helloworld.grpc.pb.o greeter_async_client.o $(CXX) $^ $(LDFLAGS) -o $@ +greeter_async_client2: helloworld.pb.o helloworld.grpc.pb.o greeter_async_client2.o + $(CXX) $^ $(LDFLAGS) -o $@ + greeter_async_server: helloworld.pb.o helloworld.grpc.pb.o greeter_async_server.o $(CXX) $^ $(LDFLAGS) -o $@ @@ -64,7 +67,7 @@ greeter_async_server: helloworld.pb.o helloworld.grpc.pb.o greeter_async_server. $(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $< clean: - rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server greeter_async_client greeter_async_server + rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server # The following is to test your system and ensure a smoother experience. diff --git a/examples/cpp/helloworld/greeter_async_client.cc b/examples/cpp/helloworld/greeter_async_client.cc index 35014267feb..c1f5eb55f05 100644 --- a/examples/cpp/helloworld/greeter_async_client.cc +++ b/examples/cpp/helloworld/greeter_async_client.cc @@ -53,7 +53,7 @@ class GreeterClient { explicit GreeterClient(std::shared_ptr channel) : stub_(Greeter::NewStub(channel)) {} - // Assambles the client's payload, sends it and presents the response back + // Assembles the client's payload, sends it and presents the response back // from the server. std::string SayHello(const std::string& user) { // Data we are sending to the server. @@ -74,9 +74,9 @@ class GreeterClient { // Storage for the status of the RPC upon completion. Status status; - // stub_->AsyncSayHello() perform the RPC call, returning an instance we - // store in "rpc". Because we are using the asynchronous API, we need the - // hold on to the "rpc" instance in order to get updates on the ongoig RPC. + // stub_->AsyncSayHello() performs the RPC call, returning an instance we + // store in "rpc". Because we are using the asynchronous API, we need to + // hold on to the "rpc" instance in order to get updates on the ongoing RPC. std::unique_ptr > rpc( stub_->AsyncSayHello(&context, request, &cq)); diff --git a/examples/cpp/helloworld/greeter_async_client2.cc b/examples/cpp/helloworld/greeter_async_client2.cc new file mode 100644 index 00000000000..0902376074e --- /dev/null +++ b/examples/cpp/helloworld/greeter_async_client2.cc @@ -0,0 +1,153 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include +#include + +#include "helloworld.grpc.pb.h" + +using grpc::Channel; +using grpc::ClientAsyncResponseReader; +using grpc::ClientContext; +using grpc::CompletionQueue; +using grpc::Status; +using helloworld::HelloRequest; +using helloworld::HelloReply; +using helloworld::Greeter; + +class GreeterClient { + public: + explicit GreeterClient(std::shared_ptr channel) + : stub_(Greeter::NewStub(channel)) {} + + // Assembles the client's payload and sends it to the server. + void SayHello(const std::string& user) { + // Data we are sending to the server. + HelloRequest request; + request.set_name(user); + + // Call object to store rpc data + AsyncClientCall* call = new AsyncClientCall; + + // stub_->AsyncSayHello() performs the RPC call, returning an instance to + // store in "call". Because we are using the asynchronous API, we need to + // hold on to the "call" instance in order to get updates on the ongoing RPC. + call->response_reader = stub_->AsyncSayHello(&call->context, request, &cq_); + + + // Request that, upon completion of the RPC, "reply" be updated with the + // server's response; "status" with the indication of whether the operation + // was successful. Tag the request with the memory address of the call object. + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + } + + // Loop while listening for completed responses. + // Prints out the response from the server. + void AsyncCompleteRpc() { + void* got_tag; + bool ok = false; + + // Block until the next result is available in the completion queue "cq". + while (cq_.Next(&got_tag, &ok)) { + // The tag in this example is the memory location of the call object + AsyncClientCall* call = static_cast(got_tag); + + // Verify that the request was completed successfully. Note that "ok" + // corresponds solely to the request for updates introduced by Finish(). + GPR_ASSERT(ok); + + if (call->status.ok()) + std::cout << "Greeter received: " << call->reply.message() << std::endl; + else + std::cout << "RPC failed" << std::endl; + + // Once we're complete, deallocate the call object. + delete call; + } + } + + private: + + // struct for keeping state and data information + struct AsyncClientCall { + // Container for the data we expect from the server. + HelloReply reply; + + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. + ClientContext context; + + // Storage for the status of the RPC upon completion. + Status status; + + + std::unique_ptr> response_reader; + }; + + // Out of the passed in Channel comes the stub, stored here, our view of the + // server's exposed services. + std::unique_ptr stub_; + + // The producer-consumer queue we use to communicate asynchronously with the + // gRPC runtime. + CompletionQueue cq_; +}; + +int main(int argc, char** argv) { + + + // Instantiate the client. It requires a channel, out of which the actual RPCs + // are created. This channel models a connection to an endpoint (in this case, + // localhost at port 50051). We indicate that the channel isn't authenticated + // (use of InsecureChannelCredentials()). + GreeterClient greeter(grpc::CreateChannel( + "localhost:50051", grpc::InsecureChannelCredentials())); + + // Spawn reader thread that loops indefinitely + std::thread thread_ = std::thread(&GreeterClient::AsyncCompleteRpc, &greeter); + + for (int i = 0; i < 100; i++) { + std::string user("world " + std::to_string(i)); + greeter.SayHello(user); // The actual RPC call! + } + + std::cout << "Press control-c to quit" << std::endl << std::endl; + thread_.join(); //blocks forever + + return 0; +} diff --git a/examples/objective-c/route_guide/ViewControllers.m b/examples/objective-c/route_guide/ViewControllers.m index 0b1a1cf4823..e32978240b6 100644 --- a/examples/objective-c/route_guide/ViewControllers.m +++ b/examples/objective-c/route_guide/ViewControllers.m @@ -80,19 +80,14 @@ static NSString * const kHostAddress = @"localhost:50051"; * Run the getFeature demo. Calls getFeature with a point known to have a feature and a point known * not to have a feature. */ -@interface GetFeatureViewController : UIViewController +@interface GetFeatureViewController : UIViewController { + RTGRouteGuide *service; +} @end @implementation GetFeatureViewController -- (void)viewDidLoad { - [super viewDidLoad]; - - // This only needs to be done once per host, before creating service objects for that host. - [GRPCCall useInsecureConnectionsForHost:kHostAddress]; - - RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; - +- (void)execRequest { void (^handler)(RTGFeature *response, NSError *error) = ^(RTGFeature *response, NSError *error) { if (response.name.length) { NSLog(@"Found feature called %@ at %@.", response.name, response.location); @@ -111,6 +106,19 @@ static NSString * const kHostAddress = @"localhost:50051"; [service getFeatureWithRequest:[RTGPoint message] handler:handler]; } +- (void)viewDidLoad { + [super viewDidLoad]; + + // This only needs to be done once per host, before creating service objects for that host. + [GRPCCall useInsecureConnectionsForHost:kHostAddress]; + + service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; +} + +- (void)viewDidAppear:(BOOL)animated { + [self execRequest]; +} + @end @@ -120,16 +128,15 @@ static NSString * const kHostAddress = @"localhost:50051"; * Run the listFeatures demo. Calls listFeatures with a rectangle containing all of the features in * the pre-generated database. Prints each response as it comes in. */ -@interface ListFeaturesViewController : UIViewController +@interface ListFeaturesViewController : UIViewController { + RTGRouteGuide *service; +} + @end @implementation ListFeaturesViewController -- (void)viewDidLoad { - [super viewDidLoad]; - - RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; - +- (void)execRequest { RTGRectangle *rectangle = [RTGRectangle message]; rectangle.lo.latitude = 405E6; rectangle.lo.longitude = -750E6; @@ -147,6 +154,16 @@ static NSString * const kHostAddress = @"localhost:50051"; }]; } +- (void)viewDidLoad { + [super viewDidLoad]; + + service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; +} + +- (void)viewDidAppear:(BOOL)animated { + [self execRequest]; +} + @end @@ -157,14 +174,15 @@ static NSString * const kHostAddress = @"localhost:50051"; * database with a variable delay in between. Prints the statistics when they are sent from the * server. */ -@interface RecordRouteViewController : UIViewController +@interface RecordRouteViewController : UIViewController { + RTGRouteGuide *service; +} + @end @implementation RecordRouteViewController -- (void)viewDidLoad { - [super viewDidLoad]; - +- (void)execRequest { NSString *dataBasePath = [NSBundle.mainBundle pathForResource:@"route_guide_db" ofType:@"json"]; NSData *dataBaseContent = [NSData dataWithContentsOfFile:dataBasePath]; @@ -178,8 +196,6 @@ static NSString * const kHostAddress = @"localhost:50051"; return location; }]; - RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; - [service recordRouteWithRequestsWriter:locations handler:^(RTGRouteSummary *response, NSError *error) { if (response) { @@ -193,6 +209,16 @@ static NSString * const kHostAddress = @"localhost:50051"; }]; } +- (void)viewDidLoad { + [super viewDidLoad]; + + service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; +} + +- (void)viewDidAppear:(BOOL)animated { + [self execRequest]; +} + @end @@ -202,14 +228,15 @@ static NSString * const kHostAddress = @"localhost:50051"; * Run the routeChat demo. Send some chat messages, and print any chat messages that are sent from * the server. */ -@interface RouteChatViewController : UIViewController +@interface RouteChatViewController : UIViewController { + RTGRouteGuide *service; +} + @end @implementation RouteChatViewController -- (void)viewDidLoad { - [super viewDidLoad]; - +- (void)execRequest { NSArray *notes = @[[RTGRouteNote noteWithMessage:@"First message" latitude:0 longitude:0], [RTGRouteNote noteWithMessage:@"Second message" latitude:0 longitude:1], [RTGRouteNote noteWithMessage:@"Third message" latitude:1 longitude:0], @@ -219,8 +246,6 @@ static NSString * const kHostAddress = @"localhost:50051"; return note; }]; - RTGRouteGuide *service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; - [service routeChatWithRequestsWriter:notesWriter eventHandler:^(BOOL done, RTGRouteNote *note, NSError *error) { if (note) { @@ -234,4 +259,14 @@ static NSString * const kHostAddress = @"localhost:50051"; }]; } +- (void)viewDidLoad { + [super viewDidLoad]; + + service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; +} + +- (void)viewDidAppear:(BOOL)animated { + [self execRequest]; +} + @end diff --git a/examples/python/helloworld/helloworld_pb2.py b/examples/python/helloworld/helloworld_pb2.py index 1b2674e4c8e..1ee80e4034c 100644 --- a/examples/python/helloworld/helloworld_pb2.py +++ b/examples/python/helloworld/helloworld_pb2.py @@ -1,6 +1,8 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # source: helloworld.proto +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -17,7 +19,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( name='helloworld.proto', package='helloworld', syntax='proto3', - serialized_pb=b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x18\n\x10io.grpc.examples\xa2\x02\x03HLWb\x06proto3' + serialized_pb=_b('\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -34,7 +36,7 @@ _HELLOREQUEST = _descriptor.Descriptor( _descriptor.FieldDescriptor( name='name', full_name='helloworld.HelloRequest.name', index=0, number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -65,7 +67,7 @@ _HELLOREPLY = _descriptor.Descriptor( _descriptor.FieldDescriptor( name='message', full_name='helloworld.HelloReply.message', index=0, number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -104,69 +106,28 @@ _sym_db.RegisterMessage(HelloReply) DESCRIPTOR.has_options = True -DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), b'\n\020io.grpc.examples\242\002\003HLW') +DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW')) import abc +import six from grpc.beta import implementations as beta_implementations -from grpc.early_adopter import implementations as early_adopter_implementations -from grpc.framework.alpha import utilities as alpha_utilities +from grpc.beta import interfaces as beta_interfaces from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities -class EarlyAdopterGreeterServicer(object): - """""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def SayHello(self, request, context): - raise NotImplementedError() -class EarlyAdopterGreeterServer(object): - """""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def start(self): - raise NotImplementedError() - @abc.abstractmethod - def stop(self): - raise NotImplementedError() -class EarlyAdopterGreeterStub(object): - """""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def SayHello(self, request): - raise NotImplementedError() - SayHello.async = None -def early_adopter_create_Greeter_server(servicer, port, private_key=None, certificate_chain=None): - import helloworld_pb2 - import helloworld_pb2 - method_service_descriptions = { - "SayHello": alpha_utilities.unary_unary_service_description( - servicer.SayHello, - helloworld_pb2.HelloRequest.FromString, - helloworld_pb2.HelloReply.SerializeToString, - ), - } - return early_adopter_implementations.server("helloworld.Greeter", method_service_descriptions, port, private_key=private_key, certificate_chain=certificate_chain) -def early_adopter_create_Greeter_stub(host, port, metadata_transformer=None, secure=False, root_certificates=None, private_key=None, certificate_chain=None, server_host_override=None): - import helloworld_pb2 - import helloworld_pb2 - method_invocation_descriptions = { - "SayHello": alpha_utilities.unary_unary_invocation_description( - helloworld_pb2.HelloRequest.SerializeToString, - helloworld_pb2.HelloReply.FromString, - ), - } - return early_adopter_implementations.stub("helloworld.Greeter", method_invocation_descriptions, host, port, metadata_transformer=metadata_transformer, secure=secure, root_certificates=root_certificates, private_key=private_key, certificate_chain=certificate_chain, server_host_override=server_host_override) class BetaGreeterServicer(object): - """""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod + """The greeting service definition. + """ def SayHello(self, request, context): - raise NotImplementedError() + """Sends a greeting + """ + context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) class BetaGreeterStub(object): - """The interface to which stubs will conform.""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod + """The greeting service definition. + """ def SayHello(self, request, timeout): + """Sends a greeting + """ raise NotImplementedError() SayHello.future = None diff --git a/examples/python/route_guide/route_guide_pb2.py b/examples/python/route_guide/route_guide_pb2.py index d4d9f8dcd5d..81d5d075274 100644 --- a/examples/python/route_guide/route_guide_pb2.py +++ b/examples/python/route_guide/route_guide_pb2.py @@ -1,6 +1,8 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # source: route_guide.proto +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -17,7 +19,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( name='route_guide.proto', package='routeguide', syntax='proto3', - serialized_pb=b'\n\x11route_guide.proto\x12\nrouteguide\",\n\x05Point\x12\x10\n\x08latitude\x18\x01 \x01(\x05\x12\x11\n\tlongitude\x18\x02 \x01(\x05\"I\n\tRectangle\x12\x1d\n\x02lo\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x1d\n\x02hi\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"<\n\x07\x46\x65\x61ture\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x08location\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"A\n\tRouteNote\x12#\n\x08location\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x0f\n\x07message\x18\x02 \x01(\t\"b\n\x0cRouteSummary\x12\x13\n\x0bpoint_count\x18\x01 \x01(\x05\x12\x15\n\rfeature_count\x18\x02 \x01(\x05\x12\x10\n\x08\x64istance\x18\x03 \x01(\x05\x12\x14\n\x0c\x65lapsed_time\x18\x04 \x01(\x05\x32\x85\x02\n\nRouteGuide\x12\x36\n\nGetFeature\x12\x11.routeguide.Point\x1a\x13.routeguide.Feature\"\x00\x12>\n\x0cListFeatures\x12\x15.routeguide.Rectangle\x1a\x13.routeguide.Feature\"\x00\x30\x01\x12>\n\x0bRecordRoute\x12\x11.routeguide.Point\x1a\x18.routeguide.RouteSummary\"\x00(\x01\x12?\n\tRouteChat\x12\x15.routeguide.RouteNote\x1a\x15.routeguide.RouteNote\"\x00(\x01\x30\x01\x42\x0f\n\x07\x65x.grpc\xa2\x02\x03RTGb\x06proto3' + serialized_pb=_b('\n\x11route_guide.proto\x12\nrouteguide\",\n\x05Point\x12\x10\n\x08latitude\x18\x01 \x01(\x05\x12\x11\n\tlongitude\x18\x02 \x01(\x05\"I\n\tRectangle\x12\x1d\n\x02lo\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x1d\n\x02hi\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"<\n\x07\x46\x65\x61ture\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x08location\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"A\n\tRouteNote\x12#\n\x08location\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x0f\n\x07message\x18\x02 \x01(\t\"b\n\x0cRouteSummary\x12\x13\n\x0bpoint_count\x18\x01 \x01(\x05\x12\x15\n\rfeature_count\x18\x02 \x01(\x05\x12\x10\n\x08\x64istance\x18\x03 \x01(\x05\x12\x14\n\x0c\x65lapsed_time\x18\x04 \x01(\x05\x32\x85\x02\n\nRouteGuide\x12\x36\n\nGetFeature\x12\x11.routeguide.Point\x1a\x13.routeguide.Feature\"\x00\x12>\n\x0cListFeatures\x12\x15.routeguide.Rectangle\x1a\x13.routeguide.Feature\"\x00\x30\x01\x12>\n\x0bRecordRoute\x12\x11.routeguide.Point\x1a\x18.routeguide.RouteSummary\"\x00(\x01\x12?\n\tRouteChat\x12\x15.routeguide.RouteNote\x1a\x15.routeguide.RouteNote\"\x00(\x01\x30\x01\x42\x36\n\x1bio.grpc.examples.routeguideB\x0fRouteGuideProtoP\x01\xa2\x02\x03RTGb\x06proto3') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -110,7 +112,7 @@ _FEATURE = _descriptor.Descriptor( _descriptor.FieldDescriptor( name='name', full_name='routeguide.Feature.name', index=0, number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -155,7 +157,7 @@ _ROUTENOTE = _descriptor.Descriptor( _descriptor.FieldDescriptor( name='message', full_name='routeguide.RouteNote.message', index=1, number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -274,149 +276,86 @@ _sym_db.RegisterMessage(RouteSummary) DESCRIPTOR.has_options = True -DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), b'\n\007ex.grpc\242\002\003RTG') +DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.routeguideB\017RouteGuideProtoP\001\242\002\003RTG')) import abc +import six from grpc.beta import implementations as beta_implementations -from grpc.early_adopter import implementations as early_adopter_implementations -from grpc.framework.alpha import utilities as alpha_utilities +from grpc.beta import interfaces as beta_interfaces from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities -class EarlyAdopterRouteGuideServicer(object): - """""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def GetFeature(self, request, context): - raise NotImplementedError() - @abc.abstractmethod - def ListFeatures(self, request, context): - raise NotImplementedError() - @abc.abstractmethod - def RecordRoute(self, request_iterator, context): - raise NotImplementedError() - @abc.abstractmethod - def RouteChat(self, request_iterator, context): - raise NotImplementedError() -class EarlyAdopterRouteGuideServer(object): - """""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def start(self): - raise NotImplementedError() - @abc.abstractmethod - def stop(self): - raise NotImplementedError() -class EarlyAdopterRouteGuideStub(object): - """""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def GetFeature(self, request): - raise NotImplementedError() - GetFeature.async = None - @abc.abstractmethod - def ListFeatures(self, request): - raise NotImplementedError() - ListFeatures.async = None - @abc.abstractmethod - def RecordRoute(self, request_iterator): - raise NotImplementedError() - RecordRoute.async = None - @abc.abstractmethod - def RouteChat(self, request_iterator): - raise NotImplementedError() - RouteChat.async = None -def early_adopter_create_RouteGuide_server(servicer, port, private_key=None, certificate_chain=None): - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - method_service_descriptions = { - "GetFeature": alpha_utilities.unary_unary_service_description( - servicer.GetFeature, - route_guide_pb2.Point.FromString, - route_guide_pb2.Feature.SerializeToString, - ), - "ListFeatures": alpha_utilities.unary_stream_service_description( - servicer.ListFeatures, - route_guide_pb2.Rectangle.FromString, - route_guide_pb2.Feature.SerializeToString, - ), - "RecordRoute": alpha_utilities.stream_unary_service_description( - servicer.RecordRoute, - route_guide_pb2.Point.FromString, - route_guide_pb2.RouteSummary.SerializeToString, - ), - "RouteChat": alpha_utilities.stream_stream_service_description( - servicer.RouteChat, - route_guide_pb2.RouteNote.FromString, - route_guide_pb2.RouteNote.SerializeToString, - ), - } - return early_adopter_implementations.server("routeguide.RouteGuide", method_service_descriptions, port, private_key=private_key, certificate_chain=certificate_chain) -def early_adopter_create_RouteGuide_stub(host, port, metadata_transformer=None, secure=False, root_certificates=None, private_key=None, certificate_chain=None, server_host_override=None): - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - import route_guide_pb2 - method_invocation_descriptions = { - "GetFeature": alpha_utilities.unary_unary_invocation_description( - route_guide_pb2.Point.SerializeToString, - route_guide_pb2.Feature.FromString, - ), - "ListFeatures": alpha_utilities.unary_stream_invocation_description( - route_guide_pb2.Rectangle.SerializeToString, - route_guide_pb2.Feature.FromString, - ), - "RecordRoute": alpha_utilities.stream_unary_invocation_description( - route_guide_pb2.Point.SerializeToString, - route_guide_pb2.RouteSummary.FromString, - ), - "RouteChat": alpha_utilities.stream_stream_invocation_description( - route_guide_pb2.RouteNote.SerializeToString, - route_guide_pb2.RouteNote.FromString, - ), - } - return early_adopter_implementations.stub("routeguide.RouteGuide", method_invocation_descriptions, host, port, metadata_transformer=metadata_transformer, secure=secure, root_certificates=root_certificates, private_key=private_key, certificate_chain=certificate_chain, server_host_override=server_host_override) class BetaRouteGuideServicer(object): - """""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod + """Interface exported by the server. + """ def GetFeature(self, request, context): - raise NotImplementedError() - @abc.abstractmethod + """A simple RPC. + + Obtains the feature at a given position. + + A feature with an empty name is returned if there's no feature at the given + position. + """ + context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) def ListFeatures(self, request, context): - raise NotImplementedError() - @abc.abstractmethod + """A server-to-client streaming RPC. + + Obtains the Features available within the given Rectangle. Results are + streamed rather than returned at once (e.g. in a response message with a + repeated field), as the rectangle may cover a large area and contain a + huge number of features. + """ + context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) def RecordRoute(self, request_iterator, context): - raise NotImplementedError() - @abc.abstractmethod + """A client-to-server streaming RPC. + + Accepts a stream of Points on a route being traversed, returning a + RouteSummary when traversal is completed. + """ + context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) def RouteChat(self, request_iterator, context): - raise NotImplementedError() + """A Bidirectional streaming RPC. + + Accepts a stream of RouteNotes sent while a route is being traversed, + while receiving other RouteNotes (e.g. from other users). + """ + context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) class BetaRouteGuideStub(object): - """The interface to which stubs will conform.""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod + """Interface exported by the server. + """ def GetFeature(self, request, timeout): + """A simple RPC. + + Obtains the feature at a given position. + + A feature with an empty name is returned if there's no feature at the given + position. + """ raise NotImplementedError() GetFeature.future = None - @abc.abstractmethod def ListFeatures(self, request, timeout): + """A server-to-client streaming RPC. + + Obtains the Features available within the given Rectangle. Results are + streamed rather than returned at once (e.g. in a response message with a + repeated field), as the rectangle may cover a large area and contain a + huge number of features. + """ raise NotImplementedError() - @abc.abstractmethod def RecordRoute(self, request_iterator, timeout): + """A client-to-server streaming RPC. + + Accepts a stream of Points on a route being traversed, returning a + RouteSummary when traversal is completed. + """ raise NotImplementedError() RecordRoute.future = None - @abc.abstractmethod def RouteChat(self, request_iterator, timeout): + """A Bidirectional streaming RPC. + + Accepts a stream of RouteNotes sent while a route is being traversed, + while receiving other RouteNotes (e.g. from other users). + """ raise NotImplementedError() def beta_create_RouteGuide_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None): diff --git a/gRPC.podspec b/gRPC.podspec index 77d35bd2c79..393733209de 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '0.12.0' + version = '0.14.0' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'http://www.grpc.io' @@ -44,7 +44,8 @@ Pod::Spec.new do |s| s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } s.source = { :git => 'https://github.com/grpc/grpc.git', - :tag => "release-#{version.gsub(/\./, '_')}-objectivec-#{version}" } + :tag => "release-#{version.gsub(/\./, '_')}-objectivec-#{version}", + :submodules => true } s.ios.deployment_target = '7.1' @@ -288,7 +289,7 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', 'third_party/nanopb/pb_common.h', 'third_party/nanopb/pb_decode.h', @@ -305,6 +306,7 @@ Pod::Spec.new do |s| 'include/grpc/grpc.h', 'include/grpc/status.h', 'include/grpc/impl/codegen/byte_buffer.h', + 'include/grpc/impl/codegen/byte_buffer_reader.h', 'include/grpc/impl/codegen/compression_types.h', 'include/grpc/impl/codegen/connectivity_state.h', 'include/grpc/impl/codegen/grpc_types.h', @@ -474,7 +476,7 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_decode.c', 'third_party/nanopb/pb_encode.c', @@ -630,7 +632,7 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', 'third_party/nanopb/pb_common.h', 'third_party/nanopb/pb_decode.h', @@ -654,7 +656,7 @@ Pod::Spec.new do |s| ss.requires_arc = false ss.libraries = 'z' - ss.dependency 'BoringSSL', '~> 2.0' + ss.dependency 'BoringSSL', '~> 3.0' # ss.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w' end diff --git a/grpc.gemspec b/grpc.gemspec index e68cd81da7a..240ea1ca1ff 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -149,6 +149,7 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/grpc.h ) s.files += %w( include/grpc/status.h ) s.files += %w( include/grpc/impl/codegen/byte_buffer.h ) + s.files += %w( include/grpc/impl/codegen/byte_buffer_reader.h ) s.files += %w( include/grpc/impl/codegen/compression_types.h ) s.files += %w( include/grpc/impl/codegen/connectivity_state.h ) s.files += %w( include/grpc/impl/codegen/grpc_types.h ) @@ -296,7 +297,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/subchannel_index.h ) s.files += %w( src/core/ext/client_config/uri_parser.h ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h ) - s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h ) + s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h ) s.files += %w( third_party/nanopb/pb.h ) s.files += %w( third_party/nanopb/pb_common.h ) s.files += %w( third_party/nanopb/pb_decode.h ) @@ -454,7 +455,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c ) - s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c ) + s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c ) s.files += %w( third_party/nanopb/pb_common.c ) s.files += %w( third_party/nanopb/pb_decode.c ) s.files += %w( third_party/nanopb/pb_encode.c ) diff --git a/include/grpc++/impl/codegen/core_codegen_interface.h b/include/grpc++/impl/codegen/core_codegen_interface.h index 16424bab358..aa9013c4cec 100644 --- a/include/grpc++/impl/codegen/core_codegen_interface.h +++ b/include/grpc++/impl/codegen/core_codegen_interface.h @@ -49,18 +49,6 @@ namespace grpc { /// \warning This interface should be considered internal and private. class CoreCodegenInterface { public: - // Serialize the msg into a buffer created inside the function. The caller - // should destroy the returned buffer when done with it. If serialization - // fails, - // false is returned and buffer is left unchanged. - virtual Status SerializeProto(const grpc::protobuf::Message& msg, - grpc_byte_buffer** buffer) = 0; - - // The caller keeps ownership of buffer and msg. - virtual Status DeserializeProto(grpc_byte_buffer* buffer, - grpc::protobuf::Message* msg, - int max_message_size) = 0; - /// Upon a failed assertion, log the error. virtual void assert_fail(const char* failed_assertion) = 0; @@ -76,9 +64,29 @@ class CoreCodegenInterface { virtual void gpr_free(void* p) = 0; virtual void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) = 0; + + virtual void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader, + grpc_byte_buffer* buffer) = 0; + virtual void grpc_byte_buffer_reader_destroy( + grpc_byte_buffer_reader* reader) = 0; + virtual int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader, + gpr_slice* slice) = 0; + + virtual grpc_byte_buffer* grpc_raw_byte_buffer_create(gpr_slice* slice, + size_t nslices) = 0; + + virtual gpr_slice gpr_slice_malloc(size_t length) = 0; + virtual void gpr_slice_unref(gpr_slice slice) = 0; + virtual gpr_slice gpr_slice_split_tail(gpr_slice* s, size_t split) = 0; + virtual void gpr_slice_buffer_add(gpr_slice_buffer* sb, gpr_slice slice) = 0; + virtual void gpr_slice_buffer_pop(gpr_slice_buffer* sb) = 0; + virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0; virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0; + virtual const Status& ok() = 0; + virtual const Status& cancelled() = 0; + virtual gpr_timespec gpr_inf_future(gpr_clock_type type) = 0; }; diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h index 2aaa3c3b300..d044ddc642d 100644 --- a/include/grpc++/impl/codegen/proto_utils.h +++ b/include/grpc++/impl/codegen/proto_utils.h @@ -41,26 +41,179 @@ #include #include #include +#include #include +#include namespace grpc { extern CoreCodegenInterface* g_core_codegen_interface; +namespace { + +const int kGrpcBufferWriterMaxBufferLength = 8192; + +class GrpcBufferWriter GRPC_FINAL + : public ::grpc::protobuf::io::ZeroCopyOutputStream { + public: + explicit GrpcBufferWriter(grpc_byte_buffer** bp, int block_size) + : block_size_(block_size), byte_count_(0), have_backup_(false) { + *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(NULL, 0); + slice_buffer_ = &(*bp)->data.raw.slice_buffer; + } + + ~GrpcBufferWriter() GRPC_OVERRIDE { + if (have_backup_) { + g_core_codegen_interface->gpr_slice_unref(backup_slice_); + } + } + + bool Next(void** data, int* size) GRPC_OVERRIDE { + if (have_backup_) { + slice_ = backup_slice_; + have_backup_ = false; + } else { + slice_ = g_core_codegen_interface->gpr_slice_malloc(block_size_); + } + *data = GPR_SLICE_START_PTR(slice_); + // On win x64, int is only 32bit + GPR_CODEGEN_ASSERT(GPR_SLICE_LENGTH(slice_) <= INT_MAX); + byte_count_ += * size = (int)GPR_SLICE_LENGTH(slice_); + g_core_codegen_interface->gpr_slice_buffer_add(slice_buffer_, slice_); + return true; + } + + void BackUp(int count) GRPC_OVERRIDE { + g_core_codegen_interface->gpr_slice_buffer_pop(slice_buffer_); + if (count == block_size_) { + backup_slice_ = slice_; + } else { + backup_slice_ = g_core_codegen_interface->gpr_slice_split_tail( + &slice_, GPR_SLICE_LENGTH(slice_) - count); + g_core_codegen_interface->gpr_slice_buffer_add(slice_buffer_, slice_); + } + have_backup_ = true; + byte_count_ -= count; + } + + grpc::protobuf::int64 ByteCount() const GRPC_OVERRIDE { return byte_count_; } + + private: + const int block_size_; + int64_t byte_count_; + gpr_slice_buffer* slice_buffer_; + bool have_backup_; + gpr_slice backup_slice_; + gpr_slice slice_; +}; + +class GrpcBufferReader GRPC_FINAL + : public ::grpc::protobuf::io::ZeroCopyInputStream { + public: + explicit GrpcBufferReader(grpc_byte_buffer* buffer) + : byte_count_(0), backup_count_(0) { + g_core_codegen_interface->grpc_byte_buffer_reader_init(&reader_, buffer); + } + ~GrpcBufferReader() GRPC_OVERRIDE { + g_core_codegen_interface->grpc_byte_buffer_reader_destroy(&reader_); + } + + bool Next(const void** data, int* size) GRPC_OVERRIDE { + if (backup_count_ > 0) { + *data = GPR_SLICE_START_PTR(slice_) + GPR_SLICE_LENGTH(slice_) - + backup_count_; + GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX); + *size = (int)backup_count_; + backup_count_ = 0; + return true; + } + if (!g_core_codegen_interface->grpc_byte_buffer_reader_next(&reader_, + &slice_)) { + return false; + } + g_core_codegen_interface->gpr_slice_unref(slice_); + *data = GPR_SLICE_START_PTR(slice_); + // On win x64, int is only 32bit + GPR_CODEGEN_ASSERT(GPR_SLICE_LENGTH(slice_) <= INT_MAX); + byte_count_ += * size = (int)GPR_SLICE_LENGTH(slice_); + return true; + } + + void BackUp(int count) GRPC_OVERRIDE { backup_count_ = count; } + + bool Skip(int count) GRPC_OVERRIDE { + const void* data; + int size; + while (Next(&data, &size)) { + if (size >= count) { + BackUp(size - count); + return true; + } + // size < count; + count -= size; + } + // error or we have too large count; + return false; + } + + grpc::protobuf::int64 ByteCount() const GRPC_OVERRIDE { + return byte_count_ - backup_count_; + } + + private: + int64_t byte_count_; + int64_t backup_count_; + grpc_byte_buffer_reader reader_; + gpr_slice slice_; +}; +} // namespace + template class SerializationTraits::value>::type> { public: static Status Serialize(const grpc::protobuf::Message& msg, - grpc_byte_buffer** buffer, bool* own_buffer) { + grpc_byte_buffer** bp, bool* own_buffer) { *own_buffer = true; - return g_core_codegen_interface->SerializeProto(msg, buffer); + int byte_size = msg.ByteSize(); + if (byte_size <= kGrpcBufferWriterMaxBufferLength) { + gpr_slice slice = g_core_codegen_interface->gpr_slice_malloc(byte_size); + GPR_CODEGEN_ASSERT( + GPR_SLICE_END_PTR(slice) == + msg.SerializeWithCachedSizesToArray(GPR_SLICE_START_PTR(slice))); + *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(&slice, 1); + g_core_codegen_interface->gpr_slice_unref(slice); + return g_core_codegen_interface->ok(); + } else { + GrpcBufferWriter writer(bp, kGrpcBufferWriterMaxBufferLength); + return msg.SerializeToZeroCopyStream(&writer) + ? g_core_codegen_interface->ok() + : Status(StatusCode::INTERNAL, "Failed to serialize message"); + } } + static Status Deserialize(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg, int max_message_size) { - return g_core_codegen_interface->DeserializeProto(buffer, msg, - max_message_size); + if (buffer == nullptr) { + return Status(StatusCode::INTERNAL, "No payload"); + } + Status result = g_core_codegen_interface->ok(); + { + GrpcBufferReader reader(buffer); + ::grpc::protobuf::io::CodedInputStream decoder(&reader); + if (max_message_size > 0) { + decoder.SetTotalBytesLimit(max_message_size, max_message_size); + } + if (!msg->ParseFromCodedStream(&decoder)) { + result = Status(StatusCode::INTERNAL, msg->InitializationErrorString()); + } + if (!decoder.ConsumedEntireMessage()) { + result = Status(StatusCode::INTERNAL, "Did not read entire message"); + } + } + g_core_codegen_interface->grpc_byte_buffer_destroy(buffer); + return result; } }; diff --git a/include/grpc/byte_buffer_reader.h b/include/grpc/byte_buffer_reader.h index 9a1c6178ab6..e95bf2f80dc 100644 --- a/include/grpc/byte_buffer_reader.h +++ b/include/grpc/byte_buffer_reader.h @@ -34,25 +34,6 @@ #ifndef GRPC_BYTE_BUFFER_READER_H #define GRPC_BYTE_BUFFER_READER_H -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct grpc_byte_buffer_reader { - grpc_byte_buffer *buffer_in; - grpc_byte_buffer *buffer_out; - /* Different current objects correspond to different types of byte buffers */ - union { - /* Index into a slice buffer's array of slices */ - unsigned index; - } current; -}; - -#ifdef __cplusplus -} -#endif +#include #endif /* GRPC_BYTE_BUFFER_READER_H */ diff --git a/include/grpc/impl/codegen/byte_buffer_reader.h b/include/grpc/impl/codegen/byte_buffer_reader.h new file mode 100644 index 00000000000..10c382924ec --- /dev/null +++ b/include/grpc/impl/codegen/byte_buffer_reader.h @@ -0,0 +1,57 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_IMPL_CODEGEN_BYTE_BUFFER_READER_H +#define GRPC_IMPL_CODEGEN_BYTE_BUFFER_READER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct grpc_byte_buffer_reader { + grpc_byte_buffer *buffer_in; + grpc_byte_buffer *buffer_out; + /* Different current objects correspond to different types of byte buffers */ + union { + /* Index into a slice buffer's array of slices */ + unsigned index; + } current; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* GRPC_IMPL_CODEGEN_BYTE_BUFFER_READER_H */ diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 4c7373006b2..af3d0c21916 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -152,6 +152,8 @@ typedef struct { channel). If this parameter is specified and the underlying is not an SSL channel, it will just be ignored. */ #define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG "grpc.ssl_target_name_override" +/* Maximum metadata size */ +#define GRPC_ARG_MAX_METADATA_SIZE "grpc.max_metadata_size" /** Result of a grpc call. If the caller satisfies the prerequisites of a particular operation, the grpc_call_error returned will be GRPC_CALL_OK. @@ -307,7 +309,9 @@ typedef enum { GRPC_OP_RECV_STATUS_ON_CLIENT, /** Receive close on the server: one and only one must be made on the server. - This op completes after the close has been received by the server. */ + This op completes after the close has been received by the server. + This operation always succeeds, meaning ops paired with this operation + will also appear to succeed, even though they may not have. */ GRPC_OP_RECV_CLOSE_ON_SERVER } grpc_op_type; diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 1229d488edb..d2d9ac78084 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -114,6 +114,38 @@ #define GPR_WIN32_ATOMIC 1 #define GPR_MSVC_TLS 1 #endif +#elif defined(GPR_MANYLINUX1) +// TODO(atash): manylinux1 is just another __linux__ but with ancient +// libraries; it should be integrated with the `__linux__` definitions below. +#define GPR_PLATFORM_STRING "manylinux" +#define GPR_POSIX_CRASH_HANDLER 1 +#define GPR_CPU_LINUX 1 +#define GPR_GCC_ATOMIC 1 +#define GPR_GCC_TLS 1 +#define GPR_LINUX 1 +#define GPR_LINUX_LOG 1 +#define GPR_POSIX_SOCKET 1 +#define GPR_POSIX_WAKEUP_FD 1 +#define GPR_POSIX_SOCKETADDR 1 +#define GPR_POSIX_NO_SPECIAL_WAKEUP_FD 1 +#define GPR_POSIX_SOCKETUTILS 1 +#define GPR_HAVE_UNIX_SOCKET 1 +#define GPR_HAVE_IP_PKTINFO 1 +#define GPR_HAVE_IPV6_RECVPKTINFO 1 +#define GPR_LINUX_ENV 1 +#define GPR_POSIX_FILE 1 +#define GPR_POSIX_TMPFILE 1 +#define GPR_POSIX_STRING 1 +#define GPR_POSIX_SUBPROCESS 1 +#define GPR_POSIX_SYNC 1 +#define GPR_POSIX_TIME 1 +#define GPR_GETPID_IN_UNISTD_H 1 +#define GPR_HAVE_MSG_NOSIGNAL 1 +#ifdef _LP64 +#define GPR_ARCH_64 1 +#else /* _LP64 */ +#define GPR_ARCH_32 1 +#endif /* _LP64 */ #elif defined(ANDROID) || defined(__ANDROID__) #define GPR_PLATFORM_STRING "android" #define GPR_ANDROID 1 diff --git a/include/grpc/impl/codegen/slice_buffer.h b/include/grpc/impl/codegen/slice_buffer.h index 8ca51baa471..7858021600a 100644 --- a/include/grpc/impl/codegen/slice_buffer.h +++ b/include/grpc/impl/codegen/slice_buffer.h @@ -42,9 +42,8 @@ extern "C" { #define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8 -/* Represents an expandable array of slices, to be interpreted as a single item - TODO(ctiller): inline some small number of elements into the struct, to - avoid per-call allocations */ +/* Represents an expandable array of slices, to be interpreted as a + single item. */ typedef struct { /* slices in the array */ gpr_slice *slices; diff --git a/package.json b/package.json index 5ed7f363d37..54a44ca5513 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "0.14.0-dev", + "version": "0.15.0-dev", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", diff --git a/package.xml b/package.xml index ffb1c56ed64..4c159e6024c 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2016-04-19 - 0.14.0 - 0.14.0 + 0.15.0 + 0.15.0 beta @@ -156,6 +156,7 @@ + @@ -303,7 +304,7 @@ - + @@ -461,7 +462,7 @@ - + @@ -1013,8 +1014,8 @@ Update to wrap gRPC C Core version 0.10.0 - 0.14.0 - 0.14.0 + 0.15.0 + 0.15.0 beta diff --git a/setup.py b/setup.py index cd0d3a1a51b..f96824fa883 100644 --- a/setup.py +++ b/setup.py @@ -54,7 +54,6 @@ sys.path.insert(0, os.path.abspath(PYTHON_STEM)) # Break import-style to ensure we can actually find our in-repo dependencies. import commands -import precompiled import grpc_core_dependencies import grpc_version @@ -173,7 +172,6 @@ COMMAND_CLASS = { 'build_project_metadata': commands.BuildProjectMetadata, 'build_py': commands.BuildPy, 'build_ext': commands.BuildExt, - 'build_tagged_ext': precompiled.BuildTaggedExt, 'gather': commands.Gather, 'run_interop': commands.RunInterop, 'test_lite': commands.TestLite @@ -229,23 +227,21 @@ else: PACKAGES = setuptools.find_packages( PYTHON_STEM, exclude=['tests', 'tests.*']) -setup_arguments = { - 'name': 'grpcio', - 'version': grpc_version.VERSION, - 'license': LICENSE, - 'ext_modules': CYTHON_EXTENSION_MODULES, - 'packages': list(PACKAGES), - 'package_dir': PACKAGE_DIRECTORIES, - 'package_data': PACKAGE_DATA, - 'install_requires': INSTALL_REQUIRES, - 'setup_requires': SETUP_REQUIRES, - 'cmdclass': COMMAND_CLASS, - 'tests_require': TESTS_REQUIRE, - 'test_suite': TEST_SUITE, - 'test_loader': TEST_LOADER, - 'test_runner': TEST_RUNNER, -} - -precompiled.update_setup_arguments(setup_arguments) - -setuptools.setup(**setup_arguments) +setuptools.setup( + name='grpcio', + version=grpc_version.VERSION, + license=LICENSE, + ext_modules=CYTHON_EXTENSION_MODULES, + packages=list(PACKAGES), + package_dir=PACKAGE_DIRECTORIES, + # TODO(atash): Figure out why auditwheel doesn't like namespace packages. + #namespace_packages=['grpc'], + package_data=PACKAGE_DATA, + install_requires=INSTALL_REQUIRES, + setup_requires=SETUP_REQUIRES, + cmdclass=COMMAND_CLASS, + tests_require=TESTS_REQUIRE, + test_suite=TEST_SUITE, + test_loader=TEST_LOADER, + test_runner=TEST_RUNNER, +) diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index ac0fee1ec4d..29c359c5395 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -214,10 +214,10 @@ std::string GetMethodReturnTypeServer(const MethodDescriptor *method) { switch (GetMethodType(method)) { case METHODTYPE_NO_STREAMING: case METHODTYPE_CLIENT_STREAMING: - return "Task<" + GetClassName(method->output_type()) + ">"; + return "global::System.Threading.Tasks.Task<" + GetClassName(method->output_type()) + ">"; case METHODTYPE_SERVER_STREAMING: case METHODTYPE_BIDI_STREAMING: - return "Task"; + return "global::System.Threading.Tasks.Task"; } GOOGLE_LOG(FATAL)<< "Can't get here."; return ""; diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index 59137e1c923..8e76e6dce6f 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -182,18 +182,40 @@ bool GetModuleAndMessagePath(const Descriptor* type, return true; } +// Get all comments (leading, leading_detached, trailing) and print them as a +// docstring. Any leading space of a line will be removed, but the line wrapping +// will not be changed. +template +static void PrintAllComments(const DescriptorType* desc, Printer* printer) { + std::vector comments; + grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED, + &comments); + grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING, + &comments); + grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_TRAILING, + &comments); + if (comments.empty()) { + return; + } + printer->Print("\"\"\""); + for (auto it = comments.begin(); it != comments.end(); ++it) { + size_t start_pos = it->find_first_not_of(' '); + if (start_pos != grpc::string::npos) { + printer->Print(it->c_str() + start_pos); + } + printer->Print("\n"); + } + printer->Print("\"\"\"\n"); +} + bool PrintBetaServicer(const ServiceDescriptor* service, Printer* out) { - grpc::string doc = ""; - map dict = ListToDict({ - "Service", service->name(), - "Documentation", doc, - }); out->Print("\n"); - out->Print(dict, "class Beta$Service$Servicer(object):\n"); + out->Print("class Beta$Service$Servicer(object):\n", "Service", + service->name()); { IndentScope raii_class_indent(out); - out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); + PrintAllComments(service, out); for (int i = 0; i < service->method_count(); ++i) { auto meth = service->method(i); grpc::string arg_name = meth->client_streaming() ? @@ -202,6 +224,7 @@ bool PrintBetaServicer(const ServiceDescriptor* service, "Method", meth->name(), "ArgName", arg_name); { IndentScope raii_method_indent(out); + PrintAllComments(meth, out); out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n"); } } @@ -211,16 +234,11 @@ bool PrintBetaServicer(const ServiceDescriptor* service, bool PrintBetaStub(const ServiceDescriptor* service, Printer* out) { - grpc::string doc = "The interface to which stubs will conform."; - map dict = ListToDict({ - "Service", service->name(), - "Documentation", doc, - }); out->Print("\n"); - out->Print(dict, "class Beta$Service$Stub(object):\n"); + out->Print("class Beta$Service$Stub(object):\n", "Service", service->name()); { IndentScope raii_class_indent(out); - out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); + PrintAllComments(service, out); for (int i = 0; i < service->method_count(); ++i) { const MethodDescriptor* meth = service->method(i); grpc::string arg_name = meth->client_streaming() ? @@ -229,6 +247,7 @@ bool PrintBetaStub(const ServiceDescriptor* service, out->Print(methdict, "def $Method$(self, $ArgName$, timeout):\n"); { IndentScope raii_method_indent(out); + PrintAllComments(meth, out); out->Print("raise NotImplementedError()\n"); } if (!meth->server_streaming()) { diff --git a/src/compiler/ruby_generator.cc b/src/compiler/ruby_generator.cc index 5ac56ad289c..936a186beb5 100644 --- a/src/compiler/ruby_generator.cc +++ b/src/compiler/ruby_generator.cc @@ -98,8 +98,8 @@ void PrintService(const ServiceDescriptor *service, const grpc::string &package, out->Print("self.marshal_class_method = :encode\n"); out->Print("self.unmarshal_class_method = :decode\n"); std::map pkg_vars = - ListToDict({"service.name", service->name(), "pkg.name", package, }); - out->Print(pkg_vars, "self.service_name = '$pkg.name$.$service.name$'\n"); + ListToDict({"service_full_name", service->full_name()}); + out->Print(pkg_vars, "self.service_name = '$service_full_name$'\n"); out->Print("\n"); for (int i = 0; i < service->method_count(); ++i) { PrintMethod(service->method(i), package, out); diff --git a/src/core/ext/client_config/resolver_registry.c b/src/core/ext/client_config/resolver_registry.c index 07f29bcb27a..e7a4abd568c 100644 --- a/src/core/ext/client_config/resolver_registry.c +++ b/src/core/ext/client_config/resolver_registry.c @@ -47,7 +47,6 @@ static int g_number_of_resolvers = 0; static char *g_default_resolver_prefix; void grpc_resolver_registry_init(const char *default_resolver_prefix) { - g_number_of_resolvers = 0; g_default_resolver_prefix = gpr_strdup(default_resolver_prefix); } @@ -57,6 +56,13 @@ void grpc_resolver_registry_shutdown(void) { grpc_resolver_factory_unref(g_all_of_the_resolvers[i]); } gpr_free(g_default_resolver_prefix); + // FIXME(ctiller): this should live in grpc_resolver_registry_init, + // however that would have the client_config plugin call this AFTER we start + // registering resolvers from third party plugins, and so they'd never show + // up. + // We likely need some kind of dependency system for plugins.... what form + // that takes is TBD. + g_number_of_resolvers = 0; } void grpc_register_resolver_type(grpc_resolver_factory *factory) { diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/lb_policy/grpclb/load_balancer_api.c index 459d6d9954d..59b89997dd9 100644 --- a/src/core/ext/lb_policy/grpclb/load_balancer_api.c +++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.c @@ -50,7 +50,7 @@ static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field, decode_serverlist_arg *dec_arg = *arg; if (dec_arg->first_pass != 0) { /* first pass */ grpc_grpclb_server server; - if (!pb_decode(stream, grpc_lb_v0_Server_fields, &server)) { + if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) { return false; } dec_arg->num_servers++; @@ -61,7 +61,7 @@ static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field, dec_arg->servers = gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers); } - if (!pb_decode(stream, grpc_lb_v0_Server_fields, server)) { + if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) { return false; } dec_arg->servers[dec_arg->i++] = server; @@ -87,13 +87,13 @@ gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request) { pb_ostream_t outputstream; gpr_slice slice; memset(&sizestream, 0, sizeof(pb_ostream_t)); - pb_encode(&sizestream, grpc_lb_v0_LoadBalanceRequest_fields, request); + pb_encode(&sizestream, grpc_lb_v1_LoadBalanceRequest_fields, request); encoded_length = sizestream.bytes_written; slice = gpr_slice_malloc(encoded_length); outputstream = pb_ostream_from_buffer(GPR_SLICE_START_PTR(slice), encoded_length); - GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v0_LoadBalanceRequest_fields, + GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v1_LoadBalanceRequest_fields, request) != 0); return slice; } @@ -109,7 +109,7 @@ grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response) { GPR_SLICE_LENGTH(encoded_response)); grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response)); memset(res, 0, sizeof(*res)); - status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res); + status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res); if (!status) { grpc_grpclb_response_destroy(res); return NULL; @@ -132,7 +132,7 @@ grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist( res->server_list.servers.funcs.decode = decode_serverlist; res->server_list.servers.arg = &arg; arg.first_pass = 1; - status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res); + status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res); if (!status) { grpc_grpclb_response_destroy(res); return NULL; @@ -140,7 +140,7 @@ grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist( arg.first_pass = 0; status = - pb_decode(&stream_at_start, grpc_lb_v0_LoadBalanceResponse_fields, res); + pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, res); if (!status) { grpc_grpclb_response_destroy(res); return NULL; diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/lb_policy/grpclb/load_balancer_api.h index 968f7d278ae..71b5616d0c8 100644 --- a/src/core/ext/lb_policy/grpclb/load_balancer_api.h +++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.h @@ -37,7 +37,7 @@ #include #include "src/core/ext/client_config/lb_policy_factory.h" -#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h" +#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" #ifdef __cplusplus extern "C" { @@ -45,10 +45,10 @@ extern "C" { #define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128 -typedef grpc_lb_v0_LoadBalanceRequest grpc_grpclb_request; -typedef grpc_lb_v0_LoadBalanceResponse grpc_grpclb_response; -typedef grpc_lb_v0_Server grpc_grpclb_server; -typedef grpc_lb_v0_Duration grpc_grpclb_duration; +typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request; +typedef grpc_lb_v1_LoadBalanceResponse grpc_grpclb_response; +typedef grpc_lb_v1_Server grpc_grpclb_server; +typedef grpc_lb_v1_Duration grpc_grpclb_duration; typedef struct grpc_grpclb_serverlist { grpc_grpclb_server **servers; size_t num_servers; diff --git a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h deleted file mode 100644 index 3599f881bb1..00000000000 --- a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.3.5-dev */ - -#ifndef PB_LOAD_BALANCER_PB_H_INCLUDED -#define PB_LOAD_BALANCER_PB_H_INCLUDED -#include "third_party/nanopb/pb.h" -#if PB_PROTO_HEADER_VERSION != 30 -#error Regenerate this file with the current version of nanopb generator. -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Struct definitions */ -typedef struct _grpc_lb_v0_ClientStats { - bool has_total_requests; - int64_t total_requests; - bool has_client_rpc_errors; - int64_t client_rpc_errors; - bool has_dropped_requests; - int64_t dropped_requests; -} grpc_lb_v0_ClientStats; - -typedef struct _grpc_lb_v0_Duration { - bool has_seconds; - int64_t seconds; - bool has_nanos; - int32_t nanos; -} grpc_lb_v0_Duration; - -typedef struct _grpc_lb_v0_InitialLoadBalanceRequest { - bool has_name; - char name[128]; -} grpc_lb_v0_InitialLoadBalanceRequest; - -typedef PB_BYTES_ARRAY_T(64) grpc_lb_v0_Server_load_balance_token_t; -typedef struct _grpc_lb_v0_Server { - bool has_ip_address; - char ip_address[46]; - bool has_port; - int32_t port; - bool has_load_balance_token; - grpc_lb_v0_Server_load_balance_token_t load_balance_token; - bool has_drop_request; - bool drop_request; -} grpc_lb_v0_Server; - -typedef struct _grpc_lb_v0_InitialLoadBalanceResponse { - bool has_client_config; - char client_config[64]; - bool has_load_balancer_delegate; - char load_balancer_delegate[64]; - bool has_client_stats_report_interval; - grpc_lb_v0_Duration client_stats_report_interval; -} grpc_lb_v0_InitialLoadBalanceResponse; - -typedef struct _grpc_lb_v0_LoadBalanceRequest { - bool has_initial_request; - grpc_lb_v0_InitialLoadBalanceRequest initial_request; - bool has_client_stats; - grpc_lb_v0_ClientStats client_stats; -} grpc_lb_v0_LoadBalanceRequest; - -typedef struct _grpc_lb_v0_ServerList { - pb_callback_t servers; - bool has_expiration_interval; - grpc_lb_v0_Duration expiration_interval; -} grpc_lb_v0_ServerList; - -typedef struct _grpc_lb_v0_LoadBalanceResponse { - bool has_initial_response; - grpc_lb_v0_InitialLoadBalanceResponse initial_response; - bool has_server_list; - grpc_lb_v0_ServerList server_list; -} grpc_lb_v0_LoadBalanceResponse; - -/* Default values for struct fields */ - -/* Initializer values for message structs */ -#define grpc_lb_v0_Duration_init_default {false, 0, false, 0} -#define grpc_lb_v0_LoadBalanceRequest_init_default {false, grpc_lb_v0_InitialLoadBalanceRequest_init_default, false, grpc_lb_v0_ClientStats_init_default} -#define grpc_lb_v0_InitialLoadBalanceRequest_init_default {false, ""} -#define grpc_lb_v0_ClientStats_init_default {false, 0, false, 0, false, 0} -#define grpc_lb_v0_LoadBalanceResponse_init_default {false, grpc_lb_v0_InitialLoadBalanceResponse_init_default, false, grpc_lb_v0_ServerList_init_default} -#define grpc_lb_v0_InitialLoadBalanceResponse_init_default {false, "", false, "", false, grpc_lb_v0_Duration_init_default} -#define grpc_lb_v0_ServerList_init_default {{{NULL}, NULL}, false, grpc_lb_v0_Duration_init_default} -#define grpc_lb_v0_Server_init_default {false, "", false, 0, false, {0, {0}}, false, 0} -#define grpc_lb_v0_Duration_init_zero {false, 0, false, 0} -#define grpc_lb_v0_LoadBalanceRequest_init_zero {false, grpc_lb_v0_InitialLoadBalanceRequest_init_zero, false, grpc_lb_v0_ClientStats_init_zero} -#define grpc_lb_v0_InitialLoadBalanceRequest_init_zero {false, ""} -#define grpc_lb_v0_ClientStats_init_zero {false, 0, false, 0, false, 0} -#define grpc_lb_v0_LoadBalanceResponse_init_zero {false, grpc_lb_v0_InitialLoadBalanceResponse_init_zero, false, grpc_lb_v0_ServerList_init_zero} -#define grpc_lb_v0_InitialLoadBalanceResponse_init_zero {false, "", false, "", false, grpc_lb_v0_Duration_init_zero} -#define grpc_lb_v0_ServerList_init_zero {{{NULL}, NULL}, false, grpc_lb_v0_Duration_init_zero} -#define grpc_lb_v0_Server_init_zero {false, "", false, 0, false, {0, {0}}, false, 0} - -/* Field tags (for use in manual encoding/decoding) */ -#define grpc_lb_v0_ClientStats_total_requests_tag 1 -#define grpc_lb_v0_ClientStats_client_rpc_errors_tag 2 -#define grpc_lb_v0_ClientStats_dropped_requests_tag 3 -#define grpc_lb_v0_Duration_seconds_tag 1 -#define grpc_lb_v0_Duration_nanos_tag 2 -#define grpc_lb_v0_InitialLoadBalanceRequest_name_tag 1 -#define grpc_lb_v0_Server_ip_address_tag 1 -#define grpc_lb_v0_Server_port_tag 2 -#define grpc_lb_v0_Server_load_balance_token_tag 3 -#define grpc_lb_v0_Server_drop_request_tag 4 -#define grpc_lb_v0_InitialLoadBalanceResponse_client_config_tag 1 -#define grpc_lb_v0_InitialLoadBalanceResponse_load_balancer_delegate_tag 2 -#define grpc_lb_v0_InitialLoadBalanceResponse_client_stats_report_interval_tag 3 -#define grpc_lb_v0_LoadBalanceRequest_initial_request_tag 1 -#define grpc_lb_v0_LoadBalanceRequest_client_stats_tag 2 -#define grpc_lb_v0_ServerList_servers_tag 1 -#define grpc_lb_v0_ServerList_expiration_interval_tag 3 -#define grpc_lb_v0_LoadBalanceResponse_initial_response_tag 1 -#define grpc_lb_v0_LoadBalanceResponse_server_list_tag 2 - -/* Struct field encoding specification for nanopb */ -extern const pb_field_t grpc_lb_v0_Duration_fields[3]; -extern const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3]; -extern const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2]; -extern const pb_field_t grpc_lb_v0_ClientStats_fields[4]; -extern const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3]; -extern const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4]; -extern const pb_field_t grpc_lb_v0_ServerList_fields[3]; -extern const pb_field_t grpc_lb_v0_Server_fields[5]; - -/* Maximum encoded size of messages (where known) */ -#define grpc_lb_v0_Duration_size 22 -#define grpc_lb_v0_LoadBalanceRequest_size 169 -#define grpc_lb_v0_InitialLoadBalanceRequest_size 131 -#define grpc_lb_v0_ClientStats_size 33 -#define grpc_lb_v0_LoadBalanceResponse_size (165 + grpc_lb_v0_ServerList_size) -#define grpc_lb_v0_InitialLoadBalanceResponse_size 156 -#define grpc_lb_v0_Server_size 127 - -/* Message IDs (where set with "msgid" option) */ -#ifdef PB_MSGID - -#define LOAD_BALANCER_MESSAGES \ - - -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c similarity index 55% rename from src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c rename to src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c index 97196731810..52e11c40bb0 100644 --- a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c +++ b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c @@ -33,7 +33,7 @@ /* Automatically generated nanopb constant definitions */ /* Generated by nanopb-0.3.5-dev */ -#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h" +#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. @@ -41,54 +41,53 @@ -const pb_field_t grpc_lb_v0_Duration_fields[3] = { - PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v0_Duration, seconds, seconds, 0), - PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v0_Duration, nanos, seconds, 0), +const pb_field_t grpc_lb_v1_Duration_fields[3] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Duration, seconds, seconds, 0), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Duration, nanos, seconds, 0), PB_LAST_FIELD }; -const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3] = { - PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v0_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v0_InitialLoadBalanceRequest_fields), - PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v0_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v0_ClientStats_fields), +const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v1_InitialLoadBalanceRequest_fields), + PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v1_ClientStats_fields), PB_LAST_FIELD }; -const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2] = { - PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v0_InitialLoadBalanceRequest, name, name, 0), +const pb_field_t grpc_lb_v1_InitialLoadBalanceRequest_fields[2] = { + PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_InitialLoadBalanceRequest, name, name, 0), PB_LAST_FIELD }; -const pb_field_t grpc_lb_v0_ClientStats_fields[4] = { - PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v0_ClientStats, total_requests, total_requests, 0), - PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v0_ClientStats, client_rpc_errors, total_requests, 0), - PB_FIELD( 3, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v0_ClientStats, dropped_requests, client_rpc_errors, 0), +const pb_field_t grpc_lb_v1_ClientStats_fields[4] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_ClientStats, total_requests, total_requests, 0), + PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, client_rpc_errors, total_requests, 0), + PB_FIELD( 3, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, dropped_requests, client_rpc_errors, 0), PB_LAST_FIELD }; -const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3] = { - PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v0_LoadBalanceResponse, initial_response, initial_response, &grpc_lb_v0_InitialLoadBalanceResponse_fields), - PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v0_LoadBalanceResponse, server_list, initial_response, &grpc_lb_v0_ServerList_fields), +const pb_field_t grpc_lb_v1_LoadBalanceResponse_fields[3] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_LoadBalanceResponse, initial_response, initial_response, &grpc_lb_v1_InitialLoadBalanceResponse_fields), + PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_LoadBalanceResponse, server_list, initial_response, &grpc_lb_v1_ServerList_fields), PB_LAST_FIELD }; -const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4] = { - PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v0_InitialLoadBalanceResponse, client_config, client_config, 0), - PB_FIELD( 2, STRING , OPTIONAL, STATIC , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, load_balancer_delegate, client_config, 0), - PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v0_Duration_fields), +const pb_field_t grpc_lb_v1_InitialLoadBalanceResponse_fields[3] = { + PB_FIELD( 2, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_InitialLoadBalanceResponse, load_balancer_delegate, load_balancer_delegate, 0), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v1_Duration_fields), PB_LAST_FIELD }; -const pb_field_t grpc_lb_v0_ServerList_fields[3] = { - PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, grpc_lb_v0_ServerList, servers, servers, &grpc_lb_v0_Server_fields), - PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v0_ServerList, expiration_interval, servers, &grpc_lb_v0_Duration_fields), +const pb_field_t grpc_lb_v1_ServerList_fields[3] = { + PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, grpc_lb_v1_ServerList, servers, servers, &grpc_lb_v1_Server_fields), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ServerList, expiration_interval, servers, &grpc_lb_v1_Duration_fields), PB_LAST_FIELD }; -const pb_field_t grpc_lb_v0_Server_fields[5] = { - PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v0_Server, ip_address, ip_address, 0), - PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v0_Server, port, ip_address, 0), - PB_FIELD( 3, BYTES , OPTIONAL, STATIC , OTHER, grpc_lb_v0_Server, load_balance_token, port, 0), - PB_FIELD( 4, BOOL , OPTIONAL, STATIC , OTHER, grpc_lb_v0_Server, drop_request, load_balance_token, 0), +const pb_field_t grpc_lb_v1_Server_fields[5] = { + PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Server, ip_address, ip_address, 0), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Server, port, ip_address, 0), + PB_FIELD( 3, STRING , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Server, load_balance_token, port, 0), + PB_FIELD( 4, BOOL , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Server, drop_request, load_balance_token, 0), PB_LAST_FIELD }; @@ -102,7 +101,7 @@ const pb_field_t grpc_lb_v0_Server_fields[5] = { * numbers or field sizes that are larger than what can fit in 8 or 16 bit * field descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v0_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server) +PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v1_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) @@ -113,7 +112,7 @@ PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v0_ServerList, servers) < 256 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server) +PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) #endif diff --git a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h new file mode 100644 index 00000000000..d5dc39ab94f --- /dev/null +++ b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h @@ -0,0 +1,178 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.5-dev */ + +#ifndef PB_LOAD_BALANCER_PB_H_INCLUDED +#define PB_LOAD_BALANCER_PB_H_INCLUDED +#include "third_party/nanopb/pb.h" +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct definitions */ +typedef struct _grpc_lb_v1_ClientStats { + bool has_total_requests; + int64_t total_requests; + bool has_client_rpc_errors; + int64_t client_rpc_errors; + bool has_dropped_requests; + int64_t dropped_requests; +} grpc_lb_v1_ClientStats; + +typedef struct _grpc_lb_v1_Duration { + bool has_seconds; + int64_t seconds; + bool has_nanos; + int32_t nanos; +} grpc_lb_v1_Duration; + +typedef struct _grpc_lb_v1_InitialLoadBalanceRequest { + bool has_name; + char name[128]; +} grpc_lb_v1_InitialLoadBalanceRequest; + +typedef struct _grpc_lb_v1_Server { + bool has_ip_address; + char ip_address[46]; + bool has_port; + int32_t port; + bool has_load_balance_token; + char load_balance_token[64]; + bool has_drop_request; + bool drop_request; +} grpc_lb_v1_Server; + +typedef struct _grpc_lb_v1_InitialLoadBalanceResponse { + bool has_load_balancer_delegate; + char load_balancer_delegate[64]; + bool has_client_stats_report_interval; + grpc_lb_v1_Duration client_stats_report_interval; +} grpc_lb_v1_InitialLoadBalanceResponse; + +typedef struct _grpc_lb_v1_LoadBalanceRequest { + bool has_initial_request; + grpc_lb_v1_InitialLoadBalanceRequest initial_request; + bool has_client_stats; + grpc_lb_v1_ClientStats client_stats; +} grpc_lb_v1_LoadBalanceRequest; + +typedef struct _grpc_lb_v1_ServerList { + pb_callback_t servers; + bool has_expiration_interval; + grpc_lb_v1_Duration expiration_interval; +} grpc_lb_v1_ServerList; + +typedef struct _grpc_lb_v1_LoadBalanceResponse { + bool has_initial_response; + grpc_lb_v1_InitialLoadBalanceResponse initial_response; + bool has_server_list; + grpc_lb_v1_ServerList server_list; +} grpc_lb_v1_LoadBalanceResponse; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define grpc_lb_v1_Duration_init_default {false, 0, false, 0} +#define grpc_lb_v1_LoadBalanceRequest_init_default {false, grpc_lb_v1_InitialLoadBalanceRequest_init_default, false, grpc_lb_v1_ClientStats_init_default} +#define grpc_lb_v1_InitialLoadBalanceRequest_init_default {false, ""} +#define grpc_lb_v1_ClientStats_init_default {false, 0, false, 0, false, 0} +#define grpc_lb_v1_LoadBalanceResponse_init_default {false, grpc_lb_v1_InitialLoadBalanceResponse_init_default, false, grpc_lb_v1_ServerList_init_default} +#define grpc_lb_v1_InitialLoadBalanceResponse_init_default {false, "", false, grpc_lb_v1_Duration_init_default} +#define grpc_lb_v1_ServerList_init_default {{{NULL}, NULL}, false, grpc_lb_v1_Duration_init_default} +#define grpc_lb_v1_Server_init_default {false, "", false, 0, false, "", false, 0} +#define grpc_lb_v1_Duration_init_zero {false, 0, false, 0} +#define grpc_lb_v1_LoadBalanceRequest_init_zero {false, grpc_lb_v1_InitialLoadBalanceRequest_init_zero, false, grpc_lb_v1_ClientStats_init_zero} +#define grpc_lb_v1_InitialLoadBalanceRequest_init_zero {false, ""} +#define grpc_lb_v1_ClientStats_init_zero {false, 0, false, 0, false, 0} +#define grpc_lb_v1_LoadBalanceResponse_init_zero {false, grpc_lb_v1_InitialLoadBalanceResponse_init_zero, false, grpc_lb_v1_ServerList_init_zero} +#define grpc_lb_v1_InitialLoadBalanceResponse_init_zero {false, "", false, grpc_lb_v1_Duration_init_zero} +#define grpc_lb_v1_ServerList_init_zero {{{NULL}, NULL}, false, grpc_lb_v1_Duration_init_zero} +#define grpc_lb_v1_Server_init_zero {false, "", false, 0, false, "", false, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define grpc_lb_v1_ClientStats_total_requests_tag 1 +#define grpc_lb_v1_ClientStats_client_rpc_errors_tag 2 +#define grpc_lb_v1_ClientStats_dropped_requests_tag 3 +#define grpc_lb_v1_Duration_seconds_tag 1 +#define grpc_lb_v1_Duration_nanos_tag 2 +#define grpc_lb_v1_InitialLoadBalanceRequest_name_tag 1 +#define grpc_lb_v1_Server_ip_address_tag 1 +#define grpc_lb_v1_Server_port_tag 2 +#define grpc_lb_v1_Server_load_balance_token_tag 3 +#define grpc_lb_v1_Server_drop_request_tag 4 +#define grpc_lb_v1_InitialLoadBalanceResponse_load_balancer_delegate_tag 2 +#define grpc_lb_v1_InitialLoadBalanceResponse_client_stats_report_interval_tag 3 +#define grpc_lb_v1_LoadBalanceRequest_initial_request_tag 1 +#define grpc_lb_v1_LoadBalanceRequest_client_stats_tag 2 +#define grpc_lb_v1_ServerList_servers_tag 1 +#define grpc_lb_v1_ServerList_expiration_interval_tag 3 +#define grpc_lb_v1_LoadBalanceResponse_initial_response_tag 1 +#define grpc_lb_v1_LoadBalanceResponse_server_list_tag 2 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t grpc_lb_v1_Duration_fields[3]; +extern const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3]; +extern const pb_field_t grpc_lb_v1_InitialLoadBalanceRequest_fields[2]; +extern const pb_field_t grpc_lb_v1_ClientStats_fields[4]; +extern const pb_field_t grpc_lb_v1_LoadBalanceResponse_fields[3]; +extern const pb_field_t grpc_lb_v1_InitialLoadBalanceResponse_fields[3]; +extern const pb_field_t grpc_lb_v1_ServerList_fields[3]; +extern const pb_field_t grpc_lb_v1_Server_fields[5]; + +/* Maximum encoded size of messages (where known) */ +#define grpc_lb_v1_Duration_size 22 +#define grpc_lb_v1_LoadBalanceRequest_size 169 +#define grpc_lb_v1_InitialLoadBalanceRequest_size 131 +#define grpc_lb_v1_ClientStats_size 33 +#define grpc_lb_v1_LoadBalanceResponse_size (98 + grpc_lb_v1_ServerList_size) +#define grpc_lb_v1_InitialLoadBalanceResponse_size 90 +#define grpc_lb_v1_Server_size 127 + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define LOAD_BALANCER_MESSAGES \ + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c index 3f6051b8925..dcdc0c62857 100644 --- a/src/core/ext/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/lb_policy/round_robin/round_robin.c @@ -306,8 +306,10 @@ static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) { size_t i; p->started_picking = 1; - gpr_log(GPR_DEBUG, "LB_POLICY: p=%p num_subchannels=%d", p, - p->num_subchannels); + if (grpc_lb_round_robin_trace) { + gpr_log(GPR_DEBUG, "LB_POLICY: p=%p num_subchannels=%d", p, + p->num_subchannels); + } for (i = 0; i < p->num_subchannels; i++) { subchannel_data *sd = p->subchannels[i]; diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 8c8593748dd..b6886a2201b 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -56,6 +56,8 @@ #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024) #define MAX_WINDOW 0x7fffffffu +#define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024) + #define MAX_CLIENT_STREAM_ID 0x7fffffffu int grpc_http_trace = 0; @@ -65,8 +67,8 @@ int grpc_flowctl_trace = 0; ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \ writing))) -#define TRANSPORT_FROM_PARSING(tw) \ - ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \ +#define TRANSPORT_FROM_PARSING(tp) \ + ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \ parsing))) #define TRANSPORT_FROM_GLOBAL(tg) \ @@ -311,6 +313,8 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); } push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW); + push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, + DEFAULT_MAX_HEADER_LIST_SIZE); if (channel_args) { for (i = 0; i < channel_args->num_args; i++) { @@ -378,6 +382,18 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, &t->writing.hpack_compressor, (uint32_t)channel_args->args[i].value.integer); } + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_MAX_METADATA_SIZE)) { + if (channel_args->args[i].type != GRPC_ARG_INTEGER) { + gpr_log(GPR_ERROR, "%s: must be an integer", + GRPC_ARG_MAX_METADATA_SIZE); + } else if (channel_args->args[i].value.integer < 0) { + gpr_log(GPR_ERROR, "%s: must be non-negative", + GRPC_ARG_MAX_METADATA_SIZE); + } else { + push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, + (uint32_t)channel_args->args[i].value.integer); + } } } } @@ -510,7 +526,7 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; *t->accepting_stream = s; grpc_chttp2_stream_map_add(&t->parsing_stream_map, s->global.id, s); - s->global.in_stream_map = 1; + s->global.in_stream_map = true; } grpc_chttp2_run_with_global_lock(exec_ctx, t, s, finish_init_stream_locked, @@ -783,7 +799,8 @@ void grpc_chttp2_add_incoming_goaway( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, uint32_t goaway_error, gpr_slice goaway_text) { char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg); + GRPC_CHTTP2_IF_TRACING( + gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg)); gpr_free(msg); gpr_slice_unref(goaway_text); transport_global->seen_goaway = 1; @@ -833,7 +850,7 @@ static void maybe_start_some_streams( grpc_chttp2_stream_map_add( &TRANSPORT_FROM_GLOBAL(transport_global)->new_stream_map, stream_global->id, STREAM_FROM_GLOBAL(stream_global)); - stream_global->in_stream_map = 1; + stream_global->in_stream_map = true; transport_global->concurrent_stream_count++; grpc_chttp2_become_writable(transport_global, stream_global); } @@ -932,24 +949,38 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, stream_global->send_initial_metadata_finished = add_closure_barrier(on_complete); stream_global->send_initial_metadata = op->send_initial_metadata; - if (contains_non_ok_status(transport_global, op->send_initial_metadata)) { - stream_global->seen_error = 1; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - if (!stream_global->write_closed) { - if (transport_global->is_client) { - GPR_ASSERT(stream_global->id == 0); - grpc_chttp2_list_add_waiting_for_concurrency(transport_global, - stream_global); - maybe_start_some_streams(exec_ctx, transport_global); + const size_t metadata_size = + grpc_metadata_batch_size(op->send_initial_metadata); + const size_t metadata_peer_limit = + transport_global->settings[GRPC_PEER_SETTINGS] + [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; + if (metadata_size > metadata_peer_limit) { + gpr_log(GPR_DEBUG, + "to-be-sent initial metadata size exceeds peer limit " + "(%lu vs. %lu)", + metadata_size, metadata_peer_limit); + cancel_from_api(exec_ctx, transport_global, stream_global, + GRPC_STATUS_RESOURCE_EXHAUSTED); + } else { + if (contains_non_ok_status(transport_global, op->send_initial_metadata)) { + stream_global->seen_error = true; + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + } + if (!stream_global->write_closed) { + if (transport_global->is_client) { + GPR_ASSERT(stream_global->id == 0); + grpc_chttp2_list_add_waiting_for_concurrency(transport_global, + stream_global); + maybe_start_some_streams(exec_ctx, transport_global); + } else { + GPR_ASSERT(stream_global->id != 0); + grpc_chttp2_become_writable(transport_global, stream_global); + } } else { - GPR_ASSERT(stream_global->id != 0); - grpc_chttp2_become_writable(transport_global, stream_global); + grpc_chttp2_complete_closure_step( + exec_ctx, stream_global, + &stream_global->send_initial_metadata_finished, 0); } - } else { - grpc_chttp2_complete_closure_step( - exec_ctx, stream_global, - &stream_global->send_initial_metadata_finished, 0); } } @@ -973,19 +1004,34 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, stream_global->send_trailing_metadata_finished = add_closure_barrier(on_complete); stream_global->send_trailing_metadata = op->send_trailing_metadata; - if (contains_non_ok_status(transport_global, op->send_trailing_metadata)) { - stream_global->seen_error = 1; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - if (stream_global->write_closed) { - grpc_chttp2_complete_closure_step( - exec_ctx, stream_global, - &stream_global->send_trailing_metadata_finished, - grpc_metadata_batch_is_empty(op->send_trailing_metadata)); - } else if (stream_global->id != 0) { - /* TODO(ctiller): check if there's flow control for any outstanding - bytes before going writable */ - grpc_chttp2_become_writable(transport_global, stream_global); + const size_t metadata_size = + grpc_metadata_batch_size(op->send_trailing_metadata); + const size_t metadata_peer_limit = + transport_global->settings[GRPC_PEER_SETTINGS] + [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; + if (metadata_size > metadata_peer_limit) { + gpr_log(GPR_DEBUG, + "to-be-sent trailing metadata size exceeds peer limit " + "(%lu vs. %lu)", + metadata_size, metadata_peer_limit); + cancel_from_api(exec_ctx, transport_global, stream_global, + GRPC_STATUS_RESOURCE_EXHAUSTED); + } else { + if (contains_non_ok_status(transport_global, + op->send_trailing_metadata)) { + stream_global->seen_error = true; + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + } + if (stream_global->write_closed) { + grpc_chttp2_complete_closure_step( + exec_ctx, stream_global, + &stream_global->send_trailing_metadata_finished, + grpc_metadata_batch_is_empty(op->send_trailing_metadata)); + } else if (stream_global->id != 0) { + /* TODO(ctiller): check if there's flow control for any outstanding + bytes before going writable */ + grpc_chttp2_become_writable(transport_global, stream_global); + } } } @@ -1148,6 +1194,16 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, grpc_chttp2_list_pop_check_read_ops(transport_global, &stream_global)) { if (stream_global->recv_initial_metadata_ready != NULL && stream_global->published_initial_metadata) { + if (stream_global->seen_error) { + while ((bs = grpc_chttp2_incoming_frame_queue_pop( + &stream_global->incoming_frames)) != NULL) { + incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + } + if (stream_global->exceeded_metadata_size) { + cancel_from_api(exec_ctx, transport_global, stream_global, + GRPC_STATUS_RESOURCE_EXHAUSTED); + } + } grpc_chttp2_incoming_metadata_buffer_publish( &stream_global->received_initial_metadata, stream_global->recv_initial_metadata); @@ -1177,10 +1233,15 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, } if (stream_global->recv_trailing_metadata_finished != NULL && stream_global->read_closed && stream_global->write_closed) { - while (stream_global->seen_error && - (bs = grpc_chttp2_incoming_frame_queue_pop( - &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + if (stream_global->seen_error) { + while ((bs = grpc_chttp2_incoming_frame_queue_pop( + &stream_global->incoming_frames)) != NULL) { + incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + } + if (stream_global->exceeded_metadata_size) { + cancel_from_api(exec_ctx, transport_global, stream_global, + GRPC_STATUS_RESOURCE_EXHAUSTED); + } } if (stream_global->all_incoming_byte_streams_finished) { grpc_chttp2_incoming_metadata_buffer_publish( @@ -1212,7 +1273,7 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id); } GPR_ASSERT(s); - s->global.in_stream_map = 0; + s->global.in_stream_map = false; if (t->parsing.incoming_stream == &s->parsing) { t->parsing.incoming_stream = NULL; grpc_chttp2_parsing_become_skip_parser(exec_ctx, &t->parsing); @@ -1256,7 +1317,7 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx, NULL); } if (status != GRPC_STATUS_OK && !stream_global->seen_error) { - stream_global->seen_error = 1; + stream_global->seen_error = true; grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1, @@ -1268,7 +1329,7 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_global *stream_global, grpc_status_code status, gpr_slice *slice) { if (status != GRPC_STATUS_OK) { - stream_global->seen_error = 1; + stream_global->seen_error = true; grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } /* stream_global->recv_trailing_metadata_finished gives us a @@ -1292,7 +1353,7 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, grpc_mdstr_from_slice(gpr_slice_ref(*slice)))); } - stream_global->published_trailing_metadata = 1; + stream_global->published_trailing_metadata = true; grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (slice) { @@ -1322,13 +1383,13 @@ void grpc_chttp2_mark_stream_closed( } grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); if (close_reads && !stream_global->read_closed) { - stream_global->read_closed = 1; - stream_global->published_initial_metadata = 1; - stream_global->published_trailing_metadata = 1; + stream_global->read_closed = true; + stream_global->published_initial_metadata = true; + stream_global->published_trailing_metadata = true; decrement_active_streams_locked(exec_ctx, transport_global, stream_global); } if (close_writes && !stream_global->write_closed) { - stream_global->write_closed = 1; + stream_global->write_closed = true; if (TRANSPORT_FROM_GLOBAL(transport_global)->executor.writing_active) { GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes"); grpc_chttp2_list_add_closed_waiting_for_writing(transport_global, diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c index 22467e9ddd2..7f01105e3ef 100644 --- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c @@ -45,15 +45,20 @@ gpr_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code, stats->framing_bytes += frame_size; uint8_t *p = GPR_SLICE_START_PTR(slice); + // Frame size. *p++ = 0; *p++ = 0; *p++ = 4; + // Frame type. *p++ = GRPC_CHTTP2_FRAME_RST_STREAM; + // Flags. *p++ = 0; + // Stream ID. *p++ = (uint8_t)(id >> 24); *p++ = (uint8_t)(id >> 16); *p++ = (uint8_t)(id >> 8); *p++ = (uint8_t)(id); + // Error code. *p++ = (uint8_t)(code >> 24); *p++ = (uint8_t)(code >> 16); *p++ = (uint8_t)(code >> 8); diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c index 555027c8660..ebeee37f0d9 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c +++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c @@ -63,6 +63,8 @@ /* don't consider adding anything bigger than this to the hpack table */ #define MAX_DECODER_SPACE_USAGE 512 +extern int grpc_http_trace; + typedef struct { int is_first_frame; /* number of bytes in 'output' when we started the frame - used to calculate @@ -532,7 +534,9 @@ void grpc_chttp2_hpack_compressor_set_max_table_size( } } c->advertise_table_size_change = 1; - gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size); + if (grpc_http_trace) { + gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size); + } } void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.c b/src/core/ext/transport/chttp2/transport/hpack_table.c index 4d64506de29..295f31c44f2 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_table.c +++ b/src/core/ext/transport/chttp2/transport/hpack_table.c @@ -253,7 +253,9 @@ void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl, if (tbl->max_bytes == max_bytes) { return; } - gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes); + if (grpc_http_trace) { + gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes); + } while (tbl->mem_used > max_bytes) { evict1(tbl); } diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.c b/src/core/ext/transport/chttp2/transport/incoming_metadata.c index db21744f0c0..3e463a79957 100644 --- a/src/core/ext/transport/chttp2/transport/incoming_metadata.c +++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.c @@ -65,6 +65,7 @@ void grpc_chttp2_incoming_metadata_buffer_add( gpr_realloc(buffer->elems, sizeof(*buffer->elems) * buffer->capacity); } buffer->elems[buffer->count++].md = elem; + buffer->size += GRPC_MDELEM_LENGTH(elem); } void grpc_chttp2_incoming_metadata_buffer_set_deadline( diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.h b/src/core/ext/transport/chttp2/transport/incoming_metadata.h index 17ecf8e1811..df4343b93ed 100644 --- a/src/core/ext/transport/chttp2/transport/incoming_metadata.h +++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.h @@ -42,6 +42,7 @@ typedef struct { size_t capacity; gpr_timespec deadline; int published; + size_t size; // total size of metadata } grpc_chttp2_incoming_metadata_buffer; /** assumes everything initially zeroed */ diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 8c4fa2d34ac..5872fd8e0a4 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -422,23 +422,21 @@ typedef struct { /** number of streams that are currently being read */ gpr_refcount active_streams; - /** when the application requests writes be closed, the write_closed is - 'queued'; when the close is flow controlled into the send path, we are - 'sending' it; when the write has been performed it is 'sent' */ + /** Is this stream closed for writing. */ bool write_closed; - /** is this stream reading half-closed (boolean) */ + /** Is this stream reading half-closed. */ bool read_closed; - /** are all published incoming byte streams closed */ + /** Are all published incoming byte streams closed. */ bool all_incoming_byte_streams_finished; - /** is this stream in the stream map? (boolean) */ + /** Is this stream in the stream map. */ bool in_stream_map; - /** has this stream seen an error? if 1, then pending incoming frames - can be thrown away */ + /** Has this stream seen an error. + If true, then pending incoming frames can be thrown away. */ bool seen_error; + bool exceeded_metadata_size; bool published_initial_metadata; bool published_trailing_metadata; - bool faked_trailing_metadata; grpc_chttp2_incoming_metadata_buffer received_initial_metadata; grpc_chttp2_incoming_metadata_buffer received_trailing_metadata; @@ -481,7 +479,8 @@ struct grpc_chttp2_stream_parsing { /** which metadata did we get (on this parse) */ uint8_t got_metadata_on_parse[2]; /** should we raise the seen_error flag in transport_global */ - uint8_t seen_error; + bool seen_error; + bool exceeded_metadata_size; /** window available for peer to send to us */ int64_t incoming_window; /** parsing state for data frames */ diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index 2995066e519..4bd374b7fa7 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -45,6 +45,10 @@ #include "src/core/lib/profiling/timers.h" #include "src/core/lib/transport/static_metadata.h" +#define TRANSPORT_FROM_PARSING(tp) \ + ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \ + parsing))) + static int init_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing); static int init_header_frame_parser( @@ -170,7 +174,9 @@ void grpc_chttp2_publish_reads( while (grpc_chttp2_list_pop_parsing_seen_stream( transport_global, transport_parsing, &stream_global, &stream_parsing)) { if (stream_parsing->seen_error) { - stream_global->seen_error = 1; + stream_global->seen_error = true; + stream_global->exceeded_metadata_size = + stream_parsing->exceeded_metadata_size; grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } @@ -612,7 +618,7 @@ static void on_initial_header(void *tp, grpc_mdelem *md) { if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) { /* TODO(ctiller): check for a status like " 0" */ - stream_parsing->seen_error = 1; + stream_parsing->seen_error = true; } if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) { @@ -633,8 +639,26 @@ static void on_initial_header(void *tp, grpc_mdelem *md) { gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout)); GRPC_MDELEM_UNREF(md); } else { - grpc_chttp2_incoming_metadata_buffer_add( - &stream_parsing->metadata_buffer[0], md); + const size_t new_size = + stream_parsing->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md); + grpc_chttp2_transport_global *transport_global = + &TRANSPORT_FROM_PARSING(transport_parsing)->global; + const size_t metadata_size_limit = + transport_global->settings[GRPC_LOCAL_SETTINGS] + [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; + if (new_size > metadata_size_limit) { + if (!stream_parsing->exceeded_metadata_size) { + gpr_log(GPR_DEBUG, + "received initial metadata size exceeds limit (%lu vs. %lu)", + new_size, metadata_size_limit); + stream_parsing->seen_error = true; + stream_parsing->exceeded_metadata_size = true; + } + GRPC_MDELEM_UNREF(md); + } else { + grpc_chttp2_incoming_metadata_buffer_add( + &stream_parsing->metadata_buffer[0], md); + } } grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing); @@ -658,12 +682,30 @@ static void on_trailing_header(void *tp, grpc_mdelem *md) { if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) { /* TODO(ctiller): check for a status like " 0" */ - stream_parsing->seen_error = 1; + stream_parsing->seen_error = true; + } + + const size_t new_size = + stream_parsing->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md); + grpc_chttp2_transport_global *transport_global = + &TRANSPORT_FROM_PARSING(transport_parsing)->global; + const size_t metadata_size_limit = + transport_global->settings[GRPC_LOCAL_SETTINGS] + [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; + if (new_size > metadata_size_limit) { + if (!stream_parsing->exceeded_metadata_size) { + gpr_log(GPR_DEBUG, + "received trailing metadata size exceeds limit (%lu vs. %lu)", + new_size, metadata_size_limit); + stream_parsing->seen_error = true; + stream_parsing->exceeded_metadata_size = true; + } + GRPC_MDELEM_UNREF(md); + } else { + grpc_chttp2_incoming_metadata_buffer_add( + &stream_parsing->metadata_buffer[1], md); } - grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->metadata_buffer[1], - md); - grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing); GPR_TIMER_END("on_trailing_header", 0); diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h index 0a51780a14e..23c7b7b897b 100644 --- a/src/core/lib/channel/channel_args.h +++ b/src/core/lib/channel/channel_args.h @@ -56,10 +56,6 @@ grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a, /** Destroy arguments created by \a grpc_channel_args_copy */ void grpc_channel_args_destroy(grpc_channel_args *a); -/** Reads census_enabled settings from channel args. Returns 1 if census_enabled - * is specified in channel args, otherwise returns 0. */ -int grpc_channel_args_is_census_enabled(const grpc_channel_args *a); - /** Returns the compression algorithm set in \a a. */ grpc_compression_algorithm grpc_channel_args_get_compression_algorithm( const grpc_channel_args *a); diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index 7210aef5d5c..e2869224f1f 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -164,7 +164,7 @@ static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, int success) { for (i = 0; i < tcp->incoming_buffer->count; i++) { char *dump = gpr_dump_slice(tcp->incoming_buffer->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "READ %p: %s", tcp, dump); + gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump); gpr_free(dump); } } @@ -398,7 +398,7 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, for (i = 0; i < buf->count; i++) { char *data = gpr_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data); + gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data); gpr_free(data); } } diff --git a/src/core/lib/surface/version.c b/src/core/lib/surface/version.c index fe954cbefb6..aca76d2bb79 100644 --- a/src/core/lib/surface/version.c +++ b/src/core/lib/surface/version.c @@ -36,4 +36,4 @@ #include -const char *grpc_version_string(void) { return "0.14.0-dev"; } +const char *grpc_version_string(void) { return "0.15.0-dev"; } diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h index 713d9e6782c..6d82f4d6819 100644 --- a/src/core/lib/transport/metadata.h +++ b/src/core/lib/transport/metadata.h @@ -147,6 +147,10 @@ const char *grpc_mdstr_as_c_string(grpc_mdstr *s); #define GRPC_MDSTR_LENGTH(s) (GPR_SLICE_LENGTH(s->slice)) +/* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */ +#define GRPC_MDELEM_LENGTH(e) \ + (GRPC_MDSTR_LENGTH((e)->key) + GRPC_MDSTR_LENGTH((e)->value) + 32) + int grpc_mdstr_is_legal_header(grpc_mdstr *s); int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s); int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s); diff --git a/src/core/lib/transport/metadata_batch.c b/src/core/lib/transport/metadata_batch.c index 4567221a48f..e4398abeb78 100644 --- a/src/core/lib/transport/metadata_batch.c +++ b/src/core/lib/transport/metadata_batch.c @@ -192,3 +192,12 @@ int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) { gpr_time_cmp(gpr_inf_future(batch->deadline.clock_type), batch->deadline) == 0; } + +size_t grpc_metadata_batch_size(grpc_metadata_batch *batch) { + size_t size = 0; + for (grpc_linked_mdelem *elem = batch->list.head; elem != NULL; + elem = elem->next) { + size += GRPC_MDELEM_LENGTH(elem->md); + } + return size; +} diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h index b62668876e4..7af823f7ca4 100644 --- a/src/core/lib/transport/metadata_batch.h +++ b/src/core/lib/transport/metadata_batch.h @@ -66,6 +66,9 @@ void grpc_metadata_batch_destroy(grpc_metadata_batch *batch); void grpc_metadata_batch_clear(grpc_metadata_batch *batch); int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch); +/* Returns the transport size of the batch. */ +size_t grpc_metadata_batch_size(grpc_metadata_batch *batch); + /** Moves the metadata information from \a src to \a dst. Upon return, \a src is * zeroed. */ void grpc_metadata_batch_move(grpc_metadata_batch *dst, diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc index 33a8f755e69..8e8d42eb294 100644 --- a/src/cpp/common/core_codegen.cc +++ b/src/cpp/common/core_codegen.cc @@ -48,124 +48,6 @@ #include "src/core/lib/profiling/timers.h" -namespace { - -const int kGrpcBufferWriterMaxBufferLength = 8192; - -class GrpcBufferWriter GRPC_FINAL - : public ::grpc::protobuf::io::ZeroCopyOutputStream { - public: - explicit GrpcBufferWriter(grpc_byte_buffer** bp, int block_size) - : block_size_(block_size), byte_count_(0), have_backup_(false) { - *bp = grpc_raw_byte_buffer_create(NULL, 0); - slice_buffer_ = &(*bp)->data.raw.slice_buffer; - } - - ~GrpcBufferWriter() GRPC_OVERRIDE { - if (have_backup_) { - gpr_slice_unref(backup_slice_); - } - } - - bool Next(void** data, int* size) GRPC_OVERRIDE { - if (have_backup_) { - slice_ = backup_slice_; - have_backup_ = false; - } else { - slice_ = gpr_slice_malloc(block_size_); - } - *data = GPR_SLICE_START_PTR(slice_); - // On win x64, int is only 32bit - GPR_ASSERT(GPR_SLICE_LENGTH(slice_) <= INT_MAX); - byte_count_ += * size = (int)GPR_SLICE_LENGTH(slice_); - gpr_slice_buffer_add(slice_buffer_, slice_); - return true; - } - - void BackUp(int count) GRPC_OVERRIDE { - gpr_slice_buffer_pop(slice_buffer_); - if (count == block_size_) { - backup_slice_ = slice_; - } else { - backup_slice_ = - gpr_slice_split_tail(&slice_, GPR_SLICE_LENGTH(slice_) - count); - gpr_slice_buffer_add(slice_buffer_, slice_); - } - have_backup_ = true; - byte_count_ -= count; - } - - grpc::protobuf::int64 ByteCount() const GRPC_OVERRIDE { return byte_count_; } - - private: - const int block_size_; - int64_t byte_count_; - gpr_slice_buffer* slice_buffer_; - bool have_backup_; - gpr_slice backup_slice_; - gpr_slice slice_; -}; - -class GrpcBufferReader GRPC_FINAL - : public ::grpc::protobuf::io::ZeroCopyInputStream { - public: - explicit GrpcBufferReader(grpc_byte_buffer* buffer) - : byte_count_(0), backup_count_(0) { - grpc_byte_buffer_reader_init(&reader_, buffer); - } - ~GrpcBufferReader() GRPC_OVERRIDE { - grpc_byte_buffer_reader_destroy(&reader_); - } - - bool Next(const void** data, int* size) GRPC_OVERRIDE { - if (backup_count_ > 0) { - *data = GPR_SLICE_START_PTR(slice_) + GPR_SLICE_LENGTH(slice_) - - backup_count_; - GPR_ASSERT(backup_count_ <= INT_MAX); - *size = (int)backup_count_; - backup_count_ = 0; - return true; - } - if (!grpc_byte_buffer_reader_next(&reader_, &slice_)) { - return false; - } - gpr_slice_unref(slice_); - *data = GPR_SLICE_START_PTR(slice_); - // On win x64, int is only 32bit - GPR_ASSERT(GPR_SLICE_LENGTH(slice_) <= INT_MAX); - byte_count_ += * size = (int)GPR_SLICE_LENGTH(slice_); - return true; - } - - void BackUp(int count) GRPC_OVERRIDE { backup_count_ = count; } - - bool Skip(int count) GRPC_OVERRIDE { - const void* data; - int size; - while (Next(&data, &size)) { - if (size >= count) { - BackUp(size - count); - return true; - } - // size < count; - count -= size; - } - // error or we have too large count; - return false; - } - - grpc::protobuf::int64 ByteCount() const GRPC_OVERRIDE { - return byte_count_ - backup_count_; - } - - private: - int64_t byte_count_; - int64_t backup_count_; - grpc_byte_buffer_reader reader_; - gpr_slice slice_; -}; -} // namespace - namespace grpc { grpc_completion_queue* CoreCodegen::grpc_completion_queue_create( @@ -192,6 +74,44 @@ void CoreCodegen::grpc_byte_buffer_destroy(grpc_byte_buffer* bb) { ::grpc_byte_buffer_destroy(bb); } +void CoreCodegen::grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader, + grpc_byte_buffer* buffer) { + ::grpc_byte_buffer_reader_init(reader, buffer); +} + +void CoreCodegen::grpc_byte_buffer_reader_destroy( + grpc_byte_buffer_reader* reader) { + ::grpc_byte_buffer_reader_destroy(reader); +} + +int CoreCodegen::grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader, + gpr_slice* slice) { + return ::grpc_byte_buffer_reader_next(reader, slice); +} + +grpc_byte_buffer* CoreCodegen::grpc_raw_byte_buffer_create(gpr_slice* slice, + size_t nslices) { + return ::grpc_raw_byte_buffer_create(slice, nslices); +} + +gpr_slice CoreCodegen::gpr_slice_malloc(size_t length) { + return ::gpr_slice_malloc(length); +} + +void CoreCodegen::gpr_slice_unref(gpr_slice slice) { ::gpr_slice_unref(slice); } + +gpr_slice CoreCodegen::gpr_slice_split_tail(gpr_slice* s, size_t split) { + return ::gpr_slice_split_tail(s, split); +} + +void CoreCodegen::gpr_slice_buffer_add(gpr_slice_buffer* sb, gpr_slice slice) { + ::gpr_slice_buffer_add(sb, slice); +} + +void CoreCodegen::gpr_slice_buffer_pop(gpr_slice_buffer* sb) { + ::gpr_slice_buffer_pop(sb); +} + void CoreCodegen::grpc_metadata_array_init(grpc_metadata_array* array) { ::grpc_metadata_array_init(array); } @@ -200,6 +120,10 @@ void CoreCodegen::grpc_metadata_array_destroy(grpc_metadata_array* array) { ::grpc_metadata_array_destroy(array); } +const Status& CoreCodegen::ok() { return grpc::Status::OK; } + +const Status& CoreCodegen::cancelled() { return grpc::Status::CANCELLED; } + gpr_timespec CoreCodegen::gpr_inf_future(gpr_clock_type type) { return ::gpr_inf_future(type); } @@ -209,48 +133,4 @@ void CoreCodegen::assert_fail(const char* failed_assertion) { abort(); } -Status CoreCodegen::SerializeProto(const grpc::protobuf::Message& msg, - grpc_byte_buffer** bp) { - GPR_TIMER_SCOPE("SerializeProto", 0); - int byte_size = msg.ByteSize(); - if (byte_size <= kGrpcBufferWriterMaxBufferLength) { - gpr_slice slice = gpr_slice_malloc(byte_size); - GPR_ASSERT(GPR_SLICE_END_PTR(slice) == - msg.SerializeWithCachedSizesToArray(GPR_SLICE_START_PTR(slice))); - *bp = grpc_raw_byte_buffer_create(&slice, 1); - gpr_slice_unref(slice); - return Status::OK; - } else { - GrpcBufferWriter writer(bp, kGrpcBufferWriterMaxBufferLength); - return msg.SerializeToZeroCopyStream(&writer) - ? Status::OK - : Status(StatusCode::INTERNAL, "Failed to serialize message"); - } -} - -Status CoreCodegen::DeserializeProto(grpc_byte_buffer* buffer, - grpc::protobuf::Message* msg, - int max_message_size) { - GPR_TIMER_SCOPE("DeserializeProto", 0); - if (buffer == nullptr) { - return Status(StatusCode::INTERNAL, "No payload"); - } - Status result = Status::OK; - { - GrpcBufferReader reader(buffer); - ::grpc::protobuf::io::CodedInputStream decoder(&reader); - if (max_message_size > 0) { - decoder.SetTotalBytesLimit(max_message_size, max_message_size); - } - if (!msg->ParseFromCodedStream(&decoder)) { - result = Status(StatusCode::INTERNAL, msg->InitializationErrorString()); - } - if (!decoder.ConsumedEntireMessage()) { - result = Status(StatusCode::INTERNAL, "Did not read entire message"); - } - } - grpc_byte_buffer_destroy(buffer); - return result; -} - } // namespace grpc diff --git a/src/cpp/common/core_codegen.h b/src/cpp/common/core_codegen.h index e15cb4c34aa..656b11e7e72 100644 --- a/src/cpp/common/core_codegen.h +++ b/src/cpp/common/core_codegen.h @@ -42,13 +42,6 @@ namespace grpc { /// Implementation of the core codegen interface. class CoreCodegen : public CoreCodegenInterface { private: - Status SerializeProto(const grpc::protobuf::Message& msg, - grpc_byte_buffer** bp) override; - - Status DeserializeProto(grpc_byte_buffer* buffer, - grpc::protobuf::Message* msg, - int max_message_size) override; - grpc_completion_queue* grpc_completion_queue_create(void* reserved) override; void grpc_completion_queue_destroy(grpc_completion_queue* cq) override; grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag, @@ -60,11 +53,30 @@ class CoreCodegen : public CoreCodegenInterface { void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override; + void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader, + grpc_byte_buffer* buffer) override; + void grpc_byte_buffer_reader_destroy( + grpc_byte_buffer_reader* reader) override; + int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader, + gpr_slice* slice) override; + + grpc_byte_buffer* grpc_raw_byte_buffer_create(gpr_slice* slice, + size_t nslices) override; + + gpr_slice gpr_slice_malloc(size_t length) override; + void gpr_slice_unref(gpr_slice slice) override; + gpr_slice gpr_slice_split_tail(gpr_slice* s, size_t split) override; + void gpr_slice_buffer_add(gpr_slice_buffer* sb, gpr_slice slice) override; + void gpr_slice_buffer_pop(gpr_slice_buffer* sb) override; + void grpc_metadata_array_init(grpc_metadata_array* array) override; void grpc_metadata_array_destroy(grpc_metadata_array* array) override; gpr_timespec gpr_inf_future(gpr_clock_type type) override; + virtual const Status& ok() override; + virtual const Status& cancelled() override; + void assert_fail(const char* failed_assertion) override; }; diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs index 6c13a4fa483..d92addbf548 100644 --- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs +++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs @@ -166,6 +166,37 @@ namespace Grpc.Core.Tests Assert.IsNotNull("xyz", call.GetTrailers()[0].Key); } + [Test] + public async Task ServerStreamingCall_EndOfStreamIsIdempotent() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => + { + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); + + Assert.IsFalse(await call.ResponseStream.MoveNext()); + Assert.IsFalse(await call.ResponseStream.MoveNext()); + } + + [Test] + public async Task ServerStreamingCall_ErrorCanBeAwaitedTwice() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => + { + context.Status = new Status(StatusCode.InvalidArgument, ""); + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); + + var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.InvalidArgument, ex.Status.StatusCode); + + // attempting MoveNext again should result in throwing the same exception. + var ex2 = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.InvalidArgument, ex2.Status.StatusCode); + } + [Test] public async Task DuplexStreamingCall() { @@ -208,6 +239,38 @@ namespace Grpc.Core.Tests Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); } + [Test] + public async Task ClientStreamingCall_ServerSideReadAfterCancelNotificationReturnsNull() + { + var handlerStartedBarrier = new TaskCompletionSource(); + var cancelNotificationReceivedBarrier = new TaskCompletionSource(); + var successTcs = new TaskCompletionSource(); + + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + handlerStartedBarrier.SetResult(null); + + // wait for cancellation to be delivered. + context.CancellationToken.Register(() => cancelNotificationReceivedBarrier.SetResult(null)); + await cancelNotificationReceivedBarrier.Task; + + var moveNextResult = await requestStream.MoveNext(); + successTcs.SetResult(!moveNextResult ? "SUCCESS" : "FAIL"); + return ""; + }); + + var cts = new CancellationTokenSource(); + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token))); + + await handlerStartedBarrier.Task; + cts.Cancel(); + + var ex = Assert.ThrowsAsync(async () => await call.ResponseAsync); + Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); + + Assert.AreEqual("SUCCESS", await successTcs.Task); + } + [Test] public async Task AsyncUnaryCall_EchoMetadata() { diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj index 0cd059c2327..47131fc454e 100644 --- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj +++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj @@ -84,6 +84,8 @@ + + diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs new file mode 100644 index 00000000000..0e204761f61 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs @@ -0,0 +1,191 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + /// + /// Uses fake native call to test interaction of AsyncCallServer wrapping code with C core in different situations. + /// + public class AsyncCallServerTest + { + Server server; + FakeNativeCall fakeCall; + AsyncCallServer asyncCallServer; + + [SetUp] + public void Init() + { + var environment = GrpcEnvironment.AddRef(); + + // Create a fake server just so we have an instance to refer to. + // The server won't actually be used at all. + server = new Server() + { + Ports = { { "localhost", 0, ServerCredentials.Insecure } } + }; + server.Start(); + + fakeCall = new FakeNativeCall(); + asyncCallServer = new AsyncCallServer( + Marshallers.StringMarshaller.Serializer, Marshallers.StringMarshaller.Deserializer, + environment, + server); + asyncCallServer.InitializeForTesting(fakeCall); + } + + [TearDown] + public void Cleanup() + { + server.ShutdownAsync().Wait(); + GrpcEnvironment.Release(); + } + + [Test] + public void CancelNotificationAfterStartDisposes() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void CancelNotificationAfterStartDisposesAfterPendingReadFinishes() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCallServer); + + var moveNextTask = requestStream.MoveNext(); + + fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); + fakeCall.ReceivedMessageHandler(true, null); + Assert.IsFalse(moveNextTask.Result); + + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void ReadAfterCancelNotificationCanSucceed() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCallServer); + + fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); + + // Check that starting a read after cancel notification has been processed is legal. + var moveNextTask = requestStream.MoveNext(); + Assert.IsFalse(moveNextTask.Result); + + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void ReadCompletionFailureClosesRequestStream() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCallServer); + + // if a read completion's success==false, the request stream will silently finish + // and we rely on C core cancelling the call. + var moveNextTask = requestStream.MoveNext(); + fakeCall.ReceivedMessageHandler(false, null); + Assert.IsFalse(moveNextTask.Result); + + fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void WriteAfterCancelNotificationFails() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCallServer); + var responseStream = new ServerResponseStream(asyncCallServer); + + fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); + + // TODO(jtattermusch): should we throw a different exception type instead? + Assert.Throws(typeof(InvalidOperationException), () => responseStream.WriteAsync("request1")); + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void WriteCompletionFailureThrows() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var responseStream = new ServerResponseStream(asyncCallServer); + + var writeTask = responseStream.WriteAsync("request1"); + fakeCall.SendCompletionHandler(false); + // TODO(jtattermusch): should we throw a different exception type instead? + Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await writeTask); + + fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void WriteAndWriteStatusCanRunConcurrently() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var responseStream = new ServerResponseStream(asyncCallServer); + + var writeTask = responseStream.WriteAsync("request1"); + var writeStatusTask = asyncCallServer.SendStatusFromServerAsync(Status.DefaultSuccess, new Metadata(), null); + + fakeCall.SendCompletionHandler(true); + fakeCall.SendStatusFromServerHandler(true); + + Assert.DoesNotThrowAsync(async () => await writeTask); + Assert.DoesNotThrowAsync(async () => await writeStatusTask); + + fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); + + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + static void AssertFinished(AsyncCallServer asyncCallServer, FakeNativeCall fakeCall, Task finishedTask) + { + Assert.IsTrue(fakeCall.IsDisposed); + Assert.IsTrue(finishedTask.IsCompleted); + Assert.DoesNotThrow(() => finishedTask.Wait()); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs index a678e4dafe1..abe9d4a2e62 100644 --- a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs +++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs @@ -32,6 +32,7 @@ #endregion using System; +using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; @@ -40,6 +41,9 @@ using NUnit.Framework; namespace Grpc.Core.Internal.Tests { + /// + /// Uses fake native call to test interaction of AsyncCall wrapping code with C core in different situations. + /// public class AsyncCallTest { Channel channel; @@ -75,8 +79,8 @@ namespace Grpc.Core.Internal.Tests public void AsyncUnary_StreamingOperationsNotAllowed() { asyncCall.UnaryCallAsync("request1"); - Assert.Throws(typeof(InvalidOperationException), - () => asyncCall.StartReadMessage((x,y) => {})); + Assert.ThrowsAsync(typeof(InvalidOperationException), + async () => await asyncCall.ReadMessageAsync()); Assert.Throws(typeof(InvalidOperationException), () => asyncCall.StartSendMessage("abc", new WriteFlags(), (x,y) => {})); } @@ -118,6 +122,14 @@ namespace Grpc.Core.Internal.Tests AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); } + [Test] + public void ClientStreaming_StreamingReadNotAllowed() + { + asyncCall.ClientStreamingCallAsync(); + Assert.ThrowsAsync(typeof(InvalidOperationException), + async () => await asyncCall.ReadMessageAsync()); + } + [Test] public void ClientStreaming_NoRequest_Success() { @@ -142,6 +154,283 @@ namespace Grpc.Core.Internal.Tests AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument); } + [Test] + public void ClientStreaming_MoreRequests_Success() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + var writeTask = requestStream.WriteAsync("request1"); + fakeCall.SendCompletionHandler(true); + writeTask.Wait(); + + var writeTask2 = requestStream.WriteAsync("request2"); + fakeCall.SendCompletionHandler(true); + writeTask2.Wait(); + + var completeTask = requestStream.CompleteAsync(); + fakeCall.SendCompletionHandler(true); + completeTask.Wait(); + + fakeCall.UnaryResponseClientHandler(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); + } + + [Test] + public void ClientStreaming_WriteFailure() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + var writeTask = requestStream.WriteAsync("request1"); + fakeCall.SendCompletionHandler(false); + Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await writeTask); + + fakeCall.UnaryResponseClientHandler(true, + CreateClientSideStatus(StatusCode.Internal), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); + } + + [Test] + public void ClientStreaming_WriteAfterReceivingStatusFails() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + fakeCall.UnaryResponseClientHandler(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); + Assert.Throws(typeof(InvalidOperationException), () => requestStream.WriteAsync("request1")); + } + + [Test] + public void ClientStreaming_CompleteAfterReceivingStatusSucceeds() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + fakeCall.UnaryResponseClientHandler(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); + Assert.DoesNotThrowAsync(async () => await requestStream.CompleteAsync()); + } + + [Test] + public void ClientStreaming_WriteAfterCancellationRequestFails() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + asyncCall.Cancel(); + Assert.IsTrue(fakeCall.IsCancelled); + + Assert.Throws(typeof(OperationCanceledException), () => requestStream.WriteAsync("request1")); + + fakeCall.UnaryResponseClientHandler(true, + CreateClientSideStatus(StatusCode.Cancelled), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Cancelled); + } + + [Test] + public void ServerStreaming_StreamingSendNotAllowed() + { + asyncCall.StartServerStreamingCall("request1"); + Assert.Throws(typeof(InvalidOperationException), + () => asyncCall.StartSendMessage("abc", new WriteFlags(), (x,y) => {})); + } + + [Test] + public void ServerStreaming_NoResponse_Success1() + { + asyncCall.StartServerStreamingCall("request1"); + var responseStream = new ClientResponseStream(asyncCall); + var readTask = responseStream.MoveNext(); + + fakeCall.ReceivedResponseHeadersHandler(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + fakeCall.ReceivedMessageHandler(true, null); + fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + } + + [Test] + public void ServerStreaming_NoResponse_Success2() + { + asyncCall.StartServerStreamingCall("request1"); + var responseStream = new ClientResponseStream(asyncCall); + var readTask = responseStream.MoveNext(); + + // try alternative order of completions + fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + fakeCall.ReceivedMessageHandler(true, null); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + } + + [Test] + public void ServerStreaming_NoResponse_ReadFailure() + { + asyncCall.StartServerStreamingCall("request1"); + var responseStream = new ClientResponseStream(asyncCall); + var readTask = responseStream.MoveNext(); + + fakeCall.ReceivedMessageHandler(false, null); // after a failed read, we rely on C core to deliver appropriate status code. + fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.Internal)); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.Internal); + } + + [Test] + public void ServerStreaming_MoreResponses_Success() + { + asyncCall.StartServerStreamingCall("request1"); + var responseStream = new ClientResponseStream(asyncCall); + + var readTask1 = responseStream.MoveNext(); + fakeCall.ReceivedMessageHandler(true, CreateResponsePayload()); + Assert.IsTrue(readTask1.Result); + Assert.AreEqual("response1", responseStream.Current); + + var readTask2 = responseStream.MoveNext(); + fakeCall.ReceivedMessageHandler(true, CreateResponsePayload()); + Assert.IsTrue(readTask2.Result); + Assert.AreEqual("response1", responseStream.Current); + + var readTask3 = responseStream.MoveNext(); + fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + fakeCall.ReceivedMessageHandler(true, null); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask3); + } + + [Test] + public void DuplexStreaming_NoRequestNoResponse_Success() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + var writeTask1 = requestStream.CompleteAsync(); + fakeCall.SendCompletionHandler(true); + Assert.DoesNotThrowAsync(async () => await writeTask1); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageHandler(true, null); + fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + } + + [Test] + public void DuplexStreaming_WriteAfterReceivingStatusFails() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageHandler(true, null); + fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + + Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await requestStream.WriteAsync("request1")); + } + + [Test] + public void DuplexStreaming_CompleteAfterReceivingStatusFails() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageHandler(true, null); + fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + + Assert.DoesNotThrowAsync(async () => await requestStream.CompleteAsync()); + } + + [Test] + public void DuplexStreaming_WriteAfterCancellationRequestFails() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + asyncCall.Cancel(); + Assert.IsTrue(fakeCall.IsCancelled); + Assert.Throws(typeof(OperationCanceledException), () => requestStream.WriteAsync("request1")); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageHandler(true, null); + fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.Cancelled)); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.Cancelled); + } + + [Test] + public void DuplexStreaming_ReadAfterCancellationRequestCanSucceed() + { + asyncCall.StartDuplexStreamingCall(); + var responseStream = new ClientResponseStream(asyncCall); + + asyncCall.Cancel(); + Assert.IsTrue(fakeCall.IsCancelled); + + var readTask1 = responseStream.MoveNext(); + fakeCall.ReceivedMessageHandler(true, CreateResponsePayload()); + Assert.IsTrue(readTask1.Result); + Assert.AreEqual("response1", responseStream.Current); + + var readTask2 = responseStream.MoveNext(); + fakeCall.ReceivedMessageHandler(true, null); + fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.Cancelled)); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask2, StatusCode.Cancelled); + } + + [Test] + public void DuplexStreaming_ReadStartedBeforeCancellationRequestCanSucceed() + { + asyncCall.StartDuplexStreamingCall(); + var responseStream = new ClientResponseStream(asyncCall); + + var readTask1 = responseStream.MoveNext(); // initiate the read before cancel request + asyncCall.Cancel(); + Assert.IsTrue(fakeCall.IsCancelled); + + fakeCall.ReceivedMessageHandler(true, CreateResponsePayload()); + Assert.IsTrue(readTask1.Result); + Assert.AreEqual("response1", responseStream.Current); + + var readTask2 = responseStream.MoveNext(); + fakeCall.ReceivedMessageHandler(true, null); + fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.Cancelled)); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask2, StatusCode.Cancelled); + } + ClientSideStatus CreateClientSideStatus(StatusCode statusCode) { return new ClientSideStatus(new Status(statusCode, ""), new Metadata()); @@ -163,6 +452,16 @@ namespace Grpc.Core.Internal.Tests Assert.AreEqual("response1", resultTask.Result); } + static void AssertStreamingResponseSuccess(AsyncCall asyncCall, FakeNativeCall fakeCall, Task moveNextTask) + { + Assert.IsTrue(moveNextTask.IsCompleted); + Assert.IsTrue(fakeCall.IsDisposed); + + Assert.IsFalse(moveNextTask.Result); + Assert.AreEqual(Status.DefaultSuccess, asyncCall.GetStatus()); + Assert.AreEqual(0, asyncCall.GetTrailers().Count); + } + static void AssertUnaryResponseError(AsyncCall asyncCall, FakeNativeCall fakeCall, Task resultTask, StatusCode expectedStatusCode) { Assert.IsTrue(resultTask.IsCompleted); @@ -175,135 +474,15 @@ namespace Grpc.Core.Internal.Tests Assert.AreEqual(0, asyncCall.GetTrailers().Count); } - internal class FakeNativeCall : INativeCall - { - public UnaryResponseClientHandler UnaryResponseClientHandler - { - get; - set; - } - - public ReceivedStatusOnClientHandler ReceivedStatusOnClientHandler - { - get; - set; - } - - public ReceivedMessageHandler ReceivedMessageHandler - { - get; - set; - } - - public ReceivedResponseHeadersHandler ReceivedResponseHeadersHandler - { - get; - set; - } - - public SendCompletionHandler SendCompletionHandler - { - get; - set; - } - - public ReceivedCloseOnServerHandler ReceivedCloseOnServerHandler - { - get; - set; - } - - public bool IsCancelled - { - get; - set; - } - - public bool IsDisposed - { - get; - set; - } - - public void Cancel() - { - IsCancelled = true; - } - - public void CancelWithStatus(Status status) - { - IsCancelled = true; - } - - public string GetPeer() - { - return "PEER"; - } - - public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) - { - UnaryResponseClientHandler = callback; - } - - public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) - { - throw new NotImplementedException(); - } - - public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray) - { - UnaryResponseClientHandler = callback; - } - - public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) - { - ReceivedStatusOnClientHandler = callback; - } - - public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray) - { - ReceivedStatusOnClientHandler = callback; - } - - public void StartReceiveMessage(ReceivedMessageHandler callback) - { - ReceivedMessageHandler = callback; - } - - public void StartReceiveInitialMetadata(ReceivedResponseHeadersHandler callback) - { - ReceivedResponseHeadersHandler = callback; - } - - public void StartSendInitialMetadata(SendCompletionHandler callback, MetadataArraySafeHandle metadataArray) - { - SendCompletionHandler = callback; - } - - public void StartSendMessage(SendCompletionHandler callback, byte[] payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata) - { - SendCompletionHandler = callback; - } - - public void StartSendCloseFromClient(SendCompletionHandler callback) - { - SendCompletionHandler = callback; - } - - public void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata) - { - SendCompletionHandler = callback; - } - - public void StartServerSide(ReceivedCloseOnServerHandler callback) - { - ReceivedCloseOnServerHandler = callback; - } - - public void Dispose() - { - IsDisposed = true; - } + static void AssertStreamingResponseError(AsyncCall asyncCall, FakeNativeCall fakeCall, Task moveNextTask, StatusCode expectedStatusCode) + { + Assert.IsTrue(moveNextTask.IsCompleted); + Assert.IsTrue(fakeCall.IsDisposed); + + var ex = Assert.ThrowsAsync(async () => await moveNextTask); + Assert.AreEqual(expectedStatusCode, ex.Status.StatusCode); + Assert.AreEqual(expectedStatusCode, asyncCall.GetStatus().StatusCode); + Assert.AreEqual(0, asyncCall.GetTrailers().Count); } } } diff --git a/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs new file mode 100644 index 00000000000..909112a47c5 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs @@ -0,0 +1,184 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + /// + /// For testing purposes. + /// + internal class FakeNativeCall : INativeCall + { + public UnaryResponseClientHandler UnaryResponseClientHandler + { + get; + set; + } + + public ReceivedStatusOnClientHandler ReceivedStatusOnClientHandler + { + get; + set; + } + + public ReceivedMessageHandler ReceivedMessageHandler + { + get; + set; + } + + public ReceivedResponseHeadersHandler ReceivedResponseHeadersHandler + { + get; + set; + } + + public SendCompletionHandler SendCompletionHandler + { + get; + set; + } + + public SendCompletionHandler SendStatusFromServerHandler + { + get; + set; + } + + public ReceivedCloseOnServerHandler ReceivedCloseOnServerHandler + { + get; + set; + } + + public bool IsCancelled + { + get; + set; + } + + public bool IsDisposed + { + get; + set; + } + + public void Cancel() + { + IsCancelled = true; + } + + public void CancelWithStatus(Status status) + { + IsCancelled = true; + } + + public string GetPeer() + { + return "PEER"; + } + + public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) + { + UnaryResponseClientHandler = callback; + } + + public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) + { + throw new NotImplementedException(); + } + + public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray) + { + UnaryResponseClientHandler = callback; + } + + public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) + { + ReceivedStatusOnClientHandler = callback; + } + + public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray) + { + ReceivedStatusOnClientHandler = callback; + } + + public void StartReceiveMessage(ReceivedMessageHandler callback) + { + ReceivedMessageHandler = callback; + } + + public void StartReceiveInitialMetadata(ReceivedResponseHeadersHandler callback) + { + ReceivedResponseHeadersHandler = callback; + } + + public void StartSendInitialMetadata(SendCompletionHandler callback, MetadataArraySafeHandle metadataArray) + { + SendCompletionHandler = callback; + } + + public void StartSendMessage(SendCompletionHandler callback, byte[] payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata) + { + SendCompletionHandler = callback; + } + + public void StartSendCloseFromClient(SendCompletionHandler callback) + { + SendCompletionHandler = callback; + } + + public void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, + byte[] optionalPayload, WriteFlags writeFlags) + { + SendStatusFromServerHandler = callback; + } + + public void StartServerSide(ReceivedCloseOnServerHandler callback) + { + ReceivedCloseOnServerHandler = callback; + } + + public void Dispose() + { + IsDisposed = true; + } + } +} diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs index a5c78cc9d7e..bee0ef1d62e 100644 --- a/src/csharp/Grpc.Core/GrpcEnvironment.cs +++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs @@ -45,11 +45,12 @@ namespace Grpc.Core /// public class GrpcEnvironment { - const int THREAD_POOL_SIZE = 4; + const int MinDefaultThreadPoolSize = 4; static object staticLock = new object(); static GrpcEnvironment instance; static int refCount; + static int? customThreadPoolSize; static ILogger logger = new ConsoleLogger(); @@ -122,6 +123,23 @@ namespace Grpc.Core logger = customLogger; } + /// + /// Sets the number of threads in the gRPC thread pool that polls for internal RPC events. + /// Can be only invoke before the GrpcEnviroment is started and cannot be changed afterwards. + /// Setting thread pool size is an advanced setting and you should only use it if you know what you are doing. + /// Most users should rely on the default value provided by gRPC library. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// + public static void SetThreadPoolSize(int threadCount) + { + lock (staticLock) + { + GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized"); + GrpcPreconditions.CheckArgument(threadCount > 0, "threadCount needs to be a positive number"); + customThreadPoolSize = threadCount; + } + } + /// /// Creates gRPC environment. /// @@ -129,7 +147,7 @@ namespace Grpc.Core { GrpcNativeInit(); completionRegistry = new CompletionRegistry(this); - threadPool = new GrpcThreadPool(this, THREAD_POOL_SIZE); + threadPool = new GrpcThreadPool(this, GetThreadPoolSizeOrDefault()); threadPool.Start(); } @@ -200,5 +218,17 @@ namespace Grpc.Core debugStats.CheckOK(); } + + private int GetThreadPoolSizeOrDefault() + { + if (customThreadPoolSize.HasValue) + { + return customThreadPoolSize.Value; + } + // In systems with many cores, use half of the cores for GrpcThreadPool + // and the other half for .NET thread pool. This heuristic definitely needs + // more work, but seems to work reasonably well for a start. + return Math.Max(MinDefaultThreadPoolSize, Environment.ProcessorCount / 2); + } } } diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index 50ba617cdb1..f522174bd0f 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -241,11 +241,10 @@ namespace Grpc.Core.Internal /// /// Receives a streaming response. Only one pending read action is allowed at any given time. - /// completionDelegate is called when the operation finishes. /// - public void StartReadMessage(AsyncCompletionDelegate completionDelegate) + public Task ReadMessageAsync() { - StartReadMessageInternal(completionDelegate); + return ReadMessageInternalAsync(); } /// diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs index ccd047f4695..42234dcac21 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs @@ -68,7 +68,8 @@ namespace Grpc.Core.Internal protected bool cancelRequested; protected AsyncCompletionDelegate sendCompletionDelegate; // Completion of a pending send or sendclose if not null. - protected AsyncCompletionDelegate readCompletionDelegate; // Completion of a pending send or sendclose if not null. + protected TaskCompletionSource streamingReadTcs; // Completion of a pending streaming read if not null. + protected TaskCompletionSource sendStatusFromServerTcs; protected bool readingDone; // True if last read (i.e. read with null payload) was already received. protected bool halfcloseRequested; // True if send close have been initiated. @@ -150,15 +151,25 @@ namespace Grpc.Core.Internal /// Initiates reading a message. Only one read operation can be active at a time. /// completionDelegate is invoked upon completion. /// - protected void StartReadMessageInternal(AsyncCompletionDelegate completionDelegate) + protected Task ReadMessageInternalAsync() { lock (myLock) { - GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null"); - CheckReadingAllowed(); + GrpcPreconditions.CheckState(started); + if (readingDone) + { + // the last read that returns null or throws an exception is idempotent + // and maintain its state. + GrpcPreconditions.CheckState(streamingReadTcs != null, "Call does not support streaming reads."); + return streamingReadTcs.Task; + } + + GrpcPreconditions.CheckState(streamingReadTcs == null, "Only one read can be pending at a time"); + GrpcPreconditions.CheckState(!disposed); call.StartReceiveMessage(HandleReadFinished); - readCompletionDelegate = completionDelegate; + streamingReadTcs = new TaskCompletionSource(); + return streamingReadTcs.Task; } } @@ -213,15 +224,6 @@ namespace Grpc.Core.Internal GrpcPreconditions.CheckState(sendCompletionDelegate == null, "Only one write can be pending at a time"); } - protected virtual void CheckReadingAllowed() - { - GrpcPreconditions.CheckState(started); - GrpcPreconditions.CheckState(!disposed); - - GrpcPreconditions.CheckState(!readingDone, "Stream has already been closed."); - GrpcPreconditions.CheckState(readCompletionDelegate == null, "Only one read can be pending at a time"); - } - protected void CheckNotCancelled() { if (cancelRequested) @@ -322,22 +324,18 @@ namespace Grpc.Core.Internal /// protected void HandleSendStatusFromServerFinished(bool success) { - AsyncCompletionDelegate origCompletionDelegate = null; lock (myLock) { - origCompletionDelegate = sendCompletionDelegate; - sendCompletionDelegate = null; - ReleaseResourcesIfPossible(); } if (!success) { - FireCompletion(origCompletionDelegate, null, new InvalidOperationException("Error sending status from server.")); + sendStatusFromServerTcs.SetException(new InvalidOperationException("Error sending status from server.")); } else { - FireCompletion(origCompletionDelegate, null, null); + sendStatusFromServerTcs.SetResult(null); } } @@ -346,15 +344,17 @@ namespace Grpc.Core.Internal /// protected void HandleReadFinished(bool success, byte[] receivedMessage) { + // if success == false, received message will be null. It that case we will + // treat this completion as the last read an rely on C core to handle the failed + // read (e.g. deliver approriate statusCode on the clientside). + TRead msg = default(TRead); var deserializeException = (success && receivedMessage != null) ? TryDeserialize(receivedMessage, out msg) : null; - AsyncCompletionDelegate origCompletionDelegate = null; + TaskCompletionSource origTcs = null; lock (myLock) { - origCompletionDelegate = readCompletionDelegate; - readCompletionDelegate = null; - + origTcs = streamingReadTcs; if (receivedMessage == null) { // This was the last read. @@ -364,20 +364,25 @@ namespace Grpc.Core.Internal if (deserializeException != null && IsClient) { readingDone = true; + + // TODO(jtattermusch): it might be too late to set the status CancelWithStatus(DeserializeResponseFailureStatus); } + if (!readingDone) + { + streamingReadTcs = null; + } + ReleaseResourcesIfPossible(); } - // TODO: handle the case when success==false - if (deserializeException != null && !IsClient) { - FireCompletion(origCompletionDelegate, default(TRead), new IOException("Failed to deserialize request message.", deserializeException)); + origTcs.SetException(new IOException("Failed to deserialize request message.", deserializeException)); return; } - FireCompletion(origCompletionDelegate, msg, null); + origTcs.SetResult(msg); } } } diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs index bea2b3660c3..b1566b44a7c 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs @@ -64,6 +64,15 @@ namespace Grpc.Core.Internal InitializeInternal(call); } + /// + /// Only for testing purposes. + /// + public void InitializeForTesting(INativeCall call) + { + server.AddCallReference(this); + InitializeInternal(call); + } + /// /// Starts a server side call. /// @@ -91,11 +100,10 @@ namespace Grpc.Core.Internal /// /// Receives a streaming request. Only one pending read action is allowed at any given time. - /// completionDelegate is called when the operation finishes. /// - public void StartReadMessage(AsyncCompletionDelegate completionDelegate) + public Task ReadMessageAsync() { - StartReadMessageInternal(completionDelegate); + return ReadMessageInternalAsync(); } /// @@ -128,24 +136,33 @@ namespace Grpc.Core.Internal } /// - /// Sends call result status, also indicating server is done with streaming responses. - /// Only one pending send action is allowed at any given time. - /// completionDelegate is called when the operation finishes. + /// Sends call result status, indicating we are done with writes. + /// Sending a status different from StatusCode.OK will also implicitly cancel the call. /// - public void StartSendStatusFromServer(Status status, Metadata trailers, AsyncCompletionDelegate completionDelegate) + public Task SendStatusFromServerAsync(Status status, Metadata trailers, Tuple optionalWrite) { + byte[] payload = optionalWrite != null ? UnsafeSerialize(optionalWrite.Item1) : null; + var writeFlags = optionalWrite != null ? optionalWrite.Item2 : default(WriteFlags); + lock (myLock) { - GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null"); - CheckSendingAllowed(allowFinished: false); + GrpcPreconditions.CheckState(started); + GrpcPreconditions.CheckState(!disposed); + GrpcPreconditions.CheckState(!halfcloseRequested, "Can only send status from server once."); using (var metadataArray = MetadataArraySafeHandle.Create(trailers)) { - call.StartSendStatusFromServer(HandleSendStatusFromServerFinished, status, metadataArray, !initialMetadataSent); + call.StartSendStatusFromServer(HandleSendStatusFromServerFinished, status, metadataArray, !initialMetadataSent, + payload, writeFlags); } halfcloseRequested = true; - readingDone = true; - sendCompletionDelegate = completionDelegate; + initialMetadataSent = true; + sendStatusFromServerTcs = new TaskCompletionSource(); + if (optionalWrite != null) + { + streamingWritesCounter++; + } + return sendStatusFromServerTcs.Task; } } @@ -174,12 +191,6 @@ namespace Grpc.Core.Internal get { return false; } } - protected override void CheckReadingAllowed() - { - base.CheckReadingAllowed(); - GrpcPreconditions.CheckArgument(!cancelRequested); - } - protected override void OnAfterReleaseResources() { server.RemoveCallReference(this); @@ -190,12 +201,21 @@ namespace Grpc.Core.Internal /// private void HandleFinishedServerside(bool success, bool cancelled) { + // NOTE: because this event is a result of batch containing GRPC_OP_RECV_CLOSE_ON_SERVER, + // success will be always set to true. lock (myLock) { finished = true; + if (streamingReadTcs == null) + { + // if there's no pending read, readingDone=true will dispose now. + // if there is a pending read, we will dispose once that read finishes. + readingDone = true; + streamingReadTcs = new TaskCompletionSource(); + streamingReadTcs.SetResult(default(TRequest)); + } ReleaseResourcesIfPossible(); } - // TODO(jtattermusch): handle error if (cancelled) { diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index 500653ba5d3..244b97d4a47 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -135,13 +135,16 @@ namespace Grpc.Core.Internal } } - public void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata) + public void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, + byte[] optionalPayload, WriteFlags writeFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); + var optionalPayloadLength = optionalPayload != null ? new UIntPtr((ulong)optionalPayload.Length) : UIntPtr.Zero; completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success)); - Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, status.Detail, metadataArray, sendEmptyInitialMetadata).CheckOk(); + Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, status.Detail, metadataArray, sendEmptyInitialMetadata, + optionalPayload, optionalPayloadLength, writeFlags).CheckOk(); } } diff --git a/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs b/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs index d6e34a0f044..ad9423ff58c 100644 --- a/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs +++ b/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs @@ -68,9 +68,7 @@ namespace Grpc.Core.Internal { throw new InvalidOperationException("Cancellation of individual reads is not supported."); } - var taskSource = new AsyncCompletionTaskSource(); - call.StartReadMessage(taskSource.CompletionDelegate); - var result = await taskSource.Task.ConfigureAwait(false); + var result = await call.ReadMessageAsync().ConfigureAwait(false); this.current = result; if (result == null) diff --git a/src/csharp/Grpc.Core/Internal/INativeCall.cs b/src/csharp/Grpc.Core/Internal/INativeCall.cs index cbef5991396..cd3719cb50c 100644 --- a/src/csharp/Grpc.Core/Internal/INativeCall.cs +++ b/src/csharp/Grpc.Core/Internal/INativeCall.cs @@ -78,7 +78,7 @@ namespace Grpc.Core.Internal void StartSendCloseFromClient(SendCompletionHandler callback); - void StartSendStatusFromServer(SendCompletionHandler callback, Grpc.Core.Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata); + void StartSendStatusFromServer(SendCompletionHandler callback, Grpc.Core.Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, byte[] optionalPayload, Grpc.Core.WriteFlags writeFlags); void StartServerSide(ReceivedCloseOnServerHandler callback); } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs index 9ee0ba3bc05..c277c73ef04 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -421,20 +421,21 @@ namespace Grpc.Core.Internal public delegate GRPCCallError grpcsharp_call_cancel_delegate(CallSafeHandle call); public delegate GRPCCallError grpcsharp_call_cancel_with_status_delegate(CallSafeHandle call, StatusCode status, string description); public delegate GRPCCallError grpcsharp_call_start_unary_delegate(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); + BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); public delegate GRPCCallError grpcsharp_call_start_client_streaming_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); public delegate GRPCCallError grpcsharp_call_start_server_streaming_delegate(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, + BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); public delegate GRPCCallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); public delegate GRPCCallError grpcsharp_call_send_message_delegate(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, WriteFlags writeFlags, bool sendEmptyInitialMetadata); + BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata); public delegate GRPCCallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); public delegate GRPCCallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call, - BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata); + BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, + byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags); public delegate GRPCCallError grpcsharp_call_recv_message_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); public delegate GRPCCallError grpcsharp_call_recv_initial_metadata_delegate(CallSafeHandle call, @@ -593,7 +594,7 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] public static extern GRPCCallError grpcsharp_call_start_unary(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); + BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); [DllImport("grpc_csharp_ext.dll")] public static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call, @@ -601,7 +602,7 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] public static extern GRPCCallError grpcsharp_call_start_server_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, + BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); [DllImport("grpc_csharp_ext.dll")] @@ -610,7 +611,7 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] public static extern GRPCCallError grpcsharp_call_send_message(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, WriteFlags writeFlags, bool sendEmptyInitialMetadata); + BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata); [DllImport("grpc_csharp_ext.dll")] public static extern GRPCCallError grpcsharp_call_send_close_from_client(CallSafeHandle call, @@ -618,7 +619,8 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] public static extern GRPCCallError grpcsharp_call_send_status_from_server(CallSafeHandle call, - BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata); + BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, + byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags); [DllImport("grpc_csharp_ext.dll")] public static extern GRPCCallError grpcsharp_call_recv_message(CallSafeHandle call, diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs index 1f83e51548e..85b7a4b01e9 100644 --- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs +++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs @@ -75,29 +75,32 @@ namespace Grpc.Core.Internal var responseStream = new ServerResponseStream(asyncCall); Status status; + Tuple responseTuple = null; var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken); try { GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false)); var request = requestStream.Current; - // TODO(jtattermusch): we need to read the full stream so that native callhandle gets deallocated. - GrpcPreconditions.CheckArgument(!await requestStream.MoveNext().ConfigureAwait(false)); - var result = await handler(request, context).ConfigureAwait(false); + var response = await handler(request, context).ConfigureAwait(false); status = context.Status; - await responseStream.WriteAsync(result).ConfigureAwait(false); + responseTuple = Tuple.Create(response, HandlerUtils.GetWriteFlags(context.WriteOptions)); } catch (Exception e) { - Logger.Error(e, "Exception occured in handler."); + if (!(e is RpcException)) + { + Logger.Warning(e, "Exception occured in handler."); + } status = HandlerUtils.StatusFromException(e); } try { - await responseStream.WriteStatusAsync(status, context.ResponseTrailers).ConfigureAwait(false); + await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, responseTuple).ConfigureAwait(false); } - catch (OperationCanceledException) + catch (Exception) { - // Call has been already cancelled. + asyncCall.Cancel(); + throw; } await finishedTask.ConfigureAwait(false); } @@ -136,24 +139,26 @@ namespace Grpc.Core.Internal { GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false)); var request = requestStream.Current; - // TODO(jtattermusch): we need to read the full stream so that native callhandle gets deallocated. - GrpcPreconditions.CheckArgument(!await requestStream.MoveNext().ConfigureAwait(false)); await handler(request, responseStream, context).ConfigureAwait(false); status = context.Status; } catch (Exception e) { - Logger.Error(e, "Exception occured in handler."); + if (!(e is RpcException)) + { + Logger.Warning(e, "Exception occured in handler."); + } status = HandlerUtils.StatusFromException(e); } try { - await responseStream.WriteStatusAsync(status, context.ResponseTrailers).ConfigureAwait(false); + await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, null).ConfigureAwait(false); } - catch (OperationCanceledException) + catch (Exception) { - // Call has been already cancelled. + asyncCall.Cancel(); + throw; } await finishedTask.ConfigureAwait(false); } @@ -187,33 +192,31 @@ namespace Grpc.Core.Internal var responseStream = new ServerResponseStream(asyncCall); Status status; + Tuple responseTuple = null; var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken); try { - var result = await handler(requestStream, context).ConfigureAwait(false); + var response = await handler(requestStream, context).ConfigureAwait(false); status = context.Status; - try - { - await responseStream.WriteAsync(result).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - status = Status.DefaultCancelled; - } + responseTuple = Tuple.Create(response, HandlerUtils.GetWriteFlags(context.WriteOptions)); } catch (Exception e) { - Logger.Error(e, "Exception occured in handler."); + if (!(e is RpcException)) + { + Logger.Warning(e, "Exception occured in handler."); + } status = HandlerUtils.StatusFromException(e); } try { - await responseStream.WriteStatusAsync(status, context.ResponseTrailers).ConfigureAwait(false); + await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, responseTuple).ConfigureAwait(false); } - catch (OperationCanceledException) + catch (Exception) { - // Call has been already cancelled. + asyncCall.Cancel(); + throw; } await finishedTask.ConfigureAwait(false); } @@ -255,16 +258,20 @@ namespace Grpc.Core.Internal } catch (Exception e) { - Logger.Error(e, "Exception occured in handler."); + if (!(e is RpcException)) + { + Logger.Warning(e, "Exception occured in handler."); + } status = HandlerUtils.StatusFromException(e); } try { - await responseStream.WriteStatusAsync(status, context.ResponseTrailers).ConfigureAwait(false); + await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, null).ConfigureAwait(false); } - catch (OperationCanceledException) + catch (Exception) { - // Call has been already cancelled. + asyncCall.Cancel(); + throw; } await finishedTask.ConfigureAwait(false); } @@ -282,9 +289,7 @@ namespace Grpc.Core.Internal asyncCall.Initialize(newRpc.Call); var finishedTask = asyncCall.ServerSideCallAsync(); - var responseStream = new ServerResponseStream(asyncCall); - - await responseStream.WriteStatusAsync(new Status(StatusCode.Unimplemented, ""), Metadata.Empty).ConfigureAwait(false); + await asyncCall.SendStatusFromServerAsync(new Status(StatusCode.Unimplemented, ""), Metadata.Empty, null).ConfigureAwait(false); await finishedTask.ConfigureAwait(false); } } @@ -300,10 +305,14 @@ namespace Grpc.Core.Internal return rpcException.Status; } - // TODO(jtattermusch): what is the right status code here? return new Status(StatusCode.Unknown, "Exception was thrown by handler."); } + public static WriteFlags GetWriteFlags(WriteOptions writeOptions) + { + return writeOptions != null ? writeOptions.Flags : default(WriteFlags); + } + public static ServerCallContext NewContext(ServerRpcNew newRpc, string peer, ServerResponseStream serverResponseStream, CancellationToken cancellationToken) where TRequest : class where TResponse : class diff --git a/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs b/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs index e7be82c3185..d76030d1add 100644 --- a/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs +++ b/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs @@ -68,9 +68,7 @@ namespace Grpc.Core.Internal { throw new InvalidOperationException("Cancellation of individual reads is not supported."); } - var taskSource = new AsyncCompletionTaskSource(); - call.StartReadMessage(taskSource.CompletionDelegate); - var result = await taskSource.Task.ConfigureAwait(false); + var result = await call.ReadMessageAsync().ConfigureAwait(false); this.current = result; return result != null; } diff --git a/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs b/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs index 03e39efc024..ecfee0bfddb 100644 --- a/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs +++ b/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs @@ -57,13 +57,6 @@ namespace Grpc.Core.Internal return taskSource.Task; } - public Task WriteStatusAsync(Status status, Metadata trailers) - { - var taskSource = new AsyncCompletionTaskSource(); - call.StartSendStatusFromServer(status, trailers, taskSource.CompletionDelegate); - return taskSource.Task; - } - public Task WriteResponseHeadersAsync(Metadata responseHeaders) { var taskSource = new AsyncCompletionTaskSource(); diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs index 5b61b7f060f..d538a4671f6 100644 --- a/src/csharp/Grpc.Core/Server.cs +++ b/src/csharp/Grpc.Core/Server.cs @@ -48,6 +48,7 @@ namespace Grpc.Core /// public class Server { + const int InitialAllowRpcTokenCount = 10; static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); readonly AtomicCounter activeCallCounter = new AtomicCounter(); @@ -65,7 +66,7 @@ namespace Grpc.Core readonly TaskCompletionSource shutdownTcs = new TaskCompletionSource(); bool startRequested; - bool shutdownRequested; + volatile bool shutdownRequested; /// /// Create a new server. @@ -129,7 +130,13 @@ namespace Grpc.Core startRequested = true; handle.Start(); - AllowOneRpc(); + + // Starting with more than one AllowOneRpc tokens can significantly increase + // unary RPC throughput. + for (int i = 0; i < InitialAllowRpcTokenCount; i++) + { + AllowOneRpc(); + } } } @@ -239,12 +246,9 @@ namespace Grpc.Core /// private void AllowOneRpc() { - lock (myLock) + if (!shutdownRequested) { - if (!shutdownRequested) - { - handle.RequestCall(HandleNewServerRpc, environment); - } + handle.RequestCall(HandleNewServerRpc, environment); } } @@ -283,6 +287,8 @@ namespace Grpc.Core /// private void HandleNewServerRpc(bool success, BatchContextSafeHandle ctx) { + Task.Run(() => AllowOneRpc()); + if (success) { ServerRpcNew newRpc = ctx.GetServerRpcNew(this); @@ -290,11 +296,9 @@ namespace Grpc.Core // after server shutdown, the callback returns with null call if (!newRpc.Call.IsInvalid) { - Task.Run(async () => await HandleCallAsync(newRpc)).ConfigureAwait(false); + HandleCallAsync(newRpc); // we don't need to await. } } - - AllowOneRpc(); } /// diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index f7a9cb9c1cb..e1609341d9a 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -48,11 +48,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "0.14.0.0"; + public const string CurrentAssemblyFileVersion = "0.15.0.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "0.14.0-dev"; + public const string CurrentVersion = "0.15.0-dev"; } } diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 2d3034d28b5..d700a18778b 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -151,25 +151,25 @@ namespace Math { /// Div divides args.dividend by args.divisor and returns the quotient and /// remainder. /// - Task Div(global::Math.DivArgs request, ServerCallContext context); + global::System.Threading.Tasks.Task Div(global::Math.DivArgs request, ServerCallContext context); /// /// DivMany accepts an arbitrary number of division args from the client stream /// and sends back the results in the reply stream. The stream continues until /// the client closes its end; the server does the same after sending all the /// replies. The stream ends immediately if either end aborts. /// - Task DivMany(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task DivMany(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); /// /// Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib /// generates up to limit numbers; otherwise it continues until the call is /// canceled. Unlike Fib above, Fib has no final FibReply. /// - Task Fib(global::Math.FibArgs request, IServerStreamWriter responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task Fib(global::Math.FibArgs request, IServerStreamWriter responseStream, ServerCallContext context); /// /// Sum sums a stream of numbers, returning the final result once the stream /// is closed. /// - Task Sum(IAsyncStreamReader requestStream, ServerCallContext context); + global::System.Threading.Tasks.Task Sum(IAsyncStreamReader requestStream, ServerCallContext context); } /// Base class for server-side implementations of Math @@ -179,7 +179,7 @@ namespace Math { /// Div divides args.dividend by args.divisor and returns the quotient and /// remainder. /// - public virtual Task Div(global::Math.DivArgs request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task Div(global::Math.DivArgs request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -190,7 +190,7 @@ namespace Math { /// the client closes its end; the server does the same after sending all the /// replies. The stream ends immediately if either end aborts. /// - public virtual Task DivMany(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task DivMany(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -200,7 +200,7 @@ namespace Math { /// generates up to limit numbers; otherwise it continues until the call is /// canceled. Unlike Fib above, Fib has no final FibReply. /// - public virtual Task Fib(global::Math.FibArgs request, IServerStreamWriter responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task Fib(global::Math.FibArgs request, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -209,7 +209,7 @@ namespace Math { /// Sum sums a stream of numbers, returning the final result once the stream /// is closed. /// - public virtual Task Sum(IAsyncStreamReader requestStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task Sum(IAsyncStreamReader requestStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 967d1170bed..51c6a39b1d8 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -72,13 +72,13 @@ namespace Grpc.Health.V1 { [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IHealth { - Task Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context); } /// Base class for server-side implementations of Health public abstract class HealthBase { - public virtual Task Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs index b4572756f24..9eaf6bf7ce2 100644 --- a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs +++ b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs @@ -142,8 +142,7 @@ namespace Grpc.IntegrationTesting for (int i = 0; i < outstandingRpcsPerChannel; i++) { var timer = CreateTimer(loadParams, 1.0 / this.channels.Count / outstandingRpcsPerChannel); - var threadBody = GetThreadBody(channel, timer); - this.runnerTasks.Add(Task.Factory.StartNew(threadBody, TaskCreationOptions.LongRunning)); + this.runnerTasks.Add(RunClientAsync(channel, timer)); } } } @@ -269,38 +268,30 @@ namespace Grpc.IntegrationTesting } } - private Action GetThreadBody(Channel channel, IInterarrivalTimer timer) + private Task RunClientAsync(Channel channel, IInterarrivalTimer timer) { if (payloadConfig.PayloadCase == PayloadConfig.PayloadOneofCase.BytebufParams) { GrpcPreconditions.CheckArgument(clientType == ClientType.ASYNC_CLIENT, "Generic client only supports async API"); GrpcPreconditions.CheckArgument(rpcType == RpcType.STREAMING, "Generic client only supports streaming calls"); - return () => - { - RunGenericStreamingAsync(channel, timer).Wait(); - }; + return RunGenericStreamingAsync(channel, timer); } GrpcPreconditions.CheckNotNull(payloadConfig.SimpleParams); if (clientType == ClientType.SYNC_CLIENT) { GrpcPreconditions.CheckArgument(rpcType == RpcType.UNARY, "Sync client can only be used for Unary calls in C#"); - return () => RunUnary(channel, timer); + // create a dedicated thread for the synchronous client + return Task.Factory.StartNew(() => RunUnary(channel, timer), TaskCreationOptions.LongRunning); } else if (clientType == ClientType.ASYNC_CLIENT) { switch (rpcType) { case RpcType.UNARY: - return () => - { - RunUnaryAsync(channel, timer).Wait(); - }; + return RunUnaryAsync(channel, timer); case RpcType.STREAMING: - return () => - { - RunStreamingPingPongAsync(channel, timer).Wait(); - }; + return RunStreamingPingPongAsync(channel, timer); } } throw new ArgumentException("Unsupported configuration."); diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs index aa4f1c5c3ec..9d31d1c5146 100644 --- a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs @@ -112,11 +112,11 @@ namespace Grpc.Testing { /// Returns the values of all the gauges that are currently being maintained by /// the service /// - Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter responseStream, ServerCallContext context); /// /// Returns the value of one gauge /// - Task GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context); } /// Base class for server-side implementations of MetricsService @@ -126,7 +126,7 @@ namespace Grpc.Testing { /// Returns the values of all the gauges that are currently being maintained by /// the service /// - public virtual Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -134,7 +134,7 @@ namespace Grpc.Testing { /// /// Returns the value of one gauge /// - public virtual Task GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs index 42bf5e0b582..f7071ebf6be 100644 --- a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs @@ -111,12 +111,12 @@ namespace Grpc.Testing { /// One request followed by one response. /// The server returns the client payload as-is. /// - Task UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); /// /// One request followed by one response. /// The server returns the client payload as-is. /// - Task StreamingCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task StreamingCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); } /// Base class for server-side implementations of BenchmarkService @@ -126,7 +126,7 @@ namespace Grpc.Testing { /// One request followed by one response. /// The server returns the client payload as-is. /// - public virtual Task UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -135,7 +135,7 @@ namespace Grpc.Testing { /// One request followed by one response. /// The server returns the client payload as-is. /// - public virtual Task StreamingCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task StreamingCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -375,7 +375,7 @@ namespace Grpc.Testing { /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// - Task RunServer(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task RunServer(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); /// /// Start client with specified workload. /// First request sent specifies the ClientConfig followed by ClientStatus @@ -384,15 +384,15 @@ namespace Grpc.Testing { /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// - Task RunClient(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task RunClient(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); /// /// Just return the core count - unary call /// - Task CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context); /// /// Quit this worker /// - Task QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context); + global::System.Threading.Tasks.Task QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context); } /// Base class for server-side implementations of WorkerService @@ -406,7 +406,7 @@ namespace Grpc.Testing { /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// - public virtual Task RunServer(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task RunServer(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -419,7 +419,7 @@ namespace Grpc.Testing { /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// - public virtual Task RunClient(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task RunClient(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -427,7 +427,7 @@ namespace Grpc.Testing { /// /// Just return the core count - unary call /// - public virtual Task CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -435,7 +435,7 @@ namespace Grpc.Testing { /// /// Quit this worker /// - public virtual Task QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index f1878cbb556..cf43a77118c 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -196,34 +196,34 @@ namespace Grpc.Testing { /// /// One empty request followed by one empty response. /// - Task EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context); + global::System.Threading.Tasks.Task EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context); /// /// One request followed by one response. /// - Task UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); /// /// One request followed by a sequence of responses (streamed download). /// The server returns the payload with client desired type and sizes. /// - Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context); /// /// A sequence of requests followed by one response (streamed upload). /// The server returns the aggregated size of client payload as the result. /// - Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context); + global::System.Threading.Tasks.Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context); /// /// A sequence of requests with each request served by the server immediately. /// As one request could lead to multiple responses, this interface /// demonstrates the idea of full duplexing. /// - Task FullDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task FullDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); /// /// A sequence of requests followed by a sequence of responses. /// The server buffers all the client requests and then serves them in order. A /// stream of responses are returned to the client when the server starts with /// first request. /// - Task HalfDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task HalfDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); } /// Base class for server-side implementations of TestService @@ -232,7 +232,7 @@ namespace Grpc.Testing { /// /// One empty request followed by one empty response. /// - public virtual Task EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -240,7 +240,7 @@ namespace Grpc.Testing { /// /// One request followed by one response. /// - public virtual Task UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -249,7 +249,7 @@ namespace Grpc.Testing { /// One request followed by a sequence of responses (streamed download). /// The server returns the payload with client desired type and sizes. /// - public virtual Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -258,7 +258,7 @@ namespace Grpc.Testing { /// A sequence of requests followed by one response (streamed upload). /// The server returns the aggregated size of client payload as the result. /// - public virtual Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -268,7 +268,7 @@ namespace Grpc.Testing { /// As one request could lead to multiple responses, this interface /// demonstrates the idea of full duplexing. /// - public virtual Task FullDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task FullDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -279,7 +279,7 @@ namespace Grpc.Testing { /// stream of responses are returned to the client when the server starts with /// first request. /// - public virtual Task HalfDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task HalfDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -525,7 +525,7 @@ namespace Grpc.Testing { /// /// A call that no server should implement /// - Task UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context); + global::System.Threading.Tasks.Task UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context); } /// Base class for server-side implementations of UnimplementedService @@ -534,7 +534,7 @@ namespace Grpc.Testing { /// /// A call that no server should implement /// - public virtual Task UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -669,19 +669,19 @@ namespace Grpc.Testing { [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IReconnectService { - Task Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context); - Task Stop(global::Grpc.Testing.Empty request, ServerCallContext context); + global::System.Threading.Tasks.Task Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context); + global::System.Threading.Tasks.Task Stop(global::Grpc.Testing.Empty request, ServerCallContext context); } /// Base class for server-side implementations of ReconnectService public abstract class ReconnectServiceBase { - public virtual Task Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } - public virtual Task Stop(global::Grpc.Testing.Empty request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task Stop(global::Grpc.Testing.Empty request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 9a60be26b63..7520b0f81a7 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -1,7 +1,7 @@ @rem Builds gRPC NuGet packages @rem Current package versions -set VERSION=0.14.0-dev +set VERSION=0.15.0-dev set PROTOBUF_VERSION=3.0.0-beta2 @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well. diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index aeef8a79e99..5b8ff9b819b 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -715,10 +715,11 @@ grpcsharp_call_send_close_from_client(grpc_call *call, GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server( grpc_call *call, grpcsharp_batch_context *ctx, grpc_status_code status_code, const char *status_details, grpc_metadata_array *trailing_metadata, - int32_t send_empty_initial_metadata) { + int32_t send_empty_initial_metadata, const char* optional_send_buffer, + size_t optional_send_buffer_len, uint32_t write_flags) { /* TODO: don't use magic number */ - grpc_op ops[2]; - size_t nops = send_empty_initial_metadata ? 2 : 1; + grpc_op ops[3]; + size_t nops = 1; ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER; ops[0].data.send_status_from_server.status = status_code; ops[0].data.send_status_from_server.status_details = @@ -731,12 +732,23 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server( ctx->send_status_from_server.trailing_metadata.metadata; ops[0].flags = 0; ops[0].reserved = NULL; - ops[1].op = GRPC_OP_SEND_INITIAL_METADATA; - ops[1].data.send_initial_metadata.count = 0; - ops[1].data.send_initial_metadata.metadata = NULL; - ops[1].flags = 0; - ops[1].reserved = NULL; - + if (optional_send_buffer) { + ops[nops].op = GRPC_OP_SEND_MESSAGE; + ctx->send_message = string_to_byte_buffer(optional_send_buffer, + optional_send_buffer_len); + ops[nops].data.send_message = ctx->send_message; + ops[nops].flags = write_flags; + ops[nops].reserved = NULL; + nops ++; + } + if (send_empty_initial_metadata) { + ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA; + ops[nops].data.send_initial_metadata.count = 0; + ops[nops].data.send_initial_metadata.metadata = NULL; + ops[nops].flags = 0; + ops[nops].reserved = NULL; + nops++; + } return grpc_call_start_batch(call, ops, nops, ctx, NULL); } diff --git a/src/csharp/tests.json b/src/csharp/tests.json index f733352a310..f6af3408d51 100644 --- a/src/csharp/tests.json +++ b/src/csharp/tests.json @@ -1,5 +1,6 @@ { "Grpc.Core.Tests": [ + "Grpc.Core.Internal.Tests.AsyncCallServerTest", "Grpc.Core.Internal.Tests.AsyncCallTest", "Grpc.Core.Internal.Tests.ChannelArgsSafeHandleTest", "Grpc.Core.Internal.Tests.CompletionQueueEventTest", diff --git a/src/node/test/math/math_server.js b/src/node/test/math/math_server.js index fa05ed01654..5e3d1dd8641 100644 --- a/src/node/test/math/math_server.js +++ b/src/node/test/math/math_server.js @@ -68,7 +68,7 @@ function mathDiv(call, cb) { function mathFib(stream) { // Here, call is a standard writable Node object Stream var previous = 0, current = 1; - for (var i = 0; i < stream.request.limit; i++) { + for (var i = 0; i < stream.request.getLimit(); i++) { var response = new math.Num(); response.setNum(current); stream.write(response); diff --git a/src/node/tools/package.json b/src/node/tools/package.json index d98ed0b1fc3..d4849c2e388 100644 --- a/src/node/tools/package.json +++ b/src/node/tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "0.14.0-dev", + "version": "0.15.0-dev", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "http://www.grpc.io/", @@ -16,8 +16,8 @@ } ], "bin": { - "grpc-tools-protoc": "./bin/protoc.js", - "grpc-tools-plugin": "./bin/protoc_plugin.js" + "grpc_tools_node_protoc": "./bin/protoc.js", + "grpc_tools_node_protoc_plugin": "./bin/protoc_plugin.js" }, "scripts": { "install": "./node_modules/.bin/node-pre-gyp install" diff --git a/src/objective-c/BoringSSL.podspec b/src/objective-c/BoringSSL.podspec index 4a6df910a75..7d1de807169 100644 --- a/src/objective-c/BoringSSL.podspec +++ b/src/objective-c/BoringSSL.podspec @@ -31,7 +31,7 @@ Pod::Spec.new do |s| s.name = 'BoringSSL' - s.version = '2.0' + s.version = '3.0' s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.' # Adapted from the homepage: s.description = <<-DESC @@ -67,7 +67,7 @@ Pod::Spec.new do |s| s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite' s.source = { :git => 'https://boringssl.googlesource.com/boringssl', - :tag => 'version_for_cocoapods_2.0' } + :tag => 'version_for_cocoapods_3.0' } s.source_files = 'ssl/*.{h,c}', 'ssl/**/*.{h,c}', diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php index aebf80f6bf0..565bfce74f7 100755 --- a/src/php/tests/interop/interop_client.php +++ b/src/php/tests/interop/interop_client.php @@ -1,7 +1,7 @@ getUpdateMetadataFunc(); + } + + if ($test_case == 'oauth2_auth_token') { $auth_credentials = ApplicationDefaultCredentials::getCredentials( $args['oauth_scope'] ); + $token = $auth_credentials->fetchAuthToken(); + $update_metadata = + function ($metadata, + $authUri = null, + ClientInterface $client = null) use ($token) { + $metadata_copy = $metadata; + $metadata_copy[CredentialsLoader::AUTH_METADATA_KEY] = + [sprintf('%s %s', + $token['token_type'], + $token['access_token'])]; + + return $metadata_copy; + }; + $opts['update_metadata'] = $update_metadata; } - $opts['update_metadata'] = $auth_credentials->getUpdateMetadataFunc(); + + $stub = new grpc\testing\TestServiceClient($server_address, $opts); + + return $stub; } -if ($test_case == 'oauth2_auth_token') { - $auth_credentials = ApplicationDefaultCredentials::getCredentials( - $args['oauth_scope'] - ); - $token = $auth_credentials->fetchAuthToken(); - $update_metadata = - function ($metadata, - $authUri = null, - ClientInterface $client = null) use ($token) { - $metadata_copy = $metadata; - $metadata_copy[CredentialsLoader::AUTH_METADATA_KEY] = - [sprintf('%s %s', - $token['token_type'], - $token['access_token'])]; - - return $metadata_copy; - }; - $opts['update_metadata'] = $update_metadata; +function interop_main($args, $stub = false) { + if (!$stub) { + $stub = _makeStub($args); + } + + $test_case = $args['test_case']; + echo "Running test case $test_case\n"; + + switch ($test_case) { + case 'empty_unary': + emptyUnary($stub); + break; + case 'large_unary': + largeUnary($stub); + break; + case 'client_streaming': + clientStreaming($stub); + break; + case 'server_streaming': + serverStreaming($stub); + break; + case 'ping_pong': + pingPong($stub); + break; + case 'empty_stream': + emptyStream($stub); + break; + case 'cancel_after_begin': + cancelAfterBegin($stub); + break; + case 'cancel_after_first_response': + cancelAfterFirstResponse($stub); + break; + case 'timeout_on_sleeping_server': + timeoutOnSleepingServer($stub); + break; + case 'service_account_creds': + serviceAccountCreds($stub, $args); + break; + case 'compute_engine_creds': + computeEngineCreds($stub, $args); + break; + case 'jwt_token_creds': + jwtTokenCreds($stub, $args); + break; + case 'oauth2_auth_token': + oauth2AuthToken($stub, $args); + break; + case 'per_rpc_creds': + perRpcCreds($stub, $args); + break; + default: + echo "Unsupported test case $test_case\n"; + exit(1); + } + + return $stub; } -$stub = new grpc\testing\TestServiceClient($server_address, $opts); - -echo "Connecting to $server_address\n"; -echo "Running test case $test_case\n"; - -switch ($test_case) { - case 'empty_unary': - emptyUnary($stub); - break; - case 'large_unary': - largeUnary($stub); - break; - case 'client_streaming': - clientStreaming($stub); - break; - case 'server_streaming': - serverStreaming($stub); - break; - case 'ping_pong': - pingPong($stub); - break; - case 'empty_stream': - emptyStream($stub); - break; - case 'cancel_after_begin': - cancelAfterBegin($stub); - break; - case 'cancel_after_first_response': - cancelAfterFirstResponse($stub); - break; - case 'timeout_on_sleeping_server': - timeoutOnSleepingServer($stub); - break; - case 'service_account_creds': - serviceAccountCreds($stub, $args); - break; - case 'compute_engine_creds': - computeEngineCreds($stub, $args); - break; - case 'jwt_token_creds': - jwtTokenCreds($stub, $args); - break; - case 'oauth2_auth_token': - oauth2AuthToken($stub, $args); - break; - case 'per_rpc_creds': - perRpcCreds($stub, $args); - break; - default: - echo "Unsupported test case $test_case\n"; - exit(1); +if (isset($_SERVER['PHP_SELF']) && preg_match('/interop_client/', $_SERVER['PHP_SELF'])) { + $args = getopt('', ['server_host:', 'server_port:', 'test_case:', + 'use_tls::', 'use_test_ca::', + 'server_host_override:', 'oauth_scope:', + 'default_service_account:', ]); + interop_main($args); } diff --git a/src/php/tests/interop/metrics_client.php b/src/php/tests/interop/metrics_client.php new file mode 100644 index 00000000000..46f4212f773 --- /dev/null +++ b/src/php/tests/interop/metrics_client.php @@ -0,0 +1,49 @@ + $deadline) { + break; + } + if ($client_connection = socket_accept($socket)) { + // there is an incoming request, respond with qps metrics + $input = socket_read($client_connection, 1024); + $qps = round($count / ($current_time - $start_time)); + socket_write($client_connection, "qps: $qps"); + socket_close($client_connection); + } else { + // do actual work, run one interop test case + $args['test_case'] = + $args['test_cases'][mt_rand(0, $num_test_cases - 1)]; + $stub = @interop_main($args, $stub); + $count++; + } + } + socket_close($socket); + echo "Number of interop tests run in $args[test_duration_secs] seconds: $count.\n"; +} + +// process command line arguments +$raw_args = getopt('', + ['server_addresses::', + 'test_cases:', + 'metrics_port::', + 'test_duration_secs::', + 'num_channels_per_server::', + 'num_stubs_per_channel::']); + +$args = []; + +if (empty($raw_args['server_addresses'])) { + $args['server_host'] = 'localhost'; + $args['server_port'] = '8080'; +} else { + $parts = explode(':', $raw_args['server_addresses']); + $args['server_host'] = $parts[0]; + $args['server_port'] = (count($parts) == 2) ? $parts[1] : ''; +} + +$args['metrics_port'] = empty($raw_args['metrics_port']) ? + '8081' : $args['metrics_port']; + +$args['test_duration_secs'] = empty($raw_args['test_duration_secs']) || + $raw_args['test_duration_secs'] == -1 ? + false : $raw_args['test_duration_secs']; + +$test_cases = []; +$test_case_strs = explode(',', $raw_args['test_cases']); +foreach ($test_case_strs as $test_case_str) { + $parts = explode(':', $test_case_str); + $test_cases = array_merge($test_cases, array_fill(0, $parts[1], $parts[0])); +} +$args['test_cases'] = $test_cases; + +stress_main($args); diff --git a/src/proto/grpc/lb/v0/load_balancer.options b/src/proto/grpc/lb/v0/load_balancer.options deleted file mode 100644 index 6d4528f838a..00000000000 --- a/src/proto/grpc/lb/v0/load_balancer.options +++ /dev/null @@ -1,6 +0,0 @@ -grpc.lb.v0.InitialLoadBalanceRequest.name max_size:128 -grpc.lb.v0.InitialLoadBalanceResponse.client_config max_size:64 -grpc.lb.v0.InitialLoadBalanceResponse.load_balancer_delegate max_size:64 -grpc.lb.v0.Server.ip_address max_size:46 -grpc.lb.v0.Server.load_balance_token max_size:64 -load_balancer.proto no_unions:true diff --git a/src/proto/grpc/lb/v1/load_balancer.options b/src/proto/grpc/lb/v1/load_balancer.options new file mode 100644 index 00000000000..d90366996e7 --- /dev/null +++ b/src/proto/grpc/lb/v1/load_balancer.options @@ -0,0 +1,6 @@ +grpc.lb.v1.InitialLoadBalanceRequest.name max_size:128 +grpc.lb.v1.InitialLoadBalanceResponse.client_config max_size:64 +grpc.lb.v1.InitialLoadBalanceResponse.load_balancer_delegate max_size:64 +grpc.lb.v1.Server.ip_address max_size:46 +grpc.lb.v1.Server.load_balance_token max_size:64 +load_balancer.proto no_unions:true diff --git a/src/proto/grpc/lb/v0/load_balancer.proto b/src/proto/grpc/lb/v1/load_balancer.proto similarity index 94% rename from src/proto/grpc/lb/v0/load_balancer.proto rename to src/proto/grpc/lb/v1/load_balancer.proto index e88a4f8c4a7..1bcad0b1d4b 100644 --- a/src/proto/grpc/lb/v0/load_balancer.proto +++ b/src/proto/grpc/lb/v1/load_balancer.proto @@ -29,7 +29,7 @@ syntax = "proto3"; -package grpc.lb.v0; +package grpc.lb.v1; message Duration { @@ -94,9 +94,8 @@ message LoadBalanceResponse { message InitialLoadBalanceResponse { oneof initial_response_type { - // Contains gRPC config options like RPC deadline or flow control. - // TODO(yetianx): Change to ClientConfig after it is defined. - string client_config = 1; + // TODO(zhangkun83): ClientConfig not yet defined + //ClientConfig client_config = 1; // This is an application layer redirect that indicates the client should // use the specified server for load balancing. When this field is set in @@ -134,9 +133,7 @@ message Server { // An opaque token that is passed from the client to the server in metadata. // The server may expect this token to indicate that the request from the // client was load balanced. - // TODO(yetianx): Not used right now, and will be used after implementing - // load report. - bytes load_balance_token = 3; + string load_balance_token = 3; // Indicates whether this particular request should be dropped by the client // when this server is chosen from the list. diff --git a/src/proto/grpc/testing/echo.proto b/src/proto/grpc/testing/echo.proto index 0eef53a92a1..c596aabfcc4 100644 --- a/src/proto/grpc/testing/echo.proto +++ b/src/proto/grpc/testing/echo.proto @@ -45,3 +45,7 @@ service EchoTestService { service UnimplementedService { rpc Unimplemented(EchoRequest) returns (EchoResponse); } + +// A service without any rpc defined to test coverage. +service NoRpcService { +} diff --git a/src/python/grpcio/README.rst b/src/python/grpcio/README.rst index cb3f6b87fe4..afc4fe6a370 100644 --- a/src/python/grpcio/README.rst +++ b/src/python/grpcio/README.rst @@ -48,6 +48,7 @@ package named :code:`python-dev`). $ export REPO_ROOT=grpc # REPO_ROOT can be any directory of your choice $ git clone https://github.com/grpc/grpc.git $REPO_ROOT $ cd $REPO_ROOT + $ git submodule update --init # For the next two commands do `sudo pip install` if you get permission-denied errors $ pip install -rrequirements.txt diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index 70865191060..b844a14c48d 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,4 +27,5 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +__import__('pkg_resources').declare_namespace(__name__) diff --git a/src/python/grpcio/grpc/beta/implementations.py b/src/python/grpcio/grpc/beta/implementations.py index 742e94dc652..822f593323b 100644 --- a/src/python/grpcio/grpc/beta/implementations.py +++ b/src/python/grpcio/grpc/beta/implementations.py @@ -1,4 +1,4 @@ -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -188,12 +188,13 @@ def insecure_channel(host, port): Args: host: The name of the remote host to which to connect. port: The port of the remote host to which to connect. + If None only the 'host' part will be used. Returns: A Channel to the remote host through which RPCs may be conducted. """ intermediary_low_channel = _intermediary_low.Channel( - '%s:%d' % (host, port), None) + '%s:%d' % (host, port) if port else host, None) return Channel(intermediary_low_channel._internal, intermediary_low_channel) # pylint: disable=protected-access @@ -203,13 +204,15 @@ def secure_channel(host, port, channel_credentials): Args: host: The name of the remote host to which to connect. port: The port of the remote host to which to connect. + If None only the 'host' part will be used. channel_credentials: A ChannelCredentials. Returns: A secure Channel to the remote host through which RPCs may be conducted. """ intermediary_low_channel = _intermediary_low.Channel( - '%s:%d' % (host, port), channel_credentials._low_credentials) + '%s:%d' % (host, port) if port else host, + channel_credentials._low_credentials) return Channel(intermediary_low_channel._internal, intermediary_low_channel) # pylint: disable=protected-access diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index dab62530aac..4b98dc1a133 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -223,7 +223,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_decode.c', 'third_party/nanopb/pb_encode.c', diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 873b4e2a913..0c13104d9da 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION='0.14.0.dev0' +VERSION='0.15.0.dev0' diff --git a/src/python/grpcio/precompiled.py b/src/python/grpcio/precompiled.py deleted file mode 100644 index b6aa7fc90ee..00000000000 --- a/src/python/grpcio/precompiled.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import os -import platform -import shutil -import sys -import sysconfig - -import setuptools - -import commands -import grpc_version - -try: - from urllib2 import urlopen -except ImportError: - from urllib.request import urlopen - -PYTHON_STEM = os.path.dirname(os.path.abspath(__file__)) -BINARIES_REPOSITORY = os.environ.get( - 'GRPC_PYTHON_BINARIES_REPOSITORY', - 'https://storage.googleapis.com/grpc-precompiled-binaries/python') -USE_PRECOMPILED_BINARIES = bool(int(os.environ.get( - 'GRPC_PYTHON_USE_PRECOMPILED_BINARIES', '1'))) - -def _tagged_ext_name(base): - uname = platform.uname() - tags = ( - grpc_version.VERSION, - 'py{}'.format(sysconfig.get_python_version()), - uname[0], - uname[4], - ) - ucs = 'ucs{}'.format(sysconfig.get_config_var('Py_UNICODE_SIZE')) - return '{base}-{tags}-{ucs}'.format( - base=base, tags='-'.join(tags), ucs=ucs) - - -class BuildTaggedExt(setuptools.Command): - - description = 'build the gRPC tagged extensions' - user_options = [] - - def initialize_options(self): - # distutils requires this override. - pass - - def finalize_options(self): - # distutils requires this override. - pass - - def run(self): - if 'linux' in sys.platform: - self.run_command('build_ext') - try: - os.makedirs('dist/') - except OSError: - pass - shutil.copyfile( - os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so'), - 'dist/{}.so'.format(_tagged_ext_name('cygrpc'))) - else: - sys.stderr.write('nothing to do for build_tagged_ext\n') - - -def update_setup_arguments(setup_arguments): - if not USE_PRECOMPILED_BINARIES: - sys.stderr.write('not using precompiled extension') - return - url = '{}/{}.so'.format(BINARIES_REPOSITORY, _tagged_ext_name('cygrpc')) - target_path = os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so') - try: - extension = urlopen(url).read() - except: - sys.stderr.write( - 'could not download precompiled extension: {}\n'.format(url)) - return - try: - with open(target_path, 'w') as target: - target.write(extension) - setup_arguments['ext_modules'] = [] - except: - sys.stderr.write( - 'could not write precompiled extension to directory: {} -> {}\n' - .format(url, target_path)) - return - setup_arguments['package_data']['grpc._cython'].append('cygrpc.so') diff --git a/src/python/grpcio/tests/stress/client.py b/src/python/grpcio/tests/stress/client.py index a733741b736..e2e016760c8 100644 --- a/src/python/grpcio/tests/stress/client.py +++ b/src/python/grpcio/tests/stress/client.py @@ -117,7 +117,10 @@ def run_test(args): for runner in runners: runner.start() try: - raise exception_queue.get(block=True, timeout=args.test_duration_secs) + timeout_secs = args.test_duration_secs + if timeout_secs < 0: + timeout_secs = None + raise exception_queue.get(block=True, timeout=timeout_secs) except Queue.Empty: # No exceptions thrown, success pass diff --git a/src/python/grpcio/tests/unit/_cython/_channel_test.py b/src/python/grpcio/tests/unit/_cython/_channel_test.py index b414f8e6f69..931cd9083ec 100644 --- a/src/python/grpcio/tests/unit/_cython/_channel_test.py +++ b/src/python/grpcio/tests/unit/_cython/_channel_test.py @@ -33,8 +33,7 @@ import unittest from grpc._cython import cygrpc -# TODO(nathaniel): This should be at least one hundred. Why not one thousand? -_PARALLELISM = 4 +from tests.unit.framework.common import test_constants def _channel_and_completion_queue(): @@ -61,7 +60,7 @@ def _create_loop_destroy(): def _in_parallel(behavior, arguments): threads = tuple( threading.Thread(target=behavior, args=arguments) - for _ in range(_PARALLELISM)) + for _ in range(test_constants.PARALLELISM)) for thread in threads: thread.start() for thread in threads: diff --git a/src/ruby/.rubocop.yml b/src/ruby/.rubocop.yml index d13ce426553..34bb4775435 100644 --- a/src/ruby/.rubocop.yml +++ b/src/ruby/.rubocop.yml @@ -11,10 +11,10 @@ AllCops: - 'pb/test/**/*' Metrics/CyclomaticComplexity: - Max: 8 + Max: 9 Metrics/PerceivedComplexity: - Max: 8 + Max: 9 Metrics/ClassLength: Max: 250 diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb index 07f7bb93b8a..6d65db83067 100644 --- a/src/ruby/ext/grpc/extconf.rb +++ b/src/ruby/ext/grpc/extconf.rb @@ -78,9 +78,11 @@ output_dir = File.expand_path(RbConfig::CONFIG['topdir']) grpc_lib_dir = File.join(output_dir, 'libs', grpc_config) ENV['BUILDDIR'] = output_dir -puts 'Building internal gRPC into ' + grpc_lib_dir -system("make -j -C #{grpc_root} #{grpc_lib_dir}/libgrpc.a CONFIG=#{grpc_config}") -exit 1 unless $? == 0 +unless windows + puts 'Building internal gRPC into ' + grpc_lib_dir + system("make -j -C #{grpc_root} #{grpc_lib_dir}/libgrpc.a CONFIG=#{grpc_config}") + exit 1 unless $? == 0 +end $CFLAGS << ' -I' + File.join(grpc_root, 'include') $LDFLAGS << ' ' + File.join(grpc_lib_dir, 'libgrpc.a') unless windows diff --git a/src/ruby/ext/grpc/rb_byte_buffer.c b/src/ruby/ext/grpc/rb_byte_buffer.c index cba910d832a..1172691116c 100644 --- a/src/ruby/ext/grpc/rb_byte_buffer.c +++ b/src/ruby/ext/grpc/rb_byte_buffer.c @@ -32,11 +32,10 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_byte_buffer.h" -#include - #include #include #include diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c index 48c49a21e91..1b06273af9d 100644 --- a/src/ruby/ext/grpc/rb_call.c +++ b/src/ruby/ext/grpc/rb_call.c @@ -32,11 +32,10 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_call.h" -#include - #include #include diff --git a/src/ruby/ext/grpc/rb_call_credentials.c b/src/ruby/ext/grpc/rb_call_credentials.c index 38bf1f7710f..79ca5b32ced 100644 --- a/src/ruby/ext/grpc/rb_call_credentials.c +++ b/src/ruby/ext/grpc/rb_call_credentials.c @@ -32,10 +32,10 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_call_credentials.h" -#include #include #include @@ -86,11 +86,11 @@ static VALUE grpc_rb_call_credentials_callback_rescue(VALUE args, rb_funcall(exception_object, rb_intern("backtrace"), 0), rb_intern("join"), 1, rb_str_new2("\n\tfrom ")); - VALUE exception_info = rb_funcall(exception_object, rb_intern("to_s"), 0); + VALUE rb_exception_info = rb_funcall(exception_object, rb_intern("to_s"), 0); const char *exception_classname = rb_obj_classname(exception_object); (void)args; gpr_log(GPR_INFO, "Call credentials callback failed: %s: %s\n%s", - exception_classname, StringValueCStr(exception_info), + exception_classname, StringValueCStr(rb_exception_info), StringValueCStr(backtrace)); rb_hash_aset(result, rb_str_new2("metadata"), Qnil); /* Currently only gives the exception class name. It should be possible get diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 984afad1073..013321ffc8a 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -32,11 +32,10 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_channel.h" -#include - #include #include #include diff --git a/src/ruby/ext/grpc/rb_channel_args.c b/src/ruby/ext/grpc/rb_channel_args.c index 2ffb8f41dae..87c0e0a7055 100644 --- a/src/ruby/ext/grpc/rb_channel_args.c +++ b/src/ruby/ext/grpc/rb_channel_args.c @@ -32,11 +32,10 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_channel_args.h" -#include - #include #include "rb_grpc.h" diff --git a/src/ruby/ext/grpc/rb_channel_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c index 09bd3093a94..cbb23885aa6 100644 --- a/src/ruby/ext/grpc/rb_channel_credentials.c +++ b/src/ruby/ext/grpc/rb_channel_credentials.c @@ -31,14 +31,13 @@ * */ +#include + #include -#include #include "rb_grpc_imports.generated.h" #include "rb_channel_credentials.h" -#include - #include #include #include diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c index 2a2eee190cd..4bb615f8bec 100644 --- a/src/ruby/ext/grpc/rb_completion_queue.c +++ b/src/ruby/ext/grpc/rb_completion_queue.c @@ -32,10 +32,10 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_completion_queue.h" -#include #include #include diff --git a/src/ruby/ext/grpc/rb_event_thread.c b/src/ruby/ext/grpc/rb_event_thread.c index 2649a1087f2..9e85bbcfbf2 100644 --- a/src/ruby/ext/grpc/rb_event_thread.c +++ b/src/ruby/ext/grpc/rb_event_thread.c @@ -32,12 +32,12 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_event_thread.h" #include -#include #include #include #include diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c index acb47b00558..5277148fc9e 100644 --- a/src/ruby/ext/grpc/rb_grpc.c +++ b/src/ruby/ext/grpc/rb_grpc.c @@ -32,11 +32,11 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_grpc.h" #include -#include #include #include @@ -50,6 +50,7 @@ #include "rb_loader.h" #include "rb_server.h" #include "rb_server_credentials.h" +#include "rb_signal.h" static VALUE grpc_rb_cTimeVal = Qnil; @@ -332,6 +333,7 @@ void Init_grpc_c() { Init_grpc_channel_credentials(); Init_grpc_server(); Init_grpc_server_credentials(); + Init_grpc_signals(); Init_grpc_status_codes(); Init_grpc_time_consts(); } diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 96e60c67763..2b3acaaf59c 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -32,11 +32,10 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_server.h" -#include - #include #include #include "rb_call.h" diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c index b2d7280a30a..3b0fb6c910d 100644 --- a/src/ruby/ext/grpc/rb_server_credentials.c +++ b/src/ruby/ext/grpc/rb_server_credentials.c @@ -32,11 +32,10 @@ */ #include + #include "rb_grpc_imports.generated.h" #include "rb_server_credentials.h" -#include - #include #include diff --git a/src/ruby/ext/grpc/rb_signal.c b/src/ruby/ext/grpc/rb_signal.c new file mode 100644 index 00000000000..a9e512374ba --- /dev/null +++ b/src/ruby/ext/grpc/rb_signal.c @@ -0,0 +1,70 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include + +#include "rb_grpc.h" + +static void (*old_sigint_handler)(int); +static void (*old_sigterm_handler)(int); + +static volatile bool signal_received = false; + +/* This has to be handled at the C level instead of Ruby, because Ruby signal + * handlers are constrained to run in the main interpreter thread. If that main + * thread is blocked on grpc_completion_queue_pluck, the signal handlers will + * never run */ +static void handle_signal(int signum) { + signal_received = true; + if (signum == SIGINT) { + old_sigint_handler(signum); + } else if (signum == SIGTERM) { + old_sigterm_handler(signum); + } +} + +static VALUE grpc_rb_signal_received(VALUE self) { + (void)self; + return signal_received ? Qtrue : Qfalse; +} + +void Init_grpc_signals() { + old_sigint_handler = signal(SIGINT, handle_signal); + old_sigterm_handler = signal(SIGTERM, handle_signal); + rb_define_singleton_method(grpc_rb_mGrpcCore, "signal_received?", + grpc_rb_signal_received, 0); +} diff --git a/src/ruby/ext/grpc/rb_signal.h b/src/ruby/ext/grpc/rb_signal.h new file mode 100644 index 00000000000..07e49c0a8be --- /dev/null +++ b/src/ruby/ext/grpc/rb_signal.h @@ -0,0 +1,39 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_RB_SIGNAL_H_ +#define GRPC_RB_SIGNAL_H_ + +void Init_grpc_signals(); + +#endif /* GRPC_RB_SIGNAL_H_ */ diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb index 79fa705b1c9..7c9aae30e95 100644 --- a/src/ruby/lib/grpc.rb +++ b/src/ruby/lib/grpc.rb @@ -33,6 +33,7 @@ require_relative 'grpc/errors' require_relative 'grpc/grpc' require_relative 'grpc/logconfig' require_relative 'grpc/notifier' +require_relative 'grpc/signals' require_relative 'grpc/version' require_relative 'grpc/core/time_consts' require_relative 'grpc/generic/active_call' @@ -47,3 +48,5 @@ begin ensure file.close end + +GRPC::Signals.wait_for_signals diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb index ecf3cc32935..fd20a861448 100644 --- a/src/ruby/lib/grpc/generic/active_call.rb +++ b/src/ruby/lib/grpc/generic/active_call.rb @@ -28,7 +28,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 'forwardable' +require 'weakref' require_relative 'bidi_call' +require_relative '../signals' class Struct # BatchResult is the struct returned by calls to call#start_batch. @@ -121,6 +123,10 @@ module GRPC @unmarshal = unmarshal @metadata_tag = metadata_tag @op_notifier = nil + weak_self = WeakRef.new(self) + remove_handler = GRPC::Signals.register_handler(&weak_self + .method(:cancel)) + ObjectSpace.define_finalizer(self, remove_handler) end # output_metadata are provides access to hash that can be used to diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 7f3a38a9f46..238aaa96563 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -28,46 +28,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require_relative '../grpc' +require_relative '../signals' require_relative 'active_call' require_relative 'service' require 'thread' -# A global that contains signals the gRPC servers should respond to. -$grpc_signals = [] - # GRPC contains the General RPC module. module GRPC - # Handles the signals in $grpc_signals. - # - # @return false if the server should exit, true if not. - def handle_signals - loop do - sig = $grpc_signals.shift - case sig - when 'INT' - return false - when 'TERM' - return false - when nil - return true - end - end - true - end - module_function :handle_signals - - # Sets up a signal handler that adds signals to the signal handling global. - # - # Signal handlers should do as little as humanly possible. - # Here, they just add themselves to $grpc_signals - # - # RpcServer (and later other parts of gRPC) monitors the signals - # $grpc_signals in its own non-signal context. - def trap_signals - %w(INT TERM).each { |sig| trap(sig) { $grpc_signals << sig } } - end - module_function :trap_signals - # Pool is a simple thread pool. class Pool # Default keep alive period is 1s @@ -328,25 +295,6 @@ module GRPC end end - # Runs the server in its own thread, then waits for signal INT or TERM on - # the current thread to terminate it. - def run_till_terminated - GRPC.trap_signals - stopped = false - t = Thread.new do - run - stopped = true - end - wait_till_running - loop do - sleep SIGNAL_CHECK_PERIOD - break if stopped - break unless GRPC.handle_signals - end - stop - t.join - end - # handle registration of classes # # service is either a class that includes GRPC::GenericService and whose @@ -405,9 +353,14 @@ module GRPC transition_running_state(:running) @run_cond.broadcast end + remove_signal_handler = GRPC::Signals.register_handler { stop } loop_handle_server_calls + # Remove signal handler when server stops + remove_signal_handler.call end + alias_method :run_till_terminated, :run + # Sends RESOURCE_EXHAUSTED if there are too many unprocessed jobs def available?(an_rpc) jobs_count, max = @pool.jobs_waiting, @max_waiting_requests @@ -416,7 +369,7 @@ module GRPC GRPC.logger.warn("NOT AVAILABLE: too many jobs_waiting: #{an_rpc}") noop = proc { |x| x } c = ActiveCall.new(an_rpc.call, @cq, noop, noop, an_rpc.deadline) - c.send_status(StatusCodes::RESOURCE_EXHAUSTED, '') + c.send_status(GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED, '') nil end @@ -427,7 +380,7 @@ module GRPC GRPC.logger.warn("UNIMPLEMENTED: #{an_rpc}") noop = proc { |x| x } c = ActiveCall.new(an_rpc.call, @cq, noop, noop, an_rpc.deadline) - c.send_status(StatusCodes::UNIMPLEMENTED, '') + c.send_status(GRPC::Core::StatusCodes::UNIMPLEMENTED, '') nil end @@ -443,7 +396,12 @@ module GRPC unless active_call.nil? @pool.schedule(active_call) do |ac| c, mth = ac - rpc_descs[mth].run_server_method(c, rpc_handlers[mth]) + begin + rpc_descs[mth].run_server_method(c, rpc_handlers[mth]) + rescue StandardError + c.send_status(GRPC::Core::StatusCodes::INTERNAL, + 'Server handler failed') + end end end rescue Core::CallError, RuntimeError => e @@ -500,10 +458,8 @@ module GRPC unless cls.include?(GenericService) fail "#{cls} must 'include GenericService'" end - if cls.rpc_descs.size.zero? - fail "#{cls} should specify some rpc descriptions" - end - cls.assert_rpc_descs_have_methods + fail "#{cls} should specify some rpc descriptions" if + cls.rpc_descs.size.zero? end # This should be called while holding @run_mutex diff --git a/src/ruby/lib/grpc/generic/service.rb b/src/ruby/lib/grpc/generic/service.rb index 8e940b5b13e..0a166e823e4 100644 --- a/src/ruby/lib/grpc/generic/service.rb +++ b/src/ruby/lib/grpc/generic/service.rb @@ -110,6 +110,9 @@ module GRPC rpc_descs[name] = RpcDesc.new(name, input, output, marshal_class_method, unmarshal_class_method) + define_method(name) do + fail GRPC::BadStatus, GRPC::Core::StatusCodes::UNIMPLEMENTED + end end def inherited(subclass) @@ -199,19 +202,6 @@ module GRPC end end end - - # Asserts that the appropriate methods are defined for each added rpc - # spec. Is intended to aid verifying that server classes are correctly - # implemented. - def assert_rpc_descs_have_methods - rpc_descs.each_pair do |m, spec| - mth_name = GenericService.underscore(m.to_s).to_sym - unless instance_methods.include?(mth_name) - fail "#{self} does not provide instance method '#{mth_name}'" - end - spec.assert_arity_matches(instance_method(mth_name)) - end - end end def self.included(o) diff --git a/src/ruby/lib/grpc/signals.rb b/src/ruby/lib/grpc/signals.rb new file mode 100644 index 00000000000..2ab85c8bb16 --- /dev/null +++ b/src/ruby/lib/grpc/signals.rb @@ -0,0 +1,69 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +require 'thread' +require_relative 'grpc' + +# GRPC contains the General RPC module. +module GRPC + # Signals contains gRPC functions related to signal handling + module Signals + @interpreter_exiting = false + @signal_handlers = [] + @handlers_mutex = Mutex.new + + def register_handler(&handler) + @handlers_mutex.synchronize do + @signal_handlers.push(handler) + handler.call if @exit_signal_received + end + # Returns a function to remove the handler + lambda do + @handlers_mutex.synchronize { @signal_handlers.delete(handler) } + end + end + module_function :register_handler + + def wait_for_signals + t = Thread.new do + sleep 0.1 until GRPC::Core.signal_received? || @interpreter_exiting + unless @interpreter_exiting + @handlers_mutex.synchronize do + @signal_handlers.each(&:call) + end + end + end + at_exit do + @interpreter_exiting = true + t.join + end + end + module_function :wait_for_signals + end +end diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 67c6a5d5a17..01c8c5ac8f1 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '0.14.0.dev' + VERSION = '0.15.0.dev' end diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb index e688057cb17..2a42736237d 100644 --- a/src/ruby/spec/generic/rpc_server_spec.rb +++ b/src/ruby/spec/generic/rpc_server_spec.rb @@ -308,10 +308,6 @@ describe GRPC::RpcServer do expect { @srv.handle(EmptyService) }.to raise_error end - it 'raises if the service does not define its rpc methods' do - expect { @srv.handle(NoRpcImplementation) }.to raise_error - end - it 'raises if a handler method is already registered' do @srv.handle(EchoService) expect { r.handle(EchoService) }.to raise_error @@ -349,6 +345,25 @@ describe GRPC::RpcServer do t.join end + it 'should return UNIMPLEMENTED on unimplemented methods', server: true do + @srv.handle(NoRpcImplementation) + t = Thread.new { @srv.run } + @srv.wait_till_running + req = EchoMsg.new + blk = proc do + cq = GRPC::Core::CompletionQueue.new + stub = GRPC::ClientStub.new(@host, cq, :this_channel_is_insecure, + **client_opts) + stub.request_response('/an_rpc', req, marshal, unmarshal) + end + expect(&blk).to raise_error do |error| + expect(error).to be_a(GRPC::BadStatus) + expect(error.code).to be(GRPC::Core::StatusCodes::UNIMPLEMENTED) + end + @srv.stop + t.join + end + it 'should handle multiple sequential requests', server: true do @srv.handle(EchoService) t = Thread.new { @srv.run } diff --git a/src/ruby/spec/generic/service_spec.rb b/src/ruby/spec/generic/service_spec.rb index 5e7b6c7abaf..76034e4f747 100644 --- a/src/ruby/spec/generic/service_spec.rb +++ b/src/ruby/spec/generic/service_spec.rb @@ -273,73 +273,4 @@ describe GenericService do end end end - - describe '#assert_rpc_descs_have_methods' do - it 'fails if there is no instance method for an rpc descriptor' do - c1 = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - end - expect { c1.assert_rpc_descs_have_methods }.to raise_error - - c2 = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - rpc :AnotherRpc, GoodMsg, GoodMsg - - def an_rpc - end - end - expect { c2.assert_rpc_descs_have_methods }.to raise_error - end - - it 'passes if there are corresponding methods for each descriptor' do - c = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - rpc :AServerStreamer, GoodMsg, stream(GoodMsg) - rpc :AClientStreamer, stream(GoodMsg), GoodMsg - rpc :ABidiStreamer, stream(GoodMsg), stream(GoodMsg) - - def an_rpc(_req, _call) - end - - def a_server_streamer(_req, _call) - end - - def a_client_streamer(_call) - end - - def a_bidi_streamer(_call) - end - end - expect { c.assert_rpc_descs_have_methods }.to_not raise_error - end - - it 'passes for subclasses of that include GenericService' do - base = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - - def an_rpc(_req, _call) - end - end - c = Class.new(base) - expect { c.assert_rpc_descs_have_methods }.to_not raise_error - expect(c.include?(GenericService)).to be(true) - end - - it 'passes if subclasses define the rpc methods' do - base = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - end - c = Class.new(base) do - def an_rpc(_req, _call) - end - end - expect { c.assert_rpc_descs_have_methods }.to_not raise_error - expect(c.include?(GenericService)).to be(true) - end - end end diff --git a/src/ruby/tools/bin/protoc.rb b/src/ruby/tools/bin/grpc_tools_ruby_protoc.rb similarity index 100% rename from src/ruby/tools/bin/protoc.rb rename to src/ruby/tools/bin/grpc_tools_ruby_protoc.rb diff --git a/src/ruby/tools/bin/protoc_grpc_ruby_plugin.rb b/src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin.rb similarity index 100% rename from src/ruby/tools/bin/protoc_grpc_ruby_plugin.rb rename to src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin.rb diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 12ad21b80eb..dca7fd7e72c 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -29,6 +29,6 @@ module GRPC module Tools - VERSION = '0.14.0.dev' + VERSION = '0.15.0.dev' end end diff --git a/templates/gRPC.podspec.template b/templates/gRPC.podspec.template index a9948a41df4..979cb1ef8e8 100644 --- a/templates/gRPC.podspec.template +++ b/templates/gRPC.podspec.template @@ -54,7 +54,7 @@ %> Pod::Spec.new do |s| s.name = 'gRPC' - version = '0.12.0' + version = '0.14.0' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'http://www.grpc.io' @@ -62,7 +62,8 @@ s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } s.source = { :git => 'https://github.com/grpc/grpc.git', - :tag => "release-#{version.gsub(/\./, '_')}-objectivec-#{version}" } + :tag => "release-#{version.gsub(/\./, '_')}-objectivec-#{version}", + :submodules => true } s.ios.deployment_target = '7.1' @@ -97,7 +98,7 @@ ss.requires_arc = false ss.libraries = 'z' - ss.dependency 'BoringSSL', '~> 2.0' + ss.dependency 'BoringSSL', '~> 3.0' # ss.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w' end diff --git a/templates/src/node/tools/package.json.template b/templates/src/node/tools/package.json.template index 4f673c48d1c..69ad71a3b83 100644 --- a/templates/src/node/tools/package.json.template +++ b/templates/src/node/tools/package.json.template @@ -18,8 +18,8 @@ } ], "bin": { - "grpc-tools-protoc": "./bin/protoc.js", - "grpc-tools-plugin": "./bin/protoc_plugin.js" + "grpc_tools_node_protoc": "./bin/protoc.js", + "grpc_tools_node_protoc_plugin": "./bin/protoc_plugin.js" }, "scripts": { "install": "./node_modules/.bin/node-pre-gyp install" diff --git a/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template b/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template new file mode 100644 index 00000000000..200905d4f3f --- /dev/null +++ b/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template @@ -0,0 +1,34 @@ +%YAML 1.2 +--- | + # Copyright 2015, Google Inc. + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are + # met: + # + # * Redistributions of source code must retain the above copyright + # notice, this list of conditions and the following disclaimer. + # * Redistributions in binary form must reproduce the above + # copyright notice, this list of conditions and the following disclaimer + # in the documentation and/or other materials provided with the + # distribution. + # * Neither the name of Google Inc. nor the names of its + # contributors may be used to endorse or promote products derived from + # this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! + + VERSION='${settings.python_version.pep440()}' diff --git a/templates/tools/dockerfile/node_deps.include b/templates/tools/dockerfile/node_deps.include index 7d37d671467..7855fbfee36 100644 --- a/templates/tools/dockerfile/node_deps.include +++ b/templates/tools/dockerfile/node_deps.include @@ -4,4 +4,8 @@ # Install nvm RUN touch .profile RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash +# Install all versions of node that we want to test RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm alias default 4" \ No newline at end of file diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile.template new file mode 100644 index 00000000000..27e9eeec5a8 --- /dev/null +++ b/templates/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile.template @@ -0,0 +1,45 @@ +%YAML 1.2 +--- | + # Copyright 2016, Google Inc. + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are + # met: + # + # * Redistributions of source code must retain the above copyright + # notice, this list of conditions and the following disclaimer. + # * Redistributions in binary form must reproduce the above + # copyright notice, this list of conditions and the following disclaimer + # in the documentation and/or other materials provided with the + # distribution. + # * Neither the name of Google Inc. nor the names of its + # contributors may be used to endorse or promote products derived from + # this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + FROM debian:jessie + + <%include file="../../apt_get_basic.include"/> + <%include file="../../ccache_setup.include"/> + <%include file="../../cxx_deps.include"/> + <%include file="../../gcp_api_libraries.include"/> + <%include file="../../python_deps.include"/> + + RUN pip install coverage + RUN pip install oauth2client + + # Define the default command. + CMD ["bash"] + diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile.template new file mode 100644 index 00000000000..8b933aaa324 --- /dev/null +++ b/templates/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile.template @@ -0,0 +1,41 @@ +%YAML 1.2 +--- | + # Copyright 2015, Google Inc. + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are + # met: + # + # * Redistributions of source code must retain the above copyright + # notice, this list of conditions and the following disclaimer. + # * Redistributions in binary form must reproduce the above + # copyright notice, this list of conditions and the following disclaimer + # in the documentation and/or other materials provided with the + # distribution. + # * Neither the name of Google Inc. nor the names of its + # contributors may be used to endorse or promote products derived from + # this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + FROM debian:jessie + + <%include file="../../apt_get_basic.include"/> + <%include file="../../ccache_setup.include"/> + <%include file="../../cxx_deps.include"/> + <%include file="../../gcp_api_libraries.include"/> + <%include file="../../ruby_deps.include"/> + # Define the default command. + CMD ["bash"] + diff --git a/templates/tools/dockerfile/test/sanity/Dockerfile.template b/templates/tools/dockerfile/test/sanity/Dockerfile.template index 8d6f52db54e..8e2140e648b 100644 --- a/templates/tools/dockerfile/test/sanity/Dockerfile.template +++ b/templates/tools/dockerfile/test/sanity/Dockerfile.template @@ -43,7 +43,17 @@ python-virtualenv ${"\\"} python-lxml RUN pip install simplejson mako - + + #====================================== + # More sanity test dependencies (bazel) + RUN echo "deb http://httpredir.debian.org/debian jessie-backports main" > \ + /etc/apt/sources.list.d/backports.list + RUN apt-get update + RUN apt-get -t jessie-backports install -y openjdk-8-jdk + RUN git clone https://github.com/bazelbuild/bazel.git /bazel + RUN cd /bazel && ./compile.sh + RUN ln -s /bazel/output/bazel /bin/ + #=================== # Docker "inception" # Note this is quite the ugly hack. diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c index cd5b5412492..e5820688ef1 100644 --- a/test/core/bad_client/bad_client.c +++ b/test/core/bad_client/bad_client.c @@ -75,9 +75,22 @@ static void server_setup_transport(void *ts, grpc_transport *transport) { grpc_exec_ctx_finish(&exec_ctx); } -void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, - const char *client_payload, - size_t client_payload_length, uint32_t flags) { +typedef struct { + grpc_bad_client_client_stream_validator validator; + gpr_slice_buffer incoming; + gpr_event read_done; +} read_args; + +static void read_done(grpc_exec_ctx *exec_ctx, void *arg, bool success) { + read_args *a = arg; + a->validator(&a->incoming); + gpr_event_set(&a->read_done, (void *)1); +} + +void grpc_run_bad_client_test( + grpc_bad_client_server_side_validator server_validator, + grpc_bad_client_client_stream_validator client_validator, + const char *client_payload, size_t client_payload_length, uint32_t flags) { grpc_endpoint_pair sfd; thd_args a; gpr_thd_id id; @@ -108,7 +121,7 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, a.cq = grpc_completion_queue_create(NULL); gpr_event_init(&a.done_thd); gpr_event_init(&a.done_write); - a.validator = validator; + a.validator = server_validator; grpc_server_register_completion_queue(a.server, a.cq, NULL); a.registered_method = grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD, @@ -151,8 +164,23 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, GPR_ASSERT(gpr_event_wait(&a.done_thd, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); - /* Shutdown */ - if (sfd.client) { + if (sfd.client != NULL) { + // Validate client stream, if requested. + if (client_validator != NULL) { + read_args args; + args.validator = client_validator; + gpr_slice_buffer_init(&args.incoming); + gpr_event_init(&args.read_done); + grpc_closure read_done_closure; + grpc_closure_init(&read_done_closure, read_done, &args); + grpc_endpoint_read(&exec_ctx, sfd.client, &args.incoming, + &read_done_closure); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT( + gpr_event_wait(&args.read_done, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); + gpr_slice_buffer_destroy(&args.incoming); + } + // Shutdown. grpc_endpoint_shutdown(&exec_ctx, sfd.client); grpc_endpoint_destroy(&exec_ctx, sfd.client); grpc_exec_ctx_finish(&exec_ctx); diff --git a/test/core/bad_client/bad_client.h b/test/core/bad_client/bad_client.h index 19ddba83bf0..c8b2a4122f0 100644 --- a/test/core/bad_client/bad_client.h +++ b/test/core/bad_client/bad_client.h @@ -44,18 +44,24 @@ typedef void (*grpc_bad_client_server_side_validator)(grpc_server *server, grpc_completion_queue *cq, void *registered_method); +typedef void (*grpc_bad_client_client_stream_validator)( + gpr_slice_buffer *incoming); + #define GRPC_BAD_CLIENT_DISCONNECT 1 /* Test runner. Create a server, and send client_payload to it as bytes from a client. - Execute validator in a separate thread to assert that the bytes are + Execute server_validator in a separate thread to assert that the bytes are handled as expected. */ -void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, - const char *client_payload, - size_t client_payload_length, uint32_t flags); +void grpc_run_bad_client_test( + grpc_bad_client_server_side_validator server_validator, + grpc_bad_client_client_stream_validator client_validator, + const char *client_payload, size_t client_payload_length, uint32_t flags); -#define GRPC_RUN_BAD_CLIENT_TEST(validator, payload, flags) \ - grpc_run_bad_client_test(validator, payload, sizeof(payload) - 1, flags) +#define GRPC_RUN_BAD_CLIENT_TEST(server_validator, client_validator, payload, \ + flags) \ + grpc_run_bad_client_test(server_validator, client_validator, payload, \ + sizeof(payload) - 1, flags) #endif /* GRPC_TEST_CORE_BAD_CLIENT_BAD_CLIENT_H */ diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py index d49858ed6d8..fb86525b1a1 100755 --- a/test/core/bad_client/gen_build_yaml.py +++ b/test/core/bad_client/gen_build_yaml.py @@ -29,7 +29,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Generates the appropriate build.json data for all the end2end tests.""" +"""Generates the appropriate build.json data for all the bad_client tests.""" import collections @@ -45,6 +45,7 @@ BAD_CLIENT_TESTS = { 'headers': default_test_options._replace(cpu_cost=0.2), 'initial_settings_frame': default_test_options._replace(cpu_cost=0.2), 'head_of_line_blocking': default_test_options, + 'large_metadata': default_test_options, 'server_registered_method': default_test_options, 'simple_request': default_test_options, 'window_overflow': default_test_options, diff --git a/test/core/bad_client/tests/badreq.c b/test/core/bad_client/tests/badreq.c index b17e3b35ee4..5d9ffef3f20 100644 --- a/test/core/bad_client/tests/badreq.c +++ b/test/core/bad_client/tests/badreq.c @@ -56,7 +56,7 @@ int main(int argc, char **argv) { /* invalid content type */ GRPC_RUN_BAD_CLIENT_TEST( - verifier, PFX_STR + verifier, NULL, PFX_STR "\x00\x00\xc2\x01\x04\x00\x00\x00\x01" "\x10\x05:path\x08/foo/bar" "\x10\x07:scheme\x04http" @@ -71,7 +71,7 @@ int main(int argc, char **argv) { /* invalid te */ GRPC_RUN_BAD_CLIENT_TEST( - verifier, PFX_STR + verifier, NULL, PFX_STR "\x00\x00\xcb\x01\x04\x00\x00\x00\x01" "\x10\x05:path\x08/foo/bar" "\x10\x07:scheme\x04http" @@ -88,7 +88,7 @@ int main(int argc, char **argv) { /* two path headers */ GRPC_RUN_BAD_CLIENT_TEST( - verifier, PFX_STR + verifier, NULL, PFX_STR "\x00\x00\xd9\x01\x04\x00\x00\x00\x01" "\x10\x05:path\x08/foo/bar" "\x10\x05:path\x08/foo/bah" @@ -105,7 +105,7 @@ int main(int argc, char **argv) { /* bad accept-encoding algorithm */ GRPC_RUN_BAD_CLIENT_TEST( - verifier, PFX_STR + verifier, NULL, PFX_STR "\x00\x00\xd2\x01\x04\x00\x00\x00\x01" "\x10\x05:path\x08/foo/bar" "\x10\x07:scheme\x04http" @@ -121,7 +121,7 @@ int main(int argc, char **argv) { /* bad grpc-encoding algorithm */ GRPC_RUN_BAD_CLIENT_TEST( - verifier, PFX_STR + verifier, NULL, PFX_STR "\x00\x00\xf5\x01\x04\x00\x00\x00\x01" "\x10\x05:path\x08/foo/bar" "\x10\x07:scheme\x04http" diff --git a/test/core/bad_client/tests/connection_prefix.c b/test/core/bad_client/tests/connection_prefix.c index 9a30aad0e93..bc5ed2e3934 100644 --- a/test/core/bad_client/tests/connection_prefix.c +++ b/test/core/bad_client/tests/connection_prefix.c @@ -46,29 +46,30 @@ static void verifier(grpc_server *server, grpc_completion_queue *cq, int main(int argc, char **argv) { grpc_test_init(argc, argv); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRIX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI *X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTPX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0\rX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0\r\nX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0\r\n\rX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0\r\n\r\nX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0\r\n\r\nSX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0\r\n\r\nSMX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0\r\n\r\nSM\rX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0\r\n\r\nSM\r\nX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, "PRI * HTTP/2.0\r\n\r\nSM\r\n\rX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRIX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI *X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTPX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\rX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\nX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\rX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSMX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSM\rX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSM\r\nX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSM\r\n\rX", + 0); return 0; } diff --git a/test/core/bad_client/tests/head_of_line_blocking.c b/test/core/bad_client/tests/head_of_line_blocking.c index 53cd4537b2f..e4051bb6685 100644 --- a/test/core/bad_client/tests/head_of_line_blocking.c +++ b/test/core/bad_client/tests/head_of_line_blocking.c @@ -144,7 +144,7 @@ int main(int argc, char **argv) { addbuf(hdr, sizeof(hdr)); addbuf(msg, FRAME_SIZE); } - grpc_run_bad_client_test(verifier, g_buffer, g_count, 0); + grpc_run_bad_client_test(verifier, NULL, g_buffer, g_count, 0); gpr_free(g_buffer); return 0; diff --git a/test/core/bad_client/tests/headers.c b/test/core/bad_client/tests/headers.c index 4c1a76743e3..f872e5006a7 100644 --- a/test/core/bad_client/tests/headers.c +++ b/test/core/bad_client/tests/headers.c @@ -51,249 +51,251 @@ int main(int argc, char **argv) { grpc_test_init(argc, argv); /* partial http2 header prefixes */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x05", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x05", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04\x00\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x01\x04\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); /* test adding prioritization data */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x01\x01\x24\x00\x00\x00\x01" "\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x02\x01\x24\x00\x00\x00\x01" "\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x03\x01\x24\x00\x00\x00\x01" "\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x04\x01\x24\x00\x00\x00\x01" "\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x05\x01\x24\x00\x00\x00\x01" "", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x05\x01\x24\x00\x00\x00\x01" "\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x05\x01\x24\x00\x00\x00\x01" "\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x05\x01\x24\x00\x00\x00\x01" "\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x05\x01\x24\x00\x00\x00\x01" "\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x05\x01\x24\x00\x00\x00\x01" "\x00\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); /* test looking up an invalid index */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x01\x01\x04\x00\x00\x00\x01" "\xfe", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x04\x01\x04\x00\x00\x00\x01" "\x7f\x7f\x01" "a", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x04\x01\x04\x00\x00\x00\x01" "\x0f\x7f\x01" "a", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x04\x01\x04\x00\x00\x00\x01" "\x1f\x7f\x01" "a", 0); /* test nvr, not indexed in static table */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" "\x01\x01" "a", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" "\x11\x01" "a", GRPC_BAD_CLIENT_DISCONNECT); /* illegal op code */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x01\x01\x04\x00\x00\x00\x01" "\x80", 0); /* parse some long indices */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x02\x01\x04\x00\x00\x00\x01" "\xff\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" "\xff\x80\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x04\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x05\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x06\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80\x80\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x07\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80\x80\x80\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x08\x01\x04\x00\x00\x00\x01" "\xff", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x08\x01\x04\x00\x00\x00\x01" "\xff\x80", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x08\x01\x04\x00\x00\x00\x01" "\xff\x80\x80", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x08\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x08\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80\x80", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x08\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80\x80\x80", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x08\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80\x80\x80\x80", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x08\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80\x80\x80\x80\x00", 0); /* overflow on byte 4 */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x06\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80\x80\x7f", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x06\x01\x04\x00\x00\x00\x01" "\xff\xff\xff\xff\xff\x0f", GRPC_BAD_CLIENT_DISCONNECT); /* overflow after byte 4 */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x08\x01\x04\x00\x00\x00\x01" "\xff\x80\x80\x80\x80\x80\x80\x02", 0); /* end of headers mid-opcode */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x01\x01\x04\x00\x00\x00\x01" "\x01", GRPC_BAD_CLIENT_DISCONNECT); /* dynamic table size update: set to default */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" "\x3f\xe1\x1f", GRPC_BAD_CLIENT_DISCONNECT); /* dynamic table size update: set too large */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" "\x3f\xf1\x1f", 0); /* dynamic table size update: set twice */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x04\x01\x04\x00\x00\x00\x01" "\x20\x3f\xe1\x1f", GRPC_BAD_CLIENT_DISCONNECT); /* dynamic table size update: set thrice */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" "\x20\x20\x20", 0); /* non-ending header followed by continuation frame */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x00\x00\x00\x00\x01" "\x00\x00\x00\x09\x04\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); /* non-ending header followed by non-continuation frame */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x00\x00\x00\x00\x01" "\x00\x00\x00\x00\x04\x00\x00\x00\x01", 0); /* non-ending header followed by a continuation frame for a different stream */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x01" "\x00\x00\x00\x01\x00\x00\x00\x00\x03" "\x00\x00\x00\x09\x04\x00\x00\x00\x01", 0); /* opening with a continuation frame */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x09\x04\x00\x00\x00\x01", 0); /* three header frames */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x01" "\x00\x00\x00\x01\x04\x00\x00\x00\x01" "\x00\x00\x00\x01\x04\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); /* an invalid header found with fuzzing */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x39\x67\xed\x1d\x64", GRPC_BAD_CLIENT_DISCONNECT); /* a badly encoded timeout value */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x19\x01\x04\x00\x00\x00\x01" "\x10\x0cgrpc-timeout\x0a" "15 seconds", GRPC_BAD_CLIENT_DISCONNECT); /* a badly encoded timeout value: twice (catches caching) */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x19\x01\x04\x00\x00\x00\x01" "\x10\x0cgrpc-timeout\x0a" "15 seconds" diff --git a/test/core/bad_client/tests/initial_settings_frame.c b/test/core/bad_client/tests/initial_settings_frame.c index 63a770df91f..b84b67a7e58 100644 --- a/test/core/bad_client/tests/initial_settings_frame.c +++ b/test/core/bad_client/tests/initial_settings_frame.c @@ -50,70 +50,72 @@ int main(int argc, char **argv) { grpc_test_init(argc, argv); /* various partial prefixes */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x06", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x06", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x06", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x06", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x06", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x06", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x04", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x04\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x04\x01", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x01", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x04\xff", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\xff", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x04\x00\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x04\x00\x00\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x04\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x04\x00\x00\x00\x00", + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x04\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); /* must not send frames with stream id != 0 */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x00\x00\x00\x00\x01", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x00\x40\x00\x00\x00", 0); /* settings frame must be a multiple of six bytes long */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x01\x04\x00\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x02\x04\x00\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x03\x04\x00\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x04\x04\x00\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x05\x04\x00\x00\x00\x00\x00", 0); /* some settings values are illegal */ /* max frame size = 0 */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR ONE_SETTING_HDR "\x00\x05\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR ONE_SETTING_HDR "\x00\x06\xff\xff\xff\xff", GRPC_BAD_CLIENT_DISCONNECT); /* update intiial window size */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR ONE_SETTING_HDR "\x00\x04\x00\x01\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); /* ack with data */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x00\x00\x00\x00\x00" "\x00\x00\x01\x04\x01\x00\x00\x00\x00", 0); /* settings frame with invalid flags */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x10\x00\x00\x00\x00", 0); /* unknown settings should be ignored */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR ONE_SETTING_HDR "\x00\x99\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); diff --git a/test/core/bad_client/tests/large_metadata.c b/test/core/bad_client/tests/large_metadata.c new file mode 100644 index 00000000000..1a8d2a29870 --- /dev/null +++ b/test/core/bad_client/tests/large_metadata.c @@ -0,0 +1,489 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "test/core/bad_client/bad_client.h" + +#include + +#include +#include "src/core/lib/surface/server.h" +#include "test/core/end2end/cq_verifier.h" + +#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_STR \ + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" /* settings frame */ \ + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* headers: generated from \ + large_metadata.headers in this \ + directory */ \ + "\x00" \ + "5{\x01\x05\x00\x00\x00\x01" \ + "\x10\x05:path\x08/foo/bar" \ + "\x10\x07:scheme\x04http" \ + "\x10\x07:method\x04POST" \ + "\x10\x0a:authority\x09localhost" \ + "\x10\x0c" \ + "content-type\x10" \ + "application/grpc" \ + "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \ + "\x10\x02te\x08trailers" \ + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" \ + "\x10\x0duser-header00~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header01~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header02~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header03~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header04~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header05~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header06~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header07~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header08~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header09~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header10~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header11~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header12~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header13~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header14~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header15~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header16~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header17~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header18~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header19~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header20~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header21~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header22~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header23~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header24~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header25~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header26~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header27~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header28~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header29~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header30~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header31~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header32~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header33~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header34~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header35~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header36~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header37~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header38~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header39~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header40~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header41~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header42~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header43~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header44~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header45~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header46~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header47~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header48~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header49~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header50~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header51~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header52~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header53~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header54~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header55~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header56~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header57~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header58~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header59~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header60~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header61~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header62~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header63~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header64~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header65~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header66~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header67~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header68~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header69~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header70~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header71~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header72~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header73~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header74~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header75~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header76~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header77~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header78~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header79~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header80~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header81~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header82~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header83~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header84~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header85~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header86~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header87~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header88~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header89~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header90~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header91~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header92~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header93~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" \ + "\x10\x0duser-header94~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaa" + +#define PFX_TOO_MUCH_METADATA_FROM_SERVER_STR \ + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" /* settings frame: sets \ + MAX_HEADER_LIST_SIZE to 16K */ \ + "\x00\x00\x06\x04\x00\x00\x00\x00\x00\x00\x06\x00\x00\x40\x00" /* headers: \ + generated \ + from \ + simple_request.headers \ + in this \ + directory \ + */ \ + "\x00\x00\xc9\x01\x04\x00\x00\x00\x01" \ + "\x10\x05:path\x08/foo/bar" \ + "\x10\x07:scheme\x04http" \ + "\x10\x07:method\x04POST" \ + "\x10\x0a:authority\x09localhost" \ + "\x10\x0c" \ + "content-type\x10" \ + "application/grpc" \ + "\x10\x14grpc-accept-encoding\x15" \ + "deflate,identity,gzip" \ + "\x10\x02te\x08trailers" \ + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" + +static void *tag(intptr_t t) { return (void *)t; } + +static void server_verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + grpc_call_error error; + grpc_call *s; + grpc_call_details call_details; + cq_verifier *cqv = cq_verifier_create(cq); + grpc_metadata_array request_metadata_recv; + + grpc_call_details_init(&call_details); + grpc_metadata_array_init(&request_metadata_recv); + + error = grpc_server_request_call(server, &s, &call_details, + &request_metadata_recv, cq, cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + cq_expect_completion(cqv, tag(101), 1); + cq_verify(cqv); + + GPR_ASSERT(0 == strcmp(call_details.host, "localhost")); + GPR_ASSERT(0 == strcmp(call_details.method, "/foo/bar")); + + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_call_destroy(s); + cq_verifier_destroy(cqv); +} + +static void server_verifier_sends_too_much_metadata(grpc_server *server, + grpc_completion_queue *cq, + void *registered_method) { + grpc_call_error error; + grpc_call *s; + grpc_call_details call_details; + cq_verifier *cqv = cq_verifier_create(cq); + grpc_metadata_array request_metadata_recv; + + grpc_call_details_init(&call_details); + grpc_metadata_array_init(&request_metadata_recv); + + error = grpc_server_request_call(server, &s, &call_details, + &request_metadata_recv, cq, cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + cq_expect_completion(cqv, tag(101), 1); + cq_verify(cqv); + + GPR_ASSERT(0 == strcmp(call_details.host, "localhost")); + GPR_ASSERT(0 == strcmp(call_details.method, "/foo/bar")); + + const size_t metadata_value_size = 16 * 1024; + grpc_metadata meta; + meta.key = "key"; + meta.value = gpr_malloc(metadata_value_size + 1); + memset((char *)meta.value, 'a', metadata_value_size); + ((char *)meta.value)[metadata_value_size] = 0; + meta.value_length = metadata_value_size; + + grpc_op op; + op.op = GRPC_OP_SEND_INITIAL_METADATA; + op.data.send_initial_metadata.count = 1; + op.data.send_initial_metadata.metadata = &meta; + op.flags = 0; + op.reserved = NULL; + error = grpc_call_start_batch(s, &op, 1, tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + cq_expect_completion(cqv, tag(102), 0); // Operation fails. + cq_verify(cqv); + + gpr_free((char *)meta.value); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_call_destroy(s); + cq_verifier_destroy(cqv); +} + +static void client_validator(gpr_slice_buffer *incoming) { + // Get last frame from incoming slice buffer. + gpr_slice_buffer last_frame_buffer; + gpr_slice_buffer_init(&last_frame_buffer); + gpr_slice_buffer_trim_end(incoming, 13, &last_frame_buffer); + GPR_ASSERT(last_frame_buffer.count == 1); + gpr_slice last_frame = last_frame_buffer.slices[0]; + // Construct expected frame. + gpr_slice expected = gpr_slice_malloc(13); + uint8_t *p = GPR_SLICE_START_PTR(expected); + // Length. + *p++ = 0; + *p++ = 0; + *p++ = 4; + // Frame type (RST_STREAM). + *p++ = 3; + // Flags. + *p++ = 0; + // Stream ID. + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 1; + // Payload (error code). + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 11; + // Compare actual and expected. + GPR_ASSERT(gpr_slice_cmp(last_frame, expected) == 0); + gpr_slice_buffer_destroy(&last_frame_buffer); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + // Test sending more metadata than the server will accept. + GRPC_RUN_BAD_CLIENT_TEST(server_verifier, client_validator, + PFX_TOO_MUCH_METADATA_FROM_CLIENT_STR, 0); + + // Test sending more metadata than the client will accept. + GRPC_RUN_BAD_CLIENT_TEST(server_verifier_sends_too_much_metadata, + client_validator, + PFX_TOO_MUCH_METADATA_FROM_SERVER_STR, 0); + + return 0; +} diff --git a/test/core/bad_client/tests/large_metadata.headers b/test/core/bad_client/tests/large_metadata.headers new file mode 100644 index 00000000000..75de3ef1001 --- /dev/null +++ b/test/core/bad_client/tests/large_metadata.headers @@ -0,0 +1,106 @@ +# headers used in simple_request.c +# use tools/codegen/core/gen_header_frame.py --set_end_stream to generate +# the binary strings contained in the source code +:path: /foo/bar +:scheme: http +:method: POST +:authority: localhost +content-type: application/grpc +grpc-accept-encoding: identity,deflate,gzip +te: trailers +user-agent: bad-client grpc-c/0.12.0.0 (linux) +user-header00: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header01: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header02: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header03: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header04: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header05: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header06: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header07: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header08: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header09: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header10: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header11: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header12: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header13: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header14: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header15: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header16: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header17: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header18: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header19: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header20: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header21: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header22: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header23: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header24: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header25: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header26: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header27: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header28: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header29: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header30: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header31: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header32: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header33: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header34: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header35: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header36: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header37: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header38: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header39: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header40: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header41: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header42: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header43: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header44: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header45: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header46: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header47: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header48: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header49: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header50: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header51: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header52: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header53: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header54: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header55: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header56: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header57: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header58: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header59: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header60: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header61: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header62: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header63: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header64: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header65: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header66: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header67: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header68: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header69: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header70: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header71: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header72: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header73: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header74: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header75: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header76: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header77: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header78: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header79: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header80: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header81: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header82: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header83: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header84: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header85: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header86: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header87: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header88: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header89: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header90: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header91: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header92: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header93: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +user-header94: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/test/core/bad_client/tests/server_registered_method.c b/test/core/bad_client/tests/server_registered_method.c index 60d3b890b22..6216553a614 100644 --- a/test/core/bad_client/tests/server_registered_method.c +++ b/test/core/bad_client/tests/server_registered_method.c @@ -111,43 +111,43 @@ int main(int argc, char **argv) { /* body generated with * tools/codegen/core/gen_server_registered_method_bad_client_test_body.py */ - GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, PFX_STR "\x00\x00\x00\x00\x00\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, PFX_STR "\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, PFX_STR "\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, PFX_STR "\x00\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); GRPC_RUN_BAD_CLIENT_TEST( - verifier_fails, + verifier_fails, NULL, PFX_STR "\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); GRPC_RUN_BAD_CLIENT_TEST( - verifier_succeeds, + verifier_succeeds, NULL, PFX_STR "\x00\x00\x05\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00", 0); GRPC_RUN_BAD_CLIENT_TEST( - verifier_fails, + verifier_fails, NULL, PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); GRPC_RUN_BAD_CLIENT_TEST( - verifier_succeeds, + verifier_succeeds, NULL, PFX_STR "\x00\x00\x06\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00", 0); GRPC_RUN_BAD_CLIENT_TEST( - verifier_fails, + verifier_fails, NULL, PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02", GRPC_BAD_CLIENT_DISCONNECT); GRPC_RUN_BAD_CLIENT_TEST( - verifier_fails, + verifier_fails, NULL, PFX_STR "\x00\x00\x06\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00", GRPC_BAD_CLIENT_DISCONNECT); GRPC_RUN_BAD_CLIENT_TEST( - verifier_succeeds, PFX_STR + verifier_succeeds, NULL, PFX_STR "\x00\x00\x07\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00\x00", 0); diff --git a/test/core/bad_client/tests/simple_request.c b/test/core/bad_client/tests/simple_request.c index 3ae6eb3592d..25bbe968e4a 100644 --- a/test/core/bad_client/tests/simple_request.c +++ b/test/core/bad_client/tests/simple_request.c @@ -139,42 +139,42 @@ int main(int argc, char **argv) { grpc_test_init(argc, argv); /* basic request: check that things are working */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR, 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR_UNUSUAL, 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR_UNUSUAL2, 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR, 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR_UNUSUAL, 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR_UNUSUAL2, 0); /* push an illegal data frame */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01" "\x34\x00\x00\x00\x00", 0); /* push a data frame with bad flags */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x00\x02\x00\x00\x00\x01", 0); /* push a window update with a bad length */ - GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, NULL, PFX_STR "\x00\x00\x01\x08\x00\x00\x00\x00\x01", 0); /* push a window update with bad flags */ - GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, NULL, PFX_STR "\x00\x00\x00\x08\x10\x00\x00\x00\x01", 0); /* push a window update with bad data */ - GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, NULL, PFX_STR "\x00\x00\x04\x08\x00\x00\x00\x00\x01" "\xff\xff\xff\xff", 0); /* push a short goaway */ - GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, NULL, PFX_STR "\x00\x00\x04\x07\x00\x00\x00\x00\x00", 0); /* disconnect before sending goaway */ - GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, NULL, PFX_STR "\x00\x01\x12\x07\x00\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); /* push a rst_stream with a bad length */ - GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, NULL, PFX_STR "\x00\x00\x01\x03\x00\x00\x00\x00\x01", 0); /* push a rst_stream with bad flags */ - GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, NULL, PFX_STR "\x00\x00\x00\x03\x10\x00\x00\x00\x01", 0); return 0; diff --git a/test/core/bad_client/tests/unknown_frame.c b/test/core/bad_client/tests/unknown_frame.c index f3870a18138..4f483d21f2e 100644 --- a/test/core/bad_client/tests/unknown_frame.c +++ b/test/core/bad_client/tests/unknown_frame.c @@ -51,7 +51,7 @@ int main(int argc, char **argv) { grpc_test_init(argc, argv); /* test adding prioritization data */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x88\x00\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); diff --git a/test/core/bad_client/tests/window_overflow.c b/test/core/bad_client/tests/window_overflow.c index 16f11e7dd0a..0d17dbe448e 100644 --- a/test/core/bad_client/tests/window_overflow.c +++ b/test/core/bad_client/tests/window_overflow.c @@ -105,7 +105,7 @@ int main(int argc, char **argv) { addbuf(message, sizeof(message)); } } - grpc_run_bad_client_test(verifier, g_buffer, g_count, 0); + grpc_run_bad_client_test(verifier, NULL, g_buffer, g_count, 0); gpr_free(g_buffer); return 0; diff --git a/test/core/end2end/fixtures/h2_census.c b/test/core/end2end/fixtures/h2_census.c index ff2f028f096..e46b39e476f 100644 --- a/test/core/end2end/fixtures/h2_census.c +++ b/test/core/end2end/fixtures/h2_census.c @@ -111,7 +111,7 @@ void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { /* All test configurations */ static grpc_end2end_test_config configs[] = { - {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, + {"chttp2/fullstack+census", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack, chttp2_init_server_fullstack, chttp2_tear_down_fullstack}, }; diff --git a/test/core/end2end/fixtures/h2_proxy.c b/test/core/end2end/fixtures/h2_proxy.c index 863673a4e01..8c50eeb5d5b 100644 --- a/test/core/end2end/fixtures/h2_proxy.c +++ b/test/core/end2end/fixtures/h2_proxy.c @@ -55,14 +55,16 @@ typedef struct fullstack_fixture_data { grpc_end2end_proxy *proxy; } fullstack_fixture_data; -static grpc_server *create_proxy_server(const char *port) { - grpc_server *s = grpc_server_create(NULL, NULL); +static grpc_server *create_proxy_server(const char *port, + grpc_channel_args *server_args) { + grpc_server *s = grpc_server_create(server_args, NULL); GPR_ASSERT(grpc_server_add_insecure_http2_port(s, port)); return s; } -static grpc_channel *create_proxy_client(const char *target) { - return grpc_insecure_channel_create(target, NULL, NULL); +static grpc_channel *create_proxy_client(const char *target, + grpc_channel_args *client_args) { + return grpc_insecure_channel_create(target, client_args, NULL); } static const grpc_end2end_proxy_def proxy_def = {create_proxy_server, @@ -74,7 +76,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); memset(&f, 0, sizeof(f)); - ffd->proxy = grpc_end2end_proxy_create(&proxy_def); + ffd->proxy = grpc_end2end_proxy_create(&proxy_def, client_args, server_args); f.fixture_data = ffd; f.cq = grpc_completion_queue_create(NULL); diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.c b/test/core/end2end/fixtures/h2_ssl_proxy.c index 1403b760f50..151a86cb8f5 100644 --- a/test/core/end2end/fixtures/h2_ssl_proxy.c +++ b/test/core/end2end/fixtures/h2_ssl_proxy.c @@ -54,8 +54,9 @@ typedef struct fullstack_secure_fixture_data { grpc_end2end_proxy *proxy; } fullstack_secure_fixture_data; -static grpc_server *create_proxy_server(const char *port) { - grpc_server *s = grpc_server_create(NULL, NULL); +static grpc_server *create_proxy_server(const char *port, + grpc_channel_args *server_args) { + grpc_server *s = grpc_server_create(server_args, NULL); grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials *ssl_creds = @@ -65,18 +66,20 @@ static grpc_server *create_proxy_server(const char *port) { return s; } -static grpc_channel *create_proxy_client(const char *target) { +static grpc_channel *create_proxy_client(const char *target, + grpc_channel_args *client_args) { grpc_channel *channel; grpc_channel_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, {"foo.test.google.fr"}}; - grpc_channel_args client_args; - client_args.num_args = 1; - client_args.args = &ssl_name_override; - channel = grpc_secure_channel_create(ssl_creds, target, &client_args, NULL); + grpc_channel_args *new_client_args = + grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); + channel = + grpc_secure_channel_create(ssl_creds, target, new_client_args, NULL); grpc_channel_credentials_release(ssl_creds); + grpc_channel_args_destroy(new_client_args); return channel; } @@ -90,7 +93,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( gpr_malloc(sizeof(fullstack_secure_fixture_data)); memset(&f, 0, sizeof(f)); - ffd->proxy = grpc_end2end_proxy_create(&proxy_def); + ffd->proxy = grpc_end2end_proxy_create(&proxy_def, client_args, server_args); f.fixture_data = ffd; f.cq = grpc_completion_queue_create(NULL); diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c index a6487a17ac2..f6e01ec41c5 100644 --- a/test/core/end2end/fixtures/proxy.c +++ b/test/core/end2end/fixtures/proxy.c @@ -89,8 +89,9 @@ typedef struct { static void thread_main(void *arg); static void request_call(grpc_end2end_proxy *proxy); -grpc_end2end_proxy *grpc_end2end_proxy_create( - const grpc_end2end_proxy_def *def) { +grpc_end2end_proxy *grpc_end2end_proxy_create(const grpc_end2end_proxy_def *def, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { gpr_thd_options opt = gpr_thd_options_default(); int proxy_port = grpc_pick_unused_port_or_die(); int server_port = grpc_pick_unused_port_or_die(); @@ -105,8 +106,8 @@ grpc_end2end_proxy *grpc_end2end_proxy_create( proxy->server_port); proxy->cq = grpc_completion_queue_create(NULL); - proxy->server = def->create_server(proxy->proxy_port); - proxy->client = def->create_client(proxy->server_port); + proxy->server = def->create_server(proxy->proxy_port, server_args); + proxy->client = def->create_client(proxy->server_port, client_args); grpc_server_register_completion_queue(proxy->server, proxy->cq, NULL); grpc_server_start(proxy->server); diff --git a/test/core/end2end/fixtures/proxy.h b/test/core/end2end/fixtures/proxy.h index c1cf01d39a4..75b75d13319 100644 --- a/test/core/end2end/fixtures/proxy.h +++ b/test/core/end2end/fixtures/proxy.h @@ -41,12 +41,15 @@ typedef struct grpc_end2end_proxy grpc_end2end_proxy; typedef struct grpc_end2end_proxy_def { - grpc_server *(*create_server)(const char *port); - grpc_channel *(*create_client)(const char *target); + grpc_server *(*create_server)(const char *port, + grpc_channel_args *server_args); + grpc_channel *(*create_client)(const char *target, + grpc_channel_args *client_args); } grpc_end2end_proxy_def; -grpc_end2end_proxy *grpc_end2end_proxy_create( - const grpc_end2end_proxy_def *def); +grpc_end2end_proxy *grpc_end2end_proxy_create(const grpc_end2end_proxy_def *def, + grpc_channel_args *client_args, + grpc_channel_args *server_args); void grpc_end2end_proxy_destroy(grpc_end2end_proxy *proxy); const char *grpc_end2end_proxy_get_client_target(grpc_end2end_proxy *proxy); diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index cffe5995bcd..3e10ad580fc 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -39,9 +39,9 @@ import hashlib FixtureOptions = collections.namedtuple( 'FixtureOptions', - 'fullstack includes_proxy dns_resolver secure platforms ci_mac tracing') + 'fullstack includes_proxy dns_resolver secure platforms ci_mac tracing exclude_configs') default_unsecure_fixture_options = FixtureOptions( - True, False, True, False, ['windows', 'linux', 'mac', 'posix'], True, False) + True, False, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, []) socketpair_unsecure_fixture_options = default_unsecure_fixture_options._replace(fullstack=False, dns_resolver=False) default_secure_fixture_options = default_unsecure_fixture_options._replace(secure=True) uds_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, platforms=['linux', 'mac', 'posix']) @@ -60,7 +60,7 @@ END2END_FIXTURES = { 'h2_proxy': default_unsecure_fixture_options._replace(includes_proxy=True, ci_mac=False), 'h2_sockpair_1byte': socketpair_unsecure_fixture_options._replace( - ci_mac=False), + ci_mac=False, exclude_configs=['msan']), 'h2_sockpair': socketpair_unsecure_fixture_options._replace(ci_mac=False), 'h2_sockpair+trace': socketpair_unsecure_fixture_options._replace( ci_mac=False, tracing=True), @@ -246,7 +246,7 @@ def main(): { 'name': '%s_nosec_test' % f, 'args': [t], - 'exclude_configs': [], + 'exclude_configs': END2END_FIXTURES[f].exclude_configs, 'platforms': END2END_FIXTURES[f].platforms, 'ci_platforms': (END2END_FIXTURES[f].platforms if END2END_FIXTURES[f].ci_mac else without( diff --git a/test/core/end2end/tests/large_metadata.c b/test/core/end2end/tests/large_metadata.c index 0e5d6b4fe01..ae1f68a2b45 100644 --- a/test/core/end2end/tests/large_metadata.c +++ b/test/core/end2end/tests/large_metadata.c @@ -97,7 +97,7 @@ static void end_test(grpc_end2end_test_fixture *f) { grpc_completion_queue_destroy(f->cq); } -/* Request with a large amount of metadata.*/ +// Request with a large amount of metadata. static void test_request_with_large_metadata(grpc_end2end_test_config config) { grpc_call *c; grpc_call *s; @@ -106,8 +106,13 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { grpc_raw_byte_buffer_create(&request_payload_slice, 1); gpr_timespec deadline = five_seconds_time(); grpc_metadata meta; + const size_t large_size = 64 * 1024; + grpc_arg arg = {GRPC_ARG_INTEGER, + GRPC_ARG_MAX_METADATA_SIZE, + {.integer = (int)large_size + 1024}}; + grpc_channel_args args = {1, &arg}; grpc_end2end_test_fixture f = - begin_test(config, "test_request_with_large_metadata", NULL, NULL); + begin_test(config, "test_request_with_large_metadata", &args, &args); cq_verifier *cqv = cq_verifier_create(f.cq); grpc_op ops[6]; grpc_op *op; @@ -121,7 +126,6 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { char *details = NULL; size_t details_capacity = 0; int was_cancelled = 2; - const size_t large_size = 64 * 1024; c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", "foo.test.google.fr", deadline, NULL); @@ -138,6 +142,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); + // Client: send request. op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 1; @@ -174,9 +179,11 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { grpc_server_request_call(f.server, &s, &call_details, &request_metadata_recv, f.cq, f.cq, tag(101)); GPR_ASSERT(GRPC_CALL_OK == error); + cq_expect_completion(cqv, tag(101), 1); cq_verify(cqv); + // Server: send initial metadata and receive request. op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; @@ -194,6 +201,8 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { cq_expect_completion(cqv, tag(102), 1); cq_verify(cqv); + // Server: receive close and send status. This should trigger + // completion of request on client. op = ops; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c index b5dbc1382a8..4f572789d95 100644 --- a/test/core/end2end/tests/max_message_length.c +++ b/test/core/end2end/tests/max_message_length.c @@ -53,7 +53,10 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_channel_args *server_args) { grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); - f = config.create_fixture(client_args, server_args); + // We intentionally do not pass the client and server args to + // create_fixture(), since we don't want the limit enforced on the + // proxy, only on the backend server. + f = config.create_fixture(NULL, NULL); config.init_server(&f, server_args); config.init_client(&f, client_args); return f; diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 0eede6c23bd..3eeb55d033d 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 7e4d6046d60..0232a9fa317 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -51,6 +51,7 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" #include "test/cpp/util/string_ref_helper.h" +#include "test/cpp/util/test_credentials_provider.h" #ifdef GPR_POSIX_SOCKET #include "src/core/lib/iomgr/ev_posix.h" @@ -58,6 +59,7 @@ using grpc::testing::EchoRequest; using grpc::testing::EchoResponse; +using grpc::testing::kTlsCredentialsType; using std::chrono::system_clock; GPR_TLS_DECL(g_is_async_end2end_test); @@ -197,20 +199,37 @@ class Verifier { bool spin_; }; -class AsyncEnd2endTest : public ::testing::TestWithParam { +class TestScenario { + public: + TestScenario(bool non_block, const grpc::string& creds_type, + const grpc::string& content) + : disable_blocking(non_block), + credentials_type(creds_type), + message_content(content) {} + void Log() const { + gpr_log(GPR_INFO, + "Scenario: disable_blocking %d, credentials %s, message size %d", + disable_blocking, credentials_type.c_str(), message_content.size()); + } + bool disable_blocking; + const grpc::string credentials_type; + const grpc::string message_content; +}; + +class AsyncEnd2endTest : public ::testing::TestWithParam { protected: - AsyncEnd2endTest() {} + AsyncEnd2endTest() { GetParam().Log(); } void SetUp() GRPC_OVERRIDE { - poll_overrider_.reset(new PollingOverrider(!GetParam())); + poll_overrider_.reset(new PollingOverrider(!GetParam().disable_blocking)); int port = grpc_pick_unused_port_or_die(); server_address_ << "localhost:" << port; // Setup server ServerBuilder builder; - builder.AddListeningPort(server_address_.str(), - grpc::InsecureServerCredentials()); + auto server_creds = GetServerCredentials(GetParam().credentials_type); + builder.AddListeningPort(server_address_.str(), server_creds); builder.RegisterService(&service_); cq_ = builder.AddCompletionQueue(); server_ = builder.BuildAndStart(); @@ -230,8 +249,11 @@ class AsyncEnd2endTest : public ::testing::TestWithParam { } void ResetStub() { + ChannelArguments args; + auto channel_creds = + GetChannelCredentials(GetParam().credentials_type, &args); std::shared_ptr channel = - CreateChannel(server_address_.str(), InsecureChannelCredentials()); + CreateCustomChannel(server_address_.str(), channel_creds, args); stub_ = grpc::testing::EchoTestService::NewStub(channel); } @@ -247,22 +269,23 @@ class AsyncEnd2endTest : public ::testing::TestWithParam { ServerContext srv_ctx; grpc::ServerAsyncResponseWriter response_writer(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::unique_ptr> response_reader( stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); send_response.set_message(recv_request.message()); response_writer.Finish(send_response, Status::OK, tag(3)); - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); - response_reader->Finish(&recv_response, &recv_status, tag(4)); - Verifier(GetParam()).Expect(4, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); EXPECT_EQ(send_response.message(), recv_response.message()); EXPECT_TRUE(recv_status.ok()); @@ -302,7 +325,7 @@ TEST_P(AsyncEnd2endTest, AsyncNextRpc) { ServerContext srv_ctx; grpc::ServerAsyncResponseWriter response_writer(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::unique_ptr> response_reader( stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); @@ -310,23 +333,22 @@ TEST_P(AsyncEnd2endTest, AsyncNextRpc) { std::chrono::system_clock::now()); std::chrono::system_clock::time_point time_limit( std::chrono::system_clock::now() + std::chrono::seconds(10)); - Verifier(GetParam()).Verify(cq_.get(), time_now); - Verifier(GetParam()).Verify(cq_.get(), time_now); + Verifier(GetParam().disable_blocking).Verify(cq_.get(), time_now); + Verifier(GetParam().disable_blocking).Verify(cq_.get(), time_now); service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get(), time_limit); + Verifier(GetParam().disable_blocking) + .Expect(2, true) + .Verify(cq_.get(), time_limit); EXPECT_EQ(send_request.message(), recv_request.message()); send_response.set_message(recv_request.message()); response_writer.Finish(send_response, Status::OK, tag(3)); - Verifier(GetParam()) - .Expect(3, true) - .Verify(cq_.get(), std::chrono::system_clock::time_point::max()); - response_reader->Finish(&recv_response, &recv_status, tag(4)); - Verifier(GetParam()) + Verifier(GetParam().disable_blocking) + .Expect(3, true) .Expect(4, true) .Verify(cq_.get(), std::chrono::system_clock::time_point::max()); @@ -347,41 +369,48 @@ TEST_P(AsyncEnd2endTest, SimpleClientStreaming) { ServerContext srv_ctx; ServerAsyncReader srv_stream(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::unique_ptr> cli_stream( stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1))); service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Expect(1, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(2, true) + .Expect(1, true) + .Verify(cq_.get()); cli_stream->Write(send_request, tag(3)); - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); - srv_stream.Read(&recv_request, tag(4)); - Verifier(GetParam()).Expect(4, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); cli_stream->Write(send_request, tag(5)); - Verifier(GetParam()).Expect(5, true).Verify(cq_.get()); - srv_stream.Read(&recv_request, tag(6)); - Verifier(GetParam()).Expect(6, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(5, true) + .Expect(6, true) + .Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); cli_stream->WritesDone(tag(7)); - Verifier(GetParam()).Expect(7, true).Verify(cq_.get()); - srv_stream.Read(&recv_request, tag(8)); - Verifier(GetParam()).Expect(8, false).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(7, true) + .Expect(8, false) + .Verify(cq_.get()); send_response.set_message(recv_request.message()); srv_stream.Finish(send_response, Status::OK, tag(9)); - Verifier(GetParam()).Expect(9, true).Verify(cq_.get()); - cli_stream->Finish(&recv_status, tag(10)); - Verifier(GetParam()).Expect(10, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(9, true) + .Expect(10, true) + .Verify(cq_.get()); EXPECT_EQ(send_response.message(), recv_response.message()); EXPECT_TRUE(recv_status.ok()); @@ -400,39 +429,45 @@ TEST_P(AsyncEnd2endTest, SimpleServerStreaming) { ServerContext srv_ctx; ServerAsyncWriter srv_stream(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::unique_ptr> cli_stream( stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1))); service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(1, true).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(1, true) + .Expect(2, true) + .Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); send_response.set_message(recv_request.message()); srv_stream.Write(send_response, tag(3)); - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); - cli_stream->Read(&recv_response, tag(4)); - Verifier(GetParam()).Expect(4, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); EXPECT_EQ(send_response.message(), recv_response.message()); srv_stream.Write(send_response, tag(5)); - Verifier(GetParam()).Expect(5, true).Verify(cq_.get()); - cli_stream->Read(&recv_response, tag(6)); - Verifier(GetParam()).Expect(6, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(5, true) + .Expect(6, true) + .Verify(cq_.get()); EXPECT_EQ(send_response.message(), recv_response.message()); srv_stream.Finish(Status::OK, tag(7)); - Verifier(GetParam()).Expect(7, true).Verify(cq_.get()); - cli_stream->Read(&recv_response, tag(8)); - Verifier(GetParam()).Expect(8, false).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(7, true) + .Expect(8, false) + .Verify(cq_.get()); cli_stream->Finish(&recv_status, tag(9)); - Verifier(GetParam()).Expect(9, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(9, true).Verify(cq_.get()); EXPECT_TRUE(recv_status.ok()); } @@ -450,41 +485,48 @@ TEST_P(AsyncEnd2endTest, SimpleBidiStreaming) { ServerContext srv_ctx; ServerAsyncReaderWriter srv_stream(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::unique_ptr> cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1))); service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(1, true).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(1, true) + .Expect(2, true) + .Verify(cq_.get()); cli_stream->Write(send_request, tag(3)); - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); - srv_stream.Read(&recv_request, tag(4)); - Verifier(GetParam()).Expect(4, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); send_response.set_message(recv_request.message()); srv_stream.Write(send_response, tag(5)); - Verifier(GetParam()).Expect(5, true).Verify(cq_.get()); - cli_stream->Read(&recv_response, tag(6)); - Verifier(GetParam()).Expect(6, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(5, true) + .Expect(6, true) + .Verify(cq_.get()); EXPECT_EQ(send_response.message(), recv_response.message()); cli_stream->WritesDone(tag(7)); - Verifier(GetParam()).Expect(7, true).Verify(cq_.get()); - srv_stream.Read(&recv_request, tag(8)); - Verifier(GetParam()).Expect(8, false).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(7, true) + .Expect(8, false) + .Verify(cq_.get()); srv_stream.Finish(Status::OK, tag(9)); - Verifier(GetParam()).Expect(9, true).Verify(cq_.get()); - cli_stream->Finish(&recv_status, tag(10)); - Verifier(GetParam()).Expect(10, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(9, true) + .Expect(10, true) + .Verify(cq_.get()); EXPECT_TRUE(recv_status.ok()); } @@ -503,7 +545,7 @@ TEST_P(AsyncEnd2endTest, ClientInitialMetadataRpc) { ServerContext srv_ctx; grpc::ServerAsyncResponseWriter response_writer(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::pair meta1("key1", "val1"); std::pair meta2("key2", "val2"); std::pair meta3("g.r.d-bin", "xyz"); @@ -516,7 +558,7 @@ TEST_P(AsyncEnd2endTest, ClientInitialMetadataRpc) { service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); auto client_initial_metadata = srv_ctx.client_metadata(); EXPECT_EQ(meta1.second, @@ -529,11 +571,11 @@ TEST_P(AsyncEnd2endTest, ClientInitialMetadataRpc) { send_response.set_message(recv_request.message()); response_writer.Finish(send_response, Status::OK, tag(3)); - - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); - response_reader->Finish(&recv_response, &recv_status, tag(4)); - Verifier(GetParam()).Expect(4, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get()); EXPECT_EQ(send_response.message(), recv_response.message()); EXPECT_TRUE(recv_status.ok()); @@ -552,7 +594,7 @@ TEST_P(AsyncEnd2endTest, ServerInitialMetadataRpc) { ServerContext srv_ctx; grpc::ServerAsyncResponseWriter response_writer(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::pair meta1("key1", "val1"); std::pair meta2("key2", "val2"); @@ -561,15 +603,15 @@ TEST_P(AsyncEnd2endTest, ServerInitialMetadataRpc) { service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); srv_ctx.AddInitialMetadata(meta1.first, meta1.second); srv_ctx.AddInitialMetadata(meta2.first, meta2.second); response_writer.SendInitialMetadata(tag(3)); - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(3, true).Verify(cq_.get()); response_reader->ReadInitialMetadata(tag(4)); - Verifier(GetParam()).Expect(4, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get()); auto server_initial_metadata = cli_ctx.GetServerInitialMetadata(); EXPECT_EQ(meta1.second, ToString(server_initial_metadata.find(meta1.first)->second)); @@ -579,10 +621,11 @@ TEST_P(AsyncEnd2endTest, ServerInitialMetadataRpc) { send_response.set_message(recv_request.message()); response_writer.Finish(send_response, Status::OK, tag(5)); - Verifier(GetParam()).Expect(5, true).Verify(cq_.get()); - response_reader->Finish(&recv_response, &recv_status, tag(6)); - Verifier(GetParam()).Expect(6, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(5, true) + .Expect(6, true) + .Verify(cq_.get()); EXPECT_EQ(send_response.message(), recv_response.message()); EXPECT_TRUE(recv_status.ok()); @@ -601,7 +644,7 @@ TEST_P(AsyncEnd2endTest, ServerTrailingMetadataRpc) { ServerContext srv_ctx; grpc::ServerAsyncResponseWriter response_writer(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::pair meta1("key1", "val1"); std::pair meta2("key2", "val2"); @@ -610,20 +653,22 @@ TEST_P(AsyncEnd2endTest, ServerTrailingMetadataRpc) { service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); response_writer.SendInitialMetadata(tag(3)); - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(3, true).Verify(cq_.get()); send_response.set_message(recv_request.message()); srv_ctx.AddTrailingMetadata(meta1.first, meta1.second); srv_ctx.AddTrailingMetadata(meta2.first, meta2.second); response_writer.Finish(send_response, Status::OK, tag(4)); + response_reader->Finish(&recv_response, &recv_status, tag(5)); - Verifier(GetParam()).Expect(4, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(4, true) + .Expect(5, true) + .Verify(cq_.get()); - response_reader->Finish(&recv_response, &recv_status, tag(5)); - Verifier(GetParam()).Expect(5, true).Verify(cq_.get()); EXPECT_EQ(send_response.message(), recv_response.message()); EXPECT_TRUE(recv_status.ok()); auto server_trailing_metadata = cli_ctx.GetServerTrailingMetadata(); @@ -647,7 +692,7 @@ TEST_P(AsyncEnd2endTest, MetadataRpc) { ServerContext srv_ctx; grpc::ServerAsyncResponseWriter response_writer(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::pair meta1("key1", "val1"); std::pair meta2( "key2-bin", @@ -671,7 +716,7 @@ TEST_P(AsyncEnd2endTest, MetadataRpc) { service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); auto client_initial_metadata = srv_ctx.client_metadata(); EXPECT_EQ(meta1.second, @@ -683,9 +728,9 @@ TEST_P(AsyncEnd2endTest, MetadataRpc) { srv_ctx.AddInitialMetadata(meta3.first, meta3.second); srv_ctx.AddInitialMetadata(meta4.first, meta4.second); response_writer.SendInitialMetadata(tag(3)); - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(3, true).Verify(cq_.get()); response_reader->ReadInitialMetadata(tag(4)); - Verifier(GetParam()).Expect(4, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get()); auto server_initial_metadata = cli_ctx.GetServerInitialMetadata(); EXPECT_EQ(meta3.second, ToString(server_initial_metadata.find(meta3.first)->second)); @@ -697,11 +742,13 @@ TEST_P(AsyncEnd2endTest, MetadataRpc) { srv_ctx.AddTrailingMetadata(meta5.first, meta5.second); srv_ctx.AddTrailingMetadata(meta6.first, meta6.second); response_writer.Finish(send_response, Status::OK, tag(5)); + response_reader->Finish(&recv_response, &recv_status, tag(6)); - Verifier(GetParam()).Expect(5, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(5, true) + .Expect(6, true) + .Verify(cq_.get()); - response_reader->Finish(&recv_response, &recv_status, tag(6)); - Verifier(GetParam()).Expect(6, true).Verify(cq_.get()); EXPECT_EQ(send_response.message(), recv_response.message()); EXPECT_TRUE(recv_status.ok()); auto server_trailing_metadata = cli_ctx.GetServerTrailingMetadata(); @@ -726,7 +773,7 @@ TEST_P(AsyncEnd2endTest, ServerCheckCancellation) { ServerContext srv_ctx; grpc::ServerAsyncResponseWriter response_writer(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::unique_ptr> response_reader( stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); @@ -734,15 +781,15 @@ TEST_P(AsyncEnd2endTest, ServerCheckCancellation) { service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); cli_ctx.TryCancel(); - Verifier(GetParam()).Expect(5, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(5, true).Verify(cq_.get()); EXPECT_TRUE(srv_ctx.IsCancelled()); response_reader->Finish(&recv_response, &recv_status, tag(4)); - Verifier(GetParam()).Expect(4, false).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(4, false).Verify(cq_.get()); EXPECT_EQ(StatusCode::CANCELLED, recv_status.error_code()); } @@ -761,7 +808,7 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) { ServerContext srv_ctx; grpc::ServerAsyncResponseWriter response_writer(&srv_ctx); - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::unique_ptr> response_reader( stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); @@ -769,25 +816,29 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) { service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); send_response.set_message(recv_request.message()); response_writer.Finish(send_response, Status::OK, tag(3)); - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); - Verifier(GetParam()).Expect(5, true).Verify(cq_.get()); - EXPECT_FALSE(srv_ctx.IsCancelled()); - response_reader->Finish(&recv_response, &recv_status, tag(4)); - Verifier(GetParam()).Expect(4, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Expect(5, true) + .Verify(cq_.get()); + EXPECT_FALSE(srv_ctx.IsCancelled()); EXPECT_EQ(send_response.message(), recv_response.message()); EXPECT_TRUE(recv_status.ok()); } TEST_P(AsyncEnd2endTest, UnimplementedRpc) { + ChannelArguments args; + auto channel_creds = + GetChannelCredentials(GetParam().credentials_type, &args); std::shared_ptr channel = - CreateChannel(server_address_.str(), InsecureChannelCredentials()); + CreateCustomChannel(server_address_.str(), channel_creds, args); std::unique_ptr stub; stub = grpc::testing::UnimplementedService::NewStub(channel); EchoRequest send_request; @@ -795,12 +846,12 @@ TEST_P(AsyncEnd2endTest, UnimplementedRpc) { Status recv_status; ClientContext cli_ctx; - send_request.set_message("Hello"); + send_request.set_message(GetParam().message_content); std::unique_ptr> response_reader( stub->AsyncUnimplemented(&cli_ctx, send_request, cq_.get())); response_reader->Finish(&recv_response, &recv_status, tag(4)); - Verifier(GetParam()).Expect(4, false).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(4, false).Verify(cq_.get()); EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code()); EXPECT_EQ("", recv_status.error_message()); @@ -847,23 +898,25 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { // Initiate the 'RequestStream' call on client std::unique_ptr> cli_stream( stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1))); - Verifier(GetParam()).Expect(1, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(1, true).Verify(cq_.get()); // On the server, request to be notified of 'RequestStream' calls // and receive the 'RequestStream' call just made by the client srv_ctx.AsyncNotifyWhenDone(tag(11)); service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); // Client sends 3 messages (tags 3, 4 and 5) for (int tag_idx = 3; tag_idx <= 5; tag_idx++) { send_request.set_message("Ping " + std::to_string(tag_idx)); cli_stream->Write(send_request, tag(tag_idx)); - Verifier(GetParam()).Expect(tag_idx, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking) + .Expect(tag_idx, true) + .Verify(cq_.get()); } cli_stream->WritesDone(tag(6)); - Verifier(GetParam()).Expect(6, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(6, true).Verify(cq_.get()); bool expected_server_cq_result = true; bool ignore_cq_result = false; @@ -871,7 +924,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { srv_ctx.TryCancel(); - Verifier(GetParam()).Expect(11, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(11, true).Verify(cq_.get()); EXPECT_TRUE(srv_ctx.IsCancelled()); // Since cancellation is done before server reads any results, we know @@ -881,7 +934,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { std::thread* server_try_cancel_thd = NULL; - auto verif = Verifier(GetParam()); + auto verif = Verifier(GetParam().disable_blocking); if (server_try_cancel == CANCEL_DURING_PROCESSING) { server_try_cancel_thd = @@ -939,13 +992,13 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { // Server sends the final message and cancelled status (but the RPC is // already cancelled at this point. So we expect the operation to fail) srv_stream.Finish(send_response, Status::CANCELLED, tag(9)); - Verifier(GetParam()).Expect(9, false).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(9, false).Verify(cq_.get()); // Client will see the cancellation cli_stream->Finish(&recv_status, tag(10)); // TODO(sreek): The expectation here should be true. This is a bug (github // issue #4972) - Verifier(GetParam()).Expect(10, false).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(10, false).Verify(cq_.get()); EXPECT_FALSE(recv_status.ok()); EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code()); } @@ -979,13 +1032,13 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { // Initiate the 'ResponseStream' call on the client std::unique_ptr> cli_stream( stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1))); - Verifier(GetParam()).Expect(1, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(1, true).Verify(cq_.get()); // On the server, request to be notified of 'ResponseStream' calls and // receive the call just made by the client srv_ctx.AsyncNotifyWhenDone(tag(11)); service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); EXPECT_EQ(send_request.message(), recv_request.message()); bool expected_cq_result = true; @@ -994,7 +1047,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { srv_ctx.TryCancel(); - Verifier(GetParam()).Expect(11, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(11, true).Verify(cq_.get()); EXPECT_TRUE(srv_ctx.IsCancelled()); // We know for sure that all cq results will be false from this point @@ -1004,7 +1057,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { std::thread* server_try_cancel_thd = NULL; - auto verif = Verifier(GetParam()); + auto verif = Verifier(GetParam().disable_blocking); if (server_try_cancel == CANCEL_DURING_PROCESSING) { server_try_cancel_thd = @@ -1064,7 +1117,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { // Client attemts to read the three messages from the server for (int tag_idx = 6; tag_idx <= 8; tag_idx++) { cli_stream->Read(&recv_response, tag(tag_idx)); - Verifier(GetParam()) + Verifier(GetParam().disable_blocking) .Expect(tag_idx, expected_cq_result) .Verify(cq_.get(), ignore_cq_result); } @@ -1075,11 +1128,11 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { // Server finishes the stream (but the RPC is already cancelled) srv_stream.Finish(Status::CANCELLED, tag(9)); - Verifier(GetParam()).Expect(9, false).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(9, false).Verify(cq_.get()); // Client will see the cancellation cli_stream->Finish(&recv_status, tag(10)); - Verifier(GetParam()).Expect(10, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(10, true).Verify(cq_.get()); EXPECT_FALSE(recv_status.ok()); EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code()); } @@ -1114,19 +1167,19 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { // Initiate the call from the client side std::unique_ptr> cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1))); - Verifier(GetParam()).Expect(1, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(1, true).Verify(cq_.get()); // On the server, request to be notified of the 'BidiStream' call and // receive the call just made by the client srv_ctx.AsyncNotifyWhenDone(tag(11)); service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), tag(2)); - Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get()); // Client sends the first and the only message send_request.set_message("Ping"); cli_stream->Write(send_request, tag(3)); - Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(3, true).Verify(cq_.get()); bool expected_cq_result = true; bool ignore_cq_result = false; @@ -1134,7 +1187,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { srv_ctx.TryCancel(); - Verifier(GetParam()).Expect(11, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(11, true).Verify(cq_.get()); EXPECT_TRUE(srv_ctx.IsCancelled()); // We know for sure that all cq results will be false from this point @@ -1144,7 +1197,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { std::thread* server_try_cancel_thd = NULL; - auto verif = Verifier(GetParam()); + auto verif = Verifier(GetParam().disable_blocking); if (server_try_cancel == CANCEL_DURING_PROCESSING) { server_try_cancel_thd = @@ -1244,10 +1297,10 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { // know that cq results are supposed to return false on server. srv_stream.Finish(Status::CANCELLED, tag(9)); - Verifier(GetParam()).Expect(9, false).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(9, false).Verify(cq_.get()); cli_stream->Finish(&recv_status, tag(10)); - Verifier(GetParam()).Expect(10, true).Verify(cq_.get()); + Verifier(GetParam().disable_blocking).Expect(10, true).Verify(cq_.get()); EXPECT_FALSE(recv_status.ok()); EXPECT_EQ(grpc::StatusCode::CANCELLED, recv_status.error_code()); } @@ -1289,11 +1342,48 @@ TEST_P(AsyncEnd2endServerTryCancelTest, ServerBidiStreamingTryCancelAfter) { TestBidiStreamingServerCancel(CANCEL_AFTER_PROCESSING); } +std::vector CreateTestScenarios(bool test_disable_blocking, + bool test_secure, + int test_big_limit) { + std::vector scenarios; + std::vector credentials_types; + std::vector messages; + + credentials_types.push_back(kInsecureCredentialsType); + auto sec_list = GetSecureCredentialsTypeList(); + for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) { + credentials_types.push_back(*sec); + } + + messages.push_back("Hello"); + for (int sz = 1; sz < test_big_limit; sz *= 2) { + grpc::string big_msg; + for (int i = 0; i < sz * 1024; i++) { + char c = 'a' + (i % 26); + big_msg += c; + } + messages.push_back(big_msg); + } + + for (auto cred = credentials_types.begin(); cred != credentials_types.end(); + ++cred) { + for (auto msg = messages.begin(); msg != messages.end(); msg++) { + scenarios.push_back(TestScenario(false, *cred, *msg)); + if (test_disable_blocking) { + scenarios.push_back(TestScenario(true, *cred, *msg)); + } + } + } + return scenarios; +} + INSTANTIATE_TEST_CASE_P(AsyncEnd2end, AsyncEnd2endTest, - ::testing::Values(false, true)); + ::testing::ValuesIn(CreateTestScenarios(true, true, + 1024))); INSTANTIATE_TEST_CASE_P(AsyncEnd2endServerTryCancel, AsyncEnd2endServerTryCancelTest, - ::testing::Values(false)); + ::testing::ValuesIn(CreateTestScenarios(false, false, + 0))); } // namespace } // namespace testing diff --git a/test/cpp/grpclb/grpclb_api_test.cc b/test/cpp/grpclb/grpclb_api_test.cc index 92f93c869c7..bf77878e0a6 100644 --- a/test/cpp/grpclb/grpclb_api_test.cc +++ b/test/cpp/grpclb/grpclb_api_test.cc @@ -35,13 +35,13 @@ #include #include "src/core/ext/lb_policy/grpclb/load_balancer_api.h" -#include "src/proto/grpc/lb/v0/load_balancer.pb.h" // C++ version +#include "src/proto/grpc/lb/v1/load_balancer.pb.h" // C++ version namespace grpc { namespace { -using grpc::lb::v0::LoadBalanceRequest; -using grpc::lb::v0::LoadBalanceResponse; +using grpc::lb::v1::LoadBalanceRequest; +using grpc::lb::v1::LoadBalanceResponse; class GrpclbTest : public ::testing::Test {}; @@ -60,9 +60,7 @@ TEST_F(GrpclbTest, CreateRequest) { TEST_F(GrpclbTest, ParseResponse) { LoadBalanceResponse response; - const std::string client_config_str = "I'm a client config"; auto* initial_response = response.mutable_initial_response(); - initial_response->set_client_config(client_config_str); auto* client_stats_report_interval = initial_response->mutable_client_stats_report_interval(); client_stats_report_interval->set_seconds(123); @@ -73,10 +71,7 @@ TEST_F(GrpclbTest, ParseResponse) { gpr_slice_from_copied_string(encoded_response.c_str()); grpc_grpclb_response* c_response = grpc_grpclb_response_parse(encoded_slice); EXPECT_TRUE(c_response->has_initial_response); - EXPECT_TRUE(c_response->initial_response.has_client_config); EXPECT_FALSE(c_response->initial_response.has_load_balancer_delegate); - EXPECT_TRUE(strcmp(c_response->initial_response.client_config, - client_config_str.c_str()) == 0); EXPECT_EQ(c_response->initial_response.client_stats_report_interval.seconds, 123); EXPECT_EQ(c_response->initial_response.client_stats_report_interval.nanos, diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py index 9d6bf2ab73c..6b3329b046b 100755 --- a/test/cpp/qps/gen_build_yaml.py +++ b/test/cpp/qps/gen_build_yaml.py @@ -43,12 +43,16 @@ sys.path.append(run_tests_root) import performance.scenario_config as scenario_config +def _scenario_json_string(scenario_json): + return json.dumps(scenario_config.remove_nonproto_fields(scenario_json)) + print yaml.dump({ 'tests': [ { 'name': 'json_run_localhost', - 'shortname': 'json_run_localhost:%s' % js['name'], - 'args': ['--scenario_json', pipes.quote(json.dumps(js))], + 'shortname': 'json_run_localhost:%s' % scenario_json['name'], + 'args': ['--scenario_json', + pipes.quote(_scenario_json_string(scenario_json))], 'ci_platforms': ['linux', 'mac', 'posix', 'windows'], 'platforms': ['linux', 'mac', 'posix', 'windows'], 'flaky': False, @@ -58,6 +62,6 @@ print yaml.dump({ 'cpu_cost': 1000.0, 'exclude_configs': [] } - for js in scenario_config.CXXLanguage().scenarios() + for scenario_json in scenario_config.CXXLanguage().scenarios() ] }) diff --git a/test/distrib/csharp/DistribTest/DistribTest.csproj b/test/distrib/csharp/DistribTest/DistribTest.csproj index 7605495f0f6..1acb34d1b2e 100644 --- a/test/distrib/csharp/DistribTest/DistribTest.csproj +++ b/test/distrib/csharp/DistribTest/DistribTest.csproj @@ -113,12 +113,12 @@ - + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + @@ -129,4 +129,4 @@ --> - \ No newline at end of file + diff --git a/test/distrib/csharp/DistribTest/packages.config b/test/distrib/csharp/DistribTest/packages.config index aca09f600cb..69630193d02 100644 --- a/test/distrib/csharp/DistribTest/packages.config +++ b/test/distrib/csharp/DistribTest/packages.config @@ -6,11 +6,10 @@ - - \ No newline at end of file + diff --git a/test/distrib/python/run_distrib_test.sh b/test/distrib/python/run_distrib_test.sh index 79893af8e54..8a983bc2488 100755 --- a/test/distrib/python/run_distrib_test.sh +++ b/test/distrib/python/run_distrib_test.sh @@ -33,8 +33,8 @@ set -ex cd $(dirname $0) # Pick up the source dist archive whatever its version is -SDIST_ARCHIVE=$EXTERNAL_GIT_ROOT/input_artifacts/grpcio-*.tar.gz -BDIST_DIR="file://$EXTERNAL_GIT_ROOT/input_artifacts" +BDIST_ARCHIVES=$EXTERNAL_GIT_ROOT/input_artifacts/grpcio-*.whl +TOOLS_BDIST_ARCHIVES=$EXTERNAL_GIT_ROOT/input_artifacts/grpcio_tools-*.whl if [ ! -f ${SDIST_ARCHIVE} ] then @@ -42,17 +42,25 @@ then exit 1 fi -PIP=pip2 -which $PIP || PIP=pip PYTHON=python2 +PIP=pip2 which $PYTHON || PYTHON=python +which $PIP || PIP=pip # TODO(jtattermusch): this shouldn't be required -$PIP install --upgrade six +# TODO(jtattermusch): run the command twice to workaround docker-on-overlay +# issue https://github.com/docker/docker/issues/12327 +# (first attempt will fail when using docker with overlayFS) +${PIP} install --upgrade six pip || ${PIP} install --upgrade six pip -GRPC_PYTHON_BINARIES_REPOSITORY="${BDIST_DIR}" \ - $PIP install \ - ${SDIST_ARCHIVE} +# At least one of the bdist packages has to succeed (whichever one matches the +# test machine, anyway). +for bdist in ${BDIST_ARCHIVES} ${TOOLS_BDIST_ARCHIVES}; do + ($PYTHON -m pip install $bdist) || true +done -$PYTHON distribtest.py +# TODO(jtattermusch): add a .proto file to the distribtest, generate python +# code from it and then use the generated code from distribtest.py +$PYTHON -m grpc.tools.protoc +$PYTHON distribtest.py diff --git a/tools/codegen/core/gen_header_frame.py b/tools/codegen/core/gen_header_frame.py index 96e6c67fa66..ee476267f23 100755 --- a/tools/codegen/core/gen_header_frame.py +++ b/tools/codegen/core/gen_header_frame.py @@ -38,6 +38,8 @@ import json import sys +set_end_stream = len(sys.argv) > 1 and sys.argv[1] == '--set_end_stream' + # parse input, fill in vals vals = [] for line in sys.stdin: @@ -65,6 +67,9 @@ for key, value in vals: payload_bytes.append(payload_line) # fill in header +flags = 0x04 # END_HEADERS +if set_end_stream: + flags |= 0x01 # END_STREAM payload_bytes[0].extend([ (payload_len >> 16) & 0xff, (payload_len >> 8) & 0xff, @@ -72,7 +77,7 @@ payload_bytes[0].extend([ # header frame 0x01, # flags - 0x04, + flags, # stream id 0x00, 0x00, diff --git a/tools/codegen/core/gen_nano_proto.sh b/tools/codegen/core/gen_nano_proto.sh index e2d2f672e93..b216a20379e 100755 --- a/tools/codegen/core/gen_nano_proto.sh +++ b/tools/codegen/core/gen_nano_proto.sh @@ -29,11 +29,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# # Example usage: # tools/codegen/core/gen_nano_proto.sh \ -# src/proto/grpc/lb/v0/load_balancer.proto -# $PWD/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0 +# src/proto/grpc/lb/v1/load_balancer.proto \ +# $PWD/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1 \ +# src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1 # # Exit statuses: # 1: Incorrect number of arguments diff --git a/tools/distrib/check_include_guards.py b/tools/distrib/check_include_guards.py index 897a899e7ed..8207f5cce08 100755 --- a/tools/distrib/check_include_guards.py +++ b/tools/distrib/check_include_guards.py @@ -31,6 +31,7 @@ import argparse import os +import os.path import re import sys import subprocess @@ -169,7 +170,7 @@ argp.add_argument('--precommit', args = argp.parse_args() KNOWN_BAD = set([ - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', ]) @@ -187,6 +188,8 @@ filename_list = [] try: filename_list = subprocess.check_output(FILE_LIST_COMMAND, shell=True).splitlines() + # Filter out non-existent files (ie, file removed or renamed) + filename_list = (f for f in filename_list if os.path.isfile(f)) except subprocess.CalledProcessError: sys.exit(0) diff --git a/tools/distrib/check_nanopb_output.sh b/tools/distrib/check_nanopb_output.sh index 92cb8ecbb49..c0707051a60 100755 --- a/tools/distrib/check_nanopb_output.sh +++ b/tools/distrib/check_nanopb_output.sh @@ -58,15 +58,15 @@ popd # # Checks for load_balancer.proto # -readonly LOAD_BALANCER_GRPC_OUTPUT_PATH='src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0' +readonly LOAD_BALANCER_GRPC_OUTPUT_PATH='src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1' # nanopb-compile the proto to a temp location ./tools/codegen/core/gen_nano_proto.sh \ - src/proto/grpc/lb/v0/load_balancer.proto \ + src/proto/grpc/lb/v1/load_balancer.proto \ "$NANOPB_TMP_OUTPUT" \ "$LOAD_BALANCER_GRPC_OUTPUT_PATH" # compare outputs to checked compiled code -if ! diff -r $NANOPB_TMP_OUTPUT src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0; then +if ! diff -r $NANOPB_TMP_OUTPUT src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1; then echo "Outputs differ: $NANOPB_TMP_OUTPUT vs $LOAD_BALANCER_GRPC_OUTPUT_PATH" exit 2 fi diff --git a/tools/distrib/python/bazel_deps.sh b/tools/distrib/python/bazel_deps.sh new file mode 100755 index 00000000000..de3ee079708 --- /dev/null +++ b/tools/distrib/python/bazel_deps.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cd $(dirname $0)/../../../ + +# First check if bazel is installed on the machine. If it is, then we don't need +# to invoke the docker bazel. +if [ "bazel version" ] +then + cd third_party/protobuf + bazel query 'deps('$1')' +else + docker build -t bazel `realpath ./tools/dockerfile/bazel/` + docker run -v "`realpath .`:/src/grpc/" \ + -w /src/grpc/third_party/protobuf \ + bazel \ + bazel query 'deps('$1')' +fi diff --git a/tools/distrib/python/check_grpcio_tools.py b/tools/distrib/python/check_grpcio_tools.py new file mode 100755 index 00000000000..baf2ff4effb --- /dev/null +++ b/tools/distrib/python/check_grpcio_tools.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import cStringIO + +import make_grpcio_tools as make + +OUT_OF_DATE_MESSAGE = """file {} is out of date + +Have you called tools/distrib/python/make_grpcio_tools.py since upgrading protobuf?""" + +check_protoc_lib_deps_content = make.get_deps(make.BAZEL_DEPS_PROTOC_LIB_QUERY) + +with open(make.GRPC_PYTHON_PROTOC_LIB_DEPS, 'r') as protoc_lib_deps_file: + if protoc_lib_deps_file.read() != check_protoc_lib_deps_content: + print(OUT_OF_DATE_MESSAGE.format(make.GRPC_PYTHON_PROTOC_LIB_DEPS)) + raise SystemExit(1) diff --git a/tools/distrib/python/grpcio_tools/.gitignore b/tools/distrib/python/grpcio_tools/.gitignore new file mode 100644 index 00000000000..979704d970b --- /dev/null +++ b/tools/distrib/python/grpcio_tools/.gitignore @@ -0,0 +1,7 @@ +build/ +protobuf/ +grpc_plugin/ +grpc_root/ +*.c +*.cpp +*.egg-info diff --git a/tools/distrib/python/grpcio_tools/MANIFEST.in b/tools/distrib/python/grpcio_tools/MANIFEST.in new file mode 100644 index 00000000000..7712834d642 --- /dev/null +++ b/tools/distrib/python/grpcio_tools/MANIFEST.in @@ -0,0 +1,7 @@ +include grpc_version.py +include protoc_deps.py +include protoc_lib_deps.py +include README.rst +graft grpc +graft grpc_root +graft third_party diff --git a/tools/distrib/python/grpcio_tools/README.rst b/tools/distrib/python/grpcio_tools/README.rst new file mode 100644 index 00000000000..10d2fe8c309 --- /dev/null +++ b/tools/distrib/python/grpcio_tools/README.rst @@ -0,0 +1,128 @@ +gRPC Python Tools +================= + +Package for gRPC Python tools. + +Installation +------------ + +The gRPC Python tools package is available for Linux, Mac OS X, and Windows +running Python 2.7. + +From PyPI +~~~~~~~~~ + +If you are installing locally... + +:: + + $ pip install grpcio-tools + +Else system wide (on Ubuntu)... + +:: + + $ sudo pip install grpcio-tools + +If you're on Windows make sure that you installed the :code:`pip.exe` component +when you installed Python (if not go back and install it!) then invoke: + +:: + + $ pip.exe install grpcio-tools + +Windows users may need to invoke :code:`pip.exe` from a command line ran as +administrator. + +n.b. On Windows and on Mac OS X one *must* have a recent release of :code:`pip` +to retrieve the proper wheel from PyPI. Be sure to upgrade to the latest +version! + +You might also need to install Cython to handle installation via the source +distribution if gRPC Python's system coverage with wheels does not happen to +include your system. + +From Source +~~~~~~~~~~~ + +Building from source requires that you have the Python headers (usually a +package named :code:`python-dev`) and Cython installed. It further requires a +GCC-like compiler to go smoothly; you can probably get it to work without +GCC-like stuff, but you may end up having a bad time. + +:: + + $ export REPO_ROOT=grpc # REPO_ROOT can be any directory of your choice + $ git clone https://github.com/grpc/grpc.git $REPO_ROOT + $ cd $REPO_ROOT + $ git submodule update --init + + $ cd tools/distrib/python/grpcio_tools + $ python ../make_grpcio_tools.py + + # For the next command do `sudo pip install` if you get permission-denied errors + $ pip install . + +You cannot currently install Python from source on Windows. Things might work +out for you in MSYS2 (follow the Linux instructions), but it isn't officially +supported at the moment. + +Troubleshooting +~~~~~~~~~~~~~~~ + +Help, I ... + +* **... see a** :code:`pkg_resources.VersionConflict` **when I try to install + grpc** + + This is likely because :code:`pip` doesn't own the offending dependency, + which in turn is likely because your operating system's package manager owns + it. You'll need to force the installation of the dependency: + + :code:`pip install --ignore-installed $OFFENDING_DEPENDENCY` + + For example, if you get an error like the following: + + :: + + Traceback (most recent call last): + File "", line 17, in + ... + File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 509, in find + raise VersionConflict(dist, req) + pkg_resources.VersionConflict: (six 1.8.0 (/usr/lib/python2.7/dist-packages), Requirement.parse('six>=1.10')) + + You can fix it by doing: + + :: + + sudo pip install --ignore-installed six + +* **... see compiler errors on some platforms when either installing from source or from the source distribution** + + If you see + + :: + + /tmp/pip-build-U8pSsr/cython/Cython/Plex/Scanners.c:4:20: fatal error: Python.h: No such file or directory + #include "Python.h" + ^ + compilation terminated. + + You can fix it by installing `python-dev` package. i.e + + :: + + sudo apt-get install python-dev + + If you see something similar to: + + :: + + third_party/protobuf/src/google/protobuf/stubs/mathlimits.h:173:31: note: in expansion of macro 'SIGNED_INT_MAX' + static const Type kPosMax = SIGNED_INT_MAX(Type); \\ + ^ + And your toolchain is GCC (at the time of this writing, up through at least + GCC 6.0), this is probably a bug where GCC chokes on constant expressions + when the :code:`-fwrapv` flag is specified. You should consider setting your + environment with :code:`CFLAGS=-fno-wrapv` or using clang (:code:`CC=clang`). diff --git a/tools/distrib/python/grpcio_tools/grpc/__init__.py b/tools/distrib/python/grpcio_tools/grpc/__init__.py new file mode 100644 index 00000000000..70ac5edd483 --- /dev/null +++ b/tools/distrib/python/grpcio_tools/grpc/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +__import__('pkg_resources').declare_namespace(__name__) diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/__init__.py b/tools/distrib/python/grpcio_tools/grpc/tools/__init__.py new file mode 100644 index 00000000000..d5ad73a74ab --- /dev/null +++ b/tools/distrib/python/grpcio_tools/grpc/tools/__init__.py @@ -0,0 +1,29 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/main.cc b/tools/distrib/python/grpcio_tools/grpc/tools/main.cc new file mode 100644 index 00000000000..81675b4e6fc --- /dev/null +++ b/tools/distrib/python/grpcio_tools/grpc/tools/main.cc @@ -0,0 +1,54 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include + +#include "src/compiler/python_generator.h" + +#include "grpc/tools/main.h" + +int protoc_main(int argc, char* argv[]) { + google::protobuf::compiler::CommandLineInterface cli; + cli.AllowPlugins("protoc-"); + + // Proto2 Python + google::protobuf::compiler::python::Generator py_generator; + cli.RegisterGenerator("--python_out", &py_generator, + "Generate Python source file."); + + // gRPC Python + grpc_python_generator::GeneratorConfiguration grpc_py_config; + grpc_py_config.beta_package_root = "grpc.beta"; + grpc_python_generator::PythonGrpcGenerator grpc_py_generator(grpc_py_config); + cli.RegisterGenerator("--grpc_python_out", &grpc_py_generator, + "Generate Python source file."); + + return cli.Run(argc, argv); +} diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/main.h b/tools/distrib/python/grpcio_tools/grpc/tools/main.h new file mode 100644 index 00000000000..ea2860ff020 --- /dev/null +++ b/tools/distrib/python/grpcio_tools/grpc/tools/main.h @@ -0,0 +1,33 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// We declare `protoc_main` here since we want access to it from Cython as an +// extern but *without* triggering a dllimport declspec when on Windows. +int protoc_main(int argc, char *argv[]); diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/protoc.py b/tools/distrib/python/grpcio_tools/grpc/tools/protoc.py new file mode 100644 index 00000000000..b4dd0ecae2e --- /dev/null +++ b/tools/distrib/python/grpcio_tools/grpc/tools/protoc.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import sys + +from grpc.tools import protoc_compiler + + +if __name__ == '__main__': + protoc_compiler.run_main(sys.argv) diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/protoc_compiler.pyx b/tools/distrib/python/grpcio_tools/grpc/tools/protoc_compiler.pyx new file mode 100644 index 00000000000..a6530127c04 --- /dev/null +++ b/tools/distrib/python/grpcio_tools/grpc/tools/protoc_compiler.pyx @@ -0,0 +1,39 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from libc cimport stdlib + +cdef extern from "grpc/tools/main.h": + int protoc_main(int argc, char *argv[]) + +def run_main(list args not None): + cdef char **argv = stdlib.malloc(len(args)*sizeof(char *)) + for i in range(len(args)): + argv[i] = args[i] + return protoc_main(len(args), argv) diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py new file mode 100644 index 00000000000..1267d0e45dc --- /dev/null +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -0,0 +1,32 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! + +VERSION='0.15.0.dev0' diff --git a/tools/distrib/python/grpcio_tools/protoc_lib_deps.py b/tools/distrib/python/grpcio_tools/protoc_lib_deps.py new file mode 100644 index 00000000000..9f31172170d --- /dev/null +++ b/tools/distrib/python/grpcio_tools/protoc_lib_deps.py @@ -0,0 +1,32 @@ + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# AUTO-GENERATED BY make_grpcio_tools.py! +CC_FILES=['google/protobuf/compiler/zip_writer.cc', 'google/protobuf/compiler/subprocess.cc', 'google/protobuf/compiler/ruby/ruby_generator.cc', 'google/protobuf/compiler/python/python_generator.cc', 'google/protobuf/compiler/plugin.pb.cc', 'google/protobuf/compiler/plugin.cc', 'google/protobuf/compiler/objectivec/objectivec_primitive_field.cc', 'google/protobuf/compiler/objectivec/objectivec_oneof.cc', 'google/protobuf/compiler/objectivec/objectivec_message_field.cc', 'google/protobuf/compiler/objectivec/objectivec_message.cc', 'google/protobuf/compiler/objectivec/objectivec_map_field.cc', 'google/protobuf/compiler/objectivec/objectivec_helpers.cc', 'google/protobuf/compiler/objectivec/objectivec_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_file.cc', 'google/protobuf/compiler/objectivec/objectivec_field.cc', 'google/protobuf/compiler/objectivec/objectivec_extension.cc', 'google/protobuf/compiler/objectivec/objectivec_enum_field.cc', 'google/protobuf/compiler/objectivec/objectivec_enum.cc', 'google/protobuf/compiler/js/js_generator.cc', 'google/protobuf/compiler/javanano/javanano_primitive_field.cc', 'google/protobuf/compiler/javanano/javanano_message_field.cc', 'google/protobuf/compiler/javanano/javanano_message.cc', 'google/protobuf/compiler/javanano/javanano_map_field.cc', 'google/protobuf/compiler/javanano/javanano_helpers.cc', 'google/protobuf/compiler/javanano/javanano_generator.cc', 'google/protobuf/compiler/javanano/javanano_file.cc', 'google/protobuf/compiler/javanano/javanano_field.cc', 'google/protobuf/compiler/javanano/javanano_extension.cc', 'google/protobuf/compiler/javanano/javanano_enum_field.cc', 'google/protobuf/compiler/javanano/javanano_enum.cc', 'google/protobuf/compiler/java/java_string_field_lite.cc', 'google/protobuf/compiler/java/java_string_field.cc', 'google/protobuf/compiler/java/java_shared_code_generator.cc', 'google/protobuf/compiler/java/java_service.cc', 'google/protobuf/compiler/java/java_primitive_field_lite.cc', 'google/protobuf/compiler/java/java_primitive_field.cc', 'google/protobuf/compiler/java/java_name_resolver.cc', 'google/protobuf/compiler/java/java_message_lite.cc', 'google/protobuf/compiler/java/java_message_field_lite.cc', 'google/protobuf/compiler/java/java_message_field.cc', 'google/protobuf/compiler/java/java_message_builder_lite.cc', 'google/protobuf/compiler/java/java_message_builder.cc', 'google/protobuf/compiler/java/java_message.cc', 'google/protobuf/compiler/java/java_map_field_lite.cc', 'google/protobuf/compiler/java/java_map_field.cc', 'google/protobuf/compiler/java/java_lazy_message_field_lite.cc', 'google/protobuf/compiler/java/java_lazy_message_field.cc', 'google/protobuf/compiler/java/java_helpers.cc', 'google/protobuf/compiler/java/java_generator_factory.cc', 'google/protobuf/compiler/java/java_generator.cc', 'google/protobuf/compiler/java/java_file.cc', 'google/protobuf/compiler/java/java_field.cc', 'google/protobuf/compiler/java/java_extension.cc', 'google/protobuf/compiler/java/java_enum_lite.cc', 'google/protobuf/compiler/java/java_enum_field_lite.cc', 'google/protobuf/compiler/java/java_enum_field.cc', 'google/protobuf/compiler/java/java_enum.cc', 'google/protobuf/compiler/java/java_doc_comment.cc', 'google/protobuf/compiler/java/java_context.cc', 'google/protobuf/compiler/csharp/csharp_wrapper_field.cc', 'google/protobuf/compiler/csharp/csharp_source_generator_base.cc', 'google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_message_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_reflection_class.cc', 'google/protobuf/compiler/csharp/csharp_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_message_field.cc', 'google/protobuf/compiler/csharp/csharp_message.cc', 'google/protobuf/compiler/csharp/csharp_map_field.cc', 'google/protobuf/compiler/csharp/csharp_helpers.cc', 'google/protobuf/compiler/csharp/csharp_generator.cc', 'google/protobuf/compiler/csharp/csharp_field_base.cc', 'google/protobuf/compiler/csharp/csharp_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_enum.cc', 'google/protobuf/compiler/csharp/csharp_doc_comment.cc', 'google/protobuf/compiler/cpp/cpp_string_field.cc', 'google/protobuf/compiler/cpp/cpp_service.cc', 'google/protobuf/compiler/cpp/cpp_primitive_field.cc', 'google/protobuf/compiler/cpp/cpp_message_field.cc', 'google/protobuf/compiler/cpp/cpp_message.cc', 'google/protobuf/compiler/cpp/cpp_map_field.cc', 'google/protobuf/compiler/cpp/cpp_helpers.cc', 'google/protobuf/compiler/cpp/cpp_generator.cc', 'google/protobuf/compiler/cpp/cpp_file.cc', 'google/protobuf/compiler/cpp/cpp_field.cc', 'google/protobuf/compiler/cpp/cpp_extension.cc', 'google/protobuf/compiler/cpp/cpp_enum_field.cc', 'google/protobuf/compiler/cpp/cpp_enum.cc', 'google/protobuf/compiler/command_line_interface.cc', 'google/protobuf/compiler/code_generator.cc', 'google/protobuf/wrappers.pb.cc', 'google/protobuf/wire_format.cc', 'google/protobuf/util/type_resolver_util.cc', 'google/protobuf/util/time_util.cc', 'google/protobuf/util/message_differencer.cc', 'google/protobuf/util/json_util.cc', 'google/protobuf/util/internal/utility.cc', 'google/protobuf/util/internal/type_info_test_helper.cc', 'google/protobuf/util/internal/type_info.cc', 'google/protobuf/util/internal/protostream_objectwriter.cc', 'google/protobuf/util/internal/protostream_objectsource.cc', 'google/protobuf/util/internal/proto_writer.cc', 'google/protobuf/util/internal/object_writer.cc', 'google/protobuf/util/internal/json_stream_parser.cc', 'google/protobuf/util/internal/json_objectwriter.cc', 'google/protobuf/util/internal/json_escaping.cc', 'google/protobuf/util/internal/field_mask_utility.cc', 'google/protobuf/util/internal/error_listener.cc', 'google/protobuf/util/internal/default_value_objectwriter.cc', 'google/protobuf/util/internal/datapiece.cc', 'google/protobuf/util/field_mask_util.cc', 'google/protobuf/util/field_comparator.cc', 'google/protobuf/unknown_field_set.cc', 'google/protobuf/type.pb.cc', 'google/protobuf/timestamp.pb.cc', 'google/protobuf/text_format.cc', 'google/protobuf/stubs/substitute.cc', 'google/protobuf/stubs/mathlimits.cc', 'google/protobuf/struct.pb.cc', 'google/protobuf/source_context.pb.cc', 'google/protobuf/service.cc', 'google/protobuf/reflection_ops.cc', 'google/protobuf/message.cc', 'google/protobuf/map_field.cc', 'google/protobuf/io/zero_copy_stream_impl.cc', 'google/protobuf/io/tokenizer.cc', 'google/protobuf/io/strtod.cc', 'google/protobuf/io/printer.cc', 'google/protobuf/io/gzip_stream.cc', 'google/protobuf/generated_message_reflection.cc', 'google/protobuf/field_mask.pb.cc', 'google/protobuf/extension_set_heavy.cc', 'google/protobuf/empty.pb.cc', 'google/protobuf/dynamic_message.cc', 'google/protobuf/duration.pb.cc', 'google/protobuf/descriptor_database.cc', 'google/protobuf/descriptor.pb.cc', 'google/protobuf/descriptor.cc', 'google/protobuf/compiler/parser.cc', 'google/protobuf/compiler/importer.cc', 'google/protobuf/api.pb.cc', 'google/protobuf/any.pb.cc', 'google/protobuf/any.cc', 'google/protobuf/wire_format_lite.cc', 'google/protobuf/stubs/time.cc', 'google/protobuf/stubs/strutil.cc', 'google/protobuf/stubs/structurally_valid.cc', 'google/protobuf/stubs/stringprintf.cc', 'google/protobuf/stubs/stringpiece.cc', 'google/protobuf/stubs/statusor.cc', 'google/protobuf/stubs/status.cc', 'google/protobuf/stubs/once.cc', 'google/protobuf/stubs/int128.cc', 'google/protobuf/stubs/common.cc', 'google/protobuf/stubs/bytestream.cc', 'google/protobuf/stubs/atomicops_internals_x86_msvc.cc', 'google/protobuf/stubs/atomicops_internals_x86_gcc.cc', 'google/protobuf/repeated_field.cc', 'google/protobuf/message_lite.cc', 'google/protobuf/io/zero_copy_stream_impl_lite.cc', 'google/protobuf/io/zero_copy_stream.cc', 'google/protobuf/io/coded_stream.cc', 'google/protobuf/generated_message_util.cc', 'google/protobuf/extension_set.cc', 'google/protobuf/arenastring.cc', 'google/protobuf/arena.cc'] diff --git a/tools/distrib/python/grpcio_tools/setup.py b/tools/distrib/python/grpcio_tools/setup.py new file mode 100644 index 00000000000..576f7ae32a5 --- /dev/null +++ b/tools/distrib/python/grpcio_tools/setup.py @@ -0,0 +1,96 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from distutils import extension +import os +import os.path +import shlex +import sys + +import setuptools +from setuptools.command import build_ext + +# TODO(atash) add flag to disable Cython use + +os.chdir(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, os.path.abspath('.')) + +# There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are +# entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support. +# We use these environment variables to thus get around that without locking +# ourselves in w.r.t. the multitude of operating systems this ought to build on. +# By default we assume a GCC-like compiler. +EXTRA_COMPILE_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_CFLAGS', + '-frtti -std=c++11')) +EXTRA_LINK_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_LDFLAGS', + '-lpthread')) + +import protoc_lib_deps +import grpc_version + +def protoc_ext_module(): + plugin_sources = [ + 'grpc/tools/main.cc', + 'grpc_root/src/compiler/python_generator.cc'] + [ + os.path.join('third_party/protobuf/src', cc_file) + for cc_file in protoc_lib_deps.CC_FILES] + plugin_ext = extension.Extension( + name='grpc.tools.protoc_compiler', + sources=['grpc/tools/protoc_compiler.pyx'] + plugin_sources, + include_dirs=[ + '.', + 'grpc_root', + 'grpc_root/include', + 'third_party/protobuf/src', + ], + language='c++', + define_macros=[('HAVE_PTHREAD', 1)], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, + ) + return plugin_ext + +def maybe_cythonize(exts): + from Cython import Build + return Build.cythonize(exts) + +setuptools.setup( + name='grpcio_tools', + version=grpc_version.VERSION, + license='3-clause BSD', + ext_modules=maybe_cythonize([ + protoc_ext_module(), + ]), + packages=setuptools.find_packages('.'), + # TODO(atash): Figure out why auditwheel doesn't like namespace packages. + #namespace_packages=['grpc'], + install_requires=[ + 'protobuf>=3.0.0a3', + ], +) diff --git a/tools/distrib/python/make_grpcio_tools.py b/tools/distrib/python/make_grpcio_tools.py new file mode 100755 index 00000000000..50fbdbb14c0 --- /dev/null +++ b/tools/distrib/python/make_grpcio_tools.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import os.path +import shutil +import subprocess +import sys +import traceback + +DEPS_FILE_CONTENT=""" +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# AUTO-GENERATED BY make_grpcio_tools.py! +CC_FILES={} +""" + +# Bazel query result prefix for expected source files in protobuf. +PROTOBUF_CC_PREFIX = '//:src/' + +GRPC_ROOT = os.path.abspath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), + '..', '..', '..')) + +GRPC_PYTHON_ROOT = os.path.join(GRPC_ROOT, 'tools/distrib/python/grpcio_tools') + +GRPC_PROTOBUF = os.path.join(GRPC_ROOT, 'third_party/protobuf/src') +GRPC_PROTOC_PLUGINS = os.path.join(GRPC_ROOT, 'src/compiler') +GRPC_PYTHON_PROTOBUF = os.path.join(GRPC_PYTHON_ROOT, + 'third_party/protobuf/src') +GRPC_PYTHON_PROTOC_PLUGINS = os.path.join(GRPC_PYTHON_ROOT, + 'grpc_root/src/compiler') +GRPC_PYTHON_PROTOC_LIB_DEPS = os.path.join(GRPC_PYTHON_ROOT, + 'protoc_lib_deps.py') + +GRPC_INCLUDE = os.path.join(GRPC_ROOT, 'include') +GRPC_PYTHON_INCLUDE = os.path.join(GRPC_PYTHON_ROOT, 'grpc_root/include') + +BAZEL_DEPS = os.path.join(GRPC_ROOT, 'tools/distrib/python/bazel_deps.sh') +BAZEL_DEPS_PROTOC_LIB_QUERY = '//:protoc_lib' + + +def get_deps(query): + """Write the result of the bazel query `query` against protobuf to + `out_file`.""" + output = subprocess.check_output([BAZEL_DEPS, query]) + output = output.splitlines() + cc_files = [ + name for name in output + if name.endswith('.cc') and name.startswith(PROTOBUF_CC_PREFIX)] + cc_files = [cc_file[len(PROTOBUF_CC_PREFIX):] for cc_file in cc_files] + deps_file_content = DEPS_FILE_CONTENT.format(cc_files) + return deps_file_content + + +def main(): + os.chdir(GRPC_ROOT) + + for tree in [GRPC_PYTHON_PROTOBUF, + GRPC_PYTHON_PROTOC_PLUGINS, + GRPC_PYTHON_INCLUDE]: + try: + shutil.rmtree(tree) + except Exception as _: + pass + shutil.copytree(GRPC_PROTOBUF, GRPC_PYTHON_PROTOBUF) + shutil.copytree(GRPC_PROTOC_PLUGINS, GRPC_PYTHON_PROTOC_PLUGINS) + shutil.copytree(GRPC_INCLUDE, GRPC_PYTHON_INCLUDE) + + try: + protoc_lib_deps_content = get_deps(BAZEL_DEPS_PROTOC_LIB_QUERY) + except Exception as error: + # We allow this script to succeed even if we couldn't get the dependencies, + # as then we can assume that even without a successful bazel run the + # dependencies currently in source control are 'good enough'. + sys.stderr.write("Got non-fatal error:\n") + traceback.print_exc(file=sys.stderr) + return + # If we successfully got the dependencies, truncate and rewrite the deps file. + with open(GRPC_PYTHON_PROTOC_LIB_DEPS, 'w') as deps_file: + deps_file.write(protoc_lib_deps_content) + +if __name__ == '__main__': + main() + diff --git a/tools/dockerfile/bazel/Dockerfile b/tools/dockerfile/bazel/Dockerfile new file mode 100644 index 00000000000..2a80a4d4d53 --- /dev/null +++ b/tools/dockerfile/bazel/Dockerfile @@ -0,0 +1,52 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:wily +RUN apt-get update +RUN apt-get -y install software-properties-common python-software-properties +RUN add-apt-repository ppa:webupd8team/java +RUN apt-get update +RUN apt-get -y install \ + vim \ + wget \ + openjdk-8-jdk \ + pkg-config \ + zip \ + g++ \ + zlib1g-dev \ + unzip \ + git + +RUN git clone https://github.com/bazelbuild/bazel.git /bazel +RUN cd /bazel && ./compile.sh + +RUN ln -s /bazel/output/bazel /bin/ + +# ensure the installation has been extracted +RUN bazel diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile index d048b725c85..4ae4ebdb06d 100644 --- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile @@ -31,12 +31,15 @@ FROM debian:jessie +RUN apt-get update && apt-get install debian-keyring && apt-key update + # Install Git and basic packages. -RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-key update && apt-get install -y \ autoconf \ autotools-dev \ build-essential \ bzip2 \ + clang \ curl \ gcc \ gcc-multilib \ diff --git a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile index 46bc9f8f524..9c2fd52eee1 100644 --- a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile @@ -31,12 +31,15 @@ FROM 32bit/debian:jessie +RUN apt-get update && apt-get install debian-keyring && apt-key update + # Install Git and basic packages. -RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-key update && apt-get install -y \ autoconf \ autotools-dev \ build-essential \ bzip2 \ + clang \ curl \ gcc \ gcc-multilib \ diff --git a/tools/dockerfile/grpc_artifact_python_manylinux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_python_manylinux_x64/Dockerfile new file mode 100644 index 00000000000..3e31a2b623d --- /dev/null +++ b/tools/dockerfile/grpc_artifact_python_manylinux_x64/Dockerfile @@ -0,0 +1,43 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Docker file for building gRPC manylinux Python artifacts. + +FROM quay.io/pypa/manylinux1_x86_64 + +# Update the package manager +RUN yum update -y + +################################### +# Install Python build requirements +RUN /opt/python/cp27-cp27m/bin/pip install cython +RUN /opt/python/cp27-cp27mu/bin/pip install cython +RUN /opt/python/cp34-cp34m/bin/pip install cython +RUN /opt/python/cp35-cp35m/bin/pip install cython + diff --git a/tools/dockerfile/grpc_artifact_python_manylinux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_python_manylinux_x86/Dockerfile new file mode 100644 index 00000000000..5fe62c28b73 --- /dev/null +++ b/tools/dockerfile/grpc_artifact_python_manylinux_x86/Dockerfile @@ -0,0 +1,43 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Docker file for building gRPC manylinux Python artifacts. + +FROM quay.io/pypa/manylinux1_i686 + +# Update the package manager +RUN yum update -y + +################################### +# Install Python build requirements +RUN /opt/python/cp27-cp27m/bin/pip install cython +RUN /opt/python/cp27-cp27mu/bin/pip install cython +RUN /opt/python/cp34-cp34m/bin/pip install cython +RUN /opt/python/cp35-cp35m/bin/pip install cython + diff --git a/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile index 64314f88642..2a8d35a5dc1 100644 --- a/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile @@ -69,8 +69,11 @@ RUN apt-get update && apt-get install -y time && apt-get clean # Install nvm RUN touch .profile RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash +# Install all versions of node that we want to test RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache" - +RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm alias default 4" # Prepare ccache RUN ln -s /usr/bin/ccache /usr/local/bin/gcc RUN ln -s /usr/bin/ccache /usr/local/bin/g++ diff --git a/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh index b99fd444eea..976f55d9ab5 100755 --- a/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh +++ b/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh @@ -38,8 +38,6 @@ git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc cp -r /var/local/jenkins/service_account $HOME || true cd /var/local/git/grpc -nvm use 0.12 -nvm alias default 0.12 # prevent the need to run 'nvm use' in every shell # build Node interop client & server npm install -g node-gyp diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile index f70add4e31a..4fd7cc29a3c 100644 --- a/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile +++ b/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile @@ -69,8 +69,11 @@ RUN apt-get update && apt-get install -y time && apt-get clean # Install nvm RUN touch .profile RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash +# Install all versions of node that we want to test RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache" - +RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm alias default 4" # Google Cloud platform API libraries RUN apt-get update && apt-get install -y python-pip && apt-get clean RUN pip install --upgrade google-api-python-client diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh index b99fd444eea..976f55d9ab5 100755 --- a/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh +++ b/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh @@ -38,8 +38,6 @@ git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc cp -r /var/local/jenkins/service_account $HOME || true cd /var/local/git/grpc -nvm use 0.12 -nvm alias default 0.12 # prevent the need to run 'nvm use' in every shell # build Node interop client & server npm install -g node-gyp diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile new file mode 100644 index 00000000000..606b7654576 --- /dev/null +++ b/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile @@ -0,0 +1,103 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM debian:jessie + +# Install Git and basic packages. +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + gcc-multilib \ + git \ + golang \ + gyp \ + lcov \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + perl \ + strace \ + python-dev \ + python-setuptools \ + python-yaml \ + telnet \ + unzip \ + wget \ + zip && apt-get clean + +#================ +# Build profiling +RUN apt-get update && apt-get install -y time && apt-get clean + +# Prepare ccache +RUN ln -s /usr/bin/ccache /usr/local/bin/gcc +RUN ln -s /usr/bin/ccache /usr/local/bin/g++ +RUN ln -s /usr/bin/ccache /usr/local/bin/cc +RUN ln -s /usr/bin/ccache /usr/local/bin/c++ +RUN ln -s /usr/bin/ccache /usr/local/bin/clang +RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ + +#================= +# C++ dependencies +RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean + +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + + +#==================== +# Python dependencies + +# Install dependencies + +RUN apt-get update && apt-get install -y \ + python-all-dev \ + python3-all-dev \ + python-pip + +# Install Python packages from PyPI +RUN pip install pip --upgrade +RUN pip install virtualenv +RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0a2 tox + + +RUN pip install coverage +RUN pip install oauth2client + +# Define the default command. +CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_python/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_python/build_interop_stress.sh new file mode 100755 index 00000000000..e65332f2f30 --- /dev/null +++ b/tools/dockerfile/stress_test/grpc_interop_stress_python/build_interop_stress.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Builds Python interop server and client in a base image. +set -e + +mkdir -p /var/local/git +git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc + +# copy service account keys if available +cp -r /var/local/jenkins/service_account $HOME || true + +cd /var/local/git/grpc + +tools/run_tests/run_tests.py -l python -c opt --build_only + +# Build c++ interop client +make metrics_client -j + diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile new file mode 100644 index 00000000000..36b54ddafe3 --- /dev/null +++ b/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile @@ -0,0 +1,99 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM debian:jessie + +# Install Git and basic packages. +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + gcc-multilib \ + git \ + golang \ + gyp \ + lcov \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + perl \ + strace \ + python-dev \ + python-setuptools \ + python-yaml \ + telnet \ + unzip \ + wget \ + zip && apt-get clean + +#================ +# Build profiling +RUN apt-get update && apt-get install -y time && apt-get clean + +# Prepare ccache +RUN ln -s /usr/bin/ccache /usr/local/bin/gcc +RUN ln -s /usr/bin/ccache /usr/local/bin/g++ +RUN ln -s /usr/bin/ccache /usr/local/bin/cc +RUN ln -s /usr/bin/ccache /usr/local/bin/c++ +RUN ln -s /usr/bin/ccache /usr/local/bin/clang +RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ + +#================= +# C++ dependencies +RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean + +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + + +#================== +# Ruby dependencies + +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 +RUN \curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.1 +RUN /bin/bash -l -c "rvm install ruby-2.1" +RUN /bin/bash -l -c "rvm use --default ruby-2.1" +RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" + +# Define the default command. +CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_ruby/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_ruby/build_interop_stress.sh new file mode 100755 index 00000000000..1b7567d87a6 --- /dev/null +++ b/tools/dockerfile/stress_test/grpc_interop_stress_ruby/build_interop_stress.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Builds Ruby interop server and client in a base image. +set -e + +mkdir -p /var/local/git +git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc + +# Copy service account keys if available +cp -r /var/local/jenkins/service_account $HOME || true + +cd /var/local/git/grpc +rvm --default use ruby-2.1 + +# Build Ruby interop client and server +(cd src/ruby && gem update bundler && bundle && rake compile) + +# Build c++ metrics client to query the metrics from ruby stress client +make metrics_client -j + diff --git a/tools/dockerfile/test/multilang_jessie_x64/Dockerfile b/tools/dockerfile/test/multilang_jessie_x64/Dockerfile index 71ebf2bf715..5c3f77405ea 100644 --- a/tools/dockerfile/test/multilang_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/multilang_jessie_x64/Dockerfile @@ -90,8 +90,11 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c # Install nvm RUN touch .profile RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash +# Install all versions of node that we want to test RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache" - +RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm alias default 4" #================= # PHP dependencies diff --git a/tools/dockerfile/test/node_jessie_x64/Dockerfile b/tools/dockerfile/test/node_jessie_x64/Dockerfile index 64314f88642..2a8d35a5dc1 100644 --- a/tools/dockerfile/test/node_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/node_jessie_x64/Dockerfile @@ -69,8 +69,11 @@ RUN apt-get update && apt-get install -y time && apt-get clean # Install nvm RUN touch .profile RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash +# Install all versions of node that we want to test RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache" - +RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache" +RUN /bin/bash -l -c "nvm alias default 4" # Prepare ccache RUN ln -s /usr/bin/ccache /usr/local/bin/gcc RUN ln -s /usr/bin/ccache /usr/local/bin/g++ diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile index 3146a922b7e..43b2a0c3d96 100644 --- a/tools/dockerfile/test/sanity/Dockerfile +++ b/tools/dockerfile/test/sanity/Dockerfile @@ -75,6 +75,15 @@ RUN apt-get update && apt-get install -y \ python-lxml RUN pip install simplejson mako +#====================================== +# More sanity test dependencies (bazel) +RUN echo "deb http://httpredir.debian.org/debian jessie-backports main" > /etc/apt/sources.list.d/backports.list +RUN apt-get update +RUN apt-get -t jessie-backports install -y openjdk-8-jdk +RUN git clone https://github.com/bazelbuild/bazel.git /bazel +RUN cd /bazel && ./compile.sh +RUN ln -s /bazel/output/bazel /bin/ + #=================== # Docker "inception" # Note this is quite the ugly hack. diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 7dc04960475..2a319db9796 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -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 = 0.14.0-dev +PROJECT_NUMBER = 0.15.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 @@ -833,6 +833,7 @@ include/grpc++/impl/codegen/sync_no_cxx11.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ include/grpc/impl/codegen/byte_buffer.h \ +include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 312fd17cb22..5fdfafbf3ed 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -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 = 0.14.0-dev +PROJECT_NUMBER = 0.15.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 @@ -833,6 +833,7 @@ include/grpc++/impl/codegen/sync_no_cxx11.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ include/grpc/impl/codegen/byte_buffer.h \ +include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 034d9c6e6f4..eed84252cc2 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.15.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 @@ -766,6 +766,7 @@ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/status.h \ include/grpc/impl/codegen/byte_buffer.h \ +include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1b1453f7ea2..7e0d5ebd37f 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.15.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 @@ -766,6 +766,7 @@ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/status.h \ include/grpc/impl/codegen/byte_buffer.h \ +include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ @@ -913,7 +914,7 @@ src/core/ext/client_config/subchannel_call_holder.h \ src/core/ext/client_config/subchannel_index.h \ src/core/ext/client_config/uri_parser.h \ src/core/ext/lb_policy/grpclb/load_balancer_api.h \ -src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h \ +src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h \ third_party/nanopb/pb.h \ third_party/nanopb/pb_common.h \ third_party/nanopb/pb_decode.h \ @@ -1071,7 +1072,7 @@ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ -src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ +src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ diff --git a/tools/gce/create_linux_worker.sh b/tools/gce/create_linux_worker.sh index dff0b1ce5f4..c41e4d299bf 100755 --- a/tools/gce/create_linux_worker.sh +++ b/tools/gce/create_linux_worker.sh @@ -43,7 +43,7 @@ gcloud compute instances create $INSTANCE_NAME \ --project="$CLOUD_PROJECT" \ --zone "$ZONE" \ --machine-type n1-standard-8 \ - --image ubuntu-14-04 \ + --image ubuntu-15-10 \ --boot-disk-size 1000 echo 'Created GCE instance, waiting 60 seconds for it to come online.' diff --git a/tools/gce/linux_performance_worker_init.sh b/tools/gce/linux_performance_worker_init.sh index 25ac3bcedea..df29581e69a 100755 --- a/tools/gce/linux_performance_worker_init.sh +++ b/tools/gce/linux_performance_worker_init.sh @@ -95,6 +95,9 @@ sudo pip install tox touch .profile curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash nvm install 0.12 && npm config set cache /tmp/npm-cache +nvm install 4 && npm config set cache /tmp/npm-cache +nvm install 5 && npm config set cache /tmp/npm-cache +nvm alias default 4 # C# dependencies (http://www.mono-project.com/docs/getting-started/install/linux/#debian-ubuntu-and-derivatives) diff --git a/tools/gce/linux_worker_init.sh b/tools/gce/linux_worker_init.sh index ef6a5d175c9..afcf7a52d92 100755 --- a/tools/gce/linux_worker_init.sh +++ b/tools/gce/linux_worker_init.sh @@ -37,7 +37,7 @@ set -ex sudo apt-get update # Install JRE -sudo apt-get install -y openjdk-7-jre +sudo apt-get install -y openjdk-8-jre sudo apt-get install -y unzip lsof # Install Docker diff --git a/tools/gcp/stress_test/run_ruby.sh b/tools/gcp/stress_test/run_ruby.sh new file mode 100755 index 00000000000..80d0567447b --- /dev/null +++ b/tools/gcp/stress_test/run_ruby.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# Copyright 2015-2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This is a wrapper script that was created to help run_server.py and +# run_client.py to launch 'node js' stress clients and stress servers +source /etc/profile.d/rvm.sh + +set -ex + +$@ diff --git a/tools/jenkins/README.md b/tools/jenkins/README.md new file mode 100644 index 00000000000..8e06b68466c --- /dev/null +++ b/tools/jenkins/README.md @@ -0,0 +1 @@ +Scripts invoked by Jenkins (our CI platform) to run gRPC test suites. diff --git a/tools/jenkins/run_fuzzer.sh b/tools/jenkins/run_fuzzer.sh index 3f25a93319d..cfa7acefab9 100755 --- a/tools/jenkins/run_fuzzer.sh +++ b/tools/jenkins/run_fuzzer.sh @@ -33,14 +33,14 @@ set -ex export RUN_COMMAND="tools/fuzzer/build_and_run_fuzzer.sh $1" -export DOCKER_RUN_SCRIPT=tools/jenkins/docker_run.sh +export DOCKER_RUN_SCRIPT=tools/run_tests/dockerize/docker_run.sh export DOCKERFILE_DIR=tools/dockerfile/test/fuzzer export OUTPUT_DIR=fuzzer_output runtime=${runtime:-3600} jobs=${jobs:-3} -tools/jenkins/build_and_run_docker.sh \ +tools/run_tests/dockerize/build_and_run_docker.sh \ -e RUN_COMMAND="$RUN_COMMAND" \ -e OUTPUT_DIR="$OUTPUT_DIR" \ -e config="$config" \ diff --git a/tools/run_tests/artifact_targets.py b/tools/run_tests/artifact_targets.py index e61c46d8b5a..bd1269ceb72 100644 --- a/tools/run_tests/artifact_targets.py +++ b/tools/run_tests/artifact_targets.py @@ -43,10 +43,10 @@ def create_docker_jobspec(name, dockerfile_dir, shell_command, environ={}, for k,v in environ.iteritems(): docker_args += ['-e', '%s=%s' % (k, v)] docker_env = {'DOCKERFILE_DIR': dockerfile_dir, - 'DOCKER_RUN_SCRIPT': 'tools/jenkins/docker_run.sh', + 'DOCKER_RUN_SCRIPT': 'tools/run_tests/dockerize/docker_run.sh', 'OUTPUT_DIR': 'artifacts'} jobspec = jobset.JobSpec( - cmdline=['tools/jenkins/build_and_run_docker.sh'] + docker_args, + cmdline=['tools/run_tests/dockerize/build_and_run_docker.sh'] + docker_args, environ=docker_env, shortname='build_artifact.%s' % (name), timeout_seconds=30*60, @@ -84,12 +84,16 @@ python_version_arch_map = { class PythonArtifact: """Builds Python artifacts.""" - def __init__(self, platform, arch): - self.name = 'python_%s_%s' % (platform, arch) + def __init__(self, platform, arch, manylinux_build=None): + if manylinux_build: + self.name = 'python_%s_%s_%s' % (platform, arch, manylinux_build) + else: + self.name = 'python_%s_%s' % (platform, arch) self.platform = platform self.arch = arch self.labels = ['artifact', 'python', platform, arch] self.python_version = python_version_arch_map[arch] + self.manylinux_build = manylinux_build def pre_build_jobspecs(self): return [] @@ -99,14 +103,26 @@ class PythonArtifact: if self.platform == 'linux': if self.arch == 'x86': environ['SETARCH_CMD'] = 'linux32' + # Inside the manylinux container, the python installations are located in + # special places... + environ['PYTHON'] = '/opt/python/{}/bin/python'.format(self.manylinux_build) + environ['PIP'] = '/opt/python/{}/bin/pip'.format(self.manylinux_build) + # Our docker image has all the prerequisites pip-installed already. + environ['SKIP_PIP_INSTALL'] = '1' + # Platform autodetection for the manylinux1 image breaks so we set the + # defines ourselves. + # TODO(atash) get better platform-detection support in core so we don't + # need to do this manually... + environ['CFLAGS'] = '-DGPR_MANYLINUX1=1' return create_docker_jobspec(self.name, - 'tools/dockerfile/grpc_artifact_linux_%s' % self.arch, + 'tools/dockerfile/grpc_artifact_python_manylinux_%s' % self.arch, 'tools/run_tests/build_artifact_python.sh', environ=environ) elif self.platform == 'windows': return create_jobspec(self.name, ['tools\\run_tests\\build_artifact_python.bat', - self.python_version + self.python_version, + '32' if self.arch == 'x86' else '64' ], shell=True) else: @@ -307,8 +323,10 @@ def targets(): for Cls in (CSharpExtArtifact, NodeExtArtifact, ProtocArtifact) for platform in ('linux', 'macos', 'windows') for arch in ('x86', 'x64')] + - [PythonArtifact('linux', 'x86'), - PythonArtifact('linux', 'x64'), + [PythonArtifact('linux', 'x86', 'cp27-cp27m'), + PythonArtifact('linux', 'x86', 'cp27-cp27mu'), + PythonArtifact('linux', 'x64', 'cp27-cp27m'), + PythonArtifact('linux', 'x64', 'cp27-cp27mu'), PythonArtifact('macos', 'x64'), PythonArtifact('windows', 'x86'), PythonArtifact('windows', 'x64'), diff --git a/tools/run_tests/build_artifact_node.bat b/tools/run_tests/build_artifact_node.bat index 84c63c28a25..c5bd726db7e 100644 --- a/tools/run_tests/build_artifact_node.bat +++ b/tools/run_tests/build_artifact_node.bat @@ -27,7 +27,7 @@ @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -set node_versions=0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 +set node_versions=0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm @@ -38,12 +38,12 @@ call npm update || goto :error mkdir artifacts for %%v in (%node_versions%) do ( - call node-pre-gyp configure build --target=%%v --target_arch=%1 + call .\node_modules\.bin\node-pre-gyp.cmd configure build --target=%%v --target_arch=%1 @rem Try again after removing openssl headers rmdir "%HOMEDRIVE%%HOMEPATH%\.node-gyp\%%v\include\node\openssl" /S /Q rmdir "%HOMEDRIVE%%HOMEPATH%\.node-gyp\iojs-%%v\include\node\openssl" /S /Q - call node-pre-gyp build package testpackage --target=%%v --target_arch=%1 || goto :error + call .\node_modules\.bin\node-pre-gyp.cmd build package testpackage --target=%%v --target_arch=%1 || goto :error xcopy /Y /I /S build\stage\* artifacts\ || goto :error ) diff --git a/tools/run_tests/build_artifact_node.sh b/tools/run_tests/build_artifact_node.sh index ef3476a0381..9d06472aa49 100755 --- a/tools/run_tests/build_artifact_node.sh +++ b/tools/run_tests/build_artifact_node.sh @@ -42,7 +42,7 @@ mkdir -p artifacts npm update -node_versions=( 0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 ) +node_versions=( 0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 ) for version in ${node_versions[@]} do diff --git a/tools/run_tests/build_artifact_python.bat b/tools/run_tests/build_artifact_python.bat index 023d3945494..fea0275426f 100644 --- a/tools/run_tests/build_artifact_python.bat +++ b/tools/run_tests/build_artifact_python.bat @@ -41,7 +41,7 @@ copy /Y vsprojects\Release\grpc_dll.dll src\python\grpcio\grpc\_cython\_windows\ copy /Y vsprojects\x64\Release\grpc_dll.dll src\python\grpcio\grpc\_cython\_windows\grpc_c.64.python || goto :error -set PATH=C:\%1;C:\%1\scripts;%PATH% +set PATH=C:\%1;C:\%1\scripts;C:\msys64\mingw%2\bin;%PATH% pip install --upgrade six pip install --upgrade setuptools @@ -50,10 +50,37 @@ pip install -rrequirements.txt set GRPC_PYTHON_USE_CUSTOM_BDIST=0 set GRPC_PYTHON_BUILD_WITH_CYTHON=1 +@rem TODO(atash): maybe we could avoid the grpc_c.(32|64).python shim above if +@rem this used the right python build? python setup.py bdist_wheel +@rem Build gRPC Python tools +@rem +@rem Because this is windows and *everything seems to hate Windows* we have to +@rem set all of these flags ourselves because Python won't help us (see the +@rem setup.py of the grpcio_tools project). +set GRPC_PYTHON_CFLAGS=-fno-wrapv -frtti -std=c++11 +@rem Further confusing things, MSYS2's mingw64 tries to dynamically link +@rem libgcc, libstdc++, and winpthreads. We have to override this or our +@rem extensions end up linking to MSYS2 DLLs, which the normal Python on +@rem Windows user won't have... and ON TOP OF THIS, there's MinGW's GCC default +@rem behavior of linking msvcrt.dll as the C runtime library, which we need to +@rem override so that Python's distutils doesn't link us against multiple C +@rem runtimes. +python -c "from distutils.cygwinccompiler import get_msvcr; print(get_msvcr()[0])" > temp.txt +set /p PYTHON_MSVCR= + diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index 15e2807fd41..491aeaeb678 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -315,6 +315,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index fcda361ef19..96bee4101c8 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -331,6 +331,7 @@ + diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index 1dc95f985ad..fe9eed781c7 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -300,6 +300,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 4eec05a3b1f..6a2843e37c9 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -273,6 +273,7 @@ + @@ -422,7 +423,7 @@ - + @@ -729,7 +730,7 @@ - + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 17c88c4805e..7d53be719cf 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -442,8 +442,8 @@ src\core\ext\lb_policy\grpclb - - src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0 + + src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1 third_party\nanopb @@ -516,6 +516,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen @@ -959,8 +962,8 @@ src\core\ext\lb_policy\grpclb - - src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0 + + src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1 third_party\nanopb @@ -1037,8 +1040,8 @@ {adf7e553-94ef-14fd-e845-03104f00a06f} - - {0406d191-8817-38c3-a562-e3541201f424} + + {bc357e2d-8ddd-a688-88a3-255228fc0818} {b63ded00-b24f-708e-333f-ce199e421875} diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 26050dcf74e..fbf26a29f33 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -264,6 +264,7 @@ + @@ -397,7 +398,7 @@ - + @@ -668,7 +669,7 @@ - + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index a4acf513bc1..2500d5c106a 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -388,8 +388,8 @@ src\core\ext\lb_policy\grpclb - - src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0 + + src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1 third_party\nanopb @@ -456,6 +456,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen @@ -851,8 +854,8 @@ src\core\ext\lb_policy\grpclb - - src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0 + + src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1 third_party\nanopb @@ -929,8 +932,8 @@ {21858d9d-30b5-8847-5882-6b47df0fa293} - - {1795a20b-3e7c-e27d-eae1-96582fa9a958} + + {e9256e96-ea3d-c1fd-6426-9d53d9f08f66} {e27f9ecf-97bb-1a2e-3135-a41f732dcf55} diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj index cd0b40c8730..34e939cf845 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj @@ -191,6 +191,7 @@ + diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters index 029b8ef7741..d66236580c2 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters @@ -120,6 +120,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj index 6d138fae1cb..890d77df22c 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj @@ -191,6 +191,7 @@ + diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters index dc3f0b2d040..4e0ba656fc7 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters @@ -120,6 +120,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj index 1509ece9f96..91b11a1f0f4 100644 --- a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj +++ b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj @@ -160,13 +160,13 @@ - + - + - + - + diff --git a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters index 6c57b8c162a..50f0a3eac25 100644 --- a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters +++ b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters @@ -1,8 +1,8 @@ - - src\proto\grpc\lb\v0 + + src\proto\grpc\lb\v1 test\cpp\grpclb @@ -22,8 +22,8 @@ {2981699e-c196-c599-bc17-c177770f89ee} - - {3d04774a-1c2f-e100-435e-08af5d539250} + + {6cce8ddf-d9a9-1d71-0810-d1e6f8685d76} {64736e1d-eb77-664f-34ab-6cf41263d3d8} diff --git a/vsprojects/vcxproj/test/large_metadata_bad_client_test/large_metadata_bad_client_test.vcxproj b/vsprojects/vcxproj/test/large_metadata_bad_client_test/large_metadata_bad_client_test.vcxproj new file mode 100644 index 00000000000..0a14694b757 --- /dev/null +++ b/vsprojects/vcxproj/test/large_metadata_bad_client_test/large_metadata_bad_client_test.vcxproj @@ -0,0 +1,202 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B706A9EC-7982-0DBC-495D-07B165F6CF56} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + large_metadata_bad_client_test + static + Debug + static + Debug + + + large_metadata_bad_client_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {BA67B418-B699-E41A-9CC4-0279C49481A5} + + + {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} + + + {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/large_metadata_bad_client_test/large_metadata_bad_client_test.vcxproj.filters b/vsprojects/vcxproj/test/large_metadata_bad_client_test/large_metadata_bad_client_test.vcxproj.filters new file mode 100644 index 00000000000..5eb9a5e7cb9 --- /dev/null +++ b/vsprojects/vcxproj/test/large_metadata_bad_client_test/large_metadata_bad_client_test.vcxproj.filters @@ -0,0 +1,24 @@ + + + + + test\core\bad_client\tests + + + + + + {6c1eb0cb-9d82-f961-7220-1f6edc913666} + + + {79d5006f-93a1-aa0e-2568-37aa63eef567} + + + {dbde5995-24a0-2332-4bee-0540ed3aa848} + + + {5cf4a13f-ae24-fd98-eb59-b5301f30367c} + + + +