diff --git a/BUILD b/BUILD index df082e47787dc909e98f7b7c8a343db13d343a7f..35e8f444963d2e59fd5f510e7e252c21684e33a3 100644 --- a/BUILD +++ b/BUILD @@ -737,6 +737,8 @@ cc_library( "src/compiler/config.h", "src/compiler/cpp_generator.h", "src/compiler/cpp_generator_helpers.h", + "src/compiler/csharp_generator.h", + "src/compiler/csharp_generator_helpers.h", "src/compiler/generator_helpers.h", "src/compiler/objective_c_generator.h", "src/compiler/objective_c_generator_helpers.h", @@ -746,6 +748,7 @@ cc_library( "src/compiler/ruby_generator_map-inl.h", "src/compiler/ruby_generator_string-inl.h", "src/compiler/cpp_generator.cc", + "src/compiler/csharp_generator.cc", "src/compiler/objective_c_generator.cc", "src/compiler/python_generator.cc", "src/compiler/ruby_generator.cc", @@ -793,6 +796,18 @@ cc_binary( ) +cc_binary( + name = "grpc_csharp_plugin", + srcs = [ + "src/compiler/csharp_plugin.cc", + ], + deps = [ + "//external:protobuf_compiler", + ":grpc_plugin_support", + ], +) + + cc_binary( name = "grpc_objective_c_plugin", srcs = [ diff --git a/Makefile b/Makefile index e48b38ad1f237cb00970d459996a8f919436e750..d646d85335102eb8deafd232f375cd3841048cd8 100644 --- a/Makefile +++ b/Makefile @@ -490,7 +490,7 @@ endif .SECONDARY = %.pb.h %.pb.cc -PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin +PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin ifeq ($(DEP_MISSING),) all: static shared plugins dep_error: @@ -666,6 +666,7 @@ timers_test: $(BINDIR)/$(CONFIG)/timers_test transport_metadata_test: $(BINDIR)/$(CONFIG)/transport_metadata_test transport_security_test: $(BINDIR)/$(CONFIG)/transport_security_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test +async_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test credentials_test: $(BINDIR)/$(CONFIG)/credentials_test @@ -674,19 +675,23 @@ end2end_test: $(BINDIR)/$(CONFIG)/end2end_test generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin +grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin interop_client: $(BINDIR)/$(CONFIG)/interop_client interop_server: $(BINDIR)/$(CONFIG)/interop_server interop_test: $(BINDIR)/$(CONFIG)/interop_test +mock_test: $(BINDIR)/$(CONFIG)/mock_test pubsub_client: $(BINDIR)/$(CONFIG)/pubsub_client pubsub_publisher_test: $(BINDIR)/$(CONFIG)/pubsub_publisher_test pubsub_subscriber_test: $(BINDIR)/$(CONFIG)/pubsub_subscriber_test qps_driver: $(BINDIR)/$(CONFIG)/qps_driver -qps_smoke_test: $(BINDIR)/$(CONFIG)/qps_smoke_test +qps_test: $(BINDIR)/$(CONFIG)/qps_test qps_worker: $(BINDIR)/$(CONFIG)/qps_worker status_test: $(BINDIR)/$(CONFIG)/status_test +sync_streaming_ping_pong_test: $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test +sync_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test thread_pool_test: $(BINDIR)/$(CONFIG)/thread_pool_test chttp2_fake_security_bad_hostname_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test chttp2_fake_security_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test @@ -1079,7 +1084,7 @@ buildtests: buildtests_c buildtests_cxx buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/census_hash_table_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test $(BINDIR)/$(CONFIG)/census_statistics_performance_test $(BINDIR)/$(CONFIG)/census_statistics_quick_test $(BINDIR)/$(CONFIG)/census_statistics_small_log_test $(BINDIR)/$(CONFIG)/census_stub_test $(BINDIR)/$(CONFIG)/census_window_stats_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_tls_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/timers_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_unsecure_test -buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/cli_call_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/cxx_time_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/generic_end2end_test $(BINDIR)/$(CONFIG)/grpc_cli $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/qps_driver $(BINDIR)/$(CONFIG)/qps_smoke_test $(BINDIR)/$(CONFIG)/qps_worker $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/thread_pool_test +buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/cli_call_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/cxx_time_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/generic_end2end_test $(BINDIR)/$(CONFIG)/grpc_cli $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/mock_test $(BINDIR)/$(CONFIG)/qps_test $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test $(BINDIR)/$(CONFIG)/thread_pool_test test: test_c test_cxx @@ -1829,6 +1834,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing interop_test" $(Q) $(BINDIR)/$(CONFIG)/interop_test || ( echo test interop_test failed ; exit 1 ) + $(E) "[RUN] Testing mock_test" + $(Q) $(BINDIR)/$(CONFIG)/mock_test || ( echo test mock_test failed ; exit 1 ) $(E) "[RUN] Testing status_test" $(Q) $(BINDIR)/$(CONFIG)/status_test || ( echo test status_test failed ; exit 1 ) $(E) "[RUN] Testing thread_pool_test" @@ -1840,7 +1847,7 @@ test_python: static_c $(Q) tools/run_tests/run_tests.py -lpython -c$(CONFIG) -tools: privatelibs $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token +tools: privatelibs $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token $(BINDIR)/$(CONFIG)/qps_driver $(BINDIR)/$(CONFIG)/qps_worker buildbenchmarks: privatelibs $(BINDIR)/$(CONFIG)/grpc_completion_queue_benchmark $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark @@ -2243,6 +2250,8 @@ else $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(prefix)/bin/grpc_cpp_plugin $(Q) $(INSTALL) -d $(prefix)/bin + $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(prefix)/bin/grpc_csharp_plugin + $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(prefix)/bin/grpc_objective_c_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin @@ -3168,6 +3177,7 @@ endif LIBGRPC_PLUGIN_SUPPORT_SRC = \ src/compiler/cpp_generator.cc \ + src/compiler/csharp_generator.cc \ src/compiler/objective_c_generator.cc \ src/compiler/python_generator.cc \ src/compiler/ruby_generator.cc \ @@ -6745,6 +6755,46 @@ endif endif +ASYNC_UNARY_PING_PONG_TEST_SRC = \ + test/cpp/qps/async_unary_ping_pong_test.cc \ + +ASYNC_UNARY_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ASYNC_UNARY_PING_PONG_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/async_unary_ping_pong_test: openssl_dep_error + +else + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/async_unary_ping_pong_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/async_unary_ping_pong_test: $(PROTOBUF_DEP) $(ASYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(ASYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/qps/async_unary_ping_pong_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +deps_async_unary_ping_pong_test: $(ASYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(ASYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep) +endif +endif + + CHANNEL_ARGUMENTS_TEST_SRC = \ test/cpp/client/channel_arguments_test.cc \ @@ -7053,6 +7103,34 @@ ifneq ($(NO_DEPS),true) endif +GRPC_CSHARP_PLUGIN_SRC = \ + src/compiler/csharp_plugin.cc \ + +GRPC_CSHARP_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CSHARP_PLUGIN_SRC)))) + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/grpc_csharp_plugin: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/grpc_csharp_plugin: $(PROTOBUF_DEP) $(GRPC_CSHARP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a + $(E) "[HOSTLD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_CSHARP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_csharp_plugin + +endif + +$(OBJDIR)/$(CONFIG)/src/compiler/csharp_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a +deps_grpc_csharp_plugin: $(GRPC_CSHARP_PLUGIN_OBJS:.o=.dep) + +ifneq ($(NO_DEPS),true) +-include $(GRPC_CSHARP_PLUGIN_OBJS:.o=.dep) +endif + + GRPC_OBJECTIVE_C_PLUGIN_SRC = \ src/compiler/objective_c_plugin.cc \ @@ -7235,6 +7313,46 @@ endif endif +MOCK_TEST_SRC = \ + test/cpp/end2end/mock_test.cc \ + +MOCK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MOCK_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/mock_test: openssl_dep_error + +else + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/mock_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/mock_test: $(PROTOBUF_DEP) $(MOCK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(MOCK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/mock_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/end2end/mock_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +deps_mock_test: $(MOCK_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(MOCK_TEST_OBJS:.o=.dep) +endif +endif + + PUBSUB_CLIENT_SRC = \ examples/pubsub/main.cc \ @@ -7379,7 +7497,7 @@ else $(BINDIR)/$(CONFIG)/qps_driver: $(PROTOBUF_DEP) $(QPS_DRIVER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(QPS_DRIVER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_driver + $(Q) $(LDXX) $(LDFLAGS) $(QPS_DRIVER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_driver endif @@ -7395,15 +7513,15 @@ endif endif -QPS_SMOKE_TEST_SRC = \ - test/cpp/qps/smoke_test.cc \ +QPS_TEST_SRC = \ + test/cpp/qps/qps_test.cc \ -QPS_SMOKE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_SMOKE_TEST_SRC)))) +QPS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL with ALPN. -$(BINDIR)/$(CONFIG)/qps_smoke_test: openssl_dep_error +$(BINDIR)/$(CONFIG)/qps_test: openssl_dep_error else @@ -7412,25 +7530,25 @@ ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. -$(BINDIR)/$(CONFIG)/qps_smoke_test: protobuf_dep_error +$(BINDIR)/$(CONFIG)/qps_test: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/qps_smoke_test: $(PROTOBUF_DEP) $(QPS_SMOKE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/qps_test: $(PROTOBUF_DEP) $(QPS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(QPS_SMOKE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_smoke_test + $(Q) $(LDXX) $(LDFLAGS) $(QPS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_test endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/qps/smoke_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_qps_smoke_test: $(QPS_SMOKE_TEST_OBJS:.o=.dep) +$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +deps_qps_test: $(QPS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(QPS_SMOKE_TEST_OBJS:.o=.dep) +-include $(QPS_TEST_OBJS:.o=.dep) endif endif @@ -7459,7 +7577,7 @@ else $(BINDIR)/$(CONFIG)/qps_worker: $(PROTOBUF_DEP) $(QPS_WORKER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(QPS_WORKER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_worker + $(Q) $(LDXX) $(LDFLAGS) $(QPS_WORKER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_worker endif @@ -7515,6 +7633,86 @@ endif endif +SYNC_STREAMING_PING_PONG_TEST_SRC = \ + test/cpp/qps/sync_streaming_ping_pong_test.cc \ + +SYNC_STREAMING_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SYNC_STREAMING_PING_PONG_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test: openssl_dep_error + +else + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test: $(PROTOBUF_DEP) $(SYNC_STREAMING_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(SYNC_STREAMING_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/qps/sync_streaming_ping_pong_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +deps_sync_streaming_ping_pong_test: $(SYNC_STREAMING_PING_PONG_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(SYNC_STREAMING_PING_PONG_TEST_OBJS:.o=.dep) +endif +endif + + +SYNC_UNARY_PING_PONG_TEST_SRC = \ + test/cpp/qps/sync_unary_ping_pong_test.cc \ + +SYNC_UNARY_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SYNC_UNARY_PING_PONG_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test: openssl_dep_error + +else + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test: $(PROTOBUF_DEP) $(SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/qps/sync_unary_ping_pong_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +deps_sync_unary_ping_pong_test: $(SYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(SYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep) +endif +endif + + THREAD_POOL_TEST_SRC = \ test/cpp/server/thread_pool_test.cc \ diff --git a/build.json b/build.json index 10fd72d99e43b725d9cb6a10dc8c705c2f1002cc..cc2dfe8cb9d35e63377238f03277b8d61551d9b4 100644 --- a/build.json +++ b/build.json @@ -563,6 +563,8 @@ "src/compiler/config.h", "src/compiler/cpp_generator.h", "src/compiler/cpp_generator_helpers.h", + "src/compiler/csharp_generator.h", + "src/compiler/csharp_generator_helpers.h", "src/compiler/generator_helpers.h", "src/compiler/objective_c_generator.h", "src/compiler/objective_c_generator_helpers.h", @@ -574,6 +576,7 @@ ], "src": [ "src/compiler/cpp_generator.cc", + "src/compiler/csharp_generator.cc", "src/compiler/objective_c_generator.cc", "src/compiler/python_generator.cc", "src/compiler/ruby_generator.cc" @@ -1794,6 +1797,24 @@ "gpr" ] }, + { + "name": "async_unary_ping_pong_test", + "build": "test", + "run": false, + "language": "c++", + "src": [ + "test/cpp/qps/async_unary_ping_pong_test.cc" + ], + "deps": [ + "qps", + "grpc++_test_util", + "grpc_test_util", + "grpc++", + "grpc", + "gpr_test_util", + "gpr" + ] + }, { "name": "channel_arguments_test", "build": "test", @@ -1913,6 +1934,18 @@ ], "secure": "no" }, + { + "name": "grpc_csharp_plugin", + "build": "protoc", + "language": "c++", + "src": [ + "src/compiler/csharp_plugin.cc" + ], + "deps": [ + "grpc_plugin_support" + ], + "secure": "no" + }, { "name": "grpc_objective_c_plugin", "build": "protoc", @@ -1999,6 +2032,22 @@ "gpr" ] }, + { + "name": "mock_test", + "build": "test", + "language": "c++", + "src": [ + "test/cpp/end2end/mock_test.cc" + ], + "deps": [ + "grpc++_test_util", + "grpc_test_util", + "grpc++", + "grpc", + "gpr_test_util", + "gpr" + ] + }, { "name": "pubsub_client", "build": "do_not_build", @@ -2053,8 +2102,7 @@ }, { "name": "qps_driver", - "build": "test", - "run": false, + "build": "tool", "language": "c++", "src": [ "test/cpp/qps/qps_driver.cc" @@ -2071,12 +2119,12 @@ ] }, { - "name": "qps_smoke_test", + "name": "qps_test", "build": "test", "run": false, "language": "c++", "src": [ - "test/cpp/qps/smoke_test.cc" + "test/cpp/qps/qps_test.cc" ], "deps": [ "qps", @@ -2090,8 +2138,7 @@ }, { "name": "qps_worker", - "build": "test", - "run": false, + "build": "tool", "language": "c++", "headers": [ "test/cpp/qps/client.h", @@ -2126,6 +2173,42 @@ "gpr" ] }, + { + "name": "sync_streaming_ping_pong_test", + "build": "test", + "run": false, + "language": "c++", + "src": [ + "test/cpp/qps/sync_streaming_ping_pong_test.cc" + ], + "deps": [ + "qps", + "grpc++_test_util", + "grpc_test_util", + "grpc++", + "grpc", + "gpr_test_util", + "gpr" + ] + }, + { + "name": "sync_unary_ping_pong_test", + "build": "test", + "run": false, + "language": "c++", + "src": [ + "test/cpp/qps/sync_unary_ping_pong_test.cc" + ], + "deps": [ + "qps", + "grpc++_test_util", + "grpc_test_util", + "grpc++", + "grpc", + "gpr_test_util", + "gpr" + ] + }, { "name": "thread_pool_test", "build": "test", diff --git a/include/grpc++/async_unary_call.h b/include/grpc++/async_unary_call.h index d1d5be5b50e37b13e76bd383efd72a004eb63fe4..97cec77955c63016686612fab84901d14230709d 100644 --- a/include/grpc++/async_unary_call.h +++ b/include/grpc++/async_unary_call.h @@ -44,8 +44,19 @@ #include <grpc/support/log.h> namespace grpc { + +template <class R> +class ClientAsyncResponseReaderInterface { + public: + virtual ~ClientAsyncResponseReaderInterface() {} + virtual void ReadInitialMetadata(void* tag) = 0; + virtual void Finish(R* msg, Status* status, void* tag) = 0; + +}; + template <class R> -class ClientAsyncResponseReader GRPC_FINAL { +class ClientAsyncResponseReader GRPC_FINAL + : public ClientAsyncResponseReaderInterface<R> { public: ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, diff --git a/include/grpc++/stream.h b/include/grpc++/stream.h index 6647e345c0c314334fd58b9853f5b71c7cf76621..0efdbdaecae463fa7040a2062cfc537759fbfdf0 100644 --- a/include/grpc++/stream.h +++ b/include/grpc++/stream.h @@ -83,8 +83,14 @@ class WriterInterface { }; template <class R> -class ClientReader GRPC_FINAL : public ClientStreamingInterface, - public ReaderInterface<R> { +class ClientReaderInterface : public ClientStreamingInterface, + public ReaderInterface<R> { + public: + virtual void WaitForInitialMetadata() = 0; +}; + +template <class R> +class ClientReader GRPC_FINAL : public ClientReaderInterface<R> { public: // Blocking create a stream and write the first request out. ClientReader(ChannelInterface* channel, const RpcMethod& method, @@ -111,7 +117,7 @@ class ClientReader GRPC_FINAL : public ClientStreamingInterface, GPR_ASSERT(cq_.Pluck(&buf)); } - virtual bool Read(R* msg) GRPC_OVERRIDE { + bool Read(R* msg) GRPC_OVERRIDE { CallOpBuffer buf; if (!context_->initial_metadata_received_) { buf.AddRecvInitialMetadata(context_); @@ -121,7 +127,7 @@ class ClientReader GRPC_FINAL : public ClientStreamingInterface, return cq_.Pluck(&buf) && buf.got_message; } - virtual Status Finish() GRPC_OVERRIDE { + Status Finish() GRPC_OVERRIDE { CallOpBuffer buf; Status status; buf.AddClientRecvStatus(context_, &status); @@ -137,8 +143,14 @@ class ClientReader GRPC_FINAL : public ClientStreamingInterface, }; template <class W> -class ClientWriter GRPC_FINAL : public ClientStreamingInterface, - public WriterInterface<W> { +class ClientWriterInterface : public ClientStreamingInterface, + public WriterInterface<W> { + public: + virtual bool WritesDone() = 0; +}; + +template <class W> +class ClientWriter GRPC_FINAL : public ClientWriterInterface<W> { public: // Blocking create a stream. ClientWriter(ChannelInterface* channel, const RpcMethod& method, @@ -152,14 +164,14 @@ class ClientWriter GRPC_FINAL : public ClientStreamingInterface, cq_.Pluck(&buf); } - virtual bool Write(const W& msg) GRPC_OVERRIDE { + bool Write(const W& msg) GRPC_OVERRIDE { CallOpBuffer buf; buf.AddSendMessage(msg); call_.PerformOps(&buf); return cq_.Pluck(&buf); } - virtual bool WritesDone() { + bool WritesDone() GRPC_OVERRIDE { CallOpBuffer buf; buf.AddClientSendClose(); call_.PerformOps(&buf); @@ -167,7 +179,7 @@ class ClientWriter GRPC_FINAL : public ClientStreamingInterface, } // Read the final response and wait for the final status. - virtual Status Finish() GRPC_OVERRIDE { + Status Finish() GRPC_OVERRIDE { CallOpBuffer buf; Status status; buf.AddRecvMessage(response_); @@ -186,9 +198,16 @@ class ClientWriter GRPC_FINAL : public ClientStreamingInterface, // Client-side interface for bi-directional streaming. template <class W, class R> -class ClientReaderWriter GRPC_FINAL : public ClientStreamingInterface, - public WriterInterface<W>, - public ReaderInterface<R> { +class ClientReaderWriterInterface : public ClientStreamingInterface, + public WriterInterface<W>, + public ReaderInterface<R> { + public: + virtual void WaitForInitialMetadata() = 0; + virtual bool WritesDone() = 0; +}; + +template <class W, class R> +class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> { public: // Blocking create a stream. ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method, @@ -213,7 +232,7 @@ class ClientReaderWriter GRPC_FINAL : public ClientStreamingInterface, GPR_ASSERT(cq_.Pluck(&buf)); } - virtual bool Read(R* msg) GRPC_OVERRIDE { + bool Read(R* msg) GRPC_OVERRIDE { CallOpBuffer buf; if (!context_->initial_metadata_received_) { buf.AddRecvInitialMetadata(context_); @@ -223,21 +242,21 @@ class ClientReaderWriter GRPC_FINAL : public ClientStreamingInterface, return cq_.Pluck(&buf) && buf.got_message; } - virtual bool Write(const W& msg) GRPC_OVERRIDE { + bool Write(const W& msg) GRPC_OVERRIDE { CallOpBuffer buf; buf.AddSendMessage(msg); call_.PerformOps(&buf); return cq_.Pluck(&buf); } - virtual bool WritesDone() { + bool WritesDone() GRPC_OVERRIDE { CallOpBuffer buf; buf.AddClientSendClose(); call_.PerformOps(&buf); return cq_.Pluck(&buf); } - virtual Status Finish() GRPC_OVERRIDE { + Status Finish() GRPC_OVERRIDE { CallOpBuffer buf; Status status; buf.AddClientRecvStatus(context_, &status); @@ -267,7 +286,7 @@ class ServerReader GRPC_FINAL : public ReaderInterface<R> { call_->cq()->Pluck(&buf); } - virtual bool Read(R* msg) GRPC_OVERRIDE { + bool Read(R* msg) GRPC_OVERRIDE { CallOpBuffer buf; buf.AddRecvMessage(msg); call_->PerformOps(&buf); @@ -294,7 +313,7 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> { call_->cq()->Pluck(&buf); } - virtual bool Write(const W& msg) GRPC_OVERRIDE { + bool Write(const W& msg) GRPC_OVERRIDE { CallOpBuffer buf; if (!ctx_->sent_initial_metadata_) { buf.AddSendInitialMetadata(&ctx_->initial_metadata_); @@ -327,14 +346,14 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>, call_->cq()->Pluck(&buf); } - virtual bool Read(R* msg) GRPC_OVERRIDE { + bool Read(R* msg) GRPC_OVERRIDE { CallOpBuffer buf; buf.AddRecvMessage(msg); call_->PerformOps(&buf); return call_->cq()->Pluck(&buf) && buf.got_message; } - virtual bool Write(const W& msg) GRPC_OVERRIDE { + bool Write(const W& msg) GRPC_OVERRIDE { CallOpBuffer buf; if (!ctx_->sent_initial_metadata_) { buf.AddSendInitialMetadata(&ctx_->initial_metadata_); @@ -380,8 +399,12 @@ class AsyncWriterInterface { }; template <class R> -class ClientAsyncReader GRPC_FINAL : public ClientAsyncStreamingInterface, - public AsyncReaderInterface<R> { +class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface, + public AsyncReaderInterface<R> { +}; + +template <class R> +class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> { public: // Create a stream and write the first request out. ClientAsyncReader(ChannelInterface* channel, CompletionQueue* cq, @@ -431,8 +454,14 @@ class ClientAsyncReader GRPC_FINAL : public ClientAsyncStreamingInterface, }; template <class W> -class ClientAsyncWriter GRPC_FINAL : public ClientAsyncStreamingInterface, - public AsyncWriterInterface<W> { +class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface, + public AsyncWriterInterface<W> { + public: + virtual void WritesDone(void* tag) = 0; +}; + +template <class W> +class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> { public: ClientAsyncWriter(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, @@ -459,7 +488,7 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncStreamingInterface, call_.PerformOps(&write_buf_); } - void WritesDone(void* tag) { + void WritesDone(void* tag) GRPC_OVERRIDE { writes_done_buf_.Reset(tag); writes_done_buf_.AddClientSendClose(); call_.PerformOps(&writes_done_buf_); @@ -488,9 +517,16 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncStreamingInterface, // Client-side interface for bi-directional streaming. template <class W, class R> -class ClientAsyncReaderWriter GRPC_FINAL : public ClientAsyncStreamingInterface, - public AsyncWriterInterface<W>, - public AsyncReaderInterface<R> { +class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface, + public AsyncWriterInterface<W>, + public AsyncReaderInterface<R> { + public: + virtual void WritesDone(void* tag) = 0; +}; + +template <class W, class R> +class ClientAsyncReaderWriter GRPC_FINAL + : public ClientAsyncReaderWriterInterface<W, R> { public: ClientAsyncReaderWriter(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, @@ -524,7 +560,7 @@ class ClientAsyncReaderWriter GRPC_FINAL : public ClientAsyncStreamingInterface, call_.PerformOps(&write_buf_); } - void WritesDone(void* tag) { + void WritesDone(void* tag) GRPC_OVERRIDE { writes_done_buf_.Reset(tag); writes_done_buf_.AddClientSendClose(); call_.PerformOps(&writes_done_buf_); @@ -671,13 +707,13 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface, call_.PerformOps(&meta_buf_); } - virtual void Read(R* msg, void* tag) GRPC_OVERRIDE { + void Read(R* msg, void* tag) GRPC_OVERRIDE { read_buf_.Reset(tag); read_buf_.AddRecvMessage(msg); call_.PerformOps(&read_buf_); } - virtual void Write(const W& msg, void* tag) GRPC_OVERRIDE { + void Write(const W& msg, void* tag) GRPC_OVERRIDE { write_buf_.Reset(tag); if (!ctx_->sent_initial_metadata_) { write_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_); diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index 735e7e58a82194fddf0d8e967c41a971c1e35570..a0c9d3d46853f89ebb2133a8f0a7b15db3c43804 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -156,50 +156,16 @@ grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file, "#include <grpc++/impl/internal_stub.h>\n" "#include <grpc++/impl/rpc_method.h>\n" "#include <grpc++/impl/service_type.h>\n" + "#include <grpc++/async_unary_call.h>\n" "#include <grpc++/status.h>\n" + "#include <grpc++/stream.h>\n" "\n" "namespace grpc {\n" "class CompletionQueue;\n" "class ChannelInterface;\n" "class RpcService;\n" - "class ServerContext;\n"; - if (HasUnaryCalls(file)) { - temp.append( - "template <class OutMessage> class ClientAsyncResponseReader;\n"); - temp.append( - "template <class OutMessage> class ServerAsyncResponseWriter;\n"); - } - if (HasClientOnlyStreaming(file)) { - temp.append("template <class OutMessage> class ClientWriter;\n"); - temp.append("template <class InMessage> class ServerReader;\n"); - temp.append("template <class OutMessage> class ClientAsyncWriter;\n"); - temp.append( - "template <class OutMessage, class InMessage> class " - "ServerAsyncReader;\n"); - } - if (HasServerOnlyStreaming(file)) { - temp.append("template <class InMessage> class ClientReader;\n"); - temp.append("template <class OutMessage> class ServerWriter;\n"); - temp.append("template <class OutMessage> class ClientAsyncReader;\n"); - temp.append("template <class InMessage> class ServerAsyncWriter;\n"); - } - if (HasBidiStreaming(file)) { - temp.append( - "template <class OutMessage, class InMessage>\n" - "class ClientReaderWriter;\n"); - temp.append( - "template <class OutMessage, class InMessage>\n" - "class ServerReaderWriter;\n"); - temp.append( - "template <class OutMessage, class InMessage>\n" - "class ClientAsyncReaderWriter;\n"); - temp.append( - "template <class OutMessage, class InMessage>\n" - "class ServerAsyncReaderWriter;\n"); - } - temp.append("} // namespace grpc\n"); - - temp.append("\n"); + "class ServerContext;\n" + "} // namespace grpc\n\n"; if (!file->package().empty()) { std::vector<grpc::string> parts = @@ -216,54 +182,314 @@ grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file, return temp; } +void PrintHeaderClientMethodInterfaces(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map<grpc::string, grpc::string> *vars, + bool is_public) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = + grpc_cpp_generator::ClassName(method->input_type(), true); + (*vars)["Response"] = + grpc_cpp_generator::ClassName(method->output_type(), true); + + if (is_public) { + if (NoStreaming(method)) { + printer->Print( + *vars, + "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, " + "const $Request$& request, $Response$* response) = 0;\n"); + printer->Print( + *vars, + "std::unique_ptr< " + "::grpc::ClientAsyncResponseReaderInterface< $Response$>> " + "Async$Method$(::grpc::ClientContext* context, " + "const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncResponseReaderInterface< $Response$>>(" + "Async$Method$Raw(context, request, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (ClientOnlyStreaming(method)) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>" + " $Method$(" + "::grpc::ClientContext* context, $Response$* response) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>" + "($Method$Raw(context, response));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>" + " Async$Method$(::grpc::ClientContext* context, $Response$* response, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncWriterInterface< $Request$>>(" + "Async$Method$Raw(context, response, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (ServerOnlyStreaming(method)) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>" + " $Method$(::grpc::ClientContext* context, const $Request$& request)" + " {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>" + "($Method$Raw(context, request));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> " + "Async$Method$(" + "::grpc::ClientContext* context, const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncReaderInterface< $Response$>>(" + "Async$Method$Raw(context, request, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (BidiStreaming(method)) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientReaderWriterInterface< $Request$, $Response$>> " + "$Method$(::grpc::ClientContext* context) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>(" + "$Method$Raw(context));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< " + "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> " + "Async$Method$(::grpc::ClientContext* context, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>(" + "Async$Method$Raw(context, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } + } else { + if (NoStreaming(method)) { + printer->Print( + *vars, + "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* " + "Async$Method$Raw(::grpc::ClientContext* context, " + "const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); + } else if (ClientOnlyStreaming(method)) { + printer->Print( + *vars, + "virtual ::grpc::ClientWriterInterface< $Request$>*" + " $Method$Raw(" + "::grpc::ClientContext* context, $Response$* response) = 0;\n"); + printer->Print( + *vars, + "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*" + " Async$Method$Raw(::grpc::ClientContext* context, " + "$Response$* response, " + "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); + } else if (ServerOnlyStreaming(method)) { + printer->Print( + *vars, + "virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request) = 0;\n"); + printer->Print( + *vars, + "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* " + "Async$Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); + } else if (BidiStreaming(method)) { + printer->Print( + *vars, + "virtual ::grpc::ClientReaderWriterInterface< $Request$, $Response$>* " + "$Method$Raw(::grpc::ClientContext* context) = 0;\n"); + printer->Print( + *vars, + "virtual ::grpc::ClientAsyncReaderWriterInterface< " + "$Request$, $Response$>* " + "Async$Method$Raw(::grpc::ClientContext* context, " + "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); + } + } +} + void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer, const grpc::protobuf::MethodDescriptor *method, - std::map<grpc::string, grpc::string> *vars) { + std::map<grpc::string, grpc::string> *vars, + bool is_public) { (*vars)["Method"] = method->name(); (*vars)["Request"] = grpc_cpp_generator::ClassName(method->input_type(), true); (*vars)["Response"] = grpc_cpp_generator::ClassName(method->output_type(), true); - if (NoStreaming(method)) { - printer->Print(*vars, - "::grpc::Status $Method$(::grpc::ClientContext* context, " - "const $Request$& request, $Response$* response);\n"); - printer->Print( - *vars, - "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> " - "Async$Method$(::grpc::ClientContext* context, " - "const $Request$& request, " - "::grpc::CompletionQueue* cq, void* tag);\n"); - } else if (ClientOnlyStreaming(method)) { - printer->Print( - *vars, - "std::unique_ptr< ::grpc::ClientWriter< $Request$>> $Method$(" - "::grpc::ClientContext* context, $Response$* response);\n"); - printer->Print( - *vars, - "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>> Async$Method$(" - "::grpc::ClientContext* context, $Response$* response, " - "::grpc::CompletionQueue* cq, void* tag);\n"); - } else if (ServerOnlyStreaming(method)) { - printer->Print( - *vars, - "std::unique_ptr< ::grpc::ClientReader< $Response$>> $Method$(" - "::grpc::ClientContext* context, const $Request$& request);\n"); - printer->Print(*vars, - "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> " - "Async$Method$(" - "::grpc::ClientContext* context, const $Request$& request, " - "::grpc::CompletionQueue* cq, void* tag);\n"); - } else if (BidiStreaming(method)) { - printer->Print( - *vars, - "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>> " - "$Method$(::grpc::ClientContext* context);\n"); - printer->Print(*vars, - "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< " - "$Request$, $Response$>> " - "Async$Method$(::grpc::ClientContext* context, " - "::grpc::CompletionQueue* cq, void* tag);\n"); + + if (is_public) { + if (NoStreaming(method)) { + printer->Print( + *vars, + "::grpc::Status $Method$(::grpc::ClientContext* context, " + "const $Request$& request, $Response$* response) GRPC_OVERRIDE;\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> " + "Async$Method$(::grpc::ClientContext* context, " + "const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncResponseReader< $Response$>>(" + "Async$Method$Raw(context, request, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (ClientOnlyStreaming(method)) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientWriter< $Request$>>" + " $Method$(" + "::grpc::ClientContext* context, $Response$* response) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>" + "($Method$Raw(context, response));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>" + " Async$Method$(::grpc::ClientContext* context, $Response$* response, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>(" + "Async$Method$Raw(context, response, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (ServerOnlyStreaming(method)) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientReader< $Response$>>" + " $Method$(::grpc::ClientContext* context, const $Request$& request)" + " {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientReader< $Response$>>" + "($Method$Raw(context, request));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> " + "Async$Method$(" + "::grpc::ClientContext* context, const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>(" + "Async$Method$Raw(context, request, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (BidiStreaming(method)) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>" + " $Method$(::grpc::ClientContext* context) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientReaderWriter< $Request$, $Response$>>(" + "$Method$Raw(context));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< " + "$Request$, $Response$>> " + "Async$Method$(::grpc::ClientContext* context, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>(" + "Async$Method$Raw(context, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } + } else { + if (NoStreaming(method)) { + printer->Print( + *vars, + "::grpc::ClientAsyncResponseReader< $Response$>* " + "Async$Method$Raw(::grpc::ClientContext* context, " + "const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); + } else if (ClientOnlyStreaming(method)) { + printer->Print( + *vars, + "::grpc::ClientWriter< $Request$>* $Method$Raw(" + "::grpc::ClientContext* context, $Response$* response) " + "GRPC_OVERRIDE;\n"); + printer->Print( + *vars, + "::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw(" + "::grpc::ClientContext* context, $Response$* response, " + "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); + } else if (ServerOnlyStreaming(method)) { + printer->Print( + *vars, + "::grpc::ClientReader< $Response$>* $Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request)" + " GRPC_OVERRIDE;\n"); + printer->Print( + *vars, + "::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); + } else if (BidiStreaming(method)) { + printer->Print( + *vars, + "::grpc::ClientReaderWriter< $Request$, $Response$>* " + "$Method$Raw(::grpc::ClientContext* context) GRPC_OVERRIDE;\n"); + printer->Print( + *vars, + "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* " + "Async$Method$Raw(::grpc::ClientContext* context, " + "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); + } } } @@ -357,17 +583,36 @@ void PrintHeaderService(grpc::protobuf::io::Printer *printer, // Client side printer->Print( - "class Stub GRPC_FINAL : public ::grpc::InternalStub {\n" + "class StubInterface {\n" " public:\n"); printer->Indent(); + printer->Print("virtual ~StubInterface() {}\n"); + for (int i = 0; i < service->method_count(); ++i) { + PrintHeaderClientMethodInterfaces(printer, service->method(i), vars, true); + } + printer->Outdent(); + printer->Print("private:\n"); + printer->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + PrintHeaderClientMethodInterfaces(printer, service->method(i), vars, false); + } + printer->Outdent(); + printer->Print("};\n"); + printer->Print( + "class Stub GRPC_FINAL : public StubInterface," + " public ::grpc::InternalStub {\n public:\n"); + printer->Indent(); printer->Print( "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n"); for (int i = 0; i < service->method_count(); ++i) { - PrintHeaderClientMethod(printer, service->method(i), vars); + PrintHeaderClientMethod(printer, service->method(i), vars, true); } printer->Outdent(); - printer->Print(" private:\n"); + printer->Print("\n private:\n"); printer->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + PrintHeaderClientMethod(printer, service->method(i), vars, false); + } for (int i = 0; i < service->method_count(); ++i) { PrintHeaderClientMethodData(printer, service->method(i), vars); } @@ -535,93 +780,85 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer, "}\n\n"); printer->Print( *vars, - "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> " - "$ns$$Service$::Stub::Async$Method$(::grpc::ClientContext* context, " + "::grpc::ClientAsyncResponseReader< $Response$>* " + "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, " "const $Request$& request, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Print(*vars, - " return std::unique_ptr< " - "::grpc::ClientAsyncResponseReader< $Response$>>(new " + " return new " "::grpc::ClientAsyncResponseReader< $Response$>(" "channel(), cq, " "rpcmethod_$Method$_, " - "context, request, tag));\n" + "context, request, tag);\n" "}\n\n"); } else if (ClientOnlyStreaming(method)) { printer->Print(*vars, - "std::unique_ptr< ::grpc::ClientWriter< $Request$>> " - "$ns$$Service$::Stub::$Method$(" + "::grpc::ClientWriter< $Request$>* " + "$ns$$Service$::Stub::$Method$Raw(" "::grpc::ClientContext* context, $Response$* response) {\n"); printer->Print(*vars, - " return std::unique_ptr< ::grpc::ClientWriter< " - "$Request$>>(new ::grpc::ClientWriter< $Request$>(" - "channel()," + " return new ::grpc::ClientWriter< $Request$>(" + "channel(), " "rpcmethod_$Method$_, " - "context, response));\n" + "context, response);\n" "}\n\n"); printer->Print(*vars, - "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>> " - "$ns$$Service$::Stub::Async$Method$(" + "::grpc::ClientAsyncWriter< $Request$>* " + "$ns$$Service$::Stub::Async$Method$Raw(" "::grpc::ClientContext* context, $Response$* response, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Print(*vars, - " return std::unique_ptr< ::grpc::ClientAsyncWriter< " - "$Request$>>(new ::grpc::ClientAsyncWriter< $Request$>(" + " return new ::grpc::ClientAsyncWriter< $Request$>(" "channel(), cq, " "rpcmethod_$Method$_, " - "context, response, tag));\n" + "context, response, tag);\n" "}\n\n"); } else if (ServerOnlyStreaming(method)) { printer->Print( *vars, - "std::unique_ptr< ::grpc::ClientReader< $Response$>> " - "$ns$$Service$::Stub::$Method$(" + "::grpc::ClientReader< $Response$>* " + "$ns$$Service$::Stub::$Method$Raw(" "::grpc::ClientContext* context, const $Request$& request) {\n"); printer->Print(*vars, - " return std::unique_ptr< ::grpc::ClientReader< " - "$Response$>>(new ::grpc::ClientReader< $Response$>(" - "channel()," + " return new ::grpc::ClientReader< $Response$>(" + "channel(), " "rpcmethod_$Method$_, " - "context, request));\n" + "context, request);\n" "}\n\n"); printer->Print(*vars, - "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> " - "$ns$$Service$::Stub::Async$Method$(" + "::grpc::ClientAsyncReader< $Response$>* " + "$ns$$Service$::Stub::Async$Method$Raw(" "::grpc::ClientContext* context, const $Request$& request, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Print(*vars, - " return std::unique_ptr< ::grpc::ClientAsyncReader< " - "$Response$>>(new ::grpc::ClientAsyncReader< $Response$>(" + " return new ::grpc::ClientAsyncReader< $Response$>(" "channel(), cq, " "rpcmethod_$Method$_, " - "context, request, tag));\n" + "context, request, tag);\n" "}\n\n"); } else if (BidiStreaming(method)) { printer->Print( *vars, - "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>> " - "$ns$$Service$::Stub::$Method$(::grpc::ClientContext* context) {\n"); + "::grpc::ClientReaderWriter< $Request$, $Response$>* " + "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n"); printer->Print(*vars, - " return std::unique_ptr< ::grpc::ClientReaderWriter< " - "$Request$, $Response$>>(new ::grpc::ClientReaderWriter< " + " return new ::grpc::ClientReaderWriter< " "$Request$, $Response$>(" - "channel()," + "channel(), " "rpcmethod_$Method$_, " - "context));\n" + "context);\n" "}\n\n"); printer->Print( *vars, - "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< " - "$Request$, $Response$>> " - "$ns$$Service$::Stub::Async$Method$(::grpc::ClientContext* context, " + "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* " + "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Print(*vars, - " return std::unique_ptr< ::grpc::ClientAsyncReaderWriter< " - "$Request$, $Response$>>(new " + " return new " "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>(" "channel(), cq, " "rpcmethod_$Method$_, " - "context, tag));\n" + "context, tag);\n" "}\n\n"); } } diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc new file mode 100644 index 0000000000000000000000000000000000000000..82dd06bcec4c39cca7d84b081b4dc5d44bdfe0dc --- /dev/null +++ b/src/compiler/csharp_generator.cc @@ -0,0 +1,480 @@ +/* + * + * 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 <cctype> +#include <map> +#include <vector> + +#include "src/compiler/config.h" +#include "src/compiler/csharp_generator_helpers.h" +#include "src/compiler/csharp_generator.h" + +using grpc::protobuf::FileDescriptor; +using grpc::protobuf::Descriptor; +using grpc::protobuf::ServiceDescriptor; +using grpc::protobuf::MethodDescriptor; +using grpc::protobuf::io::Printer; +using grpc::protobuf::io::StringOutputStream; +using grpc_generator::MethodType; +using grpc_generator::GetMethodType; +using grpc_generator::METHODTYPE_NO_STREAMING; +using grpc_generator::METHODTYPE_CLIENT_STREAMING; +using grpc_generator::METHODTYPE_SERVER_STREAMING; +using grpc_generator::METHODTYPE_BIDI_STREAMING; +using std::map; +using std::vector; + +namespace grpc_csharp_generator { +namespace { + +std::string GetCSharpNamespace(const FileDescriptor* file) { + // TODO(jtattermusch): this should be based on csharp_namespace option + return file->package(); +} + +std::string GetMessageType(const Descriptor* message) { + // TODO(jtattermusch): this has to match with C# protobuf generator + return message->name(); +} + +std::string GetServiceClassName(const ServiceDescriptor* service) { + return service->name(); +} + +std::string GetClientInterfaceName(const ServiceDescriptor* service) { + return "I" + service->name() + "Client"; +} + +std::string GetClientClassName(const ServiceDescriptor* service) { + return service->name() + "Client"; +} + +std::string GetServerInterfaceName(const ServiceDescriptor* service) { + return "I" + service->name(); +} + +std::string GetCSharpMethodType(MethodType method_type) { + switch (method_type) { + case METHODTYPE_NO_STREAMING: + return "MethodType.Unary"; + case METHODTYPE_CLIENT_STREAMING: + return "MethodType.ClientStreaming"; + case METHODTYPE_SERVER_STREAMING: + return "MethodType.ServerStreaming"; + case METHODTYPE_BIDI_STREAMING: + return "MethodType.DuplexStreaming"; + } + GOOGLE_LOG(FATAL)<< "Can't get here."; + return ""; +} + +std::string GetServiceNameFieldName() { + return "__ServiceName"; +} + +std::string GetMarshallerFieldName(const Descriptor *message) { + return "__Marshaller_" + message->name(); +} + +std::string GetMethodFieldName(const MethodDescriptor *method) { + return "__Method_" + method->name(); +} + +std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) { + if (method->client_streaming()) { + return ""; + } + return GetMessageType(method->input_type()) + " request, "; +} + +std::string GetMethodReturnTypeClient(const MethodDescriptor *method) { + switch (GetMethodType(method)) { + case METHODTYPE_NO_STREAMING: + return "Task<" + GetMessageType(method->output_type()) + ">"; + case METHODTYPE_CLIENT_STREAMING: + return "AsyncClientStreamingCall<" + GetMessageType(method->input_type()) + + ", " + GetMessageType(method->output_type()) + ">"; + case METHODTYPE_SERVER_STREAMING: + return "AsyncServerStreamingCall<" + GetMessageType(method->output_type()) + + ">"; + case METHODTYPE_BIDI_STREAMING: + return "AsyncDuplexStreamingCall<" + GetMessageType(method->input_type()) + + ", " + GetMessageType(method->output_type()) + ">"; + } + GOOGLE_LOG(FATAL)<< "Can't get here."; + return ""; +} + +std::string GetMethodRequestParamServer(const MethodDescriptor *method) { + switch (GetMethodType(method)) { + case METHODTYPE_NO_STREAMING: + case METHODTYPE_SERVER_STREAMING: + return GetMessageType(method->input_type()) + " request"; + case METHODTYPE_CLIENT_STREAMING: + case METHODTYPE_BIDI_STREAMING: + return "IAsyncStreamReader<" + GetMessageType(method->input_type()) + + "> requestStream"; + } + GOOGLE_LOG(FATAL)<< "Can't get here."; + return ""; +} + +std::string GetMethodReturnTypeServer(const MethodDescriptor *method) { + switch (GetMethodType(method)) { + case METHODTYPE_NO_STREAMING: + case METHODTYPE_CLIENT_STREAMING: + return "Task<" + GetMessageType(method->output_type()) + ">"; + case METHODTYPE_SERVER_STREAMING: + case METHODTYPE_BIDI_STREAMING: + return "Task"; + } + GOOGLE_LOG(FATAL)<< "Can't get here."; + return ""; +} + +std::string GetMethodResponseStreamMaybe(const MethodDescriptor *method) { + switch (GetMethodType(method)) { + case METHODTYPE_NO_STREAMING: + case METHODTYPE_CLIENT_STREAMING: + return ""; + case METHODTYPE_SERVER_STREAMING: + case METHODTYPE_BIDI_STREAMING: + return ", IServerStreamWriter<" + GetMessageType(method->output_type()) + + "> responseStream"; + } + GOOGLE_LOG(FATAL)<< "Can't get here."; + return ""; +} + +// Gets vector of all messages used as input or output types. +std::vector<const Descriptor*> GetUsedMessages( + const ServiceDescriptor *service) { + std::set<const Descriptor*> descriptor_set; + std::vector<const Descriptor*> result; // vector is to maintain stable ordering + for (int i = 0; i < service->method_count(); i++) { + const MethodDescriptor *method = service->method(i); + if (descriptor_set.find(method->input_type()) == descriptor_set.end()) { + descriptor_set.insert(method->input_type()); + result.push_back(method->input_type()); + } + if (descriptor_set.find(method->output_type()) == descriptor_set.end()) { + descriptor_set.insert(method->output_type()); + result.push_back(method->output_type()); + } + } + return result; +} + +void GenerateMarshallerFields(Printer* out, const ServiceDescriptor *service) { + std::vector<const Descriptor*> used_messages = GetUsedMessages(service); + for (size_t i = 0; i < used_messages.size(); i++) { + const Descriptor *message = used_messages[i]; + out->Print( + "static readonly Marshaller<$type$> $fieldname$ = Marshallers.Create((arg) => arg.ToByteArray(), $type$.ParseFrom);\n", + "fieldname", GetMarshallerFieldName(message), "type", + GetMessageType(message)); + } + out->Print("\n"); +} + +void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) { + out->Print( + "static readonly Method<$request$, $response$> $fieldname$ = new Method<$request$, $response$>(\n", + "fieldname", GetMethodFieldName(method), "request", + GetMessageType(method->input_type()), "response", + GetMessageType(method->output_type())); + out->Indent(); + out->Indent(); + out->Print("$methodtype$,\n", "methodtype", + GetCSharpMethodType(GetMethodType(method))); + out->Print("\"$methodname$\",\n", "methodname", method->name()); + out->Print("$requestmarshaller$,\n", "requestmarshaller", + GetMarshallerFieldName(method->input_type())); + out->Print("$responsemarshaller$);\n", "responsemarshaller", + GetMarshallerFieldName(method->output_type())); + out->Print("\n"); + out->Outdent(); + out->Outdent(); +} + +void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { + out->Print("// client-side stub interface\n"); + out->Print("public interface $name$\n", "name", + GetClientInterfaceName(service)); + out->Print("{\n"); + out->Indent(); + for (int i = 0; i < service->method_count(); i++) { + const MethodDescriptor *method = service->method(i); + MethodType method_type = GetMethodType(method); + + if (method_type == METHODTYPE_NO_STREAMING) { + // unary calls have an extra synchronous stub method + out->Print( + "$response$ $methodname$($request$ request, CancellationToken token = default(CancellationToken));\n", + "methodname", method->name(), "request", + GetMessageType(method->input_type()), "response", + GetMessageType(method->output_type())); + } + + std::string method_name = method->name(); + if (method_type == METHODTYPE_NO_STREAMING) { + method_name += "Async"; // prevent name clash with synchronous method. + } + out->Print( + "$returntype$ $methodname$($request_maybe$CancellationToken token = default(CancellationToken));\n", + "methodname", method_name, "request_maybe", + GetMethodRequestParamMaybe(method), "returntype", + GetMethodReturnTypeClient(method)); + } + out->Outdent(); + out->Print("}\n"); + out->Print("\n"); +} + +void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) { + out->Print("// server-side interface\n"); + out->Print("public interface $name$\n", "name", + GetServerInterfaceName(service)); + out->Print("{\n"); + out->Indent(); + for (int i = 0; i < service->method_count(); i++) { + const MethodDescriptor *method = service->method(i); + out->Print("$returntype$ $methodname$(ServerCallContext context, $request$$response_stream_maybe$);\n", + "methodname", method->name(), "returntype", + GetMethodReturnTypeServer(method), "request", + GetMethodRequestParamServer(method), "response_stream_maybe", + GetMethodResponseStreamMaybe(method)); + } + out->Outdent(); + out->Print("}\n"); + out->Print("\n"); +} + +void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { + out->Print("// client stub\n"); + out->Print( + "public class $name$ : AbstractStub<$name$, StubConfiguration>, $interface$\n", + "name", GetClientClassName(service), "interface", + GetClientInterfaceName(service)); + out->Print("{\n"); + out->Indent(); + + // constructors + out->Print( + "public $name$(Channel channel) : this(channel, StubConfiguration.Default)\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Print("}\n"); + out->Print( + "public $name$(Channel channel, StubConfiguration config) : base(channel, config)\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Print("}\n"); + + for (int i = 0; i < service->method_count(); i++) { + const MethodDescriptor *method = service->method(i); + MethodType method_type = GetMethodType(method); + + if (method_type == METHODTYPE_NO_STREAMING) { + // unary calls have an extra synchronous stub method + out->Print( + "public $response$ $methodname$($request$ request, CancellationToken token = default(CancellationToken))\n", + "methodname", method->name(), "request", + GetMessageType(method->input_type()), "response", + GetMessageType(method->output_type())); + out->Print("{\n"); + out->Indent(); + out->Print("var call = CreateCall($servicenamefield$, $methodfield$);\n", + "servicenamefield", GetServiceNameFieldName(), "methodfield", + GetMethodFieldName(method)); + out->Print("return Calls.BlockingUnaryCall(call, request, token);\n"); + out->Outdent(); + out->Print("}\n"); + } + + std::string method_name = method->name(); + if (method_type == METHODTYPE_NO_STREAMING) { + method_name += "Async"; // prevent name clash with synchronous method. + } + out->Print( + "public $returntype$ $methodname$($request_maybe$CancellationToken token = default(CancellationToken))\n", + "methodname", method_name, "request_maybe", + GetMethodRequestParamMaybe(method), "returntype", + GetMethodReturnTypeClient(method)); + out->Print("{\n"); + out->Indent(); + out->Print("var call = CreateCall($servicenamefield$, $methodfield$);\n", + "servicenamefield", GetServiceNameFieldName(), "methodfield", + GetMethodFieldName(method)); + switch (GetMethodType(method)) { + case METHODTYPE_NO_STREAMING: + out->Print("return Calls.AsyncUnaryCall(call, request, token);\n"); + break; + case METHODTYPE_CLIENT_STREAMING: + out->Print("return Calls.AsyncClientStreamingCall(call, token);\n"); + break; + case METHODTYPE_SERVER_STREAMING: + out->Print( + "return Calls.AsyncServerStreamingCall(call, request, token);\n"); + break; + case METHODTYPE_BIDI_STREAMING: + out->Print("return Calls.AsyncDuplexStreamingCall(call, token);\n"); + break; + default: + GOOGLE_LOG(FATAL)<< "Can't get here."; + } + out->Outdent(); + out->Print("}\n"); + } + out->Outdent(); + out->Print("}\n"); + out->Print("\n"); +} + +void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) { + out->Print( + "// creates service definition that can be registered with a server\n"); + out->Print( + "public static ServerServiceDefinition BindService($interface$ serviceImpl)\n", + "interface", GetServerInterfaceName(service)); + out->Print("{\n"); + out->Indent(); + + out->Print( + "return ServerServiceDefinition.CreateBuilder($servicenamefield$)\n", + "servicenamefield", GetServiceNameFieldName()); + out->Indent(); + out->Indent(); + for (int i = 0; i < service->method_count(); i++) { + const MethodDescriptor *method = service->method(i); + out->Print(".AddMethod($methodfield$, serviceImpl.$methodname$)", + "methodfield", GetMethodFieldName(method), "methodname", + method->name()); + if (i == service->method_count() - 1) { + out->Print(".Build();"); + } + out->Print("\n"); + } + out->Outdent(); + out->Outdent(); + + out->Outdent(); + out->Print("}\n"); + out->Print("\n"); +} + +void GenerateNewStubMethods(Printer* out, const ServiceDescriptor *service) { + out->Print("// creates a new client stub\n"); + out->Print("public static $interface$ NewStub(Channel channel)\n", + "interface", GetClientInterfaceName(service)); + out->Print("{\n"); + out->Indent(); + out->Print("return new $classname$(channel);\n", "classname", + GetClientClassName(service)); + out->Outdent(); + out->Print("}\n"); + out->Print("\n"); + + out->Print("// creates a new client stub\n"); + out->Print( + "public static $interface$ NewStub(Channel channel, StubConfiguration config)\n", + "interface", GetClientInterfaceName(service)); + out->Print("{\n"); + out->Indent(); + out->Print("return new $classname$(channel, config);\n", "classname", + GetClientClassName(service)); + out->Outdent(); + out->Print("}\n"); +} + +void GenerateService(Printer* out, const ServiceDescriptor *service) { + out->Print("public static class $classname$\n", "classname", + GetServiceClassName(service)); + out->Print("{\n"); + out->Indent(); + out->Print("static readonly string $servicenamefield$ = \"$servicename$\";\n", + "servicenamefield", GetServiceNameFieldName(), "servicename", + service->full_name()); + out->Print("\n"); + + GenerateMarshallerFields(out, service); + for (int i = 0; i < service->method_count(); i++) { + GenerateStaticMethodField(out, service->method(i)); + } + GenerateClientInterface(out, service); + GenerateServerInterface(out, service); + GenerateClientStub(out, service); + GenerateBindServiceMethod(out, service); + GenerateNewStubMethods(out, service); + + out->Outdent(); + out->Print("}\n"); +} + +} // anonymous namespace + +grpc::string GetServices(const FileDescriptor *file) { + grpc::string output; + StringOutputStream output_stream(&output); + Printer out(&output_stream, '$'); + + // Don't write out any output if there no services, to avoid empty service + // files being generated for proto files that don't declare any. + if (file->service_count() == 0) { + return output; + } + + // Write out a file header. + out.Print("// Generated by the protocol buffer compiler. DO NOT EDIT!\n"); + out.Print("// source: $filename$\n", "filename", file->name()); + out.Print("#region Designer generated code\n"); + out.Print("\n"); + out.Print("using System;\n"); + out.Print("using System.Threading;\n"); + out.Print("using System.Threading.Tasks;\n"); + out.Print("using Grpc.Core;\n"); + // TODO(jtattermusch): add using for protobuf message classes + out.Print("\n"); + + out.Print("namespace $namespace$ {\n", "namespace", GetCSharpNamespace(file)); + out.Indent(); + for (int i = 0; i < file->service_count(); i++) { + GenerateService(&out, file->service(i)); + } + out.Outdent(); + out.Print("}\n"); + out.Print("#endregion\n"); + return output; +} + +} // namespace grpc_csharp_generator diff --git a/src/compiler/csharp_generator.h b/src/compiler/csharp_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..ec537d3f1d2835c6bea91df798224129d72cf05e --- /dev/null +++ b/src/compiler/csharp_generator.h @@ -0,0 +1,45 @@ +/* + * + * 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_INTERNAL_COMPILER_CSHARP_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H + +#include "src/compiler/config.h" + +namespace grpc_csharp_generator { + +grpc::string GetServices(const grpc::protobuf::FileDescriptor *file); + +} // namespace grpc_csharp_generator + +#endif // GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H diff --git a/src/compiler/csharp_generator_helpers.h b/src/compiler/csharp_generator_helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..137062763374fcf59e44e62a355e2cbb2cee967d --- /dev/null +++ b/src/compiler/csharp_generator_helpers.h @@ -0,0 +1,50 @@ +/* + * + * 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_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H +#define GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H + +#include "src/compiler/config.h" +#include "src/compiler/generator_helpers.h" + +namespace grpc_csharp_generator { + +inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file, + grpc::string *file_name_or_error) { + *file_name_or_error = grpc_generator::FileNameInUpperCamel(file) + "Grpc.cs"; + return true; +} + +} // namespace grpc_csharp_generator + +#endif // GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H diff --git a/src/compiler/csharp_plugin.cc b/src/compiler/csharp_plugin.cc new file mode 100644 index 0000000000000000000000000000000000000000..8b9395f9e2b21af8c5af6e255e27724d14bbbff0 --- /dev/null +++ b/src/compiler/csharp_plugin.cc @@ -0,0 +1,72 @@ +/* + * + * 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. + * + */ + +// Generates C# gRPC service interface out of Protobuf IDL. + +#include <memory> + +#include "src/compiler/config.h" +#include "src/compiler/csharp_generator.h" +#include "src/compiler/csharp_generator_helpers.h" + +class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { + public: + CSharpGrpcGenerator() {} + ~CSharpGrpcGenerator() {} + + bool Generate(const grpc::protobuf::FileDescriptor *file, + const grpc::string ¶meter, + grpc::protobuf::compiler::GeneratorContext *context, + grpc::string *error) const { + grpc::string code = grpc_csharp_generator::GetServices(file); + if (code.size() == 0) { + return true; // don't generate a file if there are no services + } + + // Get output file name. + grpc::string file_name; + if (!grpc_csharp_generator::ServicesFilename(file, &file_name)) { + return false; + } + std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output( + context->Open(file_name)); + grpc::protobuf::io::CodedOutputStream coded_out(output.get()); + coded_out.WriteRaw(code.data(), code.size()); + return true; + } +}; + +int main(int argc, char *argv[]) { + CSharpGrpcGenerator generator; + return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); +} diff --git a/src/compiler/generator_helpers.h b/src/compiler/generator_helpers.h index 374e1374cf4c4a12de9fdabe1f28759d4bf2a671..7ce4ec526c98865a76a84afd4346ce2c6b0c616b 100644 --- a/src/compiler/generator_helpers.h +++ b/src/compiler/generator_helpers.h @@ -116,6 +116,29 @@ inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *f return LowerUnderscoreToUpperCamel(StripProto(file->name())); } +enum MethodType { + METHODTYPE_NO_STREAMING, + METHODTYPE_CLIENT_STREAMING, + METHODTYPE_SERVER_STREAMING, + METHODTYPE_BIDI_STREAMING +}; + +inline MethodType GetMethodType(const grpc::protobuf::MethodDescriptor *method) { + if (method->client_streaming()) { + if (method->server_streaming()) { + return METHODTYPE_BIDI_STREAMING; + } else { + return METHODTYPE_CLIENT_STREAMING; + } + } else { + if (method->server_streaming()) { + return METHODTYPE_SERVER_STREAMING; + } else { + return METHODTYPE_NO_STREAMING; + } + } +} + } // namespace grpc_generator #endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H diff --git a/src/core/iomgr/endpoint_pair_windows.c b/src/core/iomgr/endpoint_pair_windows.c index 58960b6028ae559b8e413d99276d2a554e538811..7c945ebad48608d68cec99031c0a3eb56da08c0b 100644 --- a/src/core/iomgr/endpoint_pair_windows.c +++ b/src/core/iomgr/endpoint_pair_windows.c @@ -68,6 +68,8 @@ static void create_sockets(SOCKET sv[2]) { GPR_ASSERT(svr_sock != INVALID_SOCKET); closesocket(lst_sock); + grpc_tcp_prepare_socket(cli_sock); + grpc_tcp_prepare_socket(svr_sock); sv[1] = cli_sock; sv[0] = svr_sock; diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c index 1cdf3da0d6258338449a32477ec2ecd610adb67f..8827bb99bcbc7414c82f0bb8b4e23c545a083c9e 100644 --- a/src/core/iomgr/iocp_windows.c +++ b/src/core/iomgr/iocp_windows.c @@ -53,6 +53,7 @@ static OVERLAPPED g_iocp_custom_overlap; static gpr_event g_shutdown_iocp; static gpr_event g_iocp_done; static gpr_atm g_orphans = 0; +static gpr_atm g_custom_events = 0; static HANDLE g_iocp; @@ -62,20 +63,19 @@ static void do_iocp_work() { DWORD flags = 0; ULONG_PTR completion_key; LPOVERLAPPED overlapped; - gpr_timespec wait_time = gpr_inf_future; grpc_winsocket *socket; grpc_winsocket_callback_info *info; void(*f)(void *, int) = NULL; void *opaque = NULL; success = GetQueuedCompletionStatus(g_iocp, &bytes, &completion_key, &overlapped, - gpr_time_to_millis(wait_time)); - if (!success && !overlapped) { - /* The deadline got attained. */ - return; - } + INFINITE); + /* success = 0 and overlapped = NULL means the deadline got attained. + Which is impossible. since our wait time is +inf */ + GPR_ASSERT(success || overlapped); GPR_ASSERT(completion_key && overlapped); if (overlapped == &g_iocp_custom_overlap) { + gpr_atm_full_fetch_add(&g_custom_events, -1); if (completion_key == (ULONG_PTR) &g_iocp_kick_token) { /* We were awoken from a kick. */ return; @@ -93,13 +93,17 @@ static void do_iocp_work() { gpr_log(GPR_ERROR, "Unknown IOCP operation"); abort(); } - success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, - FALSE, &flags); + GPR_ASSERT(info->outstanding); if (socket->orphan) { - grpc_winsocket_destroy(socket); - gpr_atm_full_fetch_add(&g_orphans, -1); + info->outstanding = 0; + if (!socket->read_info.outstanding && !socket->write_info.outstanding) { + grpc_winsocket_destroy(socket); + gpr_atm_full_fetch_add(&g_orphans, -1); + } return; } + success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, + FALSE, &flags); info->bytes_transfered = bytes; info->wsa_error = success ? 0 : WSAGetLastError(); GPR_ASSERT(overlapped == &info->overlapped); @@ -117,10 +121,14 @@ static void do_iocp_work() { } static void iocp_loop(void *p) { - while (gpr_atm_acq_load(&g_orphans) || !gpr_event_get(&g_shutdown_iocp)) { + void * eventshutdown = NULL; + while (gpr_atm_acq_load(&g_orphans) || + gpr_atm_acq_load(&g_custom_events) || + !gpr_event_get(&g_shutdown_iocp)) { grpc_maybe_call_delayed_callbacks(NULL, 1); do_iocp_work(); } + gpr_log(GPR_DEBUG, "iocp_loop is done"); gpr_event_set(&g_iocp_done, (void *)1); } @@ -128,8 +136,8 @@ static void iocp_loop(void *p) { void grpc_iocp_init(void) { gpr_thd_id id; - g_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, - (ULONG_PTR)NULL, 0); + g_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, + NULL, (ULONG_PTR)NULL, 0); GPR_ASSERT(g_iocp); gpr_event_init(&g_iocp_done); @@ -140,6 +148,7 @@ void grpc_iocp_init(void) { void grpc_iocp_kick(void) { BOOL success; + gpr_atm_full_fetch_add(&g_custom_events, 1); success = PostQueuedCompletionStatus(g_iocp, 0, (ULONG_PTR) &g_iocp_kick_token, &g_iocp_custom_overlap); diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c index 9306310d435ba5f5b6e5aaf2f2c2415a4f8aca96..35dbfa1587146a5282fec34f0457121526527d17 100644 --- a/src/core/iomgr/socket_windows.c +++ b/src/core/iomgr/socket_windows.c @@ -75,15 +75,14 @@ void grpc_winsocket_shutdown(grpc_winsocket *socket) { /* Abandons a socket. Either we're going to queue it up for garbage collecting from the IO Completion Port thread, or destroy it immediately. Note that this mechanisms assumes that we're either always waiting for an operation, or we - explicitely know that we don't. If there is a future case where we can have + explicitly know that we don't. If there is a future case where we can have an "idle" socket which is neither trying to read or write, we'd start leaking both memory and sockets. */ void grpc_winsocket_orphan(grpc_winsocket *winsocket) { SOCKET socket = winsocket->socket; - if (!winsocket->closed_early) { + if (winsocket->read_info.outstanding || winsocket->write_info.outstanding) { grpc_iocp_socket_orphan(winsocket); - } - if (winsocket->closed_early) { + } else { grpc_winsocket_destroy(winsocket); } closesocket(socket); diff --git a/src/core/iomgr/socket_windows.h b/src/core/iomgr/socket_windows.h index 6e778a776a3bbc43003e3b199a0bc0ec78e2e8fd..8898def85476c360669f366762739f76758a2cdc 100644 --- a/src/core/iomgr/socket_windows.h +++ b/src/core/iomgr/socket_windows.h @@ -65,12 +65,14 @@ typedef struct grpc_winsocket_callback_info { /* The results of the overlapped operation. */ DWORD bytes_transfered; int wsa_error; + /* A boolean indicating that we started an operation. */ + int outstanding; } grpc_winsocket_callback_info; /* This is a wrapper to a Windows socket. A socket can have one outstanding read, and one outstanding write. Doing an asynchronous accept means waiting for a read operation. Doing an asynchronous connect means waiting for a - write operation. These are completely abitrary ties between the operation + write operation. These are completely arbitrary ties between the operation and the kind of event, because we can have one overlapped per pending operation, whichever its nature is. So we could have more dedicated pending operation callbacks for connect and listen. But given the scope of listen @@ -87,17 +89,10 @@ typedef struct grpc_winsocket { /* You can't add the same socket twice to the same IO Completion Port. This prevents that. */ int added_to_iocp; - /* A boolean to indicate that the caller has abandonned that socket, but + /* A boolean to indicate that the caller has abandoned that socket, but there is a pending operation that the IO Completion Port will have to wait for. The socket will be collected at that time. */ int orphan; - /* A boolean to indicate that the socket was already closed somehow, and - that no operation is going to be pending. Trying to abandon a socket in - that state won't result in an orphan, but will instead be destroyed - without further delay. We could avoid that boolean by adding one into - grpc_winsocket_callback_info describing that the operation is pending, - but that 1) waste memory more and 2) obfuscate the intent a bit more. */ - int closed_early; } grpc_winsocket; /* Create a wrapped windows handle. This takes ownership of it, meaning that diff --git a/src/core/iomgr/tcp_client_windows.c b/src/core/iomgr/tcp_client_windows.c index 653c0c65c5157c08208bc1292f75b0966c855ca4..d95346f87ab208adc251346ac49afbdd9688dea2 100644 --- a/src/core/iomgr/tcp_client_windows.c +++ b/src/core/iomgr/tcp_client_windows.c @@ -74,7 +74,7 @@ static void async_connect_cleanup(async_connect *ac) { static void on_alarm(void *acp, int occured) { async_connect *ac = acp; gpr_mu_lock(&ac->mu); - /* If the alarm didn't occor, it got cancelled. */ + /* If the alarm didn't occur, it got cancelled. */ if (ac->socket != NULL && occured) { grpc_winsocket_shutdown(ac->socket); } @@ -98,6 +98,7 @@ static void on_connect(void *acp, int from_iocp) { if (from_iocp) { DWORD transfered_bytes = 0; DWORD flags; + info->outstanding = 0; BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped, &transfered_bytes, FALSE, &flags); @@ -106,10 +107,8 @@ static void on_connect(void *acp, int from_iocp) { char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message); gpr_free(utf8_message); - goto finish; - } else { + } else if (!aborted) { ep = grpc_tcp_create(ac->socket); - goto finish; } } else { gpr_log(GPR_ERROR, "on_connect is shutting down"); @@ -125,20 +124,12 @@ static void on_connect(void *acp, int from_iocp) { return; } - abort(); + ac->socket->write_info.outstanding = 0; -finish: /* If we don't have an endpoint, it means the connection failed, so it doesn't matter if it aborted or failed. We need to orphan that socket. */ - if (!ep || aborted) { - /* If the connection failed, it means we won't get an IOCP notification, - so let's flag it as already closed. But if the connection was aborted, - while we still got an endpoint, we have to wait for the IOCP to collect - that socket. So let's properly flag that. */ - ac->socket->closed_early = !ep; - grpc_winsocket_orphan(ac->socket); - } + if (!ep || aborted) grpc_winsocket_orphan(ac->socket); async_connect_cleanup(ac); /* If the connection was aborted, the callback was already called when the deadline was met. */ @@ -189,7 +180,7 @@ void grpc_tcp_client_connect(void(*cb)(void *arg, grpc_endpoint *tcp), &ioctl_num_bytes, NULL, NULL); if (status != 0) { - message = "Unable to retreive ConnectEx pointer: %s"; + message = "Unable to retrieve ConnectEx pointer: %s"; goto failure; } @@ -204,6 +195,7 @@ void grpc_tcp_client_connect(void(*cb)(void *arg, grpc_endpoint *tcp), socket = grpc_winsocket_create(sock); info = &socket->write_info; + info->outstanding = 1; success = ConnectEx(sock, addr, addr_len, NULL, 0, NULL, &info->overlapped); /* It wouldn't be unusual to get a success immediately. But we'll still get @@ -225,6 +217,7 @@ void grpc_tcp_client_connect(void(*cb)(void *arg, grpc_endpoint *tcp), ac->aborted = 0; grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now()); + socket->write_info.outstanding = 1; grpc_socket_notify_on_write(socket, on_connect, ac); return; @@ -233,7 +226,6 @@ failure: gpr_log(GPR_ERROR, message, utf8_message); gpr_free(utf8_message); if (socket) { - socket->closed_early = 1; grpc_winsocket_orphan(socket); } else if (sock != INVALID_SOCKET) { closesocket(sock); diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c index c6137e1e1d635fd653bcd1e52516126285a0d599..d22acc7453fe342243a0fa31e6e2358fec6d590d 100644 --- a/src/core/iomgr/tcp_server_windows.c +++ b/src/core/iomgr/tcp_server_windows.c @@ -123,7 +123,6 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s, closed by the system. */ for (i = 0; i < s->nports; i++) { server_port *sp = &s->ports[i]; - sp->socket->closed_early = 1; grpc_winsocket_orphan(sp->socket); } gpr_free(s->ports); @@ -249,6 +248,7 @@ static void on_accept(void *arg, int from_iocp) { if (sp->shutting_down) { GPR_ASSERT(from_iocp); sp->shutting_down = 0; + sp->socket->read_info.outstanding = 0; gpr_mu_lock(&sp->server->mu); if (0 == --sp->server->active_ports) { gpr_cv_broadcast(&sp->server->cv); @@ -420,6 +420,7 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollset, s->cb = cb; s->cb_arg = cb_arg; for (i = 0; i < s->nports; i++) { + s->ports[i].socket->read_info.outstanding = 1; start_accept(s->ports + i); s->active_ports++; } diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index c8483bd891cbe73aac0a1faa9e0fe6fe04413b51..f16b4c1268817ffd45e0841581006d97973ed9c0 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -86,12 +86,10 @@ typedef struct grpc_tcp { grpc_endpoint_read_cb read_cb; void *read_user_data; gpr_slice read_slice; - int outstanding_read; grpc_endpoint_write_cb write_cb; void *write_user_data; gpr_slice_buffer write_slices; - int outstanding_write; /* The IO Completion Port runs from another thread. We need some mechanism to protect ourselves when requesting a shutdown. */ @@ -141,14 +139,13 @@ static void on_read(void *tcpp, int from_iocp) { return; } - GPR_ASSERT(tcp->outstanding_read); + GPR_ASSERT(tcp->socket->read_info.outstanding); if (socket->read_info.wsa_error != 0) { char *utf8_message = gpr_format_message(info->wsa_error); gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message); gpr_free(utf8_message); status = GRPC_ENDPOINT_CB_ERROR; - socket->closed_early = 1; } else { if (info->bytes_transfered != 0) { sub = gpr_slice_sub(tcp->read_slice, 0, info->bytes_transfered); @@ -161,7 +158,7 @@ static void on_read(void *tcpp, int from_iocp) { } } - tcp->outstanding_read = 0; + tcp->socket->read_info.outstanding = 0; tcp_unref(tcp); cb(opaque, slice, nslices, status); @@ -175,13 +172,15 @@ static void win_notify_on_read(grpc_endpoint *ep, int status; DWORD bytes_read = 0; DWORD flags = 0; - int error; WSABUF buffer; - GPR_ASSERT(!tcp->outstanding_read); - GPR_ASSERT(!tcp->shutting_down); + GPR_ASSERT(!tcp->socket->read_info.outstanding); + if (tcp->shutting_down) { + cb(arg, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); + return; + } tcp_ref(tcp); - tcp->outstanding_read = 1; + tcp->socket->read_info.outstanding = 1; tcp->read_cb = cb; tcp->read_user_data = arg; @@ -208,34 +207,13 @@ static void win_notify_on_read(grpc_endpoint *ep, status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, &info->overlapped, NULL); - if (status == 0) { - grpc_socket_notify_on_read(tcp->socket, on_read, tcp); - return; - } - - error = WSAGetLastError(); - - if (error != WSA_IO_PENDING) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "WSARecv error: %s - this means we're going to leak.", - utf8_message); - gpr_free(utf8_message); - /* I'm pretty sure this is a very bad situation there. Hence the log. - What will happen now is that the socket will neither wait for read - or write, unless the caller retry, which is unlikely, but I am not - sure if that's guaranteed. And there might also be a write pending. - This means that the future orphanage of that socket will be in limbo, - and we're going to leak it. I have no idea what could cause this - specific case however, aside from a parameter error from our call. - Normal read errors would actually happen during the overlapped - operation, which is the supported way to go for that. */ - tcp->outstanding_read = 0; - tcp_unref(tcp); - cb(arg, NULL, 0, GRPC_ENDPOINT_CB_ERROR); - /* Per the comment above, I'm going to treat that case as a hard failure - for now, and leave the option to catch that and debug. */ - __debugbreak(); - return; + if (status != 0) { + int wsa_error = WSAGetLastError(); + if (wsa_error != WSA_IO_PENDING) { + info->wsa_error = wsa_error; + on_read(tcp, 1); + return; + } } grpc_socket_notify_on_read(tcp->socket, on_read, tcp); @@ -260,7 +238,7 @@ static void on_write(void *tcpp, int from_iocp) { } gpr_mu_unlock(&tcp->mu); - GPR_ASSERT(tcp->outstanding_write); + GPR_ASSERT(tcp->socket->write_info.outstanding); if (do_abort) { if (from_iocp) gpr_slice_buffer_reset_and_unref(&tcp->write_slices); @@ -274,13 +252,12 @@ static void on_write(void *tcpp, int from_iocp) { gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); gpr_free(utf8_message); status = GRPC_ENDPOINT_CB_ERROR; - tcp->socket->closed_early = 1; } else { GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length); } gpr_slice_buffer_reset_and_unref(&tcp->write_slices); - tcp->outstanding_write = 0; + tcp->socket->write_info.outstanding = 0; tcp_unref(tcp); cb(opaque, status); @@ -301,11 +278,13 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, WSABUF *allocated = NULL; WSABUF *buffers = local_buffers; - GPR_ASSERT(!tcp->outstanding_write); - GPR_ASSERT(!tcp->shutting_down); + GPR_ASSERT(!tcp->socket->write_info.outstanding); + if (tcp->shutting_down) { + return GRPC_ENDPOINT_WRITE_ERROR; + } tcp_ref(tcp); - tcp->outstanding_write = 1; + tcp->socket->write_info.outstanding = 1; tcp->write_cb = cb; tcp->write_user_data = arg; @@ -341,7 +320,7 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, } if (allocated) gpr_free(allocated); gpr_slice_buffer_reset_and_unref(&tcp->write_slices); - tcp->outstanding_write = 0; + tcp->socket->write_info.outstanding = 0; tcp_unref(tcp); return ret; } @@ -353,29 +332,12 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, &bytes_sent, 0, &socket->write_info.overlapped, NULL); if (allocated) gpr_free(allocated); - /* It is possible the operation completed then. But we'd still get an IOCP - notification. So let's ignore it and wait for the IOCP. */ if (status != 0) { - int error = WSAGetLastError(); - if (error != WSA_IO_PENDING) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "WSASend error: %s - this means we're going to leak.", - utf8_message); - gpr_free(utf8_message); - /* I'm pretty sure this is a very bad situation there. Hence the log. - What will happen now is that the socket will neither wait for read - or write, unless the caller retry, which is unlikely, but I am not - sure if that's guaranteed. And there might also be a read pending. - This means that the future orphanage of that socket will be in limbo, - and we're going to leak it. I have no idea what could cause this - specific case however, aside from a parameter error from our call. - Normal read errors would actually happen during the overlapped - operation, which is the supported way to go for that. */ - tcp->outstanding_write = 0; + int wsa_error = WSAGetLastError(); + if (wsa_error != WSA_IO_PENDING) { + gpr_slice_buffer_reset_and_unref(&tcp->write_slices); + tcp->socket->write_info.outstanding = 0; tcp_unref(tcp); - /* Per the comment above, I'm going to treat that case as a hard failure - for now, and leave the option to catch that and debug. */ - __debugbreak(); return GRPC_ENDPOINT_WRITE_ERROR; } } diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 9ee91785e8a9e32d263cf88378b6e0c1563403e1..f3658b56c404e4259ae9e5708ee35c8c78e215dc 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -711,6 +711,10 @@ static void call_on_done_recv(void *pc, int success) { break; } } + if (!success) { + grpc_stream_ops_unref_owned_objects(&call->recv_ops.ops[i], + call->recv_ops.nops - i); + } if (call->recv_state == GRPC_STREAM_RECV_CLOSED) { GPR_ASSERT(call->read_state <= READ_STATE_READ_CLOSED); call->read_state = READ_STATE_READ_CLOSED; diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index ea24796f350e046a43db574d261ba3f6f544ac47..a6f9f782a1890d3c26d1b335cd6fb3bddf8a5b83 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -1927,8 +1927,10 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, break; case GRPC_ENDPOINT_CB_OK: lock(t); - for (i = 0; i < nslices && process_read(t, slices[i]); i++) - ; + if (t->cb) { + for (i = 0; i < nslices && process_read(t, slices[i]); i++) + ; + } unlock(t); keep_reading = 1; break; diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index 08c956601c393f97792077ba3440c0a6a2ab1044..1ff9ff4b32b695e24ac90e578afcf92f24c2c359 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -446,8 +446,12 @@ void Server::RunRpc() { ScheduleCallback(); if (ok) { SyncRequest::CallData cd(this, mrd); - mrd->Request(server_); - + { + grpc::unique_lock<grpc::mutex> lock(mu_); + if (!shutdown_) { + mrd->Request(server_); + } + } cd.Run(); } } diff --git a/src/csharp/Grpc.Examples.MathClient/MathClient.cs b/src/csharp/Grpc.Examples.MathClient/MathClient.cs index ca7683d399ff2cfbfd278c3cd171e1d41d6eaa34..85d9cdc7a61468e063042332cce07baa0ad9f501 100644 --- a/src/csharp/Grpc.Examples.MathClient/MathClient.cs +++ b/src/csharp/Grpc.Examples.MathClient/MathClient.cs @@ -43,7 +43,7 @@ namespace math using (Channel channel = new Channel("127.0.0.1:23456")) { - MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel); + Math.IMathClient stub = new Math.MathClient(channel); MathExamples.DivExample(stub); MathExamples.DivAsyncExample(stub).Wait(); diff --git a/src/csharp/Grpc.Examples.MathServer/MathServer.cs b/src/csharp/Grpc.Examples.MathServer/MathServer.cs index cfde9b42c76eb736550686978c3381d66e54d46d..d05e3f28080cc167dcede1f551683c212c13e221 100644 --- a/src/csharp/Grpc.Examples.MathServer/MathServer.cs +++ b/src/csharp/Grpc.Examples.MathServer/MathServer.cs @@ -45,7 +45,7 @@ namespace math GrpcEnvironment.Initialize(); Server server = new Server(); - server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl())); + server.AddServiceDefinition(Math.BindService(new MathServiceImpl())); int port = server.AddListeningPort(host, 23456); server.Start(); diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs index b0f09dd881af412168f321c76a47eb51da9fc2d0..4997d3aa42db68bf1843a355cc23da9d8e1e925a 100644 --- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs +++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs @@ -49,7 +49,7 @@ namespace math.Tests string host = "localhost"; Server server; Channel channel; - MathGrpc.IMathServiceClient client; + Math.IMathClient client; [TestFixtureSetUp] public void Init() @@ -57,7 +57,7 @@ namespace math.Tests GrpcEnvironment.Initialize(); server = new Server(); - server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl())); + server.AddServiceDefinition(Math.BindService(new MathServiceImpl())); int port = server.AddListeningPort(host, Server.PickUnusedPort); server.Start(); channel = new Channel(host + ":" + port); @@ -68,7 +68,7 @@ namespace math.Tests { headerBuilder.Add(new Metadata.MetadataEntry("customHeader", "abcdef")); }); - client = MathGrpc.NewStub(channel, stubConfig); + client = Math.NewStub(channel, stubConfig); } [TestFixtureTearDown] diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs index bb082ec41a015f7ddde1cf500eade4ae46c3a774..ab06a44c0d8e7cafd30acd09583bd3ac8fd54745 100644 --- a/src/csharp/Grpc.Examples/MathExamples.cs +++ b/src/csharp/Grpc.Examples/MathExamples.cs @@ -38,34 +38,34 @@ namespace math { public static class MathExamples { - public static void DivExample(MathGrpc.IMathServiceClient stub) + public static void DivExample(Math.IMathClient stub) { DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build()); Console.WriteLine("Div Result: " + result); } - public static async Task DivAsyncExample(MathGrpc.IMathServiceClient stub) + public static async Task DivAsyncExample(Math.IMathClient stub) { Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build()); DivReply result = await resultTask; Console.WriteLine("DivAsync Result: " + result); } - public static async Task DivAsyncWithCancellationExample(MathGrpc.IMathServiceClient stub) + public static async Task DivAsyncWithCancellationExample(Math.IMathClient stub) { Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build()); DivReply result = await resultTask; Console.WriteLine(result); } - public static async Task FibExample(MathGrpc.IMathServiceClient stub) + public static async Task FibExample(Math.IMathClient stub) { var call = stub.Fib(new FibArgs.Builder { Limit = 5 }.Build()); List<Num> result = await call.ResponseStream.ToList(); Console.WriteLine("Fib Result: " + string.Join("|", result)); } - public static async Task SumExample(MathGrpc.IMathServiceClient stub) + public static async Task SumExample(Math.IMathClient stub) { var numbers = new List<Num> { @@ -79,7 +79,7 @@ namespace math Console.WriteLine("Sum Result: " + await call.Result); } - public static async Task DivManyExample(MathGrpc.IMathServiceClient stub) + public static async Task DivManyExample(Math.IMathClient stub) { var divArgsList = new List<DivArgs> { @@ -92,7 +92,7 @@ namespace math Console.WriteLine("DivMany Result: " + string.Join("|", await call.ResponseStream.ToList())); } - public static async Task DependendRequestsExample(MathGrpc.IMathServiceClient stub) + public static async Task DependendRequestsExample(Math.IMathClient stub) { var numbers = new List<Num> { diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index a6885c4ef4d9f0e8852983945bb5db162cc3e076..2546fd220de0eea34ff422041c1971ce2a0e5ae0 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -1,163 +1,122 @@ -#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 +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: math.proto +#region Designer generated code using System; -using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Grpc.Core; -namespace math -{ - /// <summary> - /// Math service definitions (this is handwritten version of code that will normally be generated). - /// </summary> - public class MathGrpc +namespace math { + public static class Math + { + static readonly string __ServiceName = "math.Math"; + + static readonly Marshaller<DivArgs> __Marshaller_DivArgs = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom); + static readonly Marshaller<DivReply> __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom); + static readonly Marshaller<FibArgs> __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom); + static readonly Marshaller<Num> __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom); + + static readonly Method<DivArgs, DivReply> __Method_Div = new Method<DivArgs, DivReply>( + MethodType.Unary, + "Div", + __Marshaller_DivArgs, + __Marshaller_DivReply); + + static readonly Method<DivArgs, DivReply> __Method_DivMany = new Method<DivArgs, DivReply>( + MethodType.DuplexStreaming, + "DivMany", + __Marshaller_DivArgs, + __Marshaller_DivReply); + + static readonly Method<FibArgs, Num> __Method_Fib = new Method<FibArgs, Num>( + MethodType.ServerStreaming, + "Fib", + __Marshaller_FibArgs, + __Marshaller_Num); + + static readonly Method<Num, Num> __Method_Sum = new Method<Num, Num>( + MethodType.ClientStreaming, + "Sum", + __Marshaller_Num, + __Marshaller_Num); + + // client-side stub interface + public interface IMathClient { - static readonly string ServiceName = "/math.Math"; - - static readonly Marshaller<DivArgs> DivArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom); - static readonly Marshaller<DivReply> DivReplyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom); - static readonly Marshaller<Num> NumMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom); - static readonly Marshaller<FibArgs> FibArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom); - - static readonly Method<DivArgs, DivReply> DivMethod = new Method<DivArgs, DivReply>( - MethodType.Unary, - "Div", - DivArgsMarshaller, - DivReplyMarshaller); - - static readonly Method<FibArgs, Num> FibMethod = new Method<FibArgs, Num>( - MethodType.ServerStreaming, - "Fib", - FibArgsMarshaller, - NumMarshaller); - - static readonly Method<Num, Num> SumMethod = new Method<Num, Num>( - MethodType.ClientStreaming, - "Sum", - NumMarshaller, - NumMarshaller); - - static readonly Method<DivArgs, DivReply> DivManyMethod = new Method<DivArgs, DivReply>( - MethodType.DuplexStreaming, - "DivMany", - DivArgsMarshaller, - DivReplyMarshaller); - - public interface IMathServiceClient - { - DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken)); - - Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken)); - - AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken)); - - AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken)); - - AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken)); - } - - public class MathServiceClientStub : AbstractStub<MathServiceClientStub, StubConfiguration>, IMathServiceClient - { - public MathServiceClientStub(Channel channel) : this(channel, StubConfiguration.Default) - { - } - - public MathServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config) - { - } - - public DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken)) - { - var call = CreateCall(ServiceName, DivMethod); - return Calls.BlockingUnaryCall(call, request, token); - } - - public Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken)) - { - var call = CreateCall(ServiceName, DivMethod); - return Calls.AsyncUnaryCall(call, request, token); - } - - public AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken)) - { - var call = CreateCall(ServiceName, FibMethod); - return Calls.AsyncServerStreamingCall(call, request, token); - } - - public AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken)) - { - var call = CreateCall(ServiceName, SumMethod); - return Calls.AsyncClientStreamingCall(call, token); - } - - public AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken)) - { - var call = CreateCall(ServiceName, DivManyMethod); - return Calls.AsyncDuplexStreamingCall(call, token); - } - } - - // server-side interface - public interface IMathService - { - Task<DivReply> Div(ServerCallContext context, DivArgs request); - - Task Fib(ServerCallContext context, FibArgs request, IServerStreamWriter<Num> responseStream); + DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken)); + Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken)); + AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken)); + AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken)); + AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken)); + } - Task<Num> Sum(ServerCallContext context, IAsyncStreamReader<Num> requestStream); + // server-side interface + public interface IMath + { + Task<DivReply> Div(ServerCallContext context, DivArgs request); + Task DivMany(ServerCallContext context, IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream); + Task Fib(ServerCallContext context, FibArgs request, IServerStreamWriter<Num> responseStream); + Task<Num> Sum(ServerCallContext context, IAsyncStreamReader<Num> requestStream); + } - Task DivMany(ServerCallContext context, IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream); - } + // client stub + public class MathClient : AbstractStub<MathClient, StubConfiguration>, IMathClient + { + public MathClient(Channel channel) : this(channel, StubConfiguration.Default) + { + } + public MathClient(Channel channel, StubConfiguration config) : base(channel, config) + { + } + public DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_Div); + return Calls.BlockingUnaryCall(call, request, token); + } + public Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_Div); + return Calls.AsyncUnaryCall(call, request, token); + } + public AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_DivMany); + return Calls.AsyncDuplexStreamingCall(call, token); + } + public AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_Fib); + return Calls.AsyncServerStreamingCall(call, request, token); + } + public AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_Sum); + return Calls.AsyncClientStreamingCall(call, token); + } + } - public static ServerServiceDefinition BindService(IMathService serviceImpl) - { - return ServerServiceDefinition.CreateBuilder(ServiceName) - .AddMethod(DivMethod, serviceImpl.Div) - .AddMethod(FibMethod, serviceImpl.Fib) - .AddMethod(SumMethod, serviceImpl.Sum) - .AddMethod(DivManyMethod, serviceImpl.DivMany).Build(); - } + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(IMath serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_Div, serviceImpl.Div) + .AddMethod(__Method_DivMany, serviceImpl.DivMany) + .AddMethod(__Method_Fib, serviceImpl.Fib) + .AddMethod(__Method_Sum, serviceImpl.Sum).Build(); + } - public static IMathServiceClient NewStub(Channel channel) - { - return new MathServiceClientStub(channel); - } + // creates a new client stub + public static IMathClient NewStub(Channel channel) + { + return new MathClient(channel); + } - public static IMathServiceClient NewStub(Channel channel, StubConfiguration config) - { - return new MathServiceClientStub(channel, config); - } + // creates a new client stub + public static IMathClient NewStub(Channel channel, StubConfiguration config) + { + return new MathClient(channel, config); } + } } +#endregion diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs index 24aa93e885bb33f300382a54b3501dc32fd587a9..3b33b09bbdae0f802c0f6198b87ab042b92c0f5e 100644 --- a/src/csharp/Grpc.Examples/MathServiceImpl.cs +++ b/src/csharp/Grpc.Examples/MathServiceImpl.cs @@ -43,7 +43,7 @@ namespace math /// <summary> /// Implementation of MathService server /// </summary> - public class MathServiceImpl : MathGrpc.IMathService + public class MathServiceImpl : Math.IMath { public Task<DivReply> Div(ServerCallContext context, DivArgs request) { diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 13bbb5363fa41ad8e9837e7ce9863af628d92d7c..1ca3dd24e1cdfdc86e21867363093621b9660fe8 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -3,7 +3,7 @@ <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">x86</Platform> - <ProductVersion>10.0.0</ProductVersion> + <ProductVersion>8.0.30703</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{C61154BA-DD4A-4838-8420-0162A28925E0}</ProjectGuid> <OutputType>Library</OutputType> @@ -72,7 +72,6 @@ </ItemGroup> <ItemGroup> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="TestServiceGrpc.cs" /> <Compile Include="Empty.cs" /> <Compile Include="Messages.cs" /> <Compile Include="InteropClientServerTest.cs" /> @@ -80,6 +79,7 @@ <Compile Include="InteropServer.cs" /> <Compile Include="InteropClient.cs" /> <Compile Include="TestCredentials.cs" /> + <Compile Include="TestGrpc.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <ItemGroup> diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index a433659a086de3e7d353bcb0f919aa8a9e4381a0..02f8a369defa37d64f0b39288fe5ee1749f515bb 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -132,14 +132,14 @@ namespace Grpc.IntegrationTesting stubConfig = new StubConfiguration(OAuth2InterceptorFactory.Create(credential)); } - TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel, stubConfig); + TestService.ITestServiceClient client = new TestService.TestServiceClient(channel, stubConfig); RunTestCase(options.testCase, client); } GrpcEnvironment.Shutdown(); } - private void RunTestCase(string testCase, TestServiceGrpc.ITestServiceClient client) + private void RunTestCase(string testCase, TestService.ITestServiceClient client) { switch (testCase) { @@ -181,7 +181,7 @@ namespace Grpc.IntegrationTesting } } - public static void RunEmptyUnary(TestServiceGrpc.ITestServiceClient client) + public static void RunEmptyUnary(TestService.ITestServiceClient client) { Console.WriteLine("running empty_unary"); var response = client.EmptyCall(Empty.DefaultInstance); @@ -189,7 +189,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static void RunLargeUnary(TestServiceGrpc.ITestServiceClient client) + public static void RunLargeUnary(TestService.ITestServiceClient client) { Console.WriteLine("running large_unary"); var request = SimpleRequest.CreateBuilder() @@ -205,7 +205,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static void RunClientStreaming(TestServiceGrpc.ITestServiceClient client) + public static void RunClientStreaming(TestService.ITestServiceClient client) { Task.Run(async () => { @@ -222,7 +222,7 @@ namespace Grpc.IntegrationTesting }).Wait(); } - public static void RunServerStreaming(TestServiceGrpc.ITestServiceClient client) + public static void RunServerStreaming(TestService.ITestServiceClient client) { Task.Run(async () => { @@ -248,7 +248,7 @@ namespace Grpc.IntegrationTesting }).Wait(); } - public static void RunPingPong(TestServiceGrpc.ITestServiceClient client) + public static void RunPingPong(TestService.ITestServiceClient client) { Task.Run(async () => { @@ -303,7 +303,7 @@ namespace Grpc.IntegrationTesting }).Wait(); } - public static void RunEmptyStream(TestServiceGrpc.ITestServiceClient client) + public static void RunEmptyStream(TestService.ITestServiceClient client) { Task.Run(async () => { @@ -318,7 +318,7 @@ namespace Grpc.IntegrationTesting }).Wait(); } - public static void RunServiceAccountCreds(TestServiceGrpc.ITestServiceClient client) + public static void RunServiceAccountCreds(TestService.ITestServiceClient client) { Console.WriteLine("running service_account_creds"); var request = SimpleRequest.CreateBuilder() @@ -338,7 +338,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static void RunComputeEngineCreds(TestServiceGrpc.ITestServiceClient client) + public static void RunComputeEngineCreds(TestService.ITestServiceClient client) { Console.WriteLine("running compute_engine_creds"); var request = SimpleRequest.CreateBuilder() @@ -358,7 +358,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static void RunCancelAfterBegin(TestServiceGrpc.ITestServiceClient client) + public static void RunCancelAfterBegin(TestService.ITestServiceClient client) { Task.Run(async () => { @@ -383,7 +383,7 @@ namespace Grpc.IntegrationTesting }).Wait(); } - public static void RunCancelAfterFirstResponse(TestServiceGrpc.ITestServiceClient client) + public static void RunCancelAfterFirstResponse(TestService.ITestServiceClient client) { Task.Run(async () => { @@ -419,7 +419,7 @@ namespace Grpc.IntegrationTesting } // This is not an official interop test, but it's useful. - public static void RunBenchmarkEmptyUnary(TestServiceGrpc.ITestServiceClient client) + public static void RunBenchmarkEmptyUnary(TestService.ITestServiceClient client) { BenchmarkUtil.RunBenchmark(10000, 10000, () => { client.EmptyCall(Empty.DefaultInstance); }); diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs index 9e49ce0d174d800bb829cac7e6338cc1321771cf..ddbfc61a4ef74acc08500d77c384da579d090621 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs @@ -50,7 +50,7 @@ namespace Grpc.IntegrationTesting string host = "localhost"; Server server; Channel channel; - TestServiceGrpc.ITestServiceClient client; + TestService.ITestServiceClient client; [TestFixtureSetUp] public void Init() @@ -58,7 +58,7 @@ namespace Grpc.IntegrationTesting GrpcEnvironment.Initialize(); server = new Server(); - server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl())); + server.AddServiceDefinition(TestService.BindService(new TestServiceImpl())); int port = server.AddListeningPort(host, Server.PickUnusedPort, TestCredentials.CreateTestServerCredentials()); server.Start(); @@ -66,7 +66,7 @@ namespace Grpc.IntegrationTesting .AddString(ChannelArgs.SslTargetNameOverrideKey, TestCredentials.DefaultHostOverride).Build(); channel = new Channel(host + ":" + port, TestCredentials.CreateTestClientCredentials(true), channelArgs); - client = TestServiceGrpc.NewStub(channel); + client = TestService.NewStub(channel); } [TestFixtureTearDown] diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs index ca54aed04188c4b69ccf57a5c8bd5786ed483f11..87c3cbe1d4cf3565dd5ba5e8d95d22e2aa186350 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs @@ -91,7 +91,7 @@ namespace Grpc.IntegrationTesting GrpcEnvironment.Initialize(); var server = new Server(); - server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl())); + server.AddServiceDefinition(TestService.BindService(new TestServiceImpl())); string host = "0.0.0.0"; int port = options.port.Value; diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs new file mode 100644 index 0000000000000000000000000000000000000000..679aafb57a9804636519b3f11912bae6ae474f2f --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -0,0 +1,159 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: test.proto +#region Designer generated code + +using System; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; + +namespace grpc.testing { + public static class TestService + { + static readonly string __ServiceName = "grpc.testing.TestService"; + + static readonly Marshaller<Empty> __Marshaller_Empty = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom); + static readonly Marshaller<SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom); + static readonly Marshaller<SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom); + static readonly Marshaller<StreamingOutputCallRequest> __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallRequest.ParseFrom); + static readonly Marshaller<StreamingOutputCallResponse> __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallResponse.ParseFrom); + static readonly Marshaller<StreamingInputCallRequest> __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallRequest.ParseFrom); + static readonly Marshaller<StreamingInputCallResponse> __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallResponse.ParseFrom); + + static readonly Method<Empty, Empty> __Method_EmptyCall = new Method<Empty, Empty>( + MethodType.Unary, + "EmptyCall", + __Marshaller_Empty, + __Marshaller_Empty); + + static readonly Method<SimpleRequest, SimpleResponse> __Method_UnaryCall = new Method<SimpleRequest, SimpleResponse>( + MethodType.Unary, + "UnaryCall", + __Marshaller_SimpleRequest, + __Marshaller_SimpleResponse); + + static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> __Method_StreamingOutputCall = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>( + MethodType.ServerStreaming, + "StreamingOutputCall", + __Marshaller_StreamingOutputCallRequest, + __Marshaller_StreamingOutputCallResponse); + + static readonly Method<StreamingInputCallRequest, StreamingInputCallResponse> __Method_StreamingInputCall = new Method<StreamingInputCallRequest, StreamingInputCallResponse>( + MethodType.ClientStreaming, + "StreamingInputCall", + __Marshaller_StreamingInputCallRequest, + __Marshaller_StreamingInputCallResponse); + + static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> __Method_FullDuplexCall = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>( + MethodType.DuplexStreaming, + "FullDuplexCall", + __Marshaller_StreamingOutputCallRequest, + __Marshaller_StreamingOutputCallResponse); + + static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> __Method_HalfDuplexCall = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>( + MethodType.DuplexStreaming, + "HalfDuplexCall", + __Marshaller_StreamingOutputCallRequest, + __Marshaller_StreamingOutputCallResponse); + + // client-side stub interface + public interface ITestServiceClient + { + Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken)); + Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken)); + SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken)); + Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken)); + AsyncServerStreamingCall<StreamingOutputCallResponse> StreamingOutputCall(StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken)); + AsyncClientStreamingCall<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken)); + AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken)); + AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken)); + } + + // server-side interface + public interface ITestService + { + Task<Empty> EmptyCall(ServerCallContext context, Empty request); + Task<SimpleResponse> UnaryCall(ServerCallContext context, SimpleRequest request); + Task StreamingOutputCall(ServerCallContext context, StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream); + Task<StreamingInputCallResponse> StreamingInputCall(ServerCallContext context, IAsyncStreamReader<StreamingInputCallRequest> requestStream); + Task FullDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream); + Task HalfDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream); + } + + // client stub + public class TestServiceClient : AbstractStub<TestServiceClient, StubConfiguration>, ITestServiceClient + { + public TestServiceClient(Channel channel) : this(channel, StubConfiguration.Default) + { + } + public TestServiceClient(Channel channel, StubConfiguration config) : base(channel, config) + { + } + public Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_EmptyCall); + return Calls.BlockingUnaryCall(call, request, token); + } + public Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_EmptyCall); + return Calls.AsyncUnaryCall(call, request, token); + } + public SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_UnaryCall); + return Calls.BlockingUnaryCall(call, request, token); + } + public Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_UnaryCall); + return Calls.AsyncUnaryCall(call, request, token); + } + public AsyncServerStreamingCall<StreamingOutputCallResponse> StreamingOutputCall(StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_StreamingOutputCall); + return Calls.AsyncServerStreamingCall(call, request, token); + } + public AsyncClientStreamingCall<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_StreamingInputCall); + return Calls.AsyncClientStreamingCall(call, token); + } + public AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_FullDuplexCall); + return Calls.AsyncDuplexStreamingCall(call, token); + } + public AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_HalfDuplexCall); + return Calls.AsyncDuplexStreamingCall(call, token); + } + } + + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(ITestService serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall) + .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) + .AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall) + .AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall) + .AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall) + .AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build(); + } + + // creates a new client stub + public static ITestServiceClient NewStub(Channel channel) + { + return new TestServiceClient(channel); + } + + // creates a new client stub + public static ITestServiceClient NewStub(Channel channel, StubConfiguration config) + { + return new TestServiceClient(channel, config); + } + } +} +#endregion diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs index 40f32b5a88f0ad989d6416bdd0b8abd2fd4e8e07..d6ba61ef82aefc50b33ef9df5b87571a958daa08 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs @@ -44,7 +44,7 @@ namespace grpc.testing /// <summary> /// Implementation of TestService server /// </summary> - public class TestServiceImpl : TestServiceGrpc.ITestService + public class TestServiceImpl : TestService.ITestService { public Task<Empty> EmptyCall(ServerCallContext context, Empty request) { diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh new file mode 100755 index 0000000000000000000000000000000000000000..f980787bb70ff2f133e45a6b248f713a2140afbf --- /dev/null +++ b/src/csharp/generate_proto_csharp.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# 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. + +# Regenerates gRPC service stubs from proto files. +set +e +cd $(dirname $0) + +PLUGIN=protoc-gen-grpc=../../bins/opt/grpc_csharp_plugin +EXAMPLES_DIR=Grpc.Examples +INTEROP_DIR=Grpc.IntegrationTesting + +protoc --plugin=$PLUGIN --grpc_out=$EXAMPLES_DIR \ + -I $EXAMPLES_DIR/proto $EXAMPLES_DIR/proto/math.proto + +protoc --plugin=$PLUGIN --grpc_out=$INTEROP_DIR \ + -I $INTEROP_DIR/proto $INTEROP_DIR/proto/test.proto diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..a4b2ee3ca59178b788b997aabf8b27835d8b2118 --- /dev/null +++ b/test/cpp/end2end/mock_test.cc @@ -0,0 +1,291 @@ +/* + * + * 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 <thread> + +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/echo_duplicate.grpc.pb.h" +#include "test/cpp/util/echo.grpc.pb.h" +#include "src/cpp/server/thread_pool.h" +#include <grpc++/channel_arguments.h> +#include <grpc++/channel_interface.h> +#include <grpc++/client_context.h> +#include <grpc++/create_channel.h> +#include <grpc++/credentials.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> +#include <grpc++/status.h> +#include <grpc++/stream.h> +#include <grpc++/time.h> +#include <gtest/gtest.h> + +#include <grpc/grpc.h> +#include <grpc/support/thd.h> +#include <grpc/support/time.h> + +using grpc::cpp::test::util::EchoRequest; +using grpc::cpp::test::util::EchoResponse; +using grpc::cpp::test::util::TestService; +using std::chrono::system_clock; + +namespace grpc { +namespace testing { + +namespace { +template <class W, class R> +class MockClientReaderWriter GRPC_FINAL + : public ClientReaderWriterInterface<W, R> { + public: + void WaitForInitialMetadata() {} + bool Read(R* msg) GRPC_OVERRIDE { return true; } + bool Write(const W& msg) GRPC_OVERRIDE { return true; } + bool WritesDone() GRPC_OVERRIDE { return true; } + Status Finish() GRPC_OVERRIDE { return Status::OK; } +}; +template <> +class MockClientReaderWriter<EchoRequest, EchoResponse> GRPC_FINAL + : public ClientReaderWriterInterface<EchoRequest, EchoResponse> { + public: + MockClientReaderWriter() : writes_done_(false) {} + void WaitForInitialMetadata() {} + bool Read(EchoResponse* msg) GRPC_OVERRIDE { + if (writes_done_) return false; + msg->set_message(last_message_); + return true; + } + bool Write(const EchoRequest& msg) GRPC_OVERRIDE { + gpr_log(GPR_INFO, "mock recv msg %s", msg.message().c_str()); + last_message_ = msg.message(); + return true; + } + bool WritesDone() GRPC_OVERRIDE { + writes_done_ = true; + return true; + } + Status Finish() GRPC_OVERRIDE { return Status::OK; } + + private: + bool writes_done_; + grpc::string last_message_; +}; + +// Mocked stub. +class MockStub : public TestService::StubInterface { + public: + MockStub() {} + ~MockStub() {} + Status Echo(ClientContext* context, const EchoRequest& request, + EchoResponse* response) GRPC_OVERRIDE { + response->set_message(request.message()); + return Status::OK; + } + Status Unimplemented(ClientContext* context, const EchoRequest& request, + EchoResponse* response) GRPC_OVERRIDE { + return Status::OK; + } + + private: + ClientAsyncResponseReaderInterface<EchoResponse>* AsyncEchoRaw( + ClientContext* context, const EchoRequest& request, CompletionQueue* cq, + void* tag) GRPC_OVERRIDE { + return nullptr; + } + ClientWriterInterface<EchoRequest>* RequestStreamRaw( + ClientContext* context, EchoResponse* response) GRPC_OVERRIDE { + return nullptr; + } + ClientAsyncWriterInterface<EchoRequest>* AsyncRequestStreamRaw( + ClientContext* context, EchoResponse* response, CompletionQueue* cq, + void* tag) GRPC_OVERRIDE { + return nullptr; + } + ClientReaderInterface<EchoResponse>* ResponseStreamRaw( + ClientContext* context, const EchoRequest& request) GRPC_OVERRIDE { + return nullptr; + } + ClientAsyncReaderInterface<EchoResponse>* AsyncResponseStreamRaw( + ClientContext* context, const EchoRequest& request, CompletionQueue* cq, + void* tag) GRPC_OVERRIDE { + return nullptr; + } + ClientReaderWriterInterface<EchoRequest, EchoResponse>* BidiStreamRaw( + ClientContext* context) GRPC_OVERRIDE { + return new MockClientReaderWriter<EchoRequest, EchoResponse>(); + } + ClientAsyncReaderWriterInterface<EchoRequest, EchoResponse>* + AsyncBidiStreamRaw(ClientContext* context, CompletionQueue* cq, + void* tag) GRPC_OVERRIDE { + return nullptr; + } + ClientAsyncResponseReaderInterface<EchoResponse>* AsyncUnimplementedRaw( + ClientContext* context, const EchoRequest& request, CompletionQueue* cq, + void* tag) GRPC_OVERRIDE { + return nullptr; + } +}; + +class FakeClient { + public: + explicit FakeClient(TestService::StubInterface* stub) : stub_(stub) {} + + void DoEcho() { + ClientContext context; + EchoRequest request; + EchoResponse response; + request.set_message("hello world"); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.IsOk()); + } + + void DoBidiStream() { + EchoRequest request; + EchoResponse response; + ClientContext context; + grpc::string msg("hello"); + + std::unique_ptr<ClientReaderWriterInterface<EchoRequest, EchoResponse>> + stream = stub_->BidiStream(&context); + + request.set_message(msg + "0"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "1"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "2"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + stream->WritesDone(); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.IsOk()); + } + + void ResetStub(TestService::StubInterface* stub) { stub_ = stub; } + + private: + TestService::StubInterface* stub_; +}; + +class TestServiceImpl : public TestService::Service { + public: + Status Echo(ServerContext* context, const EchoRequest* request, + EchoResponse* response) GRPC_OVERRIDE { + response->set_message(request->message()); + return Status::OK; + } + + Status BidiStream(ServerContext* context, + ServerReaderWriter<EchoResponse, EchoRequest>* stream) + GRPC_OVERRIDE { + EchoRequest request; + EchoResponse response; + while (stream->Read(&request)) { + gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); + response.set_message(request.message()); + stream->Write(response); + } + return Status::OK; + } +}; + +class MockTest : public ::testing::Test { + protected: + MockTest() : thread_pool_(2) {} + + void SetUp() GRPC_OVERRIDE { + int port = grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << port; + // Setup server + ServerBuilder builder; + builder.AddListeningPort(server_address_.str(), + InsecureServerCredentials()); + builder.RegisterService(&service_); + builder.SetThreadPool(&thread_pool_); + server_ = builder.BuildAndStart(); + } + + void TearDown() GRPC_OVERRIDE { server_->Shutdown(); } + + void ResetStub() { + std::shared_ptr<ChannelInterface> channel = CreateChannel( + server_address_.str(), InsecureCredentials(), ChannelArguments()); + stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel)); + } + + std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub_; + std::unique_ptr<Server> server_; + std::ostringstream server_address_; + TestServiceImpl service_; + ThreadPool thread_pool_; +}; + +// Do one real rpc and one mocked one +TEST_F(MockTest, SimpleRpc) { + ResetStub(); + FakeClient client(stub_.get()); + client.DoEcho(); + MockStub stub; + client.ResetStub(&stub); + client.DoEcho(); +} + +TEST_F(MockTest, BidiStream) { + ResetStub(); + FakeClient client(stub_.get()); + client.DoBidiStream(); + MockStub stub; + client.ResetStub(&stub); + client.DoBidiStream(); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/cpp/qps/smoke_test.cc b/test/cpp/qps/async_unary_ping_pong_test.cc similarity index 51% rename from test/cpp/qps/smoke_test.cc rename to test/cpp/qps/async_unary_ping_pong_test.cc index 1a448339409146a1493449247d2ab278fcc0fc2a..8b037a865628b1f3f3f942f5d29579d5607ed34c 100644 --- a/test/cpp/qps/smoke_test.cc +++ b/test/cpp/qps/async_unary_ping_pong_test.cc @@ -44,50 +44,6 @@ namespace testing { static const int WARMUP = 5; static const int BENCHMARK = 10; -static void RunSynchronousUnaryPingPong() { - gpr_log(GPR_INFO, "Running Synchronous Unary Ping Pong"); - - ClientConfig client_config; - client_config.set_client_type(SYNCHRONOUS_CLIENT); - client_config.set_enable_ssl(false); - client_config.set_outstanding_rpcs_per_channel(1); - client_config.set_client_channels(1); - client_config.set_payload_size(1); - client_config.set_rpc_type(UNARY); - - ServerConfig server_config; - server_config.set_server_type(SYNCHRONOUS_SERVER); - server_config.set_enable_ssl(false); - server_config.set_threads(1); - - auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - - ReportQPS(result); - ReportLatency(result); -} - -static void RunSynchronousStreamingPingPong() { - gpr_log(GPR_INFO, "Running Synchronous Streaming Ping Pong"); - - ClientConfig client_config; - client_config.set_client_type(SYNCHRONOUS_CLIENT); - client_config.set_enable_ssl(false); - client_config.set_outstanding_rpcs_per_channel(1); - client_config.set_client_channels(1); - client_config.set_payload_size(1); - client_config.set_rpc_type(STREAMING); - - ServerConfig server_config; - server_config.set_server_type(SYNCHRONOUS_SERVER); - server_config.set_enable_ssl(false); - server_config.set_threads(1); - - auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - - ReportQPS(result); - ReportLatency(result); -} - static void RunAsyncUnaryPingPong() { gpr_log(GPR_INFO, "Running Async Unary Ping Pong"); @@ -105,44 +61,19 @@ static void RunAsyncUnaryPingPong() { server_config.set_enable_ssl(false); server_config.set_threads(1); - auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); + const auto result = + RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); ReportQPS(result); ReportLatency(result); } -static void RunQPS() { - gpr_log(GPR_INFO, "Running QPS test"); - - ClientConfig client_config; - client_config.set_client_type(ASYNC_CLIENT); - client_config.set_enable_ssl(false); - client_config.set_outstanding_rpcs_per_channel(1000); - client_config.set_client_channels(8); - client_config.set_payload_size(1); - client_config.set_async_client_threads(8); - client_config.set_rpc_type(UNARY); - - ServerConfig server_config; - server_config.set_server_type(ASYNC_SERVER); - server_config.set_enable_ssl(false); - server_config.set_threads(4); - - auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - - ReportQPSPerCore(result, server_config); - ReportLatency(result); -} - } // namespace testing } // namespace grpc int main(int argc, char** argv) { - using namespace grpc::testing; - RunSynchronousStreamingPingPong(); - RunSynchronousUnaryPingPong(); - RunAsyncUnaryPingPong(); - RunQPS(); + signal(SIGPIPE, SIG_IGN); + grpc::testing::RunAsyncUnaryPingPong(); return 0; } diff --git a/test/cpp/qps/qps_test.cc b/test/cpp/qps/qps_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..f567e4cf06104960c39c30d92cc089168c2bdf02 --- /dev/null +++ b/test/cpp/qps/qps_test.cc @@ -0,0 +1,79 @@ +/* + * + * 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 <grpc/support/log.h> + +#include <signal.h> + +#include "test/cpp/qps/driver.h" +#include "test/cpp/qps/report.h" + +namespace grpc { +namespace testing { + +static const int WARMUP = 5; +static const int BENCHMARK = 10; + +static void RunQPS() { + gpr_log(GPR_INFO, "Running QPS test"); + + ClientConfig client_config; + client_config.set_client_type(ASYNC_CLIENT); + client_config.set_enable_ssl(false); + client_config.set_outstanding_rpcs_per_channel(1000); + client_config.set_client_channels(8); + client_config.set_payload_size(1); + client_config.set_async_client_threads(8); + client_config.set_rpc_type(UNARY); + + ServerConfig server_config; + server_config.set_server_type(ASYNC_SERVER); + server_config.set_enable_ssl(false); + server_config.set_threads(4); + + const auto result = + RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); + + ReportQPSPerCore(result, server_config); + ReportLatency(result); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + signal(SIGPIPE, SIG_IGN); + grpc::testing::RunQPS(); + + return 0; +} diff --git a/test/cpp/qps/sync_streaming_ping_pong_test.cc b/test/cpp/qps/sync_streaming_ping_pong_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..48c7ff63e03bd1896dd691dcdd2e247947c2e5a5 --- /dev/null +++ b/test/cpp/qps/sync_streaming_ping_pong_test.cc @@ -0,0 +1,78 @@ +/* + * + * 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 <grpc/support/log.h> + +#include <signal.h> + +#include "test/cpp/qps/driver.h" +#include "test/cpp/qps/report.h" + +namespace grpc { +namespace testing { + +static const int WARMUP = 5; +static const int BENCHMARK = 10; + +static void RunSynchronousStreamingPingPong() { + gpr_log(GPR_INFO, "Running Synchronous Streaming Ping Pong"); + + ClientConfig client_config; + client_config.set_client_type(SYNCHRONOUS_CLIENT); + client_config.set_enable_ssl(false); + client_config.set_outstanding_rpcs_per_channel(1); + client_config.set_client_channels(1); + client_config.set_payload_size(1); + client_config.set_rpc_type(STREAMING); + + ServerConfig server_config; + server_config.set_server_type(SYNCHRONOUS_SERVER); + server_config.set_enable_ssl(false); + server_config.set_threads(1); + + const auto result = + RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); + + ReportQPS(result); + ReportLatency(result); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + signal(SIGPIPE, SIG_IGN); + grpc::testing::RunSynchronousStreamingPingPong(); + + return 0; +} diff --git a/test/cpp/qps/sync_unary_ping_pong_test.cc b/test/cpp/qps/sync_unary_ping_pong_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..4c4de6377b8f22de244c707cf139983a86a30739 --- /dev/null +++ b/test/cpp/qps/sync_unary_ping_pong_test.cc @@ -0,0 +1,78 @@ +/* + * + * 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 <grpc/support/log.h> + +#include <signal.h> + +#include "test/cpp/qps/driver.h" +#include "test/cpp/qps/report.h" + +namespace grpc { +namespace testing { + +static const int WARMUP = 5; +static const int BENCHMARK = 10; + +static void RunSynchronousUnaryPingPong() { + gpr_log(GPR_INFO, "Running Synchronous Unary Ping Pong"); + + ClientConfig client_config; + client_config.set_client_type(SYNCHRONOUS_CLIENT); + client_config.set_enable_ssl(false); + client_config.set_outstanding_rpcs_per_channel(1); + client_config.set_client_channels(1); + client_config.set_payload_size(1); + client_config.set_rpc_type(UNARY); + + ServerConfig server_config; + server_config.set_server_type(SYNCHRONOUS_SERVER); + server_config.set_enable_ssl(false); + server_config.set_threads(1); + + const auto result = + RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); + + ReportQPS(result); + ReportLatency(result); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + signal(SIGPIPE, SIG_IGN); + grpc::testing::RunSynchronousUnaryPingPong(); + + return 0; +} diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index 6a1b4a41b2d1f16f8772204ff4f40fc4dc83e0aa..8c17c271896c97da03aa8f95fb0fa4a4a470e995 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -666,6 +666,15 @@ "posix" ] }, + { + "flaky": false, + "language": "c++", + "name": "mock_test", + "platforms": [ + "windows", + "posix" + ] + }, { "flaky": false, "language": "c++",