diff --git a/Makefile b/Makefile index ecd049d8020..46b5af50f40 100644 --- a/Makefile +++ b/Makefile @@ -1229,9 +1229,9 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc ifeq ($(EMBED_OPENSSL),true) -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_reflection_codegen.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_reflection_codegen.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a else -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_reflection_codegen.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_reflection_codegen.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a endif diff --git a/build.yaml b/build.yaml index 522eb55c0d3..011b003d97b 100644 --- a/build.yaml +++ b/build.yaml @@ -1029,7 +1029,7 @@ libs: src: - src/proto/grpc/reflection/v1alpha/reflection.proto - name: grpc++_test - build: test + build: private language: c++ headers: - include/grpc++/test/server_context_test_spouse.h diff --git a/examples/node/dynamic_codegen/route_guide/route_guide_client.js b/examples/node/dynamic_codegen/route_guide/route_guide_client.js index 775b9addbfc..b7550b201a8 100644 --- a/examples/node/dynamic_codegen/route_guide/route_guide_client.js +++ b/examples/node/dynamic_codegen/route_guide/route_guide_client.js @@ -55,6 +55,7 @@ function runGetFeature(callback) { function featureCallback(error, feature) { if (error) { callback(error); + return; } if (feature.name === '') { console.log('Found no feature at ' + @@ -117,13 +118,17 @@ function runRecordRoute(callback) { string: 'db_path' }); fs.readFile(path.resolve(argv.db_path), function(err, data) { - if (err) callback(err); + if (err) { + callback(err); + return; + } var feature_list = JSON.parse(data); var num_points = 10; var call = client.recordRoute(function(error, stats) { if (error) { callback(error); + return; } console.log('Finished trip with', stats.point_count, 'points'); console.log('Passed', stats.feature_count, 'features'); diff --git a/examples/node/static_codegen/route_guide/route_guide_client.js b/examples/node/static_codegen/route_guide/route_guide_client.js index ecde78616b5..e16de44a1ac 100644 --- a/examples/node/static_codegen/route_guide/route_guide_client.js +++ b/examples/node/static_codegen/route_guide/route_guide_client.js @@ -56,6 +56,7 @@ function runGetFeature(callback) { function featureCallback(error, feature) { if (error) { callback(error); + return; } var latitude = feature.getLocation().getLatitude(); var longitude = feature.getLocation().getLongitude(); @@ -115,7 +116,10 @@ function runRecordRoute(callback) { string: 'db_path' }); fs.readFile(path.resolve(argv.db_path), function(err, data) { - if (err) callback(err); + if (err) { + callback(err); + return; + } // Transform the loaded features to Feature objects var feature_list = _.map(JSON.parse(data), function(value) { var feature = new messages.Feature(); @@ -131,6 +135,7 @@ function runRecordRoute(callback) { var call = client.recordRoute(function(error, stats) { if (error) { callback(error); + return; } console.log('Finished trip with', stats.getPointCount(), 'points'); console.log('Passed', stats.getFeatureCount(), 'features'); diff --git a/include/grpc++/ext/reflection.grpc.pb.h b/include/grpc++/ext/reflection.grpc.pb.h index 6e56088497a..151271c65b8 100644 --- a/include/grpc++/ext/reflection.grpc.pb.h +++ b/include/grpc++/ext/reflection.grpc.pb.h @@ -176,6 +176,8 @@ class ServerReflection GRPC_FINAL { } }; typedef Service StreamedUnaryService; + typedef Service SplitStreamedService; + typedef Service StreamedService; }; } // namespace v1alpha diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index 52f927631c9..bb992f0e185 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -236,6 +236,19 @@ class StreamedUnaryHandler ServerUnaryStreamer, true>(func) {} }; +template +class SplitServerStreamingHandler + : public TemplatedBidiStreamingHandler< + ServerSplitStreamer, false> { + public: + explicit SplitServerStreamingHandler( + std::function*)> + func) + : TemplatedBidiStreamingHandler< + ServerSplitStreamer, false>(func) {} +}; + // Handle unknown method by returning UNIMPLEMENTED error. class UnknownMethodHandler : public MethodHandler { public: diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h index 975f710f132..ddf50b019da 100644 --- a/include/grpc++/impl/codegen/server_context.h +++ b/include/grpc++/impl/codegen/server_context.h @@ -44,7 +44,6 @@ #include #include -struct gpr_timespec; struct grpc_metadata; struct grpc_call; struct census_context; diff --git a/include/grpc++/impl/codegen/service_type.h b/include/grpc++/impl/codegen/service_type.h index 72b22253128..bd65ea009e2 100644 --- a/include/grpc++/impl/codegen/service_type.h +++ b/include/grpc++/impl/codegen/service_type.h @@ -147,14 +147,15 @@ class Service { methods_[index].reset(); } - void MarkMethodStreamedUnary(int index, - MethodHandler* streamed_unary_method) { + void MarkMethodStreamed(int index, MethodHandler* streamed_method) { GPR_CODEGEN_ASSERT(methods_[index] && methods_[index]->handler() && - "Cannot mark an async or generic method Streamed Unary"); - methods_[index]->SetHandler(streamed_unary_method); + "Cannot mark an async or generic method Streamed"); + methods_[index]->SetHandler(streamed_method); // From the server's point of view, streamed unary is a special - // case of BIDI_STREAMING that has 1 read and 1 write, in that order. + // case of BIDI_STREAMING that has 1 read and 1 write, in that order, + // and split server-side streaming is BIDI_STREAMING with 1 read and + // any number of writes, in that order methods_[index]->SetMethodType(::grpc::RpcMethod::BIDI_STREAMING); } diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h index e3c5a919b1e..9a3efb51193 100644 --- a/include/grpc++/impl/codegen/sync_stream.h +++ b/include/grpc++/impl/codegen/sync_stream.h @@ -538,7 +538,7 @@ class ServerReaderWriter GRPC_FINAL : public ServerReaderWriterInterface { /// the \a NextMessageSize method to determine an upper-bound on the size of /// the message. /// A key difference relative to streaming: ServerUnaryStreamer -/// must have exactly 1 Read and exactly 1 Write, in that order, to function +/// must have exactly 1 Read and exactly 1 Write, in that order, to function /// correctly. Otherwise, the RPC is in error. template class ServerUnaryStreamer GRPC_FINAL @@ -577,6 +577,43 @@ class ServerUnaryStreamer GRPC_FINAL bool write_done_; }; +/// A class to represent a flow-controlled server-side streaming call. +/// This is something of a hybrid between server-side and bidi streaming. +/// This is invoked through a server-side streaming call on the client side, +/// but the server responds to it as though it were a bidi streaming call that +/// must first have exactly 1 Read and then any number of Writes. +template +class ServerSplitStreamer GRPC_FINAL + : public ServerReaderWriterInterface { + public: + ServerSplitStreamer(Call* call, ServerContext* ctx) + : body_(call, ctx), read_done_(false) {} + + void SendInitialMetadata() GRPC_OVERRIDE { body_.SendInitialMetadata(); } + + bool NextMessageSize(uint32_t* sz) GRPC_OVERRIDE { + return body_.NextMessageSize(sz); + } + + bool Read(RequestType* request) GRPC_OVERRIDE { + if (read_done_) { + return false; + } + read_done_ = true; + return body_.Read(request); + } + + using WriterInterface::Write; + bool Write(const ResponseType& response, + const WriteOptions& options) GRPC_OVERRIDE { + return read_done_ && body_.Write(response, options); + } + + private: + internal::ServerReaderWriterBody body_; + bool read_done_; +}; + } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_SYNC_STREAM_H diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index d0c35ea1ab3..fa72f9b0d97 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -624,7 +624,7 @@ void PrintHeaderServerMethodStreamedUnary( printer->Indent(); printer->Print(*vars, "WithStreamedUnaryMethod_$Method$() {\n" - " ::grpc::Service::MarkMethodStreamedUnary($Idx$,\n" + " ::grpc::Service::MarkMethodStreamed($Idx$,\n" " new ::grpc::StreamedUnaryHandler< $Request$, " "$Response$>(std::bind" "(&WithStreamedUnaryMethod_$Method$::" @@ -656,6 +656,58 @@ void PrintHeaderServerMethodStreamedUnary( } } +void PrintHeaderServerMethodSplitStreaming( + Printer *printer, const Method *method, + std::map *vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->ServerOnlyStreaming()) { + printer->Print(*vars, "template \n"); + printer->Print(*vars, + "class WithSplitStreamingMethod_$Method$ : " + "public BaseClass {\n"); + printer->Print( + " private:\n" + " void BaseClassMustBeDerivedFromService(const Service *service) " + "{}\n"); + printer->Print(" public:\n"); + printer->Indent(); + printer->Print(*vars, + "WithSplitStreamingMethod_$Method$() {\n" + " ::grpc::Service::MarkMethodStreamed($Idx$,\n" + " new ::grpc::SplitServerStreamingHandler< $Request$, " + "$Response$>(std::bind" + "(&WithSplitStreamingMethod_$Method$::" + "Streamed$Method$, this, std::placeholders::_1, " + "std::placeholders::_2)));\n" + "}\n"); + printer->Print(*vars, + "~WithSplitStreamingMethod_$Method$() GRPC_OVERRIDE {\n" + " BaseClassMustBeDerivedFromService(this);\n" + "}\n"); + printer->Print( + *vars, + "// disable regular version of this method\n" + "::grpc::Status $Method$(" + "::grpc::ServerContext* context, const $Request$* request, " + "::grpc::ServerWriter< $Response$>* writer) GRPC_FINAL GRPC_OVERRIDE " + "{\n" + " abort();\n" + " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" + "}\n"); + printer->Print(*vars, + "// replace default version of method with split streamed\n" + "virtual ::grpc::Status Streamed$Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerSplitStreamer< " + "$Request$,$Response$>* server_split_streamer)" + " = 0;\n"); + printer->Outdent(); + printer->Print(*vars, "};\n"); + } +} + void PrintHeaderServerMethodGeneric( Printer *printer, const Method *method, std::map *vars) { @@ -844,6 +896,48 @@ void PrintHeaderService(Printer *printer, const Service *service, } printer->Print(" StreamedUnaryService;\n"); + // Server side - controlled server-side streaming + for (int i = 0; i < service->method_count(); ++i) { + (*vars)["Idx"] = as_string(i); + PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(), + vars); + } + + printer->Print("typedef "); + for (int i = 0; i < service->method_count(); ++i) { + (*vars)["method_name"] = service->method(i).get()->name(); + if (service->method(i)->ServerOnlyStreaming()) { + printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<"); + } + } + printer->Print("Service"); + for (int i = 0; i < service->method_count(); ++i) { + if (service->method(i)->ServerOnlyStreaming()) { + printer->Print(" >"); + } + } + printer->Print(" SplitStreamedService;\n"); + + // Server side - typedef for controlled both unary and server-side streaming + printer->Print("typedef "); + for (int i = 0; i < service->method_count(); ++i) { + (*vars)["method_name"] = service->method(i).get()->name(); + if (service->method(i)->ServerOnlyStreaming()) { + printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<"); + } + if (service->method(i)->NoStreaming()) { + printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<"); + } + } + printer->Print("Service"); + for (int i = 0; i < service->method_count(); ++i) { + if (service->method(i)->NoStreaming() || + service->method(i)->ServerOnlyStreaming()) { + printer->Print(" >"); + } + } + printer->Print(" StreamedService;\n"); + printer->Outdent(); printer->Print("};\n"); printer->Print(service->GetTrailingComments().c_str()); diff --git a/src/core/ext/load_reporting/load_reporting.h b/src/core/ext/load_reporting/load_reporting.h index e13097654d5..a157844734e 100644 --- a/src/core/ext/load_reporting/load_reporting.h +++ b/src/core/ext/load_reporting/load_reporting.h @@ -51,7 +51,7 @@ * The value corresponding to this key is an opaque binary blob reported by the * backend as part of its trailing metadata containing cost information for the * call. */ -#define GRPC_LB_COST_MD_KEY "lb-cost" +#define GRPC_LB_COST_MD_KEY "lb-cost-bin" /** Identifiers for the invocation point of the users LR callback */ typedef enum grpc_load_reporting_source { diff --git a/src/core/ext/load_reporting/load_reporting_filter.c b/src/core/ext/load_reporting/load_reporting_filter.c index 22bf36367f6..eeae2400fbc 100644 --- a/src/core/ext/load_reporting/load_reporting_filter.c +++ b/src/core/ext/load_reporting/load_reporting_filter.c @@ -193,7 +193,7 @@ static grpc_mdelem *lr_trailing_md_filter(void *user_data, grpc_mdelem *md) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; - if (md->key == GRPC_MDSTR_LB_COST) { + if (md->key == GRPC_MDSTR_LB_COST_BIN) { calld->trailing_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value)); return NULL; } diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index 31c54ff74c6..cba7ec472aa 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -290,8 +290,6 @@ static grpc_channel *client_channel_factory_create_channel( channel = NULL; } - GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, - "client_channel_factory_create_channel"); return channel; } @@ -360,6 +358,9 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, grpc_channel *channel = client_channel_factory_create_channel( &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL); + GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, + "client_channel_factory_create_channel"); + grpc_client_channel_factory_unref(&exec_ctx, &f->base); grpc_exec_ctx_finish(&exec_ctx); diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c index 0f2bf97824b..f2221fb0fbe 100644 --- a/src/core/lib/channel/http_server_filter.c +++ b/src/core/lib/channel/http_server_filter.c @@ -42,6 +42,8 @@ #define EXPECTED_CONTENT_TYPE "application/grpc" #define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1 +extern int grpc_http_trace; + typedef struct call_data { uint8_t seen_path; uint8_t seen_method; @@ -209,6 +211,11 @@ static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, err, GRPC_ERROR_CREATE("Missing te: trailers header")); } /* Error this call out */ + if (grpc_http_trace) { + const char *error_str = grpc_error_string(err); + gpr_log(GPR_ERROR, "Invalid http2 headers: %s", error_str); + grpc_error_free_string(error_str); + } grpc_call_element_send_cancel(exec_ctx, elem); } } else { diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c index f019ef156a7..8b22592b45d 100644 --- a/src/core/lib/transport/static_metadata.c +++ b/src/core/lib/transport/static_metadata.c @@ -126,7 +126,7 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "if-range", "if-unmodified-since", "last-modified", - "lb-cost", + "lb-cost-bin", "lb-token", "link", "location", diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h index e0a8196419e..28ad6f2961a 100644 --- a/src/core/lib/transport/static_metadata.h +++ b/src/core/lib/transport/static_metadata.h @@ -175,8 +175,8 @@ extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; #define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_mdstr_table[62]) /* "last-modified" */ #define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[63]) -/* "lb-cost" */ -#define GRPC_MDSTR_LB_COST (&grpc_static_mdstr_table[64]) +/* "lb-cost-bin" */ +#define GRPC_MDSTR_LB_COST_BIN (&grpc_static_mdstr_table[64]) /* "lb-token" */ #define GRPC_MDSTR_LB_TOKEN (&grpc_static_mdstr_table[65]) /* "link" */ @@ -337,8 +337,8 @@ extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; #define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[44]) /* "last-modified": "" */ #define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[45]) -/* "lb-cost": "" */ -#define GRPC_MDELEM_LB_COST_EMPTY (&grpc_static_mdelem_table[46]) +/* "lb-cost-bin": "" */ +#define GRPC_MDELEM_LB_COST_BIN_EMPTY (&grpc_static_mdelem_table[46]) /* "lb-token": "" */ #define GRPC_MDELEM_LB_TOKEN_EMPTY (&grpc_static_mdelem_table[47]) /* "link": "" */ diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json index 1b900c8af32..fe200f8d440 100644 --- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json +++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json @@ -67,5 +67,10 @@ } } } + }, + "runtimeOptions": { + "configProperties": { + "System.GC.Server": true + } } } diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index cb926328e08..7a46a55a5b8 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -583,7 +583,6 @@ namespace Grpc.IntegrationTesting var e = Assert.Throws(() => client.UnimplementedCall(new Empty())); Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode); - Assert.AreEqual("", e.Status.Detail); Console.WriteLine("Passed!"); } diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc index 745b5023d59..848c601587f 100644 --- a/src/node/ext/node_grpc.cc +++ b/src/node/ext/node_grpc.cc @@ -261,10 +261,10 @@ void InitLogConstants(Local exports) { Nan::HandleScope scope; Local log_verbosity = Nan::New(); Nan::Set(exports, Nan::New("logVerbosity").ToLocalChecked(), log_verbosity); - Local DEBUG(Nan::New(GPR_LOG_SEVERITY_DEBUG)); - Nan::Set(log_verbosity, Nan::New("DEBUG").ToLocalChecked(), DEBUG); - Local INFO(Nan::New(GPR_LOG_SEVERITY_INFO)); - Nan::Set(log_verbosity, Nan::New("INFO").ToLocalChecked(), INFO); + Local LOG_DEBUG(Nan::New(GPR_LOG_SEVERITY_DEBUG)); + Nan::Set(log_verbosity, Nan::New("DEBUG").ToLocalChecked(), LOG_DEBUG); + Local LOG_INFO(Nan::New(GPR_LOG_SEVERITY_INFO)); + Nan::Set(log_verbosity, Nan::New("INFO").ToLocalChecked(), LOG_INFO); Local LOG_ERROR(Nan::New(GPR_LOG_SEVERITY_ERROR)); Nan::Set(log_verbosity, Nan::New("ERROR").ToLocalChecked(), LOG_ERROR); } diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj index 8d34b26c4fc..ab7159cda2f 100644 --- a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 48; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -129,7 +129,7 @@ 6369A2621A9322E20015FC5C /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0730; ORGANIZATIONNAME = gRPC; TargetAttributes = { 6369A2691A9322E20015FC5C = { @@ -138,7 +138,7 @@ }; }; buildConfigurationList = 6369A2651A9322E20015FC5C /* Build configuration list for PBXProject "Sample" */; - compatibilityVersion = "Xcode 8.0"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( @@ -253,10 +253,8 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -265,7 +263,6 @@ ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -299,10 +296,8 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -310,7 +305,6 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme b/src/objective-c/examples/Sample/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme index 881474b111c..d399e22e460 100644 --- a/src/objective-c/examples/Sample/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme +++ b/src/objective-c/examples/Sample/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme @@ -1,6 +1,6 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) + gRPC.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 8dccbf0f72b..c4a6567ae0e 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 48; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -535,7 +535,7 @@ 635697BF1B14FC11007A7283 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0630; ORGANIZATIONNAME = gRPC; TargetAttributes = { 5E8A5DA31D3840B4000F8BC4 = { @@ -565,7 +565,7 @@ }; }; buildConfigurationList = 635697C21B14FC11007A7283 /* Build configuration list for PBXProject "Tests" */; - compatibilityVersion = "Xcode 8.0"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( @@ -1151,10 +1151,8 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; @@ -1207,7 +1205,6 @@ ); INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "gRPC.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Cronet; @@ -1365,7 +1362,6 @@ ); INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "gRPC.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -1380,7 +1376,6 @@ ); INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "gRPC.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -1398,16 +1393,13 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -1444,10 +1436,8 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme index 740a1c0672d..d1d616c4cf2 100644 --- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme @@ -1,6 +1,6 @@ (std::bind(&WithStreamedUnaryMethod_MethodA1::StreamedMethodA1, this, std::placeholders::_1, std::placeholders::_2))); } ~WithStreamedUnaryMethod_MethodA1() GRPC_OVERRIDE { @@ -228,6 +228,8 @@ class ServiceA GRPC_FINAL { virtual ::grpc::Status StreamedMethodA1(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::grpc::testing::Request,::grpc::testing::Response>* server_unary_streamer) = 0; }; typedef WithStreamedUnaryMethod_MethodA1 StreamedUnaryService; + typedef Service SplitStreamedService; + typedef WithStreamedUnaryMethod_MethodA1 StreamedService; }; // ServiceB leading comment 1 @@ -312,7 +314,7 @@ class ServiceB GRPC_FINAL { void BaseClassMustBeDerivedFromService(const Service *service) {} public: WithStreamedUnaryMethod_MethodB1() { - ::grpc::Service::MarkMethodStreamedUnary(0, + ::grpc::Service::MarkMethodStreamed(0, new ::grpc::StreamedUnaryHandler< ::grpc::testing::Request, ::grpc::testing::Response>(std::bind(&WithStreamedUnaryMethod_MethodB1::StreamedMethodB1, this, std::placeholders::_1, std::placeholders::_2))); } ~WithStreamedUnaryMethod_MethodB1() GRPC_OVERRIDE { @@ -327,6 +329,8 @@ class ServiceB GRPC_FINAL { virtual ::grpc::Status StreamedMethodB1(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::grpc::testing::Request,::grpc::testing::Response>* server_unary_streamer) = 0; }; typedef WithStreamedUnaryMethod_MethodB1 StreamedUnaryService; + typedef Service SplitStreamedService; + typedef WithStreamedUnaryMethod_MethodB1 StreamedService; }; // ServiceB trailing comment 1 diff --git a/test/cpp/end2end/hybrid_end2end_test.cc b/test/cpp/end2end/hybrid_end2end_test.cc index 8cd2e663470..76a5732f338 100644 --- a/test/cpp/end2end/hybrid_end2end_test.cc +++ b/test/cpp/end2end/hybrid_end2end_test.cc @@ -320,6 +320,29 @@ class HybridEnd2endTest : public ::testing::Test { EXPECT_TRUE(s.ok()); } + void SendSimpleServerStreamingToDupService() { + std::shared_ptr channel = + CreateChannel(server_address_.str(), InsecureChannelCredentials()); + auto stub = grpc::testing::duplicate::EchoTestService::NewStub(channel); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_wait_for_ready(true); + request.set_message("hello"); + + auto stream = stub->ResponseStream(&context, request); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "0_dup"); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "1_dup"); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "2_dup"); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); + } + void SendBidiStreaming() { EchoRequest request; EchoResponse response; @@ -498,6 +521,140 @@ TEST_F(HybridEnd2endTest, request_stream_handler_thread.join(); } +// Add a second service with one sync split server streaming method. +class SplitResponseStreamDupPkg + : public duplicate::EchoTestService:: + WithSplitStreamingMethod_ResponseStream { + public: + Status StreamedResponseStream( + ServerContext* context, + ServerSplitStreamer* stream) GRPC_OVERRIDE { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Split Streamed Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + for (int i = 0; i < kNumResponseStreamsMsgs; i++) { + resp.set_message(req.message() + grpc::to_string(i) + "_dup"); + GPR_ASSERT(stream->Write(resp)); + } + return Status::OK; + } +}; + +TEST_F(HybridEnd2endTest, + AsyncRequestStreamResponseStream_SyncSplitStreamedDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream> + SType; + SType service; + SplitResponseStreamDupPkg dup_service; + SetUpServer(&service, &dup_service, nullptr, 8192); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming, + &service, cqs_[1].get()); + TestAllMethods(); + SendSimpleServerStreamingToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service that is fully split server streamed +class FullySplitStreamedDupPkg + : public duplicate::EchoTestService::SplitStreamedService { + public: + Status StreamedResponseStream( + ServerContext* context, + ServerSplitStreamer* stream) GRPC_OVERRIDE { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Split Streamed Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + for (int i = 0; i < kNumResponseStreamsMsgs; i++) { + resp.set_message(req.message() + grpc::to_string(i) + "_dup"); + GPR_ASSERT(stream->Write(resp)); + } + return Status::OK; + } +}; + +TEST_F(HybridEnd2endTest, + AsyncRequestStreamResponseStream_FullySplitStreamedDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream> + SType; + SType service; + FullySplitStreamedDupPkg dup_service; + SetUpServer(&service, &dup_service, nullptr, 8192); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming, + &service, cqs_[1].get()); + TestAllMethods(); + SendSimpleServerStreamingToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service that is fully server streamed +class FullyStreamedDupPkg : public duplicate::EchoTestService::StreamedService { + public: + Status StreamedEcho(ServerContext* context, + ServerUnaryStreamer* stream) + GRPC_OVERRIDE { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Streamed Unary Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + resp.set_message(req.message() + "_dup"); + GPR_ASSERT(stream->Write(resp)); + return Status::OK; + } + Status StreamedResponseStream( + ServerContext* context, + ServerSplitStreamer* stream) GRPC_OVERRIDE { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Split Streamed Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + for (int i = 0; i < kNumResponseStreamsMsgs; i++) { + resp.set_message(req.message() + grpc::to_string(i) + "_dup"); + GPR_ASSERT(stream->Write(resp)); + } + return Status::OK; + } +}; + +TEST_F(HybridEnd2endTest, + AsyncRequestStreamResponseStream_FullyStreamedDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream> + SType; + SType service; + FullyStreamedDupPkg dup_service; + SetUpServer(&service, &dup_service, nullptr, 8192); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming, + &service, cqs_[1].get()); + TestAllMethods(); + SendEchoToDupService(); + SendSimpleServerStreamingToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + // Add a second service with one async method. TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream_AsyncDupService) { typedef EchoTestService::WithAsyncMethod_RequestStream< diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index 245e27b2bba..4197ba8bab2 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -80,7 +80,7 @@ DEFINE_string(test_case, "large_unary", "slow client consumer;\n" "status_code_and_message: verify status code & message;\n" "timeout_on_sleeping_server: deadline exceeds on stream;\n" - "unimplemented_method: client calls an unimplemented_method;\n"); + "unimplemented_method: client calls an unimplemented method;\n"); DEFINE_string(default_service_account, "", "Email of GCE default service account"); DEFINE_string(service_account_key_file, "", diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc index f95d8c6ef6d..1668589cc4a 100644 --- a/test/cpp/interop/interop_client.cc +++ b/test/cpp/interop/interop_client.cc @@ -1010,7 +1010,7 @@ bool InteropClient::DoUnimplementedMethod() { ClientContext context; Status s = - serviceStub_.Get()->UnimplementedMethod(&context, request, &response); + serviceStub_.Get()->UnimplementedCall(&context, request, &response); if (!AssertStatusCode(s, StatusCode::UNIMPLEMENTED)) { return false; diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py index 6f8cad279c8..cf3762dbb8d 100755 --- a/tools/codegen/core/gen_static_metadata.py +++ b/tools/codegen/core/gen_static_metadata.py @@ -110,7 +110,7 @@ CONFIG = [ ('if-unmodified-since', ''), ('last-modified', ''), ('lb-token', ''), - ('lb-cost', ''), + ('lb-cost-bin', ''), ('link', ''), ('location', ''), ('max-forwards', ''), diff --git a/tools/run_tests/filter_pull_request_tests.py b/tools/run_tests/filter_pull_request_tests.py index 55dab42f8a7..e2027a23402 100644 --- a/tools/run_tests/filter_pull_request_tests.py +++ b/tools/run_tests/filter_pull_request_tests.py @@ -36,18 +36,16 @@ from subprocess import call, check_output class TestSuite: """ - Contains tag to identify job as belonging to this test suite and + Contains label to identify job as belonging to this test suite and triggers to identify if changed files are relevant """ - def __init__(self, tags): + def __init__(self, labels): """ - Build TestSuite to group tests by their tags - :param tag: string used to identify if a job belongs to this TestSuite - todo(mattkwong): Change the use of tag because do not want to depend on - job.shortname to identify what suite a test belongs to + Build TestSuite to group tests based on labeling + :param label: strings that should match a jobs's platform, config, language, or test group """ self.triggers = [] - self.tags = tags + self.labels = labels def add_trigger(self, trigger): """ @@ -56,46 +54,75 @@ class TestSuite: """ self.triggers.append(trigger) + # Create test suites -_core_test_suite = TestSuite(['_c_']) -_cpp_test_suite = TestSuite(['_c++_']) -_csharp_test_suite = TestSuite(['_csharp_']) -_node_test_suite = TestSuite(['_node_']) -_objc_test_suite = TestSuite(['_objc_']) -_php_test_suite = TestSuite(['_php_', '_php7_']) -_python_test_suite = TestSuite(['_python_']) -_ruby_test_suite = TestSuite(['_ruby']) -_all_test_suites = [_core_test_suite, _cpp_test_suite, _csharp_test_suite, - _node_test_suite, _objc_test_suite, _php_test_suite, - _python_test_suite, _ruby_test_suite] +_SANITY_TEST_SUITE = TestSuite(['sanity']) +_CORE_TEST_SUITE = TestSuite(['c']) +_CPP_TEST_SUITE = TestSuite(['c++']) +_CSHARP_TEST_SUITE = TestSuite(['csharp']) +_NODE_TEST_SUITE = TestSuite(['node']) +_OBJC_TEST_SUITE = TestSuite(['objc']) +_PHP_TEST_SUITE = TestSuite(['php', 'php7']) +_PYTHON_TEST_SUITE = TestSuite(['python']) +_RUBY_TEST_SUITE = TestSuite(['ruby']) +_LINUX_TEST_SUITE = TestSuite(['linux']) +_WINDOWS_TEST_SUITE = TestSuite(['windows']) +_MACOS_TEST_SUITE = TestSuite(['macos']) +_ALL_TEST_SUITES = [_SANITY_TEST_SUITE, _CORE_TEST_SUITE, _CPP_TEST_SUITE, + _CSHARP_TEST_SUITE, _NODE_TEST_SUITE, _OBJC_TEST_SUITE, + _PHP_TEST_SUITE, _PYTHON_TEST_SUITE, _RUBY_TEST_SUITE, + _LINUX_TEST_SUITE, _WINDOWS_TEST_SUITE, _MACOS_TEST_SUITE] # Dictionary of whitelistable files where the key is a regex matching changed files # and the value is a list of tests that should be run. An empty list means that # the changed files should not trigger any tests. Any changed file that does not # match any of these regexes will trigger all tests _WHITELIST_DICT = { - '^templates/.*': [], - '^doc/.*': [], - '^examples/.*': [], - '^summerofcode/.*': [], - '.*README.md$': [], - '.*LICENSE$': [], - '^src/cpp.*': [_cpp_test_suite], - '^src/csharp.*': [_csharp_test_suite], - '^src/node.*': [_node_test_suite], - '^src/objective-c.*': [_objc_test_suite], - '^src/php.*': [_php_test_suite], - '^src/python.*': [_python_test_suite], - '^src/ruby.*': [_ruby_test_suite], - '^test/core.*': [_core_test_suite], - '^test/cpp.*': [_cpp_test_suite], - '^test/distrib/cpp.*': [_cpp_test_suite], - '^test/distrib/csharp.*': [_csharp_test_suite], - '^test/distrib/node.*': [_node_test_suite], - '^test/distrib/php.*': [_php_test_suite], - '^test/distrib/python.*': [_python_test_suite], - '^test/distrib/ruby.*': [_ruby_test_suite] + '^doc/': [], + '^examples/': [], + '^include/grpc\+\+/': [_CPP_TEST_SUITE], + '^summerofcode/': [], + '^src/cpp/': [_CPP_TEST_SUITE], + '^src/csharp/': [_CSHARP_TEST_SUITE], + '^src/node/': [_NODE_TEST_SUITE], + '^src/objective\-c/': [_OBJC_TEST_SUITE], + '^src/php/': [_PHP_TEST_SUITE], + '^src/python/': [_PYTHON_TEST_SUITE], + '^src/ruby/': [_RUBY_TEST_SUITE], + '^templates/': [_SANITY_TEST_SUITE], + '^test/core/': [_CORE_TEST_SUITE], + '^test/cpp/': [_CPP_TEST_SUITE], + '^test/distrib/cpp/': [_CPP_TEST_SUITE], + '^test/distrib/csharp/': [_CSHARP_TEST_SUITE], + '^test/distrib/node/': [_NODE_TEST_SUITE], + '^test/distrib/php/': [_PHP_TEST_SUITE], + '^test/distrib/python/': [_PYTHON_TEST_SUITE], + '^test/distrib/ruby/': [_RUBY_TEST_SUITE], + '^vsprojects/': [_WINDOWS_TEST_SUITE], + 'binding\.gyp$': [_NODE_TEST_SUITE], + 'composer\.json$': [_PHP_TEST_SUITE], + 'config\.m4$': [_PHP_TEST_SUITE], + 'CONTRIBUTING\.md$': [], + 'Gemfile$': [_RUBY_TEST_SUITE], + 'grpc.def$': [_WINDOWS_TEST_SUITE], + 'grpc\.gemspec$': [_RUBY_TEST_SUITE], + 'gRPC\.podspec$': [_OBJC_TEST_SUITE], + 'gRPC\-Core\.podspec$': [_OBJC_TEST_SUITE], + 'gRPC\-ProtoRPC\.podspec$': [_OBJC_TEST_SUITE], + 'gRPC\-RxLibrary\.podspec$': [_OBJC_TEST_SUITE], + 'INSTALL\.md$': [], + 'LICENSE$': [], + 'MANIFEST\.md$': [], + 'package\.json$': [_PHP_TEST_SUITE], + 'package\.xml$': [_PHP_TEST_SUITE], + 'PATENTS$': [], + 'PYTHON\-MANIFEST\.in$': [_PYTHON_TEST_SUITE], + 'README\.md$': [], + 'requirements\.txt$': [_PYTHON_TEST_SUITE], + 'setup\.cfg$': [_PYTHON_TEST_SUITE], + 'setup\.py$': [_PYTHON_TEST_SUITE] } + # Add all triggers to their respective test suites for trigger, test_suites in _WHITELIST_DICT.iteritems(): for test_suite in test_suites: @@ -106,10 +133,6 @@ def _get_changed_files(base_branch): """ Get list of changed files between current branch and base of target merge branch """ - # git fetch might need to be called on Jenkins slave - # todo(mattkwong): remove or uncomment below after seeing if Jenkins needs this - # call(['git', 'fetch']) - # Get file changes between branch and merge-base of specified branch # Not combined to be Windows friendly base_commit = check_output(["git", "merge-base", base_branch, "HEAD"]).rstrip() @@ -129,27 +152,17 @@ def _can_skip_tests(file_names, triggers): return True -def _remove_irrelevant_tests(tests, tag): +def _remove_irrelevant_tests(tests, skippable_labels): """ Filters out tests by config or language - will not remove sanitizer tests :param tests: list of all tests generated by run_tests_matrix.py - :param tag: string representing language or config to filter - "_(language)_" or "_(config)" - :return: list of relevant tests - """ - # todo(mattkwong): find a more reliable way to filter tests - don't use shortname - return [test for test in tests if tag not in test.shortname or - any(san_tag in test.shortname for san_tag in ['_asan', '_tsan', '_msan'])] - - -def _remove_sanitizer_tests(tests): - """ - Filters out sanitizer tests - :param tests: list of all tests generated by run_tests_matrix.py + :param skippable_labels: list of languages and platforms with skippable tests :return: list of relevant tests """ - # todo(mattkwong): find a more reliable way to filter tests - don't use shortname - return [test for test in tests if - all(san_tag not in test.shortname for san_tag in ['_asan', '_tsan', '_msan'])] + # test.labels[0] is platform and test.labels[2] is language + # We skip a test if both are considered safe to skip + return [test for test in tests if test.labels[0] not in skippable_labels or \ + test.labels[2] not in skippable_labels] def filter_tests(tests, base_branch): @@ -158,7 +171,7 @@ def filter_tests(tests, base_branch): :param tests: list of all tests generated by run_tests_matrix.py :return: list of relevant tests """ - print("Finding file differences between %s repo and current branch...\n" % base_branch) + print("Finding file differences between gRPC %s branch and pull request...\n" % base_branch) changed_files = _get_changed_files(base_branch) for changed_file in changed_files: print(changed_file) @@ -170,15 +183,13 @@ def filter_tests(tests, base_branch): for changed_file in changed_files: if not re.match(all_triggers, changed_file): return(tests) - # Filter out tests by language - for test_suite in _all_test_suites: + # Figure out which language and platform tests to run + skippable_labels = [] + for test_suite in _ALL_TEST_SUITES: if _can_skip_tests(changed_files, test_suite.triggers): - for tag in test_suite.tags: - print(" Filtering %s tests" % tag) - tests = _remove_irrelevant_tests(tests, tag) - # Sanitizer tests skipped if core and c++ are skipped - if _can_skip_tests(changed_files, _cpp_test_suite.triggers + _core_test_suite.triggers): - print(" Filtering Sanitizer tests") - tests = _remove_sanitizer_tests(tests) + for label in test_suite.labels: + print(" Filtering %s tests" % label) + skippable_labels.append(label) + tests = _remove_irrelevant_tests(tests, skippable_labels) return tests diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py index 725ca299bd4..e1c1bc65b6b 100644 --- a/tools/run_tests/performance/scenario_config.py +++ b/tools/run_tests/performance/scenario_config.py @@ -219,6 +219,16 @@ class CXXLanguage: server_core_limit=1, async_server_threads=1, secure=secure) + yield _ping_pong_scenario( + 'cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_%s' % + (secstr), + rpc_type='UNARY', + client_type='ASYNC_CLIENT', + server_type='SYNC_SERVER', + unconstrained_client='async', + secure=secure, + categories=smoketest_categories + [SCALABLE]) + for rpc_type in ['unary', 'streaming']: for synchronicity in ['sync', 'async']: yield _ping_pong_scenario( diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index b26bba71be7..b6cd64b4d5b 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -33595,6 +33595,27 @@ "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_secure", "timeout_seconds": 180 }, + { + "args": [ + "--scenarios_json", + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}]}" + ], + "boringssl": true, + "ci_platforms": [ + "linux" + ], + "cpu_cost": 8, + "defaults": "boringssl", + "exclude_configs": [], + "flaky": false, + "language": "c++", + "name": "json_run_localhost", + "platforms": [ + "linux" + ], + "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure", + "timeout_seconds": 180 + }, { "args": [ "--scenarios_json", @@ -33826,6 +33847,27 @@ "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_insecure", "timeout_seconds": 180 }, + { + "args": [ + "--scenarios_json", + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}]}" + ], + "boringssl": true, + "ci_platforms": [ + "linux" + ], + "cpu_cost": 8, + "defaults": "boringssl", + "exclude_configs": [], + "flaky": false, + "language": "c++", + "name": "json_run_localhost", + "platforms": [ + "linux" + ], + "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure", + "timeout_seconds": 180 + }, { "args": [ "--scenarios_json", diff --git a/vsprojects/vcxproj/test/grpc++_test/grpc++_test.vcxproj b/vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj similarity index 65% rename from vsprojects/vcxproj/test/grpc++_test/grpc++_test.vcxproj rename to vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj index 995d60d09ea..cd3e406f9dc 100644 --- a/vsprojects/vcxproj/test/grpc++_test/grpc++_test.vcxproj +++ b/vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj @@ -1,6 +1,5 @@ - Debug @@ -38,12 +37,12 @@ v140 - Application + StaticLibrary true Unicode - Application + StaticLibrary false true Unicode @@ -53,27 +52,15 @@ - - - - grpc++_test - static - Debug - static - Debug grpc++_test - static - Release - static - Release @@ -171,25 +158,13 @@ {C187A093-A0FE-489D-A40A-6E33DE0F9FEB} - - - - - - - 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/grpc++_test/grpc++_test.vcxproj.filters b/vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj.filters similarity index 100% rename from vsprojects/vcxproj/test/grpc++_test/grpc++_test.vcxproj.filters rename to vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj.filters diff --git a/vsprojects/vcxproj/test/server_context_test_spouse_test/server_context_test_spouse_test.vcxproj b/vsprojects/vcxproj/test/server_context_test_spouse_test/server_context_test_spouse_test.vcxproj index 8ba7432824d..9e586c647c7 100644 --- a/vsprojects/vcxproj/test/server_context_test_spouse_test/server_context_test_spouse_test.vcxproj +++ b/vsprojects/vcxproj/test/server_context_test_spouse_test/server_context_test_spouse_test.vcxproj @@ -167,7 +167,7 @@ {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} - + {3D3EAEA9-76C4-0CFE-4718-5A1F6B7F72C8}