diff --git a/CMakeLists.txt b/CMakeLists.txt index c11643eca6d..c43039a4fed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -441,17 +441,6 @@ add_dependencies(buildtests_c udp_server_test) endif() add_dependencies(buildtests_c uri_parser_test) add_dependencies(buildtests_c public_headers_must_be_c89) -add_dependencies(buildtests_c badreq_bad_client_test) -add_dependencies(buildtests_c connection_prefix_bad_client_test) -add_dependencies(buildtests_c duplicate_header_bad_client_test) -add_dependencies(buildtests_c head_of_line_blocking_bad_client_test) -add_dependencies(buildtests_c headers_bad_client_test) -add_dependencies(buildtests_c initial_settings_frame_bad_client_test) -add_dependencies(buildtests_c large_metadata_bad_client_test) -add_dependencies(buildtests_c server_registered_method_bad_client_test) -add_dependencies(buildtests_c simple_request_bad_client_test) -add_dependencies(buildtests_c unknown_frame_bad_client_test) -add_dependencies(buildtests_c window_overflow_bad_client_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c bad_ssl_cert_server) endif() @@ -736,6 +725,17 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx writes_per_rpc_test) endif() add_dependencies(buildtests_cxx xds_end2end_test) +add_dependencies(buildtests_cxx badreq_bad_client_test) +add_dependencies(buildtests_cxx connection_prefix_bad_client_test) +add_dependencies(buildtests_cxx duplicate_header_bad_client_test) +add_dependencies(buildtests_cxx head_of_line_blocking_bad_client_test) +add_dependencies(buildtests_cxx headers_bad_client_test) +add_dependencies(buildtests_cxx initial_settings_frame_bad_client_test) +add_dependencies(buildtests_cxx large_metadata_bad_client_test) +add_dependencies(buildtests_cxx server_registered_method_bad_client_test) +add_dependencies(buildtests_cxx simple_request_bad_client_test) +add_dependencies(buildtests_cxx unknown_frame_bad_client_test) +add_dependencies(buildtests_cxx window_overflow_bad_client_test) add_dependencies(buildtests_cxx resolver_component_test_unsecure) add_dependencies(buildtests_cxx resolver_component_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -5852,18 +5852,19 @@ target_include_directories(bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(bad_client_test PROPERTIES LINKER_LANGUAGE C) - # only use the flags for C++ source files - target_compile_options(bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() target_link_libraries(bad_client_test + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) @@ -17072,6 +17073,8 @@ if (gRPC_BUILD_TESTS) add_executable(badreq_bad_client_test test/core/bad_client/tests/badreq.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17086,28 +17089,32 @@ target_include_directories(badreq_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(badreq_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(badreq_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(badreq_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(connection_prefix_bad_client_test test/core/bad_client/tests/connection_prefix.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17122,28 +17129,32 @@ target_include_directories(connection_prefix_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(connection_prefix_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(connection_prefix_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(connection_prefix_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(duplicate_header_bad_client_test test/core/bad_client/tests/duplicate_header.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17158,28 +17169,32 @@ target_include_directories(duplicate_header_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(duplicate_header_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(duplicate_header_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(duplicate_header_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(head_of_line_blocking_bad_client_test test/core/bad_client/tests/head_of_line_blocking.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17194,28 +17209,32 @@ target_include_directories(head_of_line_blocking_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(head_of_line_blocking_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(head_of_line_blocking_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(head_of_line_blocking_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(headers_bad_client_test test/core/bad_client/tests/headers.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17230,28 +17249,32 @@ target_include_directories(headers_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(headers_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(headers_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(headers_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(initial_settings_frame_bad_client_test test/core/bad_client/tests/initial_settings_frame.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17266,28 +17289,32 @@ target_include_directories(initial_settings_frame_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(initial_settings_frame_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(initial_settings_frame_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(initial_settings_frame_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(large_metadata_bad_client_test test/core/bad_client/tests/large_metadata.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17302,28 +17329,32 @@ target_include_directories(large_metadata_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(large_metadata_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(large_metadata_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(large_metadata_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_registered_method_bad_client_test test/core/bad_client/tests/server_registered_method.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17338,28 +17369,32 @@ target_include_directories(server_registered_method_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(server_registered_method_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(server_registered_method_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(server_registered_method_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(simple_request_bad_client_test test/core/bad_client/tests/simple_request.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17374,28 +17409,32 @@ target_include_directories(simple_request_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(simple_request_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(simple_request_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(simple_request_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(unknown_frame_bad_client_test test/core/bad_client/tests/unknown_frame.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17410,28 +17449,32 @@ target_include_directories(unknown_frame_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(unknown_frame_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(unknown_frame_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(unknown_frame_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(window_overflow_bad_client_test test/core/bad_client/tests/window_overflow.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc ) @@ -17446,22 +17489,24 @@ target_include_directories(window_overflow_bad_client_test PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(window_overflow_bad_client_test ${_gRPC_SSL_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr + ${_gRPC_GFLAGS_LIBRARIES} ) - # avoid dependency on libstdc++ - if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(window_overflow_bad_client_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(window_overflow_bad_client_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) - endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index 9f05975da87..a188ae668d9 100644 --- a/Makefile +++ b/Makefile @@ -1406,7 +1406,7 @@ plugins: $(PROTOC_PLUGINS) privatelibs: privatelibs_c privatelibs_cxx -privatelibs_c: $(LIBDIR)/$(CONFIG)/libalts_test_util.a $(LIBDIR)/$(CONFIG)/libcxxabi.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libupb.a $(LIBDIR)/$(CONFIG)/libz.a $(LIBDIR)/$(CONFIG)/libares.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a +privatelibs_c: $(LIBDIR)/$(CONFIG)/libalts_test_util.a $(LIBDIR)/$(CONFIG)/libcxxabi.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libupb.a $(LIBDIR)/$(CONFIG)/libz.a $(LIBDIR)/$(CONFIG)/libares.a $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a pc_c: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc $(LIBDIR)/$(CONFIG)/pkgconfig/gpr.pc pc_c_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc $(LIBDIR)/$(CONFIG)/pkgconfig/gpr.pc @@ -1416,9 +1416,9 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc ifeq ($(EMBED_OPENSSL),true) -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libdns_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libbenchmark.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libdns_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a else -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libdns_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libdns_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a endif @@ -1557,17 +1557,6 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/udp_server_test \ $(BINDIR)/$(CONFIG)/uri_parser_test \ $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 \ - $(BINDIR)/$(CONFIG)/badreq_bad_client_test \ - $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \ - $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test \ - $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \ - $(BINDIR)/$(CONFIG)/headers_bad_client_test \ - $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \ - $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test \ - $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \ - $(BINDIR)/$(CONFIG)/simple_request_bad_client_test \ - $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \ - $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test \ $(BINDIR)/$(CONFIG)/bad_ssl_cert_server \ $(BINDIR)/$(CONFIG)/bad_ssl_cert_test \ $(BINDIR)/$(CONFIG)/h2_census_test \ @@ -1764,6 +1753,17 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/xds_end2end_test \ $(BINDIR)/$(CONFIG)/boringssl_ssl_test \ $(BINDIR)/$(CONFIG)/boringssl_crypto_test \ + $(BINDIR)/$(CONFIG)/badreq_bad_client_test \ + $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \ + $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test \ + $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \ + $(BINDIR)/$(CONFIG)/headers_bad_client_test \ + $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \ + $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test \ + $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \ + $(BINDIR)/$(CONFIG)/simple_request_bad_client_test \ + $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \ + $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test \ $(BINDIR)/$(CONFIG)/resolver_component_test_unsecure \ $(BINDIR)/$(CONFIG)/resolver_component_test \ $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure \ @@ -1912,6 +1912,17 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/transport_security_common_api_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \ $(BINDIR)/$(CONFIG)/xds_end2end_test \ + $(BINDIR)/$(CONFIG)/badreq_bad_client_test \ + $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \ + $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test \ + $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \ + $(BINDIR)/$(CONFIG)/headers_bad_client_test \ + $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \ + $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test \ + $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \ + $(BINDIR)/$(CONFIG)/simple_request_bad_client_test \ + $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \ + $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test \ $(BINDIR)/$(CONFIG)/resolver_component_test_unsecure \ $(BINDIR)/$(CONFIG)/resolver_component_test \ $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure \ @@ -2180,28 +2191,6 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/uri_parser_test || ( echo test uri_parser_test failed ; exit 1 ) $(E) "[RUN] Testing public_headers_must_be_c89" $(Q) $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 || ( echo test public_headers_must_be_c89 failed ; exit 1 ) - $(E) "[RUN] Testing badreq_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/badreq_bad_client_test || ( echo test badreq_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing connection_prefix_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test || ( echo test connection_prefix_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing duplicate_header_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test || ( echo test duplicate_header_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing head_of_line_blocking_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test || ( echo test head_of_line_blocking_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing headers_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/headers_bad_client_test || ( echo test headers_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing initial_settings_frame_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test || ( echo test initial_settings_frame_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing large_metadata_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test || ( echo test large_metadata_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing server_registered_method_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test || ( echo test server_registered_method_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing simple_request_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/simple_request_bad_client_test || ( echo test simple_request_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing unknown_frame_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test || ( echo test unknown_frame_bad_client_test failed ; exit 1 ) - $(E) "[RUN] Testing window_overflow_bad_client_test" - $(Q) $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test || ( echo test window_overflow_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing bad_ssl_cert_test" $(Q) $(BINDIR)/$(CONFIG)/bad_ssl_cert_test || ( echo test bad_ssl_cert_test failed ; exit 1 ) @@ -2456,6 +2445,28 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 ) $(E) "[RUN] Testing xds_end2end_test" $(Q) $(BINDIR)/$(CONFIG)/xds_end2end_test || ( echo test xds_end2end_test failed ; exit 1 ) + $(E) "[RUN] Testing badreq_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/badreq_bad_client_test || ( echo test badreq_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing connection_prefix_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test || ( echo test connection_prefix_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing duplicate_header_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test || ( echo test duplicate_header_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing head_of_line_blocking_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test || ( echo test head_of_line_blocking_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing headers_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/headers_bad_client_test || ( echo test headers_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing initial_settings_frame_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test || ( echo test initial_settings_frame_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing large_metadata_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test || ( echo test large_metadata_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing server_registered_method_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test || ( echo test server_registered_method_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing simple_request_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/simple_request_bad_client_test || ( echo test simple_request_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing unknown_frame_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test || ( echo test unknown_frame_bad_client_test failed ; exit 1 ) + $(E) "[RUN] Testing window_overflow_bad_client_test" + $(Q) $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test || ( echo test window_overflow_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing resolver_component_tests_runner_invoker_unsecure" $(Q) $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure || ( echo test resolver_component_tests_runner_invoker_unsecure failed ; exit 1 ) $(E) "[RUN] Testing resolver_component_tests_runner_invoker" @@ -8549,7 +8560,7 @@ endif LIBBAD_CLIENT_TEST_SRC = \ test/core/bad_client/bad_client.cc \ -PUBLIC_HEADERS_C += \ +PUBLIC_HEADERS_CXX += \ LIBBAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBAD_CLIENT_TEST_SRC)))) @@ -8563,8 +8574,16 @@ $(LIBDIR)/$(CONFIG)/libbad_client_test.a: openssl_dep_error else +ifeq ($(NO_PROTOBUF),true) + +# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. + +$(LIBDIR)/$(CONFIG)/libbad_client_test.a: protobuf_dep_error + -$(LIBDIR)/$(CONFIG)/libbad_client_test.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(LIBBAD_CLIENT_TEST_OBJS) +else + +$(LIBDIR)/$(CONFIG)/libbad_client_test.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(PROTOBUF_DEP) $(LIBBAD_CLIENT_TEST_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libbad_client_test.a @@ -8576,6 +8595,8 @@ endif +endif + endif ifneq ($(NO_SECURE),true) @@ -20350,10 +20371,21 @@ BADREQ_BAD_CLIENT_TEST_SRC = \ BADREQ_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BADREQ_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/badreq_bad_client_test: $(BADREQ_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/badreq_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/badreq_bad_client_test: $(PROTOBUF_DEP) $(BADREQ_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(BADREQ_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/badreq_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(BADREQ_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/badreq_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/badreq.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20370,10 +20402,21 @@ CONNECTION_PREFIX_BAD_CLIENT_TEST_SRC = \ CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CONNECTION_PREFIX_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test: $(CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test: $(PROTOBUF_DEP) $(CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/connection_prefix.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20390,10 +20433,21 @@ DUPLICATE_HEADER_BAD_CLIENT_TEST_SRC = \ DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DUPLICATE_HEADER_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test: $(DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test: $(PROTOBUF_DEP) $(DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/duplicate_header.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20410,10 +20464,21 @@ HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC = \ HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test: $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test: $(PROTOBUF_DEP) $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/head_of_line_blocking.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20430,10 +20495,21 @@ HEADERS_BAD_CLIENT_TEST_SRC = \ HEADERS_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEADERS_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/headers_bad_client_test: $(HEADERS_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/headers_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/headers_bad_client_test: $(PROTOBUF_DEP) $(HEADERS_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(HEADERS_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/headers_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(HEADERS_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/headers_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/headers.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20450,10 +20526,21 @@ INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_SRC = \ INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test: $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test: $(PROTOBUF_DEP) $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/initial_settings_frame.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20470,10 +20557,21 @@ LARGE_METADATA_BAD_CLIENT_TEST_SRC = \ LARGE_METADATA_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LARGE_METADATA_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/large_metadata_bad_client_test: $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/large_metadata_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/large_metadata_bad_client_test: $(PROTOBUF_DEP) $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/large_metadata.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20490,10 +20588,21 @@ SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC = \ SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test: $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test: $(PROTOBUF_DEP) $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/server_registered_method.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20510,10 +20619,21 @@ SIMPLE_REQUEST_BAD_CLIENT_TEST_SRC = \ SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SIMPLE_REQUEST_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/simple_request_bad_client_test: $(SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/simple_request_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/simple_request_bad_client_test: $(PROTOBUF_DEP) $(SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/simple_request_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/simple_request_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/simple_request.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20530,10 +20650,21 @@ UNKNOWN_FRAME_BAD_CLIENT_TEST_SRC = \ UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(UNKNOWN_FRAME_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test: $(UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test: $(PROTOBUF_DEP) $(UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/unknown_frame.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a @@ -20550,10 +20681,21 @@ WINDOW_OVERFLOW_BAD_CLIENT_TEST_SRC = \ WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_SRC)))) -$(BINDIR)/$(CONFIG)/window_overflow_bad_client_test: $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/window_overflow_bad_client_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/window_overflow_bad_client_test: $(PROTOBUF_DEP) $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test + $(Q) $(LDXX) $(LDFLAGS) $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test + +endif $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/window_overflow.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a diff --git a/doc/environment_variables.md b/doc/environment_variables.md index 6782f1ee6a6..ff6eaba57b7 100644 --- a/doc/environment_variables.md +++ b/doc/environment_variables.md @@ -39,7 +39,6 @@ some configuration as environment variables that can be set. gRPC C core is processing requests via debug logs. Available tracers include: - api - traces api calls to the C core - bdp_estimator - traces behavior of bdp estimation logic - - call_combiner - traces call combiner state - call_error - traces the possible errors contributing to final call status - cares_resolver - traces operations of the c-ares based DNS resolver - cares_address_sorting - traces operations of the c-ares based DNS @@ -52,9 +51,6 @@ some configuration as environment variables that can be set. - connectivity_state - traces connectivity state changes to channels - cronet - traces state in the cronet transport engine - executor - traces grpc's internal thread pool ('the executor') - - fd_trace - traces fd create(), shutdown() and close() calls for channel fds. - Also traces epoll fd create()/close() calls in epollex polling engine - traces epoll-fd creation/close calls for epollex polling engine - glb - traces the grpclb load balancer - handshaker - traces handshaking state - health_check_client - traces health checking client code @@ -86,7 +82,11 @@ some configuration as environment variables that can be set. - alarm_refcount - refcounting traces for grpc_alarm structure - metadata - tracks creation and mutation of metadata - combiner - traces combiner lock state + - call_combiner - traces call combiner state - closure - tracks closure creation, scheduling, and completion + - fd_trace - traces fd create(), shutdown() and close() calls for channel fds. + Also traces epoll fd create()/close() calls in epollex polling engine + traces epoll-fd creation/close calls for epollex polling engine - pending_tags - traces still-in-progress tags on completion queues - polling - traces the selected polling engine - polling_api - traces the api calls to polling engine diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 95664a800fa..c3ae6c4e3d2 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -188,11 +188,6 @@ class WriteOptions { /// \sa GRPC_WRITE_LAST_MESSAGE bool is_last_message() const { return last_message_; } - WriteOptions& operator=(const WriteOptions& rhs) { - flags_ = rhs.flags_; - return *this; - } - private: void SetBit(const uint32_t mask) { flags_ |= mask; } diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h index da08ec963e4..ab47873e40a 100644 --- a/include/grpcpp/impl/codegen/server_callback.h +++ b/include/grpcpp/impl/codegen/server_callback.h @@ -348,7 +348,8 @@ class ServerBidiReactor : public internal::ServerReactor { private: friend class ServerCallbackReaderWriter; - void BindStream(ServerCallbackReaderWriter* stream) { + virtual void BindStream( + ServerCallbackReaderWriter* stream) { stream_ = stream; } @@ -382,7 +383,9 @@ class ServerReadReactor : public internal::ServerReactor { private: friend class ServerCallbackReader; - void BindReader(ServerCallbackReader* reader) { reader_ = reader; } + virtual void BindReader(ServerCallbackReader* reader) { + reader_ = reader; + } ServerCallbackReader* reader_; }; @@ -424,7 +427,9 @@ class ServerWriteReactor : public internal::ServerReactor { private: friend class ServerCallbackWriter; - void BindWriter(ServerCallbackWriter* writer) { writer_ = writer; } + virtual void BindWriter(ServerCallbackWriter* writer) { + writer_ = writer; + } ServerCallbackWriter* writer_; }; diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 81562ab2107..40f8cef522b 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -147,6 +147,9 @@ class ChannelData { return service_config_; } + RefCountedPtr GetConnectedSubchannelInDataPlane( + SubchannelInterface* subchannel) const; + grpc_connectivity_state CheckConnectivityState(bool try_to_connect); void AddExternalConnectivityWatcher(grpc_polling_entity pollent, grpc_connectivity_state* state, @@ -161,9 +164,9 @@ class ChannelData { } private: + class SubchannelWrapper; class ConnectivityStateAndPickerSetter; class ServiceConfigSetter; - class GrpcSubchannel; class ClientChannelControlHelper; class ExternalConnectivityWatcher { @@ -262,7 +265,14 @@ class ChannelData { UniquePtr health_check_service_name_; RefCountedPtr saved_service_config_; bool received_first_resolver_result_ = false; + // The number of SubchannelWrapper instances referencing a given Subchannel. Map subchannel_refcount_map_; + // Pending ConnectedSubchannel updates for each SubchannelWrapper. + // Updates are queued here in the control plane combiner and then applied + // in the data plane combiner when the picker is updated. + Map, RefCountedPtr, + RefCountedPtrLess> + pending_subchannel_updates_; // // Fields accessed from both data plane and control plane combiners. @@ -706,6 +716,247 @@ class CallData { grpc_metadata_batch send_trailing_metadata_; }; +// +// ChannelData::SubchannelWrapper +// + +// This class is a wrapper for Subchannel that hides details of the +// channel's implementation (such as the health check service name and +// connected subchannel) from the LB policy API. +// +// Note that no synchronization is needed here, because even if the +// underlying subchannel is shared between channels, this wrapper will only +// be used within one channel, so it will always be synchronized by the +// control plane combiner. +class ChannelData::SubchannelWrapper : public SubchannelInterface { + public: + SubchannelWrapper(ChannelData* chand, Subchannel* subchannel, + UniquePtr health_check_service_name) + : SubchannelInterface(&grpc_client_channel_routing_trace), + chand_(chand), + subchannel_(subchannel), + health_check_service_name_(std::move(health_check_service_name)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, + "chand=%p: creating subchannel wrapper %p for subchannel %p", + chand, this, subchannel_); + } + GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "SubchannelWrapper"); + auto* subchannel_node = subchannel_->channelz_node(); + if (subchannel_node != nullptr) { + intptr_t subchannel_uuid = subchannel_node->uuid(); + auto it = chand_->subchannel_refcount_map_.find(subchannel_); + if (it == chand_->subchannel_refcount_map_.end()) { + chand_->channelz_node_->AddChildSubchannel(subchannel_uuid); + it = chand_->subchannel_refcount_map_.emplace(subchannel_, 0).first; + } + ++it->second; + } + } + + ~SubchannelWrapper() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, + "chand=%p: destroying subchannel wrapper %p for subchannel %p", + chand_, this, subchannel_); + } + auto* subchannel_node = subchannel_->channelz_node(); + if (subchannel_node != nullptr) { + intptr_t subchannel_uuid = subchannel_node->uuid(); + auto it = chand_->subchannel_refcount_map_.find(subchannel_); + GPR_ASSERT(it != chand_->subchannel_refcount_map_.end()); + --it->second; + if (it->second == 0) { + chand_->channelz_node_->RemoveChildSubchannel(subchannel_uuid); + chand_->subchannel_refcount_map_.erase(it); + } + } + GRPC_SUBCHANNEL_UNREF(subchannel_, "unref from LB"); + GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "SubchannelWrapper"); + } + + grpc_connectivity_state CheckConnectivityState() override { + RefCountedPtr connected_subchannel; + grpc_connectivity_state connectivity_state = + subchannel_->CheckConnectivityState(health_check_service_name_.get(), + &connected_subchannel); + MaybeUpdateConnectedSubchannel(std::move(connected_subchannel)); + return connectivity_state; + } + + void WatchConnectivityState( + grpc_connectivity_state initial_state, + UniquePtr watcher) override { + auto& watcher_wrapper = watcher_map_[watcher.get()]; + GPR_ASSERT(watcher_wrapper == nullptr); + watcher_wrapper = New( + std::move(watcher), Ref(DEBUG_LOCATION, "WatcherWrapper")); + subchannel_->WatchConnectivityState( + initial_state, + UniquePtr(gpr_strdup(health_check_service_name_.get())), + OrphanablePtr( + watcher_wrapper)); + } + + void CancelConnectivityStateWatch( + ConnectivityStateWatcherInterface* watcher) override { + auto it = watcher_map_.find(watcher); + GPR_ASSERT(it != watcher_map_.end()); + subchannel_->CancelConnectivityStateWatch(health_check_service_name_.get(), + it->second); + watcher_map_.erase(it); + } + + void AttemptToConnect() override { subchannel_->AttemptToConnect(); } + + void ResetBackoff() override { subchannel_->ResetBackoff(); } + + const grpc_channel_args* channel_args() override { + return subchannel_->channel_args(); + } + + // Caller must be holding the control-plane combiner. + ConnectedSubchannel* connected_subchannel() const { + return connected_subchannel_.get(); + } + + // Caller must be holding the data-plane combiner. + ConnectedSubchannel* connected_subchannel_in_data_plane() const { + return connected_subchannel_in_data_plane_.get(); + } + void set_connected_subchannel_in_data_plane( + RefCountedPtr connected_subchannel) { + connected_subchannel_in_data_plane_ = std::move(connected_subchannel); + } + + private: + // Subchannel and SubchannelInterface have different interfaces for + // their respective ConnectivityStateWatcherInterface classes. + // The one in Subchannel updates the ConnectedSubchannel along with + // the state, whereas the one in SubchannelInterface does not expose + // the ConnectedSubchannel. + // + // This wrapper provides a bridge between the two. It implements + // Subchannel::ConnectivityStateWatcherInterface and wraps + // the instance of SubchannelInterface::ConnectivityStateWatcherInterface + // that was passed in by the LB policy. We pass an instance of this + // class to the underlying Subchannel, and when we get updates from + // the subchannel, we pass those on to the wrapped watcher to return + // the update to the LB policy. This allows us to set the connected + // subchannel before passing the result back to the LB policy. + class WatcherWrapper : public Subchannel::ConnectivityStateWatcherInterface { + public: + WatcherWrapper( + UniquePtr + watcher, + RefCountedPtr parent) + : watcher_(std::move(watcher)), parent_(std::move(parent)) {} + + ~WatcherWrapper() { parent_.reset(DEBUG_LOCATION, "WatcherWrapper"); } + + void Orphan() override { Unref(); } + + void OnConnectivityStateChange( + grpc_connectivity_state new_state, + RefCountedPtr connected_subchannel) override { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, + "chand=%p: connectivity change for subchannel wrapper %p " + "subchannel %p (connected_subchannel=%p state=%s); " + "hopping into combiner", + parent_->chand_, parent_.get(), parent_->subchannel_, + connected_subchannel.get(), + grpc_connectivity_state_name(new_state)); + } + // Will delete itself. + New(Ref(), new_state, std::move(connected_subchannel)); + } + + grpc_pollset_set* interested_parties() override { + return watcher_->interested_parties(); + } + + private: + class Updater { + public: + Updater(RefCountedPtr parent, + grpc_connectivity_state new_state, + RefCountedPtr connected_subchannel) + : parent_(std::move(parent)), + state_(new_state), + connected_subchannel_(std::move(connected_subchannel)) { + GRPC_CLOSURE_INIT( + &closure_, ApplyUpdateInControlPlaneCombiner, this, + grpc_combiner_scheduler(parent_->parent_->chand_->combiner_)); + GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE); + } + + private: + static void ApplyUpdateInControlPlaneCombiner(void* arg, + grpc_error* error) { + Updater* self = static_cast(arg); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, + "chand=%p: processing connectivity change in combiner " + "for subchannel wrapper %p subchannel %p " + "(connected_subchannel=%p state=%s)", + self->parent_->parent_->chand_, self->parent_->parent_.get(), + self->parent_->parent_->subchannel_, + self->connected_subchannel_.get(), + grpc_connectivity_state_name(self->state_)); + } + self->parent_->parent_->MaybeUpdateConnectedSubchannel( + std::move(self->connected_subchannel_)); + self->parent_->watcher_->OnConnectivityStateChange(self->state_); + Delete(self); + } + + RefCountedPtr parent_; + grpc_connectivity_state state_; + RefCountedPtr connected_subchannel_; + grpc_closure closure_; + }; + + UniquePtr watcher_; + RefCountedPtr parent_; + }; + + void MaybeUpdateConnectedSubchannel( + RefCountedPtr connected_subchannel) { + // Update the connected subchannel only if the channel is not shutting + // down. This is because once the channel is shutting down, we + // ignore picker updates from the LB policy, which means that + // ConnectivityStateAndPickerSetter will never process the entries + // in chand_->pending_subchannel_updates_. So we don't want to add + // entries there that will never be processed, since that would + // leave dangling refs to the channel and prevent its destruction. + grpc_error* disconnect_error = chand_->disconnect_error(); + if (disconnect_error != GRPC_ERROR_NONE) return; + // Not shutting down, so do the update. + if (connected_subchannel_ != connected_subchannel) { + connected_subchannel_ = std::move(connected_subchannel); + // Record the new connected subchannel so that it can be updated + // in the data plane combiner the next time the picker is updated. + chand_->pending_subchannel_updates_[Ref( + DEBUG_LOCATION, "ConnectedSubchannelUpdate")] = connected_subchannel_; + } + } + + ChannelData* chand_; + Subchannel* subchannel_; + UniquePtr health_check_service_name_; + // Maps from the address of the watcher passed to us by the LB policy + // to the address of the WrapperWatcher that we passed to the underlying + // subchannel. This is needed so that when the LB policy calls + // CancelConnectivityStateWatch() with its watcher, we know the + // corresponding WrapperWatcher to cancel on the underlying subchannel. + Map watcher_map_; + // To be accessed only in the control plane combiner. + RefCountedPtr connected_subchannel_; + // To be accessed only in the data plane combiner. + RefCountedPtr connected_subchannel_in_data_plane_; +}; + // // ChannelData::ConnectivityStateAndPickerSetter // @@ -729,10 +980,13 @@ class ChannelData::ConnectivityStateAndPickerSetter { grpc_slice_from_static_string( GetChannelConnectivityStateChangeString(state))); } + // Grab any pending subchannel updates. + pending_subchannel_updates_ = + std::move(chand_->pending_subchannel_updates_); // Bounce into the data plane combiner to reset the picker. GRPC_CHANNEL_STACK_REF(chand->owning_stack_, "ConnectivityStateAndPickerSetter"); - GRPC_CLOSURE_INIT(&closure_, SetPicker, this, + GRPC_CLOSURE_INIT(&closure_, SetPickerInDataPlane, this, grpc_combiner_scheduler(chand->data_plane_combiner_)); GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE); } @@ -755,16 +1009,38 @@ class ChannelData::ConnectivityStateAndPickerSetter { GPR_UNREACHABLE_CODE(return "UNKNOWN"); } - static void SetPicker(void* arg, grpc_error* ignored) { + static void SetPickerInDataPlane(void* arg, grpc_error* ignored) { auto* self = static_cast(arg); - // Update picker. - self->chand_->picker_ = std::move(self->picker_); + // Handle subchannel updates. + for (auto& p : self->pending_subchannel_updates_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, + "chand=%p: updating subchannel wrapper %p data plane " + "connected_subchannel to %p", + self->chand_, p.first.get(), p.second.get()); + } + p.first->set_connected_subchannel_in_data_plane(std::move(p.second)); + } + // Swap out the picker. We hang on to the old picker so that it can + // be deleted in the control-plane combiner, since that's where we need + // to unref the subchannel wrappers that are reffed by the picker. + self->picker_.swap(self->chand_->picker_); // Re-process queued picks. for (QueuedPick* pick = self->chand_->queued_picks_; pick != nullptr; pick = pick->next) { CallData::StartPickLocked(pick->elem, GRPC_ERROR_NONE); } - // Clean up. + // Pop back into the control plane combiner to delete ourself, so + // that we make sure to unref subchannel wrappers there. This + // includes both the ones reffed by the old picker (now stored in + // self->picker_) and the ones in self->pending_subchannel_updates_. + GRPC_CLOSURE_INIT(&self->closure_, CleanUpInControlPlane, self, + grpc_combiner_scheduler(self->chand_->combiner_)); + GRPC_CLOSURE_SCHED(&self->closure_, GRPC_ERROR_NONE); + } + + static void CleanUpInControlPlane(void* arg, grpc_error* ignored) { + auto* self = static_cast(arg); GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack_, "ConnectivityStateAndPickerSetter"); Delete(self); @@ -772,6 +1048,9 @@ class ChannelData::ConnectivityStateAndPickerSetter { ChannelData* chand_; UniquePtr picker_; + Map, RefCountedPtr, + RefCountedPtrLess> + pending_subchannel_updates_; grpc_closure closure_; }; @@ -946,89 +1225,6 @@ void ChannelData::ExternalConnectivityWatcher::WatchConnectivityStateLocked( &self->chand_->state_tracker_, self->state_, &self->my_closure_); } -// -// ChannelData::GrpcSubchannel -// - -// This class is a wrapper for Subchannel that hides details of the -// channel's implementation (such as the health check service name) from -// the LB policy API. -// -// Note that no synchronization is needed here, because even if the -// underlying subchannel is shared between channels, this wrapper will only -// be used within one channel, so it will always be synchronized by the -// control plane combiner. -class ChannelData::GrpcSubchannel : public SubchannelInterface { - public: - GrpcSubchannel(ChannelData* chand, Subchannel* subchannel, - UniquePtr health_check_service_name) - : chand_(chand), - subchannel_(subchannel), - health_check_service_name_(std::move(health_check_service_name)) { - GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "GrpcSubchannel"); - auto* subchannel_node = subchannel_->channelz_node(); - if (subchannel_node != nullptr) { - intptr_t subchannel_uuid = subchannel_node->uuid(); - auto it = chand_->subchannel_refcount_map_.find(subchannel_); - if (it == chand_->subchannel_refcount_map_.end()) { - chand_->channelz_node_->AddChildSubchannel(subchannel_uuid); - it = chand_->subchannel_refcount_map_.emplace(subchannel_, 0).first; - } - ++it->second; - } - } - - ~GrpcSubchannel() { - auto* subchannel_node = subchannel_->channelz_node(); - if (subchannel_node != nullptr) { - intptr_t subchannel_uuid = subchannel_node->uuid(); - auto it = chand_->subchannel_refcount_map_.find(subchannel_); - GPR_ASSERT(it != chand_->subchannel_refcount_map_.end()); - --it->second; - if (it->second == 0) { - chand_->channelz_node_->RemoveChildSubchannel(subchannel_uuid); - chand_->subchannel_refcount_map_.erase(it); - } - } - GRPC_SUBCHANNEL_UNREF(subchannel_, "unref from LB"); - GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "GrpcSubchannel"); - } - - grpc_connectivity_state CheckConnectivityState( - RefCountedPtr* connected_subchannel) - override { - RefCountedPtr tmp; - auto retval = subchannel_->CheckConnectivityState( - health_check_service_name_.get(), &tmp); - *connected_subchannel = std::move(tmp); - return retval; - } - - void WatchConnectivityState( - grpc_connectivity_state initial_state, - UniquePtr watcher) override { - subchannel_->WatchConnectivityState( - initial_state, - UniquePtr(gpr_strdup(health_check_service_name_.get())), - std::move(watcher)); - } - - void CancelConnectivityStateWatch( - ConnectivityStateWatcher* watcher) override { - subchannel_->CancelConnectivityStateWatch(health_check_service_name_.get(), - watcher); - } - - void AttemptToConnect() override { subchannel_->AttemptToConnect(); } - - void ResetBackoff() override { subchannel_->ResetBackoff(); } - - private: - ChannelData* chand_; - Subchannel* subchannel_; - UniquePtr health_check_service_name_; -}; - // // ChannelData::ClientChannelControlHelper // @@ -1066,8 +1262,8 @@ class ChannelData::ClientChannelControlHelper chand_->client_channel_factory_->CreateSubchannel(new_args); grpc_channel_args_destroy(new_args); if (subchannel == nullptr) return nullptr; - return MakeRefCounted(chand_, subchannel, - std::move(health_check_service_name)); + return MakeRefCounted( + chand_, subchannel, std::move(health_check_service_name)); } grpc_channel* CreateChannel(const char* target, @@ -1078,8 +1274,7 @@ class ChannelData::ClientChannelControlHelper void UpdateState( grpc_connectivity_state state, UniquePtr picker) override { - grpc_error* disconnect_error = - chand_->disconnect_error_.Load(MemoryOrder::ACQUIRE); + grpc_error* disconnect_error = chand_->disconnect_error(); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { const char* extra = disconnect_error == GRPC_ERROR_NONE ? "" @@ -1180,6 +1375,10 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error) interested_parties_(grpc_pollset_set_create()), subchannel_pool_(GetSubchannelPool(args->channel_args)), disconnect_error_(GRPC_ERROR_NONE) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, "chand=%p: creating client_channel for channel stack %p", + this, owning_stack_); + } // Initialize data members. grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, "client_channel"); @@ -1236,10 +1435,8 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error) std::move(target_uri), ProcessResolverResultLocked, this, error)); grpc_channel_args_destroy(new_args); if (*error != GRPC_ERROR_NONE) { - // Orphan the resolving LB policy and flush the exec_ctx to ensure - // that it finishes shutting down. This ensures that if we are - // failing, we destroy the ClientChannelControlHelper (and thus - // unref the channel stack) before we return. + // Before we return, shut down the resolving LB policy, which destroys + // the ClientChannelControlHelper and therefore unrefs the channel stack. // TODO(roth): This is not a complete solution, because it only // catches the case where channel stack initialization fails in this // particular filter. If there is a failure in a different filter, we @@ -1247,7 +1444,6 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error) // in practice, there are no other filters that can cause failures in // channel stack initialization, so this works for now. resolving_lb_policy_.reset(); - ExecCtx::Get()->Flush(); } else { grpc_pollset_set_add_pollset_set(resolving_lb_policy_->interested_parties(), interested_parties_); @@ -1259,6 +1455,9 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error) } ChannelData::~ChannelData() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, "chand=%p: destroying channel", this); + } if (resolving_lb_policy_ != nullptr) { grpc_pollset_set_del_pollset_set(resolving_lb_policy_->interested_parties(), interested_parties_); @@ -1444,9 +1643,13 @@ grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) { } LoadBalancingPolicy::PickResult result = picker_->Pick(LoadBalancingPolicy::PickArgs()); - if (result.connected_subchannel != nullptr) { - ConnectedSubchannel* connected_subchannel = - static_cast(result.connected_subchannel.get()); + ConnectedSubchannel* connected_subchannel = nullptr; + if (result.subchannel != nullptr) { + SubchannelWrapper* subchannel = + static_cast(result.subchannel.get()); + connected_subchannel = subchannel->connected_subchannel(); + } + if (connected_subchannel != nullptr) { connected_subchannel->Ping(op->send_ping.on_initiate, op->send_ping.on_ack); } else { if (result.error == GRPC_ERROR_NONE) { @@ -1489,6 +1692,10 @@ void ChannelData::StartTransportOpLocked(void* arg, grpc_error* ignored) { } // Disconnect. if (op->disconnect_with_error != GRPC_ERROR_NONE) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { + gpr_log(GPR_INFO, "chand=%p: channel shut down from API: %s", chand, + grpc_error_string(op->disconnect_with_error)); + } grpc_error* error = GRPC_ERROR_NONE; GPR_ASSERT(chand->disconnect_error_.CompareExchangeStrong( &error, op->disconnect_with_error, MemoryOrder::ACQ_REL, @@ -1563,6 +1770,17 @@ void ChannelData::RemoveQueuedPick(QueuedPick* to_remove, } } +RefCountedPtr +ChannelData::GetConnectedSubchannelInDataPlane( + SubchannelInterface* subchannel) const { + SubchannelWrapper* subchannel_wrapper = + static_cast(subchannel); + ConnectedSubchannel* connected_subchannel = + subchannel_wrapper->connected_subchannel_in_data_plane(); + if (connected_subchannel == nullptr) return nullptr; + return connected_subchannel->Ref(); +} + void ChannelData::TryToConnectLocked(void* arg, grpc_error* error_ignored) { auto* chand = static_cast(arg); if (chand->resolving_lb_policy_ != nullptr) { @@ -3490,10 +3708,9 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) { auto result = chand->picker()->Pick(pick_args); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, - "chand=%p calld=%p: LB pick returned %s (connected_subchannel=%p, " - "error=%s)", + "chand=%p calld=%p: LB pick returned %s (subchannel=%p, error=%s)", chand, calld, PickResultTypeName(result.type), - result.connected_subchannel.get(), grpc_error_string(result.error)); + result.subchannel.get(), grpc_error_string(result.error)); } switch (result.type) { case LoadBalancingPolicy::PickResult::PICK_TRANSIENT_FAILURE: { @@ -3535,11 +3752,16 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) { break; default: // PICK_COMPLETE // Handle drops. - if (GPR_UNLIKELY(result.connected_subchannel == nullptr)) { + if (GPR_UNLIKELY(result.subchannel == nullptr)) { result.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Call dropped by load balancing policy"); + } else { + // Grab a ref to the connected subchannel while we're still + // holding the data plane combiner. + calld->connected_subchannel_ = + chand->GetConnectedSubchannelInDataPlane(result.subchannel.get()); + GPR_ASSERT(calld->connected_subchannel_ != nullptr); } - calld->connected_subchannel_ = std::move(result.connected_subchannel); calld->lb_recv_trailing_metadata_ready_ = result.recv_trailing_metadata_ready; calld->lb_recv_trailing_metadata_ready_user_data_ = diff --git a/src/core/ext/filters/client_channel/lb_policy.cc b/src/core/ext/filters/client_channel/lb_policy.cc index 3e4d3703c82..3207f888044 100644 --- a/src/core/ext/filters/client_channel/lb_policy.cc +++ b/src/core/ext/filters/client_channel/lb_policy.cc @@ -43,23 +43,8 @@ LoadBalancingPolicy::~LoadBalancingPolicy() { } void LoadBalancingPolicy::Orphan() { - // Invoke ShutdownAndUnrefLocked() inside of the combiner. - // TODO(roth): Is this actually needed? We should already be in the - // combiner here. Note that if we directly call ShutdownLocked(), - // then we can probably remove the hack whereby the helper is - // destroyed at shutdown instead of at destruction. - GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_CREATE(&LoadBalancingPolicy::ShutdownAndUnrefLocked, this, - grpc_combiner_scheduler(combiner_)), - GRPC_ERROR_NONE); -} - -void LoadBalancingPolicy::ShutdownAndUnrefLocked(void* arg, - grpc_error* ignored) { - LoadBalancingPolicy* policy = static_cast(arg); - policy->ShutdownLocked(); - policy->channel_control_helper_.reset(); - policy->Unref(); + ShutdownLocked(); + Unref(); } // diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h index d508932015d..ecc235bb71b 100644 --- a/src/core/ext/filters/client_channel/lb_policy.h +++ b/src/core/ext/filters/client_channel/lb_policy.h @@ -128,7 +128,7 @@ class LoadBalancingPolicy : public InternallyRefCounted { /// Used only if type is PICK_COMPLETE. Will be set to the selected /// subchannel, or nullptr if the LB policy decides to drop the call. - RefCountedPtr connected_subchannel; + RefCountedPtr subchannel; /// Used only if type is PICK_TRANSIENT_FAILURE. /// Error to be set when returning a transient failure. @@ -282,6 +282,7 @@ class LoadBalancingPolicy : public InternallyRefCounted { grpc_pollset_set* interested_parties() const { return interested_parties_; } + // Note: This must be invoked while holding the combiner. void Orphan() override; // A picker that returns PICK_QUEUE for all picks. @@ -292,6 +293,8 @@ class LoadBalancingPolicy : public InternallyRefCounted { explicit QueuePicker(RefCountedPtr parent) : parent_(std::move(parent)) {} + ~QueuePicker() { parent_.reset(DEBUG_LOCATION, "QueuePicker"); } + PickResult Pick(PickArgs args) override; private: @@ -320,7 +323,6 @@ class LoadBalancingPolicy : public InternallyRefCounted { // Note: LB policies MUST NOT call any method on the helper from their // constructor. - // Note: This will return null after ShutdownLocked() has been called. ChannelControlHelper* channel_control_helper() const { return channel_control_helper_.get(); } @@ -329,8 +331,6 @@ class LoadBalancingPolicy : public InternallyRefCounted { virtual void ShutdownLocked() GRPC_ABSTRACT; private: - static void ShutdownAndUnrefLocked(void* arg, grpc_error* ignored); - /// Combiner under which LB policy actions take place. grpc_combiner* combiner_; /// Owned pointer to interested parties in load balancing decisions. diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index a87dfda7321..dad10f0ce86 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -575,13 +575,12 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) { result = child_picker_->Pick(args); // If pick succeeded, add LB token to initial metadata. if (result.type == PickResult::PICK_COMPLETE && - result.connected_subchannel != nullptr) { + result.subchannel != nullptr) { const grpc_arg* arg = grpc_channel_args_find( - result.connected_subchannel->args(), GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN); + result.subchannel->channel_args(), GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN); if (arg == nullptr) { - gpr_log(GPR_ERROR, - "[grpclb %p picker %p] No LB token for connected subchannel %p", - parent_, this, result.connected_subchannel.get()); + gpr_log(GPR_ERROR, "[grpclb %p picker %p] No LB token for subchannel %p", + parent_, this, result.subchannel.get()); abort(); } grpc_mdelem lb_token = {reinterpret_cast(arg->value.pointer.p)}; diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index e4b58eb7558..8bf3d825b23 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -28,7 +28,6 @@ #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/sync.h" -#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -85,9 +84,8 @@ class PickFirst : public LoadBalancingPolicy { public: PickFirstSubchannelList(PickFirst* policy, TraceFlag* tracer, const ServerAddressList& addresses, - grpc_combiner* combiner, const grpc_channel_args& args) - : SubchannelList(policy, tracer, addresses, combiner, + : SubchannelList(policy, tracer, addresses, policy->channel_control_helper(), args) { // Need to maintain a ref to the LB policy as long as we maintain // any references to subchannels, since the subchannels' @@ -111,19 +109,18 @@ class PickFirst : public LoadBalancingPolicy { class Picker : public SubchannelPicker { public: - explicit Picker( - RefCountedPtr connected_subchannel) - : connected_subchannel_(std::move(connected_subchannel)) {} + explicit Picker(RefCountedPtr subchannel) + : subchannel_(std::move(subchannel)) {} PickResult Pick(PickArgs args) override { PickResult result; result.type = PickResult::PICK_COMPLETE; - result.connected_subchannel = connected_subchannel_; + result.subchannel = subchannel_; return result; } private: - RefCountedPtr connected_subchannel_; + RefCountedPtr subchannel_; }; void ShutdownLocked() override; @@ -166,6 +163,9 @@ void PickFirst::ShutdownLocked() { void PickFirst::ExitIdleLocked() { if (shutdown_) return; if (idle_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) { + gpr_log(GPR_INFO, "Pick First %p exiting idle", this); + } idle_ = false; if (subchannel_list_ == nullptr || subchannel_list_->num_subchannels() == 0) { @@ -200,7 +200,7 @@ void PickFirst::UpdateLocked(UpdateArgs args) { grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args.args, &new_arg, 1); auto subchannel_list = MakeOrphanable( - this, &grpc_lb_pick_first_trace, args.addresses, combiner(), *new_args); + this, &grpc_lb_pick_first_trace, args.addresses, *new_args); grpc_channel_args_destroy(new_args); if (subchannel_list->num_subchannels() == 0) { // Empty update or no valid subchannels. Unsubscribe from all current @@ -329,7 +329,8 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( } else { p->channel_control_helper()->UpdateState( GRPC_CHANNEL_CONNECTING, - UniquePtr(New(p->Ref()))); + UniquePtr( + New(p->Ref(DEBUG_LOCATION, "QueuePicker")))); } } else { if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { @@ -342,20 +343,20 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( p->selected_ = nullptr; CancelConnectivityWatchLocked("selected subchannel failed; going IDLE"); p->channel_control_helper()->UpdateState( - GRPC_CHANNEL_IDLE, - UniquePtr(New(p->Ref()))); + GRPC_CHANNEL_IDLE, UniquePtr(New( + p->Ref(DEBUG_LOCATION, "QueuePicker")))); } else { // This is unlikely but can happen when a subchannel has been asked // to reconnect by a different channel and this channel has dropped // some connectivity state notifications. if (connectivity_state == GRPC_CHANNEL_READY) { p->channel_control_helper()->UpdateState( - GRPC_CHANNEL_READY, UniquePtr(New( - connected_subchannel()->Ref()))); + GRPC_CHANNEL_READY, + UniquePtr(New(subchannel()->Ref()))); } else { // CONNECTING p->channel_control_helper()->UpdateState( - connectivity_state, - UniquePtr(New(p->Ref()))); + connectivity_state, UniquePtr(New( + p->Ref(DEBUG_LOCATION, "QueuePicker")))); } } } @@ -411,7 +412,8 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( if (subchannel_list() == p->subchannel_list_.get()) { p->channel_control_helper()->UpdateState( GRPC_CHANNEL_CONNECTING, - UniquePtr(New(p->Ref()))); + UniquePtr( + New(p->Ref(DEBUG_LOCATION, "QueuePicker")))); } break; } @@ -445,13 +447,13 @@ void PickFirst::PickFirstSubchannelData::ProcessUnselectedReadyLocked() { p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_); } // Cases 1 and 2. - p->selected_ = this; - p->channel_control_helper()->UpdateState( - GRPC_CHANNEL_READY, - UniquePtr(New(connected_subchannel()->Ref()))); if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) { gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p, subchannel()); } + p->selected_ = this; + p->channel_control_helper()->UpdateState( + GRPC_CHANNEL_READY, + UniquePtr(New(subchannel()->Ref()))); } void PickFirst::PickFirstSubchannelData:: diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index 17c65d8b551..04308ee254c 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -38,7 +38,6 @@ #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" -#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/static_metadata.h" @@ -106,9 +105,8 @@ class RoundRobin : public LoadBalancingPolicy { public: RoundRobinSubchannelList(RoundRobin* policy, TraceFlag* tracer, const ServerAddressList& addresses, - grpc_combiner* combiner, const grpc_channel_args& args) - : SubchannelList(policy, tracer, addresses, combiner, + : SubchannelList(policy, tracer, addresses, policy->channel_control_helper(), args) { // Need to maintain a ref to the LB policy as long as we maintain // any references to subchannels, since the subchannels' @@ -155,7 +153,7 @@ class RoundRobin : public LoadBalancingPolicy { RoundRobin* parent_; size_t last_picked_index_; - InlinedVector, 10> subchannels_; + InlinedVector, 10> subchannels_; }; void ShutdownLocked() override; @@ -180,10 +178,9 @@ RoundRobin::Picker::Picker(RoundRobin* parent, RoundRobinSubchannelList* subchannel_list) : parent_(parent) { for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) { - auto* connected_subchannel = - subchannel_list->subchannel(i)->connected_subchannel(); - if (connected_subchannel != nullptr) { - subchannels_.push_back(connected_subchannel->Ref()); + RoundRobinSubchannelData* sd = subchannel_list->subchannel(i); + if (sd->connectivity_state() == GRPC_CHANNEL_READY) { + subchannels_.push_back(sd->subchannel()->Ref()); } } // For discussion on why we generate a random starting index for @@ -204,14 +201,13 @@ RoundRobin::PickResult RoundRobin::Picker::Pick(PickArgs args) { last_picked_index_ = (last_picked_index_ + 1) % subchannels_.size(); if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) { gpr_log(GPR_INFO, - "[RR %p picker %p] returning index %" PRIuPTR - ", connected_subchannel=%p", + "[RR %p picker %p] returning index %" PRIuPTR ", subchannel=%p", parent_, this, last_picked_index_, subchannels_[last_picked_index_].get()); } PickResult result; result.type = PickResult::PICK_COMPLETE; - result.connected_subchannel = subchannels_[last_picked_index_]; + result.subchannel = subchannels_[last_picked_index_]; return result; } @@ -323,8 +319,8 @@ void RoundRobin::RoundRobinSubchannelList:: } else if (num_connecting_ > 0) { /* 2) CONNECTING */ p->channel_control_helper()->UpdateState( - GRPC_CHANNEL_CONNECTING, - UniquePtr(New(p->Ref()))); + GRPC_CHANNEL_CONNECTING, UniquePtr(New( + p->Ref(DEBUG_LOCATION, "QueuePicker")))); } else if (num_transient_failure_ == num_subchannels()) { /* 3) TRANSIENT_FAILURE */ grpc_error* error = @@ -424,7 +420,7 @@ void RoundRobin::UpdateLocked(UpdateArgs args) { } } latest_pending_subchannel_list_ = MakeOrphanable( - this, &grpc_lb_round_robin_trace, args.addresses, combiner(), *args.args); + this, &grpc_lb_round_robin_trace, args.addresses, *args.args); if (latest_pending_subchannel_list_->num_subchannels() == 0) { // If the new list is empty, immediately promote the new list to the // current list and transition to TRANSIENT_FAILURE. diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index 7d70928a83c..34cd0f549fe 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -39,7 +39,6 @@ #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/closure.h" -#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -64,8 +63,7 @@ class MySubchannelList }; */ -// All methods with a Locked() suffix must be called from within the -// client_channel combiner. +// All methods will be called from within the client_channel combiner. namespace grpc_core { @@ -93,20 +91,13 @@ class SubchannelData { // Returns a pointer to the subchannel. SubchannelInterface* subchannel() const { return subchannel_.get(); } - // Returns the connected subchannel. Will be null if the subchannel - // is not connected. - ConnectedSubchannelInterface* connected_subchannel() const { - return connected_subchannel_.get(); - } - // Synchronously checks the subchannel's connectivity state. // Must not be called while there is a connectivity notification // pending (i.e., between calling StartConnectivityWatchLocked() and // calling CancelConnectivityWatchLocked()). grpc_connectivity_state CheckConnectivityStateLocked() { GPR_ASSERT(pending_watcher_ == nullptr); - connectivity_state_ = - subchannel()->CheckConnectivityState(&connected_subchannel_); + connectivity_state_ = subchannel_->CheckConnectivityState(); return connectivity_state_; } @@ -144,7 +135,8 @@ class SubchannelData { private: // Watcher for subchannel connectivity state. - class Watcher : public SubchannelInterface::ConnectivityStateWatcher { + class Watcher + : public SubchannelInterface::ConnectivityStateWatcherInterface { public: Watcher( SubchannelData* subchannel_data, @@ -154,42 +146,13 @@ class SubchannelData { ~Watcher() { subchannel_list_.reset(DEBUG_LOCATION, "Watcher dtor"); } - void OnConnectivityStateChange(grpc_connectivity_state new_state, - RefCountedPtr - connected_subchannel) override; + void OnConnectivityStateChange(grpc_connectivity_state new_state) override; grpc_pollset_set* interested_parties() override { return subchannel_list_->policy()->interested_parties(); } private: - // A fire-and-forget class that bounces into the combiner to process - // a connectivity state update. - class Updater { - public: - Updater( - SubchannelData* - subchannel_data, - RefCountedPtr> - subchannel_list, - grpc_connectivity_state state, - RefCountedPtr connected_subchannel); - - ~Updater() { - subchannel_list_.reset(DEBUG_LOCATION, "Watcher::Updater dtor"); - } - - private: - static void OnUpdateLocked(void* arg, grpc_error* error); - - SubchannelData* subchannel_data_; - RefCountedPtr> - subchannel_list_; - const grpc_connectivity_state state_; - RefCountedPtr connected_subchannel_; - grpc_closure closure_; - }; - SubchannelData* subchannel_data_; RefCountedPtr subchannel_list_; }; @@ -202,10 +165,10 @@ class SubchannelData { // The subchannel. RefCountedPtr subchannel_; // Will be non-null when the subchannel's state is being watched. - SubchannelInterface::ConnectivityStateWatcher* pending_watcher_ = nullptr; + SubchannelInterface::ConnectivityStateWatcherInterface* pending_watcher_ = + nullptr; // Data updated by the watcher. grpc_connectivity_state connectivity_state_; - RefCountedPtr connected_subchannel_; }; // A list of subchannels. @@ -232,7 +195,6 @@ class SubchannelList : public InternallyRefCounted { // the backoff code out of subchannels and into LB policies. void ResetBackoffLocked(); - // Note: Caller must ensure that this is invoked inside of the combiner. void Orphan() override { ShutdownLocked(); InternallyRefCounted::Unref(DEBUG_LOCATION, "shutdown"); @@ -242,7 +204,7 @@ class SubchannelList : public InternallyRefCounted { protected: SubchannelList(LoadBalancingPolicy* policy, TraceFlag* tracer, - const ServerAddressList& addresses, grpc_combiner* combiner, + const ServerAddressList& addresses, LoadBalancingPolicy::ChannelControlHelper* helper, const grpc_channel_args& args); @@ -263,8 +225,6 @@ class SubchannelList : public InternallyRefCounted { TraceFlag* tracer_; - grpc_combiner* combiner_; - // The list of subchannels. SubchannelVector subchannels_; @@ -284,59 +244,26 @@ class SubchannelList : public InternallyRefCounted { template void SubchannelData::Watcher:: - OnConnectivityStateChange( - grpc_connectivity_state new_state, - RefCountedPtr connected_subchannel) { - // Will delete itself. - New(subchannel_data_, - subchannel_list_->Ref(DEBUG_LOCATION, "Watcher::Updater"), - new_state, std::move(connected_subchannel)); -} - -template -SubchannelData::Watcher::Updater:: - Updater( - SubchannelData* subchannel_data, - RefCountedPtr> - subchannel_list, - grpc_connectivity_state state, - RefCountedPtr connected_subchannel) - : subchannel_data_(subchannel_data), - subchannel_list_(std::move(subchannel_list)), - state_(state), - connected_subchannel_(std::move(connected_subchannel)) { - GRPC_CLOSURE_INIT(&closure_, &OnUpdateLocked, this, - grpc_combiner_scheduler(subchannel_list_->combiner_)); - GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE); -} - -template -void SubchannelData::Watcher::Updater:: - OnUpdateLocked(void* arg, grpc_error* error) { - Updater* self = static_cast(arg); - SubchannelData* sd = self->subchannel_data_; - if (GRPC_TRACE_FLAG_ENABLED(*sd->subchannel_list_->tracer())) { + OnConnectivityStateChange(grpc_connectivity_state new_state) { + if (GRPC_TRACE_FLAG_ENABLED(*subchannel_list_->tracer())) { gpr_log(GPR_INFO, "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR " (subchannel %p): connectivity changed: state=%s, " - "connected_subchannel=%p, shutting_down=%d, pending_watcher=%p", - sd->subchannel_list_->tracer()->name(), - sd->subchannel_list_->policy(), sd->subchannel_list_, sd->Index(), - sd->subchannel_list_->num_subchannels(), sd->subchannel_.get(), - grpc_connectivity_state_name(self->state_), - self->connected_subchannel_.get(), - sd->subchannel_list_->shutting_down(), sd->pending_watcher_); + "shutting_down=%d, pending_watcher=%p", + subchannel_list_->tracer()->name(), subchannel_list_->policy(), + subchannel_list_.get(), subchannel_data_->Index(), + subchannel_list_->num_subchannels(), + subchannel_data_->subchannel_.get(), + grpc_connectivity_state_name(new_state), + subchannel_list_->shutting_down(), + subchannel_data_->pending_watcher_); } - if (!sd->subchannel_list_->shutting_down() && - sd->pending_watcher_ != nullptr) { - sd->connectivity_state_ = self->state_; - // Get or release ref to connected subchannel. - sd->connected_subchannel_ = std::move(self->connected_subchannel_); + if (!subchannel_list_->shutting_down() && + subchannel_data_->pending_watcher_ != nullptr) { + subchannel_data_->connectivity_state_ = new_state; // Call the subclass's ProcessConnectivityChangeLocked() method. - sd->ProcessConnectivityChangeLocked(sd->connectivity_state_); + subchannel_data_->ProcessConnectivityChangeLocked(new_state); } - // Clean up. - Delete(self); } // @@ -371,7 +298,6 @@ void SubchannelData:: subchannel_.get()); } subchannel_.reset(); - connected_subchannel_.reset(); } } @@ -400,7 +326,7 @@ void SubchannelData(this, subchannel_list()->Ref(DEBUG_LOCATION, "Watcher")); subchannel_->WatchConnectivityState( connectivity_state_, - UniquePtr( + UniquePtr( pending_watcher_)); } @@ -434,13 +360,12 @@ void SubchannelData::ShutdownLocked() { template SubchannelList::SubchannelList( LoadBalancingPolicy* policy, TraceFlag* tracer, - const ServerAddressList& addresses, grpc_combiner* combiner, + const ServerAddressList& addresses, LoadBalancingPolicy::ChannelControlHelper* helper, const grpc_channel_args& args) : InternallyRefCounted(tracer), policy_(policy), - tracer_(tracer), - combiner_(GRPC_COMBINER_REF(combiner, "subchannel_list")) { + tracer_(tracer) { if (GRPC_TRACE_FLAG_ENABLED(*tracer_)) { gpr_log(GPR_INFO, "[%s %p] Creating subchannel list %p for %" PRIuPTR " subchannels", @@ -509,7 +434,6 @@ SubchannelList::~SubchannelList() { gpr_log(GPR_INFO, "[%s %p] Destroying subchannel_list %p", tracer_->name(), policy_, this); } - GRPC_COMBINER_UNREF(combiner_, "subchannel_list"); } template diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc index 136d85bba14..ca6ab216515 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc @@ -333,6 +333,8 @@ class XdsLb : public LoadBalancingPolicy { explicit FallbackHelper(RefCountedPtr parent) : parent_(std::move(parent)) {} + ~FallbackHelper() { parent_.reset(DEBUG_LOCATION, "FallbackHelper"); } + RefCountedPtr CreateSubchannel( const grpc_channel_args& args) override; grpc_channel* CreateChannel(const char* target, @@ -377,19 +379,30 @@ class XdsLb : public LoadBalancingPolicy { strcmp(subzone_.get(), other.subzone_.get()) == 0; } + const char* AsHumanReadableString() { + if (human_readable_string_ == nullptr) { + char* tmp; + gpr_asprintf(&tmp, "{region=\"%s\", zone=\"%s\", subzone=\"%s\"}", + region_.get(), zone_.get(), subzone_.get()); + human_readable_string_.reset(tmp); + } + return human_readable_string_.get(); + } + private: UniquePtr region_; UniquePtr zone_; UniquePtr subzone_; + UniquePtr human_readable_string_; }; class LocalityMap { public: class LocalityEntry : public InternallyRefCounted { public: - LocalityEntry(RefCountedPtr parent, uint32_t locality_weight) - : parent_(std::move(parent)), locality_weight_(locality_weight) {} - ~LocalityEntry() = default; + LocalityEntry(RefCountedPtr parent, + RefCountedPtr name, uint32_t locality_weight); + ~LocalityEntry(); void UpdateLocked(xds_grpclb_serverlist* serverlist, LoadBalancingPolicy::Config* child_policy_config, @@ -404,6 +417,8 @@ class XdsLb : public LoadBalancingPolicy { explicit Helper(RefCountedPtr entry) : entry_(std::move(entry)) {} + ~Helper() { entry_.reset(DEBUG_LOCATION, "Helper"); } + RefCountedPtr CreateSubchannel( const grpc_channel_args& args) override; grpc_channel* CreateChannel(const char* target, @@ -428,9 +443,10 @@ class XdsLb : public LoadBalancingPolicy { grpc_channel_args* CreateChildPolicyArgsLocked( const grpc_channel_args* args); + RefCountedPtr parent_; + RefCountedPtr name_; OrphanablePtr child_policy_; OrphanablePtr pending_child_policy_; - RefCountedPtr parent_; RefCountedPtr picker_ref_; grpc_connectivity_state connectivity_state_; uint32_t locality_weight_; @@ -554,7 +570,7 @@ XdsLb::PickResult XdsLb::Picker::Pick(PickArgs args) { PickResult result = PickFromLocality(key, args); // If pick succeeded, add client stats. if (result.type == PickResult::PICK_COMPLETE && - result.connected_subchannel != nullptr && client_stats_ != nullptr) { + result.subchannel != nullptr && client_stats_ != nullptr) { // TODO(roth): Add support for client stats. } return result; @@ -743,7 +759,7 @@ ServerAddressList ProcessServerlist(const xds_grpclb_serverlist* serverlist) { XdsLb::BalancerChannelState::BalancerChannelState( const char* balancer_name, const grpc_channel_args& args, - grpc_core::RefCountedPtr parent_xdslb_policy) + RefCountedPtr parent_xdslb_policy) : InternallyRefCounted(&grpc_lb_xds_trace), xdslb_policy_(std::move(parent_xdslb_policy)), lb_call_backoff_( @@ -763,6 +779,7 @@ XdsLb::BalancerChannelState::BalancerChannelState( } XdsLb::BalancerChannelState::~BalancerChannelState() { + xdslb_policy_.reset(DEBUG_LOCATION, "BalancerChannelState"); grpc_channel_destroy(channel_); } @@ -1414,12 +1431,18 @@ XdsLb::XdsLb(Args args) } XdsLb::~XdsLb() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) { + gpr_log(GPR_INFO, "[xdslb %p] destroying xds LB policy", this); + } gpr_free((void*)server_name_); grpc_channel_args_destroy(args_); locality_serverlist_.clear(); } void XdsLb::ShutdownLocked() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) { + gpr_log(GPR_INFO, "[xdslb %p] shutting down", this); + } shutting_down_ = true; if (fallback_at_startup_checks_pending_) { grpc_timer_cancel(&lb_fallback_timer_); @@ -1486,8 +1509,9 @@ void XdsLb::ProcessAddressesAndChannelArgsLocked( } if (create_lb_channel) { OrphanablePtr lb_chand = - MakeOrphanable(balancer_name_.get(), - *lb_channel_args, Ref()); + MakeOrphanable( + balancer_name_.get(), *lb_channel_args, + Ref(DEBUG_LOCATION, "BalancerChannelState")); if (lb_chand_ == nullptr || !lb_chand_->HasActiveCall()) { GPR_ASSERT(pending_lb_chand_ == nullptr); // If we do not have a working LB channel yet, use the newly created one. @@ -1676,7 +1700,8 @@ void XdsLb::UpdateFallbackPolicyLocked() { OrphanablePtr XdsLb::CreateFallbackPolicyLocked( const char* name, const grpc_channel_args* args) { - FallbackHelper* helper = New(Ref()); + FallbackHelper* helper = + New(Ref(DEBUG_LOCATION, "FallbackHelper")); LoadBalancingPolicy::Args lb_policy_args; lb_policy_args.combiner = combiner(); lb_policy_args.args = args; @@ -1739,7 +1764,9 @@ void XdsLb::LocalityMap::UpdateLocked( auto iter = map_.find(locality_serverlist[i]->locality_name); if (iter == map_.end()) { OrphanablePtr new_entry = MakeOrphanable( - parent->Ref(), locality_serverlist[i]->locality_weight); + parent->Ref(DEBUG_LOCATION, "LocalityEntry"), + locality_serverlist[i]->locality_name, + locality_serverlist[i]->locality_weight); iter = map_.emplace(locality_serverlist[i]->locality_name, std::move(new_entry)) .first; @@ -1764,6 +1791,27 @@ void XdsLb::LocalityMap::ResetBackoffLocked() { // XdsLb::LocalityMap::LocalityEntry // +XdsLb::LocalityMap::LocalityEntry::LocalityEntry( + RefCountedPtr parent, RefCountedPtr name, + uint32_t locality_weight) + : parent_(std::move(parent)), + name_(std::move(name)), + locality_weight_(locality_weight) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) { + gpr_log(GPR_INFO, "[xdslb %p] created LocalityEntry %p for %s", + parent_.get(), this, name_->AsHumanReadableString()); + } +} + +XdsLb::LocalityMap::LocalityEntry::~LocalityEntry() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) { + gpr_log(GPR_INFO, + "[xdslb %p] LocalityEntry %p %s: destroying locality entry", + parent_.get(), this, name_->AsHumanReadableString()); + } + parent_.reset(DEBUG_LOCATION, "LocalityEntry"); +} + grpc_channel_args* XdsLb::LocalityMap::LocalityEntry::CreateChildPolicyArgsLocked( const grpc_channel_args* args_in) { @@ -1785,7 +1833,7 @@ XdsLb::LocalityMap::LocalityEntry::CreateChildPolicyArgsLocked( OrphanablePtr XdsLb::LocalityMap::LocalityEntry::CreateChildPolicyLocked( const char* name, const grpc_channel_args* args) { - Helper* helper = New(this->Ref()); + Helper* helper = New(this->Ref(DEBUG_LOCATION, "Helper")); LoadBalancingPolicy::Args lb_policy_args; lb_policy_args.combiner = parent_->combiner(); lb_policy_args.args = args; @@ -1795,13 +1843,16 @@ XdsLb::LocalityMap::LocalityEntry::CreateChildPolicyLocked( LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy( name, std::move(lb_policy_args)); if (GPR_UNLIKELY(lb_policy == nullptr)) { - gpr_log(GPR_ERROR, "[xdslb %p] Failure creating child policy %s", this, - name); + gpr_log(GPR_ERROR, + "[xdslb %p] LocalityEntry %p %s: failure creating child policy %s", + parent_.get(), this, name_->AsHumanReadableString(), name); return nullptr; } helper->set_child(lb_policy.get()); if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) { - gpr_log(GPR_INFO, "[xdslb %p] Created new child policy %s (%p)", this, name, + gpr_log(GPR_INFO, + "[xdslb %p] LocalityEntry %p %s: Created new child policy %s (%p)", + parent_.get(), this, name_->AsHumanReadableString(), name, lb_policy.get()); } // Add the xDS's interested_parties pollset_set to that of the newly created @@ -1892,7 +1943,9 @@ void XdsLb::LocalityMap::LocalityEntry::UpdateLocked( // If child_policy_ is null, we set it (case 1), else we set // pending_child_policy_ (cases 2b and 3b). if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) { - gpr_log(GPR_INFO, "[xdslb %p] Creating new %schild policy %s", this, + gpr_log(GPR_INFO, + "[xdslb %p] LocalityEntry %p %s: Creating new %schild policy %s", + parent_.get(), this, name_->AsHumanReadableString(), child_policy_ == nullptr ? "" : "pending ", child_policy_name); } auto& lb_policy = @@ -1910,7 +1963,9 @@ void XdsLb::LocalityMap::LocalityEntry::UpdateLocked( GPR_ASSERT(policy_to_update != nullptr); // Update the policy. if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) { - gpr_log(GPR_INFO, "[xdslb %p] Updating %schild policy %p", this, + gpr_log(GPR_INFO, + "[xdslb %p] LocalityEntry %p %s: Updating %schild policy %p", + parent_.get(), this, name_->AsHumanReadableString(), policy_to_update == pending_child_policy_.get() ? "pending " : "", policy_to_update); } @@ -1918,17 +1973,25 @@ void XdsLb::LocalityMap::LocalityEntry::UpdateLocked( } void XdsLb::LocalityMap::LocalityEntry::ShutdownLocked() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) { + gpr_log(GPR_INFO, + "[xdslb %p] LocalityEntry %p %s: shutting down locality entry", + parent_.get(), this, name_->AsHumanReadableString()); + } // Remove the child policy's interested_parties pollset_set from the // xDS policy. grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(), parent_->interested_parties()); + child_policy_.reset(); if (pending_child_policy_ != nullptr) { grpc_pollset_set_del_pollset_set( pending_child_policy_->interested_parties(), parent_->interested_parties()); + pending_child_policy_.reset(); } - child_policy_.reset(); - pending_child_policy_.reset(); + // Drop our ref to the child's picker, in case it's holding a ref to + // the child. + picker_ref_.reset(); } void XdsLb::LocalityMap::LocalityEntry::ResetBackoffLocked() { @@ -2061,11 +2124,13 @@ void XdsLb::LocalityMap::LocalityEntry::Helper::UpdateState( } else if (num_connecting > 0) { entry_->parent_->channel_control_helper()->UpdateState( GRPC_CHANNEL_CONNECTING, - UniquePtr(New(this->entry_->parent_))); + UniquePtr(New( + this->entry_->parent_->Ref(DEBUG_LOCATION, "QueuePicker")))); } else if (num_idle > 0) { entry_->parent_->channel_control_helper()->UpdateState( GRPC_CHANNEL_IDLE, - UniquePtr(New(this->entry_->parent_))); + UniquePtr(New( + this->entry_->parent_->Ref(DEBUG_LOCATION, "QueuePicker")))); } else { GPR_ASSERT(num_transient_failures == locality_map.size()); grpc_error* error = diff --git a/src/core/ext/filters/client_channel/resolver.h b/src/core/ext/filters/client_channel/resolver.h index 87a4442d75b..829a860040a 100644 --- a/src/core/ext/filters/client_channel/resolver.h +++ b/src/core/ext/filters/client_channel/resolver.h @@ -117,12 +117,10 @@ class Resolver : public InternallyRefCounted { /// implementations. At that point, this method can go away. virtual void ResetBackoffLocked() {} + // Note: This must be invoked while holding the combiner. void Orphan() override { - // Invoke ShutdownAndUnrefLocked() inside of the combiner. - GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_CREATE(&Resolver::ShutdownAndUnrefLocked, this, - grpc_combiner_scheduler(combiner_)), - GRPC_ERROR_NONE); + ShutdownLocked(); + Unref(); } GRPC_ABSTRACT_BASE_CLASS @@ -147,12 +145,6 @@ class Resolver : public InternallyRefCounted { ResultHandler* result_handler() const { return result_handler_.get(); } private: - static void ShutdownAndUnrefLocked(void* arg, grpc_error* ignored) { - Resolver* resolver = static_cast(arg); - resolver->ShutdownLocked(); - resolver->Unref(); - } - UniquePtr result_handler_; grpc_combiner* combiner_; }; diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index dd16eded826..99c7721e5e5 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -86,7 +86,7 @@ ConnectedSubchannel::ConnectedSubchannel( grpc_channel_stack* channel_stack, const grpc_channel_args* args, RefCountedPtr channelz_subchannel, intptr_t socket_uuid) - : ConnectedSubchannelInterface(&grpc_trace_subchannel_refcount), + : RefCounted(&grpc_trace_subchannel_refcount), channel_stack_(channel_stack), args_(grpc_channel_args_copy(args)), channelz_subchannel_(std::move(channelz_subchannel)), @@ -378,12 +378,12 @@ class Subchannel::ConnectedSubchannelStateWatcher { // void Subchannel::ConnectivityStateWatcherList::AddWatcherLocked( - UniquePtr watcher) { + OrphanablePtr watcher) { watchers_.insert(MakePair(watcher.get(), std::move(watcher))); } void Subchannel::ConnectivityStateWatcherList::RemoveWatcherLocked( - ConnectivityStateWatcher* watcher) { + ConnectivityStateWatcherInterface* watcher) { watchers_.erase(watcher); } @@ -438,8 +438,9 @@ class Subchannel::HealthWatcherMap::HealthWatcher grpc_connectivity_state state() const { return state_; } - void AddWatcherLocked(grpc_connectivity_state initial_state, - UniquePtr watcher) { + void AddWatcherLocked( + grpc_connectivity_state initial_state, + OrphanablePtr watcher) { if (state_ != initial_state) { RefCountedPtr connected_subchannel; if (state_ == GRPC_CHANNEL_READY) { @@ -451,7 +452,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher watcher_list_.AddWatcherLocked(std::move(watcher)); } - void RemoveWatcherLocked(ConnectivityStateWatcher* watcher) { + void RemoveWatcherLocked(ConnectivityStateWatcherInterface* watcher) { watcher_list_.RemoveWatcherLocked(watcher); } @@ -527,7 +528,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher void Subchannel::HealthWatcherMap::AddWatcherLocked( Subchannel* subchannel, grpc_connectivity_state initial_state, UniquePtr health_check_service_name, - UniquePtr watcher) { + OrphanablePtr watcher) { // If the health check service name is not already present in the map, // add it. auto it = map_.find(health_check_service_name.get()); @@ -546,7 +547,8 @@ void Subchannel::HealthWatcherMap::AddWatcherLocked( } void Subchannel::HealthWatcherMap::RemoveWatcherLocked( - const char* health_check_service_name, ConnectivityStateWatcher* watcher) { + const char* health_check_service_name, + ConnectivityStateWatcherInterface* watcher) { auto it = map_.find(health_check_service_name); GPR_ASSERT(it != map_.end()); it->second->RemoveWatcherLocked(watcher); @@ -818,7 +820,7 @@ grpc_connectivity_state Subchannel::CheckConnectivityState( void Subchannel::WatchConnectivityState( grpc_connectivity_state initial_state, UniquePtr health_check_service_name, - UniquePtr watcher) { + OrphanablePtr watcher) { MutexLock lock(&mu_); grpc_pollset_set* interested_parties = watcher->interested_parties(); if (interested_parties != nullptr) { @@ -837,7 +839,8 @@ void Subchannel::WatchConnectivityState( } void Subchannel::CancelConnectivityStateWatch( - const char* health_check_service_name, ConnectivityStateWatcher* watcher) { + const char* health_check_service_name, + ConnectivityStateWatcherInterface* watcher) { MutexLock lock(&mu_); grpc_pollset_set* interested_parties = watcher->interested_parties(); if (interested_parties != nullptr) { diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 2f05792b872..9e8de767839 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -23,7 +23,6 @@ #include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/connector.h" -#include "src/core/ext/filters/client_channel/subchannel_interface.h" #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_stack.h" @@ -70,7 +69,7 @@ namespace grpc_core { class SubchannelCall; -class ConnectedSubchannel : public ConnectedSubchannelInterface { +class ConnectedSubchannel : public RefCounted { public: struct CallArgs { grpc_polling_entity* pollent; @@ -97,7 +96,7 @@ class ConnectedSubchannel : public ConnectedSubchannelInterface { grpc_error** error); grpc_channel_stack* channel_stack() const { return channel_stack_; } - const grpc_channel_args* args() const override { return args_; } + const grpc_channel_args* args() const { return args_; } channelz::SubchannelNode* channelz_subchannel() const { return channelz_subchannel_.get(); } @@ -176,10 +175,35 @@ class SubchannelCall { // A subchannel that knows how to connect to exactly one target address. It // provides a target for load balancing. +// +// Note that this is the "real" subchannel implementation, whose API is +// different from the SubchannelInterface that is exposed to LB policy +// implementations. The client channel provides an adaptor class +// (SubchannelWrapper) that "converts" between the two. class Subchannel { public: - typedef SubchannelInterface::ConnectivityStateWatcher - ConnectivityStateWatcher; + class ConnectivityStateWatcherInterface + : public InternallyRefCounted { + public: + virtual ~ConnectivityStateWatcherInterface() = default; + + // Will be invoked whenever the subchannel's connectivity state + // changes. There will be only one invocation of this method on a + // given watcher instance at any given time. + // + // When the state changes to READY, connected_subchannel will + // contain a ref to the connected subchannel. When it changes from + // READY to some other state, the implementation must release its + // ref to the connected subchannel. + virtual void OnConnectivityStateChange( + grpc_connectivity_state new_state, + RefCountedPtr connected_subchannel) // NOLINT + GRPC_ABSTRACT; + + virtual grpc_pollset_set* interested_parties() GRPC_ABSTRACT; + + GRPC_ABSTRACT_BASE_CLASS + }; // The ctor and dtor are not intended to use directly. Subchannel(SubchannelKey* key, grpc_connector* connector, @@ -206,6 +230,8 @@ class Subchannel { // Caller doesn't take ownership. const char* GetTargetAddress(); + const grpc_channel_args* channel_args() const { return args_; } + channelz::SubchannelNode* channelz_node(); // Returns the current connectivity state of the subchannel. @@ -225,14 +251,15 @@ class Subchannel { // changes. // The watcher will be destroyed either when the subchannel is // destroyed or when CancelConnectivityStateWatch() is called. - void WatchConnectivityState(grpc_connectivity_state initial_state, - UniquePtr health_check_service_name, - UniquePtr watcher); + void WatchConnectivityState( + grpc_connectivity_state initial_state, + UniquePtr health_check_service_name, + OrphanablePtr watcher); // Cancels a connectivity state watch. // If the watcher has already been destroyed, this is a no-op. void CancelConnectivityStateWatch(const char* health_check_service_name, - ConnectivityStateWatcher* watcher); + ConnectivityStateWatcherInterface* watcher); // Attempt to connect to the backend. Has no effect if already connected. void AttemptToConnect(); @@ -257,14 +284,15 @@ class Subchannel { grpc_resolved_address* addr); private: - // A linked list of ConnectivityStateWatchers that are monitoring the - // subchannel's state. + // A linked list of ConnectivityStateWatcherInterfaces that are monitoring + // the subchannel's state. class ConnectivityStateWatcherList { public: ~ConnectivityStateWatcherList() { Clear(); } - void AddWatcherLocked(UniquePtr watcher); - void RemoveWatcherLocked(ConnectivityStateWatcher* watcher); + void AddWatcherLocked( + OrphanablePtr watcher); + void RemoveWatcherLocked(ConnectivityStateWatcherInterface* watcher); // Notifies all watchers in the list about a change to state. void NotifyLocked(Subchannel* subchannel, grpc_connectivity_state state); @@ -276,12 +304,13 @@ class Subchannel { private: // TODO(roth): This could be a set instead of a map if we had a set // implementation. - Map> + Map> watchers_; }; - // A map that tracks ConnectivityStateWatchers using a particular health - // check service name. + // A map that tracks ConnectivityStateWatcherInterfaces using a particular + // health check service name. // // There is one entry in the map for each health check service name. // Entries exist only as long as there are watchers using the @@ -291,12 +320,12 @@ class Subchannel { // state READY. class HealthWatcherMap { public: - void AddWatcherLocked(Subchannel* subchannel, - grpc_connectivity_state initial_state, - UniquePtr health_check_service_name, - UniquePtr watcher); + void AddWatcherLocked( + Subchannel* subchannel, grpc_connectivity_state initial_state, + UniquePtr health_check_service_name, + OrphanablePtr watcher); void RemoveWatcherLocked(const char* health_check_service_name, - ConnectivityStateWatcher* watcher); + ConnectivityStateWatcherInterface* watcher); // Notifies the watcher when the subchannel's state changes. void NotifyLocked(grpc_connectivity_state state); diff --git a/src/core/ext/filters/client_channel/subchannel_interface.h b/src/core/ext/filters/client_channel/subchannel_interface.h index 10b1bf124c2..2e448dc5a64 100644 --- a/src/core/ext/filters/client_channel/subchannel_interface.h +++ b/src/core/ext/filters/client_channel/subchannel_interface.h @@ -21,42 +21,22 @@ #include -#include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" namespace grpc_core { -// TODO(roth): In a subsequent PR, remove this from this API. -class ConnectedSubchannelInterface - : public RefCounted { - public: - virtual const grpc_channel_args* args() const GRPC_ABSTRACT; - - protected: - template - explicit ConnectedSubchannelInterface(TraceFlagT* trace_flag = nullptr) - : RefCounted(trace_flag) {} -}; - +// The interface for subchannels that is exposed to LB policy implementations. class SubchannelInterface : public RefCounted { public: - class ConnectivityStateWatcher { + class ConnectivityStateWatcherInterface { public: - virtual ~ConnectivityStateWatcher() = default; + virtual ~ConnectivityStateWatcherInterface() = default; // Will be invoked whenever the subchannel's connectivity state // changes. There will be only one invocation of this method on a // given watcher instance at any given time. - // - // When the state changes to READY, connected_subchannel will - // contain a ref to the connected subchannel. When it changes from - // READY to some other state, the implementation must release its - // ref to the connected subchannel. - virtual void OnConnectivityStateChange( - grpc_connectivity_state new_state, - RefCountedPtr - connected_subchannel) // NOLINT + virtual void OnConnectivityStateChange(grpc_connectivity_state new_state) GRPC_ABSTRACT; // TODO(roth): Remove this as soon as we move to EventManager-based @@ -66,12 +46,14 @@ class SubchannelInterface : public RefCounted { GRPC_ABSTRACT_BASE_CLASS }; + template + explicit SubchannelInterface(TraceFlagT* trace_flag = nullptr) + : RefCounted(trace_flag) {} + virtual ~SubchannelInterface() = default; // Returns the current connectivity state of the subchannel. - virtual grpc_connectivity_state CheckConnectivityState( - RefCountedPtr* connected_subchannel) - GRPC_ABSTRACT; + virtual grpc_connectivity_state CheckConnectivityState() GRPC_ABSTRACT; // Starts watching the subchannel's connectivity state. // The first callback to the watcher will be delivered when the @@ -86,12 +68,12 @@ class SubchannelInterface : public RefCounted { // the previous watcher using CancelConnectivityStateWatch(). virtual void WatchConnectivityState( grpc_connectivity_state initial_state, - UniquePtr watcher) GRPC_ABSTRACT; + UniquePtr watcher) GRPC_ABSTRACT; // Cancels a connectivity state watch. // If the watcher has already been destroyed, this is a no-op. - virtual void CancelConnectivityStateWatch(ConnectivityStateWatcher* watcher) - GRPC_ABSTRACT; + virtual void CancelConnectivityStateWatch( + ConnectivityStateWatcherInterface* watcher) GRPC_ABSTRACT; // Attempt to connect to the backend. Has no effect if already connected. // If the subchannel is currently in backoff delay due to a previously @@ -105,6 +87,9 @@ class SubchannelInterface : public RefCounted { // attempt will be started as soon as AttemptToConnect() is called. virtual void ResetBackoff() GRPC_ABSTRACT; + // TODO(roth): Need a better non-grpc-specific abstraction here. + virtual const grpc_channel_args* channel_args() GRPC_ABSTRACT; + GRPC_ABSTRACT_BASE_CLASS }; diff --git a/src/core/lib/gprpp/map.h b/src/core/lib/gprpp/map.h index 36e32d60c07..566691df580 100644 --- a/src/core/lib/gprpp/map.h +++ b/src/core/lib/gprpp/map.h @@ -30,6 +30,7 @@ #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/pair.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" namespace grpc_core { struct StringLess { @@ -41,6 +42,13 @@ struct StringLess { } }; +template +struct RefCountedPtrLess { + bool operator()(const RefCountedPtr& p1, const RefCountedPtr& p2) { + return p1.get() < p2.get(); + } +}; + namespace testing { class MapTest; } @@ -55,8 +63,28 @@ class Map { typedef Compare key_compare; class iterator; + Map() {} ~Map() { clear(); } + // Copying not currently supported. + Map(const Map& other) = delete; + + // Move support. + Map(Map&& other) : root_(other.root_), size_(other.size_) { + other.root_ = nullptr; + other.size_ = 0; + } + Map& operator=(Map&& other) { + if (this != &other) { + clear(); + root_ = other.root_; + size_ = other.size_; + other.root_ = nullptr; + other.size_ = 0; + } + return *this; + } + T& operator[](key_type&& key); T& operator[](const key_type& key); iterator find(const key_type& k); diff --git a/src/core/lib/iomgr/call_combiner.cc b/src/core/lib/iomgr/call_combiner.cc index 6a4e85de4df..6530d1c6ce6 100644 --- a/src/core/lib/iomgr/call_combiner.cc +++ b/src/core/lib/iomgr/call_combiner.cc @@ -28,7 +28,7 @@ namespace grpc_core { -TraceFlag grpc_call_combiner_trace(false, "call_combiner"); +DebugOnlyTraceFlag grpc_call_combiner_trace(false, "call_combiner"); namespace { diff --git a/src/core/lib/iomgr/call_combiner.h b/src/core/lib/iomgr/call_combiner.h index a10b437c15a..b56966f4196 100644 --- a/src/core/lib/iomgr/call_combiner.h +++ b/src/core/lib/iomgr/call_combiner.h @@ -43,7 +43,7 @@ namespace grpc_core { -extern TraceFlag grpc_call_combiner_trace; +extern DebugOnlyTraceFlag grpc_call_combiner_trace; class CallCombiner { public: diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc index 2fda160f68a..8d01386a8f9 100644 --- a/src/core/lib/iomgr/cfstream_handle.cc +++ b/src/core/lib/iomgr/cfstream_handle.cc @@ -18,6 +18,7 @@ #include +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/port.h" #ifdef GRPC_CFSTREAM @@ -47,7 +48,7 @@ void CFStreamHandle::Release(void* info) { CFStreamHandle* CFStreamHandle::CreateStreamHandle( CFReadStreamRef read_stream, CFWriteStreamRef write_stream) { - return new CFStreamHandle(read_stream, write_stream); + return grpc_core::New(read_stream, write_stream); } void CFStreamHandle::ReadCallback(CFReadStreamRef stream, @@ -188,7 +189,7 @@ void CFStreamHandle::Unref(const char* file, int line, const char* reason) { reason, val, val - 1); } if (gpr_unref(&refcount_)) { - delete this; + grpc_core::Delete(this); } } diff --git a/src/core/lib/iomgr/cfstream_handle.h b/src/core/lib/iomgr/cfstream_handle.h index 4f4d15966e4..05f45ed6251 100644 --- a/src/core/lib/iomgr/cfstream_handle.h +++ b/src/core/lib/iomgr/cfstream_handle.h @@ -29,6 +29,7 @@ #ifdef GRPC_CFSTREAM #import +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/lockfree_event.h" @@ -65,6 +66,9 @@ class CFStreamHandle final { dispatch_queue_t dispatch_queue_; gpr_refcount refcount_; + + GRPC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + GRPC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE }; #ifdef DEBUG diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc index ddafb7b5539..92f81c2efb8 100644 --- a/src/core/lib/iomgr/ev_posix.cc +++ b/src/core/lib/iomgr/ev_posix.cc @@ -44,11 +44,11 @@ GPR_GLOBAL_CONFIG_DEFINE_STRING( "This is a comma-separated list of engines, which are tried in priority " "order first -> last.") -grpc_core::TraceFlag grpc_polling_trace(false, - "polling"); /* Disabled by default */ +grpc_core::DebugOnlyTraceFlag grpc_polling_trace( + false, "polling"); /* Disabled by default */ /* Traces fd create/close operations */ -grpc_core::TraceFlag grpc_fd_trace(false, "fd_trace"); +grpc_core::DebugOnlyTraceFlag grpc_fd_trace(false, "fd_trace"); grpc_core::DebugOnlyTraceFlag grpc_trace_fd_refcount(false, "fd_refcount"); grpc_core::DebugOnlyTraceFlag grpc_polling_api_trace(false, "polling_api"); diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h index 30bb5e40faf..84edabce71e 100644 --- a/src/core/lib/iomgr/ev_posix.h +++ b/src/core/lib/iomgr/ev_posix.h @@ -32,8 +32,9 @@ GPR_GLOBAL_CONFIG_DECLARE_STRING(grpc_poll_strategy); -extern grpc_core::TraceFlag grpc_fd_trace; /* Disabled by default */ -extern grpc_core::TraceFlag grpc_polling_trace; /* Disabled by default */ +extern grpc_core::DebugOnlyTraceFlag grpc_fd_trace; /* Disabled by default */ +extern grpc_core::DebugOnlyTraceFlag + grpc_polling_trace; /* Disabled by default */ #define GRPC_FD_TRACE(format, ...) \ if (GRPC_TRACE_FLAG_ENABLED(grpc_fd_trace)) { \ diff --git a/src/core/lib/iomgr/ev_windows.cc b/src/core/lib/iomgr/ev_windows.cc index 32c62b7a762..e3f5715a873 100644 --- a/src/core/lib/iomgr/ev_windows.cc +++ b/src/core/lib/iomgr/ev_windows.cc @@ -24,7 +24,7 @@ #include "src/core/lib/debug/trace.h" -grpc_core::TraceFlag grpc_polling_trace(false, - "polling"); /* Disabled by default */ +grpc_core::DebugOnlyTraceFlag grpc_polling_trace( + false, "polling"); /* Disabled by default */ #endif // GRPC_WINSOCK_SOCKET diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc index f0c40b4827d..f33485ee59d 100644 --- a/src/core/lib/iomgr/lockfree_event.cc +++ b/src/core/lib/iomgr/lockfree_event.cc @@ -24,7 +24,7 @@ #include "src/core/lib/debug/trace.h" -extern grpc_core::TraceFlag grpc_polling_trace; +extern grpc_core::DebugOnlyTraceFlag grpc_polling_trace; /* 'state' holds the to call when the fd is readable or writable respectively. It can contain one of the following values: diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index 605692ac0d6..63a0269ed62 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -26,6 +26,11 @@ #define GRPC_CUSTOM_SOCKET #endif #endif +/* This needs to be separate from the other conditions because it needs to + * apply to custom sockets too */ +#ifdef GPR_WINDOWS +#define GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY 1 +#endif #if defined(GRPC_CUSTOM_SOCKET) // Do Nothing #elif defined(GPR_MANYLINUX1) @@ -45,7 +50,6 @@ #define GRPC_WINSOCK_SOCKET 1 #define GRPC_WINDOWS_SOCKETUTILS 1 #define GRPC_WINDOWS_SOCKET_ARES_EV_DRIVER 1 -#define GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY 1 #elif defined(GPR_ANDROID) #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_IP_PKTINFO 1 diff --git a/src/core/lib/iomgr/tcp_uv.cc b/src/core/lib/iomgr/tcp_uv.cc index e53ff472fef..f0847a195ca 100644 --- a/src/core/lib/iomgr/tcp_uv.cc +++ b/src/core/lib/iomgr/tcp_uv.cc @@ -53,7 +53,7 @@ typedef struct uv_socket_t { char* read_buf; size_t read_len; - bool pending_connection; + int pending_connections; grpc_custom_socket* accept_socket; grpc_error* accept_error; @@ -206,7 +206,7 @@ static grpc_error* uv_socket_init_helper(uv_socket_t* uv_socket, int domain) { // Node uses a garbage collector to call destructors, so we don't // want to hold the uv loop open with active gRPC objects. uv_unref((uv_handle_t*)uv_socket->handle); - uv_socket->pending_connection = false; + uv_socket->pending_connections = 0; uv_socket->accept_socket = nullptr; uv_socket->accept_error = GRPC_ERROR_NONE; return GRPC_ERROR_NONE; @@ -243,14 +243,14 @@ static grpc_error* uv_socket_getsockname(grpc_custom_socket* socket, static void accept_new_connection(grpc_custom_socket* socket) { uv_socket_t* uv_socket = (uv_socket_t*)socket->impl; - if (!uv_socket->pending_connection || !uv_socket->accept_socket) { + if (uv_socket->pending_connections == 0 || !uv_socket->accept_socket) { return; } grpc_custom_socket* new_socket = uv_socket->accept_socket; grpc_error* error = uv_socket->accept_error; uv_socket->accept_socket = nullptr; uv_socket->accept_error = GRPC_ERROR_NONE; - uv_socket->pending_connection = false; + uv_socket->pending_connections -= 1; if (uv_socket->accept_error != GRPC_ERROR_NONE) { uv_stream_t dummy_handle; uv_accept((uv_stream_t*)uv_socket->handle, &dummy_handle); @@ -270,8 +270,6 @@ static void accept_new_connection(grpc_custom_socket* socket) { static void uv_on_connect(uv_stream_t* server, int status) { grpc_custom_socket* socket = (grpc_custom_socket*)server->data; uv_socket_t* uv_socket = (uv_socket_t*)socket->impl; - GPR_ASSERT(!uv_socket->pending_connection); - uv_socket->pending_connection = true; if (status < 0) { switch (status) { case UV_EINTR: @@ -281,6 +279,7 @@ static void uv_on_connect(uv_stream_t* server, int status) { uv_socket->accept_error = tcp_error_create("accept failed", status); } } + uv_socket->pending_connections += 1; accept_new_connection(socket); } diff --git a/src/core/lib/security/transport/security_handshaker.cc b/src/core/lib/security/transport/security_handshaker.cc index fdc64727b96..3ad04774837 100644 --- a/src/core/lib/security/transport/security_handshaker.cc +++ b/src/core/lib/security/transport/security_handshaker.cc @@ -195,7 +195,7 @@ void SecurityHandshaker::HandshakeFailedLocked(grpc_error* error) { void SecurityHandshaker::OnPeerCheckedInner(grpc_error* error) { MutexLock lock(&mu_); if (error != GRPC_ERROR_NONE || is_shutdown_) { - HandshakeFailedLocked(GRPC_ERROR_REF(error)); + HandshakeFailedLocked(error); return; } // Create zero-copy frame protector, if implemented. @@ -255,7 +255,7 @@ void SecurityHandshaker::OnPeerCheckedInner(grpc_error* error) { void SecurityHandshaker::OnPeerCheckedFn(void* arg, grpc_error* error) { RefCountedPtr(static_cast(arg)) - ->OnPeerCheckedInner(error); + ->OnPeerCheckedInner(GRPC_ERROR_REF(error)); } grpc_error* SecurityHandshaker::CheckPeerLocked() { diff --git a/src/core/lib/slice/slice_buffer.cc b/src/core/lib/slice/slice_buffer.cc index e1929250d4a..2b69f576a3c 100644 --- a/src/core/lib/slice/slice_buffer.cc +++ b/src/core/lib/slice/slice_buffer.cc @@ -32,35 +32,45 @@ /* grow a buffer; requires GRPC_SLICE_BUFFER_INLINE_ELEMENTS > 1 */ #define GROW(x) (3 * (x) / 2) +/* Typically, we do not actually need to embiggen (by calling + * memmove/malloc/realloc) - only if we were up against the full capacity of the + * slice buffer. If do_embiggen is inlined, the compiler clobbers multiple + * registers pointlessly in the common case. */ +static void GPR_ATTRIBUTE_NOINLINE do_embiggen(grpc_slice_buffer* sb, + const size_t slice_count, + const size_t slice_offset) { + if (slice_offset != 0) { + /* Make room by moving elements if there's still space unused */ + memmove(sb->base_slices, sb->slices, sb->count * sizeof(grpc_slice)); + sb->slices = sb->base_slices; + } else { + /* Allocate more memory if no more space is available */ + const size_t new_capacity = GROW(sb->capacity); + sb->capacity = new_capacity; + if (sb->base_slices == sb->inlined) { + sb->base_slices = static_cast( + gpr_malloc(new_capacity * sizeof(grpc_slice))); + memcpy(sb->base_slices, sb->inlined, slice_count * sizeof(grpc_slice)); + } else { + sb->base_slices = static_cast( + gpr_realloc(sb->base_slices, new_capacity * sizeof(grpc_slice))); + } + + sb->slices = sb->base_slices + slice_offset; + } +} + static void maybe_embiggen(grpc_slice_buffer* sb) { if (sb->count == 0) { sb->slices = sb->base_slices; + return; } /* How far away from sb->base_slices is sb->slices pointer */ size_t slice_offset = static_cast(sb->slices - sb->base_slices); size_t slice_count = sb->count + slice_offset; - - if (slice_count == sb->capacity) { - if (sb->base_slices != sb->slices) { - /* Make room by moving elements if there's still space unused */ - memmove(sb->base_slices, sb->slices, sb->count * sizeof(grpc_slice)); - sb->slices = sb->base_slices; - } else { - /* Allocate more memory if no more space is available */ - sb->capacity = GROW(sb->capacity); - GPR_ASSERT(sb->capacity > slice_count); - if (sb->base_slices == sb->inlined) { - sb->base_slices = static_cast( - gpr_malloc(sb->capacity * sizeof(grpc_slice))); - memcpy(sb->base_slices, sb->inlined, slice_count * sizeof(grpc_slice)); - } else { - sb->base_slices = static_cast( - gpr_realloc(sb->base_slices, sb->capacity * sizeof(grpc_slice))); - } - - sb->slices = sb->base_slices + slice_offset; - } + if (GPR_UNLIKELY(slice_count == sb->capacity)) { + do_embiggen(sb, slice_count, slice_offset); } } diff --git a/src/core/lib/transport/metadata.cc b/src/core/lib/transport/metadata.cc index 1523ced16d8..7766ee186c6 100644 --- a/src/core/lib/transport/metadata.cc +++ b/src/core/lib/transport/metadata.cc @@ -222,7 +222,12 @@ void grpc_mdctx_global_shutdown() { abort(); } } + // For ASAN builds, we don't want to crash here, because that will + // prevent ASAN from providing leak detection information, which is + // far more useful than this simple assertion. +#ifndef GRPC_ASAN_ENABLED GPR_DEBUG_ASSERT(shard->count == 0); +#endif gpr_free(shard->elems); } } diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index 29c1e561891..80ffabce0e5 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -90,7 +90,7 @@ void grpc_stream_ref_init(grpc_stream_refcount* refcount, int initial_refs, #endif GRPC_CLOSURE_INIT(&refcount->destroy, cb, cb_arg, grpc_schedule_on_exec_ctx); - new (&refcount->refs) grpc_core::RefCount(); + new (&refcount->refs) grpc_core::RefCount(1, &grpc_trace_stream_refcount); new (&refcount->slice_refcount) grpc_slice_refcount( grpc_slice_refcount::Type::REGULAR, &refcount->refs, slice_stream_destroy, refcount, &refcount->slice_refcount); diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index a6a6e904f08..17608f4bc60 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -80,11 +80,13 @@ inline void grpc_stream_ref(grpc_stream_refcount* refcount, gpr_log(GPR_DEBUG, "%s %p:%p REF %s", refcount->object_type, refcount, refcount->destroy.cb_arg, reason); } + refcount->refs.RefNonZero(DEBUG_LOCATION, reason); +} #else inline void grpc_stream_ref(grpc_stream_refcount* refcount) { -#endif refcount->refs.RefNonZero(); } +#endif void grpc_stream_destroy(grpc_stream_refcount* refcount); @@ -95,13 +97,17 @@ inline void grpc_stream_unref(grpc_stream_refcount* refcount, gpr_log(GPR_DEBUG, "%s %p:%p UNREF %s", refcount->object_type, refcount, refcount->destroy.cb_arg, reason); } + if (GPR_UNLIKELY(refcount->refs.Unref(DEBUG_LOCATION, reason))) { + grpc_stream_destroy(refcount); + } +} #else inline void grpc_stream_unref(grpc_stream_refcount* refcount) { -#endif if (GPR_UNLIKELY(refcount->refs.Unref())) { grpc_stream_destroy(refcount); } } +#endif /* Wrap a buffer that is owned by some stream object into a slice that shares the same refcount */ diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m index 78fe687b3d4..ae60d6208e1 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m @@ -51,9 +51,6 @@ case GRPCCompressGzip: hostConfig.compressAlgorithm = GRPC_COMPRESS_GZIP; break; - case GRPCStreamCompressGzip: - hostConfig.compressAlgorithm = GRPC_COMPRESS_STREAM_GZIP; - break; default: NSLog(@"Invalid compression algorithm"); abort(); diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index b957e11fbea..98511e3f5cb 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -156,8 +156,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { // HTTP/2 keep-alive feature. The parameter \a keepaliveInterval specifies the interval between two // PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the // call should wait for PING ACK. If PING ACK is not received after this period, the call fails. -// Negative values are invalid; setting these parameters to negative value will reset the -// corresponding parameter to the internal default value. +// Negative values are not allowed. @property(readonly) NSTimeInterval keepaliveInterval; @property(readonly) NSTimeInterval keepaliveTimeout; @@ -321,7 +320,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { // PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the // call should wait for PING ACK. If PING ACK is not received after this period, the call fails. // Negative values are invalid; setting these parameters to negative value will reset the -// corresponding parameter to the internal default value. +// corresponding parameter to 0. @property(readwrite) NSTimeInterval keepaliveInterval; @property(readwrite) NSTimeInterval keepaliveTimeout; diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index f02486a7c44..392e42a9d47 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -30,7 +30,7 @@ static const NSUInteger kDefaultResponseSizeLimit = 0; static const GRPCCompressionAlgorithm kDefaultCompressionAlgorithm = GRPCCompressNone; static const BOOL kDefaultRetryEnabled = YES; static const NSTimeInterval kDefaultKeepaliveInterval = 0; -static const NSTimeInterval kDefaultKeepaliveTimeout = -1; +static const NSTimeInterval kDefaultKeepaliveTimeout = 0; static const NSTimeInterval kDefaultConnectMinTimeout = 0; static const NSTimeInterval kDefaultConnectInitialBackoff = 0; static const NSTimeInterval kDefaultConnectMaxBackoff = 0; @@ -181,7 +181,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { _compressionAlgorithm = compressionAlgorithm; _retryEnabled = retryEnabled; _keepaliveInterval = keepaliveInterval < 0 ? 0 : keepaliveInterval; - _keepaliveTimeout = keepaliveTimeout; + _keepaliveTimeout = keepaliveTimeout < 0 ? 0 : keepaliveTimeout; _connectMinTimeout = connectMinTimeout < 0 ? 0 : connectMinTimeout; _connectInitialBackoff = connectInitialBackoff < 0 ? 0 : connectInitialBackoff; _connectMaxBackoff = connectMaxBackoff < 0 ? 0 : connectMaxBackoff; @@ -486,7 +486,11 @@ static BOOL areObjectsEqual(id obj1, id obj2) { } - (void)setKeepaliveTimeout:(NSTimeInterval)keepaliveTimeout { - _keepaliveTimeout = keepaliveTimeout; + if (keepaliveTimeout < 0) { + _keepaliveTimeout = 0; + } else { + _keepaliveTimeout = keepaliveTimeout; + } } - (void)setConnectMinTimeout:(NSTimeInterval)connectMinTimeout { diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 4a187ae9081..1a79fb04a0d 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -109,8 +109,6 @@ if (_callOptions.keepaliveInterval != 0) { args[@GRPC_ARG_KEEPALIVE_TIME_MS] = [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveInterval * 1000)]; - } - if (_callOptions.keepaliveTimeout >= 0) { args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveTimeout * 1000)]; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 24ed83d3341..60a33eda824 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -118,7 +118,9 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; _lastTimedDestroy = nil; grpc_call *unmanagedCall = - [_wrappedChannel unmanagedCallWithPath:path completionQueue:queue callOptions:callOptions]; + [_wrappedChannel unmanagedCallWithPath:path + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:callOptions]; if (unmanagedCall == NULL) { NSAssert(unmanagedCall != NULL, @"Unable to create grpc_call object"); return nil; diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index c4287731efd..24348c3aed7 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -105,11 +105,11 @@ static NSMutableDictionary *gHostCache; options.responseSizeLimit = _responseSizeLimitOverride; options.compressionAlgorithm = (GRPCCompressionAlgorithm)_compressAlgorithm; options.retryEnabled = _retryEnabled; - options.keepaliveInterval = (NSTimeInterval)_keepaliveInterval / 1000.0; - options.keepaliveTimeout = (NSTimeInterval)_keepaliveTimeout / 1000.0; - options.connectMinTimeout = (NSTimeInterval)_minConnectTimeout / 1000.0; - options.connectInitialBackoff = (NSTimeInterval)_initialConnectBackoff / 1000.0; - options.connectMaxBackoff = (NSTimeInterval)_maxConnectBackoff / 1000.0; + options.keepaliveInterval = (NSTimeInterval)_keepaliveInterval / 1000; + options.keepaliveTimeout = (NSTimeInterval)_keepaliveTimeout / 1000; + options.connectMinTimeout = (NSTimeInterval)_minConnectTimeout / 1000; + options.connectInitialBackoff = (NSTimeInterval)_initialConnectBackoff / 1000; + options.connectMaxBackoff = (NSTimeInterval)_maxConnectBackoff / 1000; options.PEMRootCertificates = _PEMRootCertificates; options.PEMPrivateKey = _PEMPrivateKey; options.PEMCertificateChain = _PEMCertificateChain; diff --git a/src/objective-c/tests/CronetTests/InteropTestsRemoteWithCronet.m b/src/objective-c/tests/CronetTests/InteropTestsRemoteWithCronet.m index 30741e9a0da..a2a79c46316 100644 --- a/src/objective-c/tests/CronetTests/InteropTestsRemoteWithCronet.m +++ b/src/objective-c/tests/CronetTests/InteropTestsRemoteWithCronet.m @@ -48,10 +48,6 @@ static int32_t kRemoteInteropServerOverhead = 12; return YES; } -+ (BOOL)canRunCompressionTest { - return NO; -} - - (int32_t)encodingOverhead { return kRemoteInteropServerOverhead; // bytes } diff --git a/src/objective-c/tests/InteropTests/InteropTests.h b/src/objective-c/tests/InteropTests/InteropTests.h index 0c896ae18a8..cffa90ac497 100644 --- a/src/objective-c/tests/InteropTests/InteropTests.h +++ b/src/objective-c/tests/InteropTests/InteropTests.h @@ -64,10 +64,4 @@ */ + (BOOL)useCronet; -/** - * Whether we can run compression tests in the test suite. - */ - -+ (BOOL)canRunCompressionTest; - @end diff --git a/src/objective-c/tests/InteropTests/InteropTests.m b/src/objective-c/tests/InteropTests/InteropTests.m index e55849fecfa..91e133a1300 100644 --- a/src/objective-c/tests/InteropTests/InteropTests.m +++ b/src/objective-c/tests/InteropTests/InteropTests.m @@ -347,10 +347,6 @@ initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager return NO; } -+ (BOOL)canRunCompressionTest { - return YES; -} - + (void)setUp { #ifdef GRPC_COMPILE_WITH_CRONET configureCronet(); @@ -434,16 +430,10 @@ initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager __block BOOL messageReceived = NO; __block BOOL done = NO; - __block BOOL initialMetadataReceived = YES; NSCondition *cond = [[NSCondition alloc] init]; GRPCUnaryProtoCall *call = [_service emptyCallWithMessage:request - responseHandler:[[InteropTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - [cond lock]; - initialMetadataReceived = YES; - [cond unlock]; - } + responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil messageCallback:^(id message) { if (message) { id expectedResponse = [GPBEmpty message]; @@ -469,7 +459,6 @@ initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager while (!done && [deadline timeIntervalSinceNow] > 0) { [cond waitUntilDate:deadline]; } - XCTAssertTrue(initialMetadataReceived); XCTAssertTrue(messageReceived); XCTAssertTrue(done); [cond unlock]; @@ -1025,78 +1014,6 @@ initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -- (void)testInitialMetadataWithV2API { - __weak XCTestExpectation *initialMetadataReceived = - [self expectationWithDescription:@"Received initial metadata."]; - __weak XCTestExpectation *closeReceived = [self expectationWithDescription:@"RPC completed."]; - - __block NSDictionary *init_md = - [NSDictionary dictionaryWithObjectsAndKeys:@"FOOBAR", @"x-grpc-test-echo-initial", nil]; - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.initialMetadata = init_md; - options.transportType = self.class.transportType; - options.PEMRootCertificates = self.class.PEMRootCertificates; - options.hostNameOverride = [[self class] hostNameOverride]; - RMTSimpleRequest *request = [RMTSimpleRequest message]; - __block bool init_md_received = NO; - GRPCUnaryProtoCall *call = [_service - unaryCallWithMessage:request - responseHandler:[[InteropTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - XCTAssertEqualObjects(initialMetadata[@"x-grpc-test-echo-initial"], - init_md[@"x-grpc-test-echo-initial"]); - init_md_received = YES; - [initialMetadataReceived fulfill]; - } - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - XCTAssertNil(error, @"Unexpected error: %@", error); - [closeReceived fulfill]; - }] - callOptions:options]; - - [call start]; - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - -- (void)testTrailingMetadataWithV2API { - // This test needs to be disabled for remote test because interop server grpc-test - // does not send trailing binary metadata. - if (isRemoteInteropTest([[self class] host])) { - return; - } - - __weak XCTestExpectation *expectation = - [self expectationWithDescription:@"Received trailing metadata."]; - const unsigned char raw_bytes[] = {0x1, 0x2, 0x3, 0x4}; - NSData *trailer_data = [NSData dataWithBytes:raw_bytes length:sizeof(raw_bytes)]; - __block NSDictionary *trailer = [NSDictionary - dictionaryWithObjectsAndKeys:trailer_data, @"x-grpc-test-echo-trailing-bin", nil]; - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.initialMetadata = trailer; - options.transportType = self.class.transportType; - options.PEMRootCertificates = self.class.PEMRootCertificates; - options.hostNameOverride = [[self class] hostNameOverride]; - RMTSimpleRequest *request = [RMTSimpleRequest message]; - GRPCUnaryProtoCall *call = [_service - unaryCallWithMessage:request - responseHandler: - [[InteropTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, - NSError *error) { - XCTAssertNil(error, @"Unexpected error: %@", error); - XCTAssertEqualObjects( - trailingMetadata[@"x-grpc-test-echo-trailing-bin"], - trailer[@"x-grpc-test-echo-trailing-bin"]); - [expectation fulfill]; - }] - callOptions:options]; - [call start]; - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - - (void)testCancelAfterFirstResponseRPC { XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = @@ -1231,7 +1148,13 @@ initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -- (void)RPCWithCompressMethod:(GRPCCompressionAlgorithm)compressMethod { +- (void)testCompressedUnaryRPC { + // This test needs to be disabled for remote test because interop server grpc-test + // does not support compression. + if (isRemoteInteropTest([[self class] host])) { + return; + } + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -1239,7 +1162,7 @@ initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager request.responseSize = 314159; request.payload.body = [NSMutableData dataWithLength:271828]; request.expectCompressed.value = YES; - [GRPCCall setDefaultCompressMethod:compressMethod forhost:[[self class] host]]; + [GRPCCall setDefaultCompressMethod:GRPCCompressGzip forhost:[[self class] host]]; [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { @@ -1256,67 +1179,6 @@ initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -- (void)RPCWithCompressMethodWithV2API:(GRPCCompressionAlgorithm)compressMethod { - __weak XCTestExpectation *expectMessage = - [self expectationWithDescription:@"Reived response from server."]; - __weak XCTestExpectation *expectComplete = [self expectationWithDescription:@"RPC completed."]; - - RMTSimpleRequest *request = [RMTSimpleRequest message]; - request.responseType = RMTPayloadType_Compressable; - request.responseSize = 314159; - request.payload.body = [NSMutableData dataWithLength:271828]; - request.expectCompressed.value = YES; - - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.transportType = self.class.transportType; - options.PEMRootCertificates = self.class.PEMRootCertificates; - options.hostNameOverride = [[self class] hostNameOverride]; - options.compressionAlgorithm = compressMethod; - - GRPCUnaryProtoCall *call = [_service - unaryCallWithMessage:request - responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil - messageCallback:^(id message) { - XCTAssertNotNil(message); - if (message) { - RMTSimpleResponse *expectedResponse = - [RMTSimpleResponse message]; - expectedResponse.payload.type = RMTPayloadType_Compressable; - expectedResponse.payload.body = - [NSMutableData dataWithLength:314159]; - XCTAssertEqualObjects(message, expectedResponse); - - [expectMessage fulfill]; - } - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - XCTAssertNil(error, @"Unexpected error: %@", error); - [expectComplete fulfill]; - }] - callOptions:options]; - [call start]; - - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - -- (void)testCompressedUnaryRPC { - if ([[self class] canRunCompressionTest]) { - for (GRPCCompressionAlgorithm compress = GRPCCompressDeflate; - compress <= GRPCStreamCompressGzip; ++compress) { - [self RPCWithCompressMethod:compress]; - } - } -} - -- (void)testCompressedUnaryRPCWithV2API { - if ([[self class] canRunCompressionTest]) { - for (GRPCCompressionAlgorithm compress = GRPCCompressDeflate; - compress <= GRPCStreamCompressGzip; ++compress) { - [self RPCWithCompressMethodWithV2API:compress]; - } - } -} - #ifndef GRPC_COMPILE_WITH_CRONET - (void)testKeepalive { XCTAssertNotNil([[self class] host]); @@ -1358,40 +1220,6 @@ initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - -- (void)testKeepaliveWithV2API { - XCTAssertNotNil([[self class] host]); - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Keepalive"]; - - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.transportType = self.class.transportType; - options.PEMRootCertificates = self.class.PEMRootCertificates; - options.hostNameOverride = [[self class] hostNameOverride]; - options.keepaliveInterval = 1.5; - options.keepaliveTimeout = 0; - - id request = - [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 requestedResponseSize:@31415]; - - __block GRPCStreamingProtoCall *call = [_service - fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:nil - closeCallback:^( - NSDictionary *trailingMetadata, - NSError *error) { - XCTAssertNotNil(error); - XCTAssertEqual( - error.code, - GRPC_STATUS_UNAVAILABLE); - [expectation fulfill]; - }] - callOptions:options]; - [call start]; - [call writeMessage:request]; - - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} #endif - (void)testDefaultInterceptor { diff --git a/src/objective-c/tests/InteropTests/InteropTestsRemote.m b/src/objective-c/tests/InteropTests/InteropTestsRemote.m index 7bd5b28780c..c1cd9b81efc 100644 --- a/src/objective-c/tests/InteropTests/InteropTestsRemote.m +++ b/src/objective-c/tests/InteropTests/InteropTestsRemote.m @@ -49,10 +49,6 @@ static int32_t kRemoteInteropServerOverhead = 12; return nil; } -+ (BOOL)canRunCompressionTest { - return NO; -} - - (int32_t)encodingOverhead { return kRemoteInteropServerOverhead; // bytes } diff --git a/src/objective-c/tests/MacTests/StressTests.m b/src/objective-c/tests/MacTests/StressTests.m index 7475dc77fcc..22174b58665 100644 --- a/src/objective-c/tests/MacTests/StressTests.m +++ b/src/objective-c/tests/MacTests/StressTests.m @@ -29,7 +29,7 @@ #import #import -#define TEST_TIMEOUT 64 +#define TEST_TIMEOUT 32 extern const char *kCFStreamVarName; @@ -136,11 +136,7 @@ extern const char *kCFStreamVarName; return GRPCTransportTypeChttp2BoringSSL; } -- (int)getRandomNumberBetween:(int)min max:(int)max { - return min + arc4random_uniform((max - min + 1)); -} - -- (void)testNetworkFlapOnUnaryCallWithV2API { +- (void)testNetworkFlapWithV2API { NSMutableArray *completeExpectations = [NSMutableArray array]; NSMutableArray *calls = [NSMutableArray array]; int num_rpcs = 100; @@ -179,7 +175,6 @@ extern const char *kCFStreamVarName; UTF8String]); address_removed = YES; } else if (error != nil && !address_readded) { - XCTAssertTrue(address_removed); system([ [NSString stringWithFormat:@"sudo ifconfig lo0 alias %@", [[self class] hostAddress]] @@ -201,241 +196,7 @@ extern const char *kCFStreamVarName; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -- (void)testNetworkFlapOnClientStreamingCallWithV2API { - NSMutableArray *completeExpectations = [NSMutableArray array]; - NSMutableArray *calls = [NSMutableArray array]; - int num_rpcs = 100; - __block BOOL address_removed = FALSE; - __block BOOL address_readded = FALSE; - for (int i = 0; i < num_rpcs; ++i) { - [completeExpectations - addObject:[self expectationWithDescription: - [NSString stringWithFormat:@"Received trailer for RPC %d", i]]]; - - GRPCStreamingProtoCall *call = [_service - streamingInputCallWithResponseHandler: - [[MacTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - @synchronized(self) { - if (error == nil && !address_removed) { - system([[NSString - stringWithFormat:@"sudo ifconfig lo0 -alias %@", - [[self class] hostAddress]] - UTF8String]); - address_removed = YES; - } else if (error != nil && !address_readded) { - XCTAssertTrue(address_removed); - system([[NSString - stringWithFormat:@"sudo ifconfig lo0 alias %@", - [[self class] hostAddress]] - UTF8String]); - address_readded = YES; - } - } - [completeExpectations[i] fulfill]; - }] - callOptions:nil]; - [calls addObject:call]; - } - - for (int i = 0; i < num_rpcs; ++i) { - GRPCStreamingProtoCall *call = calls[i]; - [call start]; - RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message]; - request1.payload.body = [NSMutableData dataWithLength:27182]; - RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message]; - request2.payload.body = [NSMutableData dataWithLength:8]; - - [call writeMessage:request1]; - [NSThread sleepForTimeInterval:0.1f]; - [call writeMessage:request2]; - [call finish]; - } - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - -- (void)testNetworkFlapOnServerStreamingCallWithV2API { - NSMutableArray *completeExpectations = [NSMutableArray array]; - NSMutableArray *calls = [NSMutableArray array]; - int num_rpcs = 100; - __block BOOL address_removed = FALSE; - __block BOOL address_readded = FALSE; - for (int i = 0; i < num_rpcs; ++i) { - [completeExpectations - addObject:[self expectationWithDescription: - [NSString stringWithFormat:@"Received trailer for RPC %d", i]]]; - - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - for (int i = 0; i < 5; i++) { - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = 10000; - [request.responseParametersArray addObject:parameters]; - } - - request.payload.body = [NSMutableData dataWithLength:100]; - - GRPCUnaryProtoCall *call = [_service - streamingOutputCallWithMessage:request - responseHandler: - [[MacTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, - NSError *error) { - @synchronized(self) { - if (error == nil && !address_removed) { - system([[NSString - stringWithFormat: - @"sudo ifconfig lo0 -alias %@", - [[self class] hostAddress]] - UTF8String]); - address_removed = YES; - } else if (error != nil && !address_readded) { - XCTAssertTrue(address_removed); - system([[NSString - stringWithFormat: - @"sudo ifconfig lo0 alias %@", - [[self class] hostAddress]] - UTF8String]); - address_readded = YES; - } - } - [completeExpectations[i] fulfill]; - }] - callOptions:nil]; - [calls addObject:call]; - } - - for (int i = 0; i < num_rpcs; ++i) { - GRPCStreamingProtoCall *call = calls[i]; - [call start]; - [NSThread sleepForTimeInterval:0.1f]; - } - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - -- (void)testNetworkFlapOnHalfDuplexCallWithV2API { - NSMutableArray *completeExpectations = [NSMutableArray array]; - NSMutableArray *calls = [NSMutableArray array]; - int num_rpcs = 100; - __block BOOL address_removed = FALSE; - __block BOOL address_readded = FALSE; - for (int i = 0; i < num_rpcs; ++i) { - [completeExpectations - addObject:[self expectationWithDescription: - [NSString stringWithFormat:@"Received trailer for RPC %d", i]]]; - - GRPCStreamingProtoCall *call = [_service - halfDuplexCallWithResponseHandler: - [[MacTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - @synchronized(self) { - if (error == nil && !address_removed) { - system([[NSString - stringWithFormat:@"sudo ifconfig lo0 -alias %@", - [[self class] hostAddress]] - UTF8String]); - address_removed = YES; - } else if (error != nil && !address_readded) { - XCTAssertTrue(address_removed); - system([[NSString - stringWithFormat:@"sudo ifconfig lo0 alias %@", - [[self class] hostAddress]] - UTF8String]); - address_readded = YES; - } - } - [completeExpectations[i] fulfill]; - }] - callOptions:nil]; - [calls addObject:call]; - } - - for (int i = 0; i < num_rpcs; ++i) { - GRPCStreamingProtoCall *call = calls[i]; - [call start]; - RMTStreamingOutputCallRequest *request1 = [RMTStreamingOutputCallRequest message]; - RMTStreamingOutputCallRequest *request2 = [RMTStreamingOutputCallRequest message]; - for (int i = 0; i < 5; i++) { - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = 1000; - [request1.responseParametersArray addObject:parameters]; - [request2.responseParametersArray addObject:parameters]; - } - - request1.payload.body = [NSMutableData dataWithLength:100]; - request2.payload.body = [NSMutableData dataWithLength:100]; - - [call writeMessage:request1]; - [NSThread sleepForTimeInterval:0.1f]; - [call writeMessage:request2]; - [call finish]; - } - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - -- (void)testNetworkFlapOnFullDuplexCallWithV2API { - NSMutableArray *completeExpectations = [NSMutableArray array]; - NSMutableArray *calls = [NSMutableArray array]; - int num_rpcs = 100; - __block BOOL address_removed = FALSE; - __block BOOL address_readded = FALSE; - for (int i = 0; i < num_rpcs; ++i) { - [completeExpectations - addObject:[self expectationWithDescription: - [NSString stringWithFormat:@"Received trailer for RPC %d", i]]]; - - GRPCStreamingProtoCall *call = [_service - fullDuplexCallWithResponseHandler: - [[MacTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - @synchronized(self) { - if (error == nil && !address_removed) { - system([[NSString - stringWithFormat:@"sudo ifconfig lo0 -alias %@", - [[self class] hostAddress]] - UTF8String]); - address_removed = YES; - } else if (error != nil && !address_readded) { - XCTAssertTrue(address_removed); - system([[NSString - stringWithFormat:@"sudo ifconfig lo0 alias %@", - [[self class] hostAddress]] - UTF8String]); - address_readded = YES; - } - } - [completeExpectations[i] fulfill]; - }] - callOptions:nil]; - [calls addObject:call]; - } - - for (int i = 0; i < num_rpcs; ++i) { - GRPCStreamingProtoCall *call = calls[i]; - [call start]; - - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = 1000; - for (int i = 0; i < 5; i++) { - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - [request.responseParametersArray addObject:parameters]; - request.payload.body = [NSMutableData dataWithLength:100]; - [call writeMessage:request]; - } - [call finish]; - [NSThread sleepForTimeInterval:0.1f]; - } - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - -- (void)testNetworkFlapOnUnaryCallWithV1API { +- (void)testNetworkFlapWithV1API { NSMutableArray *completeExpectations = [NSMutableArray array]; int num_rpcs = 100; __block BOOL address_removed = FALSE; @@ -459,7 +220,6 @@ extern const char *kCFStreamVarName; UTF8String]); address_removed = YES; } else if (error != nil && !address_readded) { - XCTAssertTrue(address_removed); system([[NSString stringWithFormat:@"sudo ifconfig lo0 alias %@", [[self class] hostAddress]] UTF8String]); @@ -474,141 +234,4 @@ extern const char *kCFStreamVarName; } } -- (void)testTimeoutOnFullDuplexCallWithV2API { - NSMutableArray *completeExpectations = [NSMutableArray array]; - NSMutableArray *calls = [NSMutableArray array]; - int num_rpcs = 100; - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.transportType = [[self class] transportType]; - options.PEMRootCertificates = [[self class] PEMRootCertificates]; - options.hostNameOverride = [[self class] hostNameOverride]; - options.timeout = 0.3; - for (int i = 0; i < num_rpcs; ++i) { - [completeExpectations - addObject:[self expectationWithDescription: - [NSString stringWithFormat:@"Received trailer for RPC %d", i]]]; - - GRPCStreamingProtoCall *call = [_service - fullDuplexCallWithResponseHandler: - [[MacTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - if (error != nil) { - XCTAssertEqual(error.code, GRPC_STATUS_DEADLINE_EXCEEDED); - } - [completeExpectations[i] fulfill]; - }] - callOptions:options]; - [calls addObject:call]; - } - - for (int i = 0; i < num_rpcs; ++i) { - GRPCStreamingProtoCall *call = calls[i]; - [call start]; - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = 1000; - // delay response by 100-200 milliseconds - parameters.intervalUs = [self getRandomNumberBetween:100 * 1000 max:200 * 1000]; - [request.responseParametersArray addObject:parameters]; - request.payload.body = [NSMutableData dataWithLength:100]; - - [call writeMessage:request]; - [call writeMessage:request]; - [call finish]; - } - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - -- (void)testServerStreamingCallSlowClientWithV2API { - NSMutableArray *completeExpectations = [NSMutableArray array]; - NSMutableArray *calls = [NSMutableArray array]; - int num_rpcs = 100; - dispatch_queue_t q = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT); - for (int i = 0; i < num_rpcs; ++i) { - [completeExpectations - addObject:[self expectationWithDescription: - [NSString stringWithFormat:@"Received trailer for RPC %d", i]]]; - - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - for (int i = 0; i < 5; i++) { - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = 10000; - [request.responseParametersArray addObject:parameters]; - [request.responseParametersArray addObject:parameters]; - [request.responseParametersArray addObject:parameters]; - [request.responseParametersArray addObject:parameters]; - [request.responseParametersArray addObject:parameters]; - } - - request.payload.body = [NSMutableData dataWithLength:100]; - - GRPCUnaryProtoCall *call = [_service - streamingOutputCallWithMessage:request - responseHandler:[[MacTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:^(id message) { - // inject a delay - [NSThread sleepForTimeInterval:0.5f]; - } - closeCallback:^(NSDictionary *trailingMetadata, - NSError *error) { - XCTAssertNil(error, @"Unexpected error: %@", error); - [completeExpectations[i] fulfill]; - }] - callOptions:nil]; - [calls addObject:call]; - } - - for (int i = 0; i < num_rpcs; ++i) { - dispatch_async(q, ^{ - GRPCStreamingProtoCall *call = calls[i]; - [call start]; - }); - } - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - -- (void)testCancelOnFullDuplexCallWithV2API { - NSMutableArray *completeExpectations = [NSMutableArray array]; - NSMutableArray *calls = [NSMutableArray array]; - int num_rpcs = 100; - dispatch_queue_t q = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT); - for (int i = 0; i < num_rpcs; ++i) { - [completeExpectations - addObject:[self expectationWithDescription: - [NSString stringWithFormat:@"Received trailer for RPC %d", i]]]; - - GRPCStreamingProtoCall *call = [_service - fullDuplexCallWithResponseHandler:[[MacTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:nil - closeCallback:^( - NSDictionary *trailingMetadata, - NSError *error) { - [completeExpectations[i] fulfill]; - }] - callOptions:nil]; - [calls addObject:call]; - } - - for (int i = 0; i < num_rpcs; ++i) { - GRPCStreamingProtoCall *call = calls[i]; - [call start]; - dispatch_async(q, ^{ - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = 1000; - for (int i = 0; i < 100; i++) { - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - [request.responseParametersArray addObject:parameters]; - [call writeMessage:request]; - } - [NSThread sleepForTimeInterval:0.01f]; - [call cancel]; - }); - } - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - @end diff --git a/src/objective-c/tests/UnitTests/APIv2Tests.m b/src/objective-c/tests/UnitTests/APIv2Tests.m index 066800613f6..db293750ca3 100644 --- a/src/objective-c/tests/UnitTests/APIv2Tests.m +++ b/src/objective-c/tests/UnitTests/APIv2Tests.m @@ -21,11 +21,6 @@ #import #import -#import "../../GRPCClient/private/GRPCCallInternal.h" -#import "../../GRPCClient/private/GRPCChannel.h" -#import "../../GRPCClient/private/GRPCChannelPool.h" -#import "../../GRPCClient/private/GRPCWrappedCall.h" - #include #include @@ -53,41 +48,12 @@ static const int kSimpleDataLength = 100; static const NSTimeInterval kTestTimeout = 8; static const NSTimeInterval kInvertedTimeout = 2; -// Reveal the _class ivars for testing access +// Reveal the _class ivar for testing access @interface GRPCCall2 () { - @public - id _firstInterceptor; -} -@end - -@interface GRPCCall2Internal () { @public GRPCCall *_call; } -@end - -@interface GRPCCall () { - @public - GRPCWrappedCall *_wrappedCall; -} -@end - -@interface GRPCWrappedCall () { - @public - GRPCPooledChannel *_pooledChannel; -} -@end - -@interface GRPCPooledChannel () { - @public - GRPCChannel *_wrappedChannel; -} -@end -@interface GRPCChannel () { - @public - grpc_channel *_unmanagedChannel; -} @end // Convenience class to use blocks as callbacks @@ -182,7 +148,6 @@ static const NSTimeInterval kInvertedTimeout = 2; kOutputStreamingCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"StreamingOutputCall"]; - kFullDuplexCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"FullDuplexCall"]; } @@ -214,7 +179,7 @@ static const NSTimeInterval kInvertedTimeout = 2; closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { trailing_md = trailingMetadata; if (error) { - XCTAssertEqual(error.code, GRPCErrorCodeUnauthenticated, + XCTAssertEqual(error.code, 16, @"Finished with unexpected error: %@", error); XCTAssertEqualObjects(init_md, error.userInfo[kGRPCHeadersKey]); @@ -794,7 +759,7 @@ static const NSTimeInterval kInvertedTimeout = 2; } closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { XCTAssertNotNil(error, @"Expecting non-nil error"); - XCTAssertEqual(error.code, GRPCErrorCodeUnknown); + XCTAssertEqual(error.code, 2); [completion fulfill]; }] callOptions:options]; @@ -805,293 +770,4 @@ static const NSTimeInterval kInvertedTimeout = 2; [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; } -- (void)testAdditionalChannelArgs { - __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; - - GRPCRequestOptions *requestOptions = - [[GRPCRequestOptions alloc] initWithHost:kHostAddress - path:kUnaryCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - // set max message length = 1 byte. - options.additionalChannelArgs = - [NSDictionary dictionaryWithObjectsAndKeys:@1, @GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, nil]; - options.transportType = GRPCTransportTypeInsecure; - - RMTSimpleRequest *request = [RMTSimpleRequest message]; - request.payload.body = [NSMutableData dataWithLength:options.responseSizeLimit]; - - GRPCCall2 *call = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions - responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil - messageCallback:^(NSData *data) { - XCTFail(@"Received unexpected message"); - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - XCTAssertNotNil(error, @"Expecting non-nil error"); - NSLog(@"Got error: %@", error); - XCTAssertEqual(error.code, GRPCErrorCodeResourceExhausted, - @"Finished with unexpected error: %@", error); - - [completion fulfill]; - }] - callOptions:options]; - [call writeData:[request data]]; - [call start]; - [call finish]; - - [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; -} - -- (void)testChannelReuseIdentical { - __weak XCTestExpectation *completion1 = [self expectationWithDescription:@"RPC1 completed."]; - __weak XCTestExpectation *completion2 = [self expectationWithDescription:@"RPC2 completed."]; - NSArray *rpcDone = [NSArray arrayWithObjects:completion1, completion2, nil]; - __weak XCTestExpectation *metadata1 = - [self expectationWithDescription:@"Received initial metadata for RPC1."]; - __weak XCTestExpectation *metadata2 = - [self expectationWithDescription:@"Received initial metadata for RPC2."]; - NSArray *initialMetadataDone = [NSArray arrayWithObjects:metadata1, metadata2, nil]; - - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = kSimpleDataLength; - [request.responseParametersArray addObject:parameters]; - request.payload.body = [NSMutableData dataWithLength:kSimpleDataLength]; - - GRPCRequestOptions *requestOptions = - [[GRPCRequestOptions alloc] initWithHost:kHostAddress - path:kFullDuplexCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; - GRPCMutableCallOptions *callOptions = [[GRPCMutableCallOptions alloc] init]; - callOptions.transportType = GRPCTransportTypeInsecure; - GRPCCall2 *call1 = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions - responseHandler:[[ClientTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - [metadata1 fulfill]; - } - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - [completion1 fulfill]; - }] - callOptions:callOptions]; - GRPCCall2 *call2 = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions - responseHandler:[[ClientTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - [metadata2 fulfill]; - } - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - [completion2 fulfill]; - }] - callOptions:callOptions]; - [call1 start]; - [call2 start]; - [call1 writeData:[request data]]; - [call2 writeData:[request data]]; - [self waitForExpectations:initialMetadataDone timeout:kTestTimeout]; - GRPCCall2Internal *internalCall1 = call1->_firstInterceptor; - GRPCCall2Internal *internalCall2 = call2->_firstInterceptor; - XCTAssertEqual( - internalCall1->_call->_wrappedCall->_pooledChannel->_wrappedChannel->_unmanagedChannel, - internalCall2->_call->_wrappedCall->_pooledChannel->_wrappedChannel->_unmanagedChannel); - [call1 finish]; - [call2 finish]; - [self waitForExpectations:rpcDone timeout:kTestTimeout]; -} - -- (void)testChannelReuseDifferentCallSafety { - __weak XCTestExpectation *completion1 = [self expectationWithDescription:@"RPC1 completed."]; - __weak XCTestExpectation *completion2 = [self expectationWithDescription:@"RPC2 completed."]; - NSArray *rpcDone = [NSArray arrayWithObjects:completion1, completion2, nil]; - __weak XCTestExpectation *metadata1 = - [self expectationWithDescription:@"Received initial metadata for RPC1."]; - __weak XCTestExpectation *metadata2 = - [self expectationWithDescription:@"Received initial metadata for RPC2."]; - NSArray *initialMetadataDone = [NSArray arrayWithObjects:metadata1, metadata2, nil]; - - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = kSimpleDataLength; - [request.responseParametersArray addObject:parameters]; - request.payload.body = [NSMutableData dataWithLength:kSimpleDataLength]; - - GRPCRequestOptions *requestOptions1 = - [[GRPCRequestOptions alloc] initWithHost:kHostAddress - path:kFullDuplexCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; - GRPCRequestOptions *requestOptions2 = - [[GRPCRequestOptions alloc] initWithHost:kHostAddress - path:kFullDuplexCallMethod.HTTPPath - safety:GRPCCallSafetyIdempotentRequest]; - - GRPCMutableCallOptions *callOptions = [[GRPCMutableCallOptions alloc] init]; - callOptions.transportType = GRPCTransportTypeInsecure; - GRPCCall2 *call1 = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions1 - responseHandler:[[ClientTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - [metadata1 fulfill]; - } - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - [completion1 fulfill]; - }] - callOptions:callOptions]; - GRPCCall2 *call2 = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions2 - responseHandler:[[ClientTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - [metadata2 fulfill]; - } - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - [completion2 fulfill]; - }] - callOptions:callOptions]; - [call1 start]; - [call2 start]; - [call1 writeData:[request data]]; - [call2 writeData:[request data]]; - [self waitForExpectations:initialMetadataDone timeout:kTestTimeout]; - GRPCCall2Internal *internalCall1 = call1->_firstInterceptor; - GRPCCall2Internal *internalCall2 = call2->_firstInterceptor; - XCTAssertEqual( - internalCall1->_call->_wrappedCall->_pooledChannel->_wrappedChannel->_unmanagedChannel, - internalCall2->_call->_wrappedCall->_pooledChannel->_wrappedChannel->_unmanagedChannel); - [call1 finish]; - [call2 finish]; - [self waitForExpectations:rpcDone timeout:kTestTimeout]; -} - -- (void)testChannelReuseDifferentHost { - __weak XCTestExpectation *completion1 = [self expectationWithDescription:@"RPC1 completed."]; - __weak XCTestExpectation *completion2 = [self expectationWithDescription:@"RPC2 completed."]; - NSArray *rpcDone = [NSArray arrayWithObjects:completion1, completion2, nil]; - __weak XCTestExpectation *metadata1 = - [self expectationWithDescription:@"Received initial metadata for RPC1."]; - __weak XCTestExpectation *metadata2 = - [self expectationWithDescription:@"Received initial metadata for RPC2."]; - NSArray *initialMetadataDone = [NSArray arrayWithObjects:metadata1, metadata2, nil]; - - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = kSimpleDataLength; - [request.responseParametersArray addObject:parameters]; - request.payload.body = [NSMutableData dataWithLength:kSimpleDataLength]; - - GRPCRequestOptions *requestOptions1 = - [[GRPCRequestOptions alloc] initWithHost:@"[::1]:5050" - path:kFullDuplexCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; - GRPCRequestOptions *requestOptions2 = - [[GRPCRequestOptions alloc] initWithHost:@"127.0.0.1:5050" - path:kFullDuplexCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; - - GRPCMutableCallOptions *callOptions = [[GRPCMutableCallOptions alloc] init]; - callOptions.transportType = GRPCTransportTypeInsecure; - - GRPCCall2 *call1 = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions1 - responseHandler:[[ClientTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - [metadata1 fulfill]; - } - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - [completion1 fulfill]; - }] - callOptions:callOptions]; - GRPCCall2 *call2 = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions2 - responseHandler:[[ClientTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - [metadata2 fulfill]; - } - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - [completion2 fulfill]; - }] - callOptions:callOptions]; - [call1 start]; - [call2 start]; - [call1 writeData:[request data]]; - [call2 writeData:[request data]]; - [self waitForExpectations:initialMetadataDone timeout:kTestTimeout]; - GRPCCall2Internal *internalCall1 = call1->_firstInterceptor; - GRPCCall2Internal *internalCall2 = call2->_firstInterceptor; - XCTAssertNotEqual( - internalCall1->_call->_wrappedCall->_pooledChannel->_wrappedChannel->_unmanagedChannel, - internalCall2->_call->_wrappedCall->_pooledChannel->_wrappedChannel->_unmanagedChannel); - [call1 finish]; - [call2 finish]; - [self waitForExpectations:rpcDone timeout:kTestTimeout]; -} - -- (void)testChannelReuseDifferentChannelArgs { - __weak XCTestExpectation *completion1 = [self expectationWithDescription:@"RPC1 completed."]; - __weak XCTestExpectation *completion2 = [self expectationWithDescription:@"RPC2 completed."]; - NSArray *rpcDone = [NSArray arrayWithObjects:completion1, completion2, nil]; - __weak XCTestExpectation *metadata1 = - [self expectationWithDescription:@"Received initial metadata for RPC1."]; - __weak XCTestExpectation *metadata2 = - [self expectationWithDescription:@"Received initial metadata for RPC2."]; - NSArray *initialMetadataDone = [NSArray arrayWithObjects:metadata1, metadata2, nil]; - - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = kSimpleDataLength; - [request.responseParametersArray addObject:parameters]; - request.payload.body = [NSMutableData dataWithLength:kSimpleDataLength]; - - GRPCRequestOptions *requestOptions = - [[GRPCRequestOptions alloc] initWithHost:kHostAddress - path:kFullDuplexCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; - GRPCMutableCallOptions *callOptions1 = [[GRPCMutableCallOptions alloc] init]; - callOptions1.transportType = GRPCTransportTypeInsecure; - GRPCMutableCallOptions *callOptions2 = [[GRPCMutableCallOptions alloc] init]; - callOptions2.transportType = GRPCTransportTypeInsecure; - callOptions2.channelID = 2; - - GRPCCall2 *call1 = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions - responseHandler:[[ClientTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - [metadata1 fulfill]; - } - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - [completion1 fulfill]; - }] - callOptions:callOptions1]; - GRPCCall2 *call2 = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions - responseHandler:[[ClientTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - [metadata2 fulfill]; - } - messageCallback:nil - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - [completion2 fulfill]; - }] - callOptions:callOptions2]; - [call1 start]; - [call2 start]; - [call1 writeData:[request data]]; - [call2 writeData:[request data]]; - [self waitForExpectations:initialMetadataDone timeout:kTestTimeout]; - GRPCCall2Internal *internalCall1 = call1->_firstInterceptor; - GRPCCall2Internal *internalCall2 = call2->_firstInterceptor; - XCTAssertNotEqual( - internalCall1->_call->_wrappedCall->_pooledChannel->_wrappedChannel->_unmanagedChannel, - internalCall2->_call->_wrappedCall->_pooledChannel->_wrappedChannel->_unmanagedChannel); - [call1 finish]; - [call2 finish]; - [self waitForExpectations:rpcDone timeout:kTestTimeout]; -} - @end diff --git a/templates/tools/dockerfile/test/python_stretch_3.8_x64/Dockerfile.template b/templates/tools/dockerfile/test/python_stretch_3.8_x64/Dockerfile.template new file mode 100644 index 00000000000..8f2585a4d59 --- /dev/null +++ b/templates/tools/dockerfile/test/python_stretch_3.8_x64/Dockerfile.template @@ -0,0 +1,28 @@ + +%YAML 1.2 +--- | + # Copyright 2019 The gRPC Authors + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + + <%include file="../../python_stretch.include"/> + RUN apt-get install -y jq zlib1g-dev libssl-dev + + COPY get_cpython.sh /tmp + RUN apt-get install -y jq build-essential libffi-dev && ${'\\'} + chmod +x /tmp/get_cpython.sh && ${'\\'} + /tmp/get_cpython.sh && ${'\\'} + rm /tmp/get_cpython.sh + + RUN python3.8 -m ensurepip && ${'\\'} + python3.8 -m pip install coverage diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py index 6a40b4e5e9d..bd311ccfd90 100755 --- a/test/core/bad_client/gen_build_yaml.py +++ b/test/core/bad_client/gen_build_yaml.py @@ -45,7 +45,7 @@ def main(): { 'name': 'bad_client_test', 'build': 'private', - 'language': 'c', + 'language': 'c++', 'src': [ 'test/core/bad_client/bad_client.cc' ], @@ -64,7 +64,7 @@ def main(): 'name': '%s_bad_client_test' % t, 'cpu_cost': BAD_CLIENT_TESTS[t].cpu_cost, 'build': 'test', - 'language': 'c', + 'language': 'c++', 'secure': 'no', 'src': ['test/core/bad_client/tests/%s.cc' % t], 'vs_proj_dir': 'test', diff --git a/test/core/bad_client/generate_tests.bzl b/test/core/bad_client/generate_tests.bzl index 2769d5c3bb6..9ff55877c53 100755 --- a/test/core/bad_client/generate_tests.bzl +++ b/test/core/bad_client/generate_tests.bzl @@ -42,6 +42,10 @@ def grpc_bad_client_tests(): name = 'bad_client_test', srcs = ['bad_client.cc'], hdrs = ['bad_client.h'], + external_deps = [ + "gtest", + ], + language = "C++", deps = ['//test/core/util:grpc_test_util', '//:grpc', '//:gpr', '//test/core/end2end:cq_verifier'] ) for t, topt in BAD_CLIENT_TESTS.items(): diff --git a/test/core/bad_client/tests/unknown_frame.cc b/test/core/bad_client/tests/unknown_frame.cc index 9e0cf3f6a90..e58166ccd56 100644 --- a/test/core/bad_client/tests/unknown_frame.cc +++ b/test/core/bad_client/tests/unknown_frame.cc @@ -16,13 +16,14 @@ * */ +#include + +#include + +#include #include "src/core/lib/surface/server.h" #include "test/core/bad_client/bad_client.h" -#define PFX_STR \ - "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \ - "\x00\x00\x00\x04\x00\x00\x00\x00\x00" - static void verifier(grpc_server* server, grpc_completion_queue* cq, void* registered_method) { while (grpc_server_has_open_connections(server)) { @@ -32,15 +33,33 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } } +#define APPEND_BUFFER(string, to_append) \ + ((string).append((to_append), sizeof(to_append) - 1)) + +namespace { +TEST(UnknownFrameType, Test) { + /* test that all invalid/unknown frame types are handled */ + for (int i = 10; i <= 255; i++) { + std::string unknown_frame_string; + APPEND_BUFFER(unknown_frame_string, "\x00\x00\x00"); + char frame_type = static_cast(i); + unknown_frame_string.append(&frame_type, 1); + APPEND_BUFFER(unknown_frame_string, "\x00\x00\x00\x00\x01"); + grpc_bad_client_arg args[2]; + args[0] = connection_preface_arg; + args[1].client_validator = nullptr; + args[1].client_payload = unknown_frame_string.c_str(); + args[1].client_payload_length = unknown_frame_string.size(); + grpc_run_bad_client_test(verifier, args, 2, GRPC_BAD_CLIENT_DISCONNECT); + } +} +} // namespace + int main(int argc, char** argv) { grpc_init(); grpc::testing::TestEnvironment env(argc, argv); - - /* test adding prioritization data */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, - PFX_STR "\x00\x00\x00\x88\x00\x00\x00\x00\x01", - GRPC_BAD_CLIENT_DISCONNECT); - + ::testing::InitGoogleTest(&argc, argv); + int retval = RUN_ALL_TESTS(); grpc_shutdown(); - return 0; + return retval; } diff --git a/test/core/gprpp/map_test.cc b/test/core/gprpp/map_test.cc index 30d9eb0b207..21aeee82486 100644 --- a/test/core/gprpp/map_test.cc +++ b/test/core/gprpp/map_test.cc @@ -437,6 +437,35 @@ TEST_F(MapTest, LowerBound) { EXPECT_EQ(it, test_map.end()); } +// Test move ctor +TEST_F(MapTest, MoveCtor) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], Payload(i)); + } + Map test_map2 = std::move(test_map); + for (int i = 0; i < 5; i++) { + EXPECT_EQ(test_map.end(), test_map.find(kKeys[i])); + EXPECT_EQ(i, test_map2.find(kKeys[i])->second.data()); + } +} + +// Test move assignment +TEST_F(MapTest, MoveAssignment) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], Payload(i)); + } + Map test_map2; + test_map2.emplace("xxx", Payload(123)); + test_map2 = std::move(test_map); + for (int i = 0; i < 5; i++) { + EXPECT_EQ(test_map.end(), test_map.find(kKeys[i])); + EXPECT_EQ(i, test_map2.find(kKeys[i])->second.data()); + } + EXPECT_EQ(test_map2.end(), test_map2.find("xxx")); +} + } // namespace testing } // namespace grpc_core diff --git a/test/core/util/test_lb_policies.cc b/test/core/util/test_lb_policies.cc index 2c1f988d173..041ce1f45a1 100644 --- a/test/core/util/test_lb_policies.cc +++ b/test/core/util/test_lb_policies.cc @@ -117,7 +117,7 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy PickResult Pick(PickArgs args) override { PickResult result = delegate_picker_->Pick(args); if (result.type == PickResult::PICK_COMPLETE && - result.connected_subchannel != nullptr) { + result.subchannel != nullptr) { new (args.call_state->Alloc(sizeof(TrailingMetadataHandler))) TrailingMetadataHandler(&result, cb_, user_data_); } diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc index cf55efa5409..6570bbf9696 100644 --- a/test/cpp/interop/interop_server.cc +++ b/test/cpp/interop/interop_server.cc @@ -118,8 +118,7 @@ bool CheckExpectedCompression(const ServerContext& context, "Expected compression but got uncompressed request from client."); return false; } - if (!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS) && - received_compression != GRPC_COMPRESS_STREAM_GZIP) { + if (!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS)) { gpr_log(GPR_ERROR, "Failure: Requested compression in a compressable request, but " "compression bit in message flags not set."); diff --git a/tools/dockerfile/test/python_stretch_3.8_x64/Dockerfile b/tools/dockerfile/test/python_stretch_3.8_x64/Dockerfile new file mode 100644 index 00000000000..d5ecbc7110a --- /dev/null +++ b/tools/dockerfile/test/python_stretch_3.8_x64/Dockerfile @@ -0,0 +1,79 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM debian:stretch + +# Install Git and basic packages. +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + dnsutils \ + gcc \ + gcc-multilib \ + git \ + golang \ + gyp \ + lcov \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + perl \ + strace \ + python-dev \ + python-setuptools \ + python-yaml \ + telnet \ + unzip \ + wget \ + zip && apt-get clean + +#================ +# Build profiling +RUN apt-get update && apt-get install -y time && apt-get clean + +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client oauth2client + +# Install Python 2.7 +RUN apt-get update && apt-get install -y python2.7 python-all-dev +RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7 + +# Add Debian 'testing' repository +RUN echo 'deb http://ftp.de.debian.org/debian testing main' >> /etc/apt/sources.list +RUN echo 'APT::Default-Release "stable";' | tee -a /etc/apt/apt.conf.d/00local + + +RUN mkdir /var/local/jenkins + +# Define the default command. +CMD ["bash"] + +RUN apt-get install -y jq zlib1g-dev libssl-dev + +COPY get_cpython.sh /tmp +RUN apt-get install -y jq build-essential libffi-dev && \ + chmod +x /tmp/get_cpython.sh && \ + /tmp/get_cpython.sh && \ + rm /tmp/get_cpython.sh + +RUN python3.8 -m ensurepip && \ + python3.8 -m pip install coverage diff --git a/tools/dockerfile/test/python_stretch_3.8_x64/get_cpython.sh b/tools/dockerfile/test/python_stretch_3.8_x64/get_cpython.sh new file mode 100644 index 00000000000..e051e974b38 --- /dev/null +++ b/tools/dockerfile/test/python_stretch_3.8_x64/get_cpython.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +VERSION_REGEX="v3.8.*" +REPO="python/cpython" + +LATEST=$(curl -s https://api.github.com/repos/$REPO/tags | \ + jq -r '.[] | select(.name|test("'$VERSION_REGEX'")) | .name' \ + | sort | tail -n1) + +wget https://github.com/$REPO/archive/$LATEST.tar.gz +tar xzvf *.tar.gz +( cd cpython* + ./configure + make install +) diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 12827875e32..6860b8b42ef 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -5292,7 +5292,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "badreq_bad_client_test", "src": [ "test/core/bad_client/tests/badreq.cc" @@ -5309,7 +5309,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "connection_prefix_bad_client_test", "src": [ "test/core/bad_client/tests/connection_prefix.cc" @@ -5326,7 +5326,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "duplicate_header_bad_client_test", "src": [ "test/core/bad_client/tests/duplicate_header.cc" @@ -5343,7 +5343,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "head_of_line_blocking_bad_client_test", "src": [ "test/core/bad_client/tests/head_of_line_blocking.cc" @@ -5360,7 +5360,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "headers_bad_client_test", "src": [ "test/core/bad_client/tests/headers.cc" @@ -5377,7 +5377,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "initial_settings_frame_bad_client_test", "src": [ "test/core/bad_client/tests/initial_settings_frame.cc" @@ -5394,7 +5394,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "large_metadata_bad_client_test", "src": [ "test/core/bad_client/tests/large_metadata.cc" @@ -5411,7 +5411,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "server_registered_method_bad_client_test", "src": [ "test/core/bad_client/tests/server_registered_method.cc" @@ -5428,7 +5428,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "simple_request_bad_client_test", "src": [ "test/core/bad_client/tests/simple_request.cc" @@ -5445,7 +5445,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "unknown_frame_bad_client_test", "src": [ "test/core/bad_client/tests/unknown_frame.cc" @@ -5462,7 +5462,7 @@ ], "headers": [], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "window_overflow_bad_client_test", "src": [ "test/core/bad_client/tests/window_overflow.cc" @@ -7756,7 +7756,7 @@ "test/core/bad_client/bad_client.h" ], "is_filegroup": false, - "language": "c", + "language": "c++", "name": "bad_client_test", "src": [ "test/core/bad_client/bad_client.cc", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 545d9c77233..8a5d0a60e82 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -5958,7 +5958,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "badreq_bad_client_test", "platforms": [ "linux", @@ -5984,7 +5984,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "connection_prefix_bad_client_test", "platforms": [ "linux", @@ -6010,7 +6010,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "duplicate_header_bad_client_test", "platforms": [ "linux", @@ -6036,7 +6036,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "head_of_line_blocking_bad_client_test", "platforms": [ "linux", @@ -6062,7 +6062,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "headers_bad_client_test", "platforms": [ "linux", @@ -6088,7 +6088,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "initial_settings_frame_bad_client_test", "platforms": [ "linux", @@ -6114,7 +6114,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "large_metadata_bad_client_test", "platforms": [ "linux", @@ -6140,7 +6140,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "server_registered_method_bad_client_test", "platforms": [ "linux", @@ -6166,7 +6166,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "simple_request_bad_client_test", "platforms": [ "linux", @@ -6192,7 +6192,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "unknown_frame_bad_client_test", "platforms": [ "linux", @@ -6218,7 +6218,7 @@ ], "flaky": false, "gtest": false, - "language": "c", + "language": "c++", "name": "window_overflow_bad_client_test", "platforms": [ "linux", diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index a7a9dbd48d0..43d8c64da0b 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -753,7 +753,7 @@ class PythonLanguage(object): def _python_manager_name(self): """Choose the docker image to use based on python version.""" if self.args.compiler in [ - 'python2.7', 'python3.5', 'python3.6', 'python3.7' + 'python2.7', 'python3.5', 'python3.6', 'python3.7', 'python3.8' ]: return 'stretch_' + self.args.compiler[len('python'):] elif self.args.compiler == 'python_alpine': @@ -829,6 +829,12 @@ class PythonLanguage(object): minor='7', bits=bits, config_vars=config_vars) + python38_config = _python_config_generator( + name='py38', + major='3', + minor='8', + bits=bits, + config_vars=config_vars) pypy27_config = _pypy_config_generator( name='pypy', major='2', config_vars=config_vars) pypy32_config = _pypy_config_generator( @@ -852,6 +858,8 @@ class PythonLanguage(object): return (python36_config,) elif args.compiler == 'python3.7': return (python37_config,) + elif args.compiler == 'python3.8': + return (python38_config,) elif args.compiler == 'pypy': return (pypy27_config,) elif args.compiler == 'pypy3': @@ -865,6 +873,7 @@ class PythonLanguage(object): python35_config, python36_config, python37_config, + # TODO: Add Python 3.8 once it's released. ) else: raise Exception('Compiler %s not supported.' % args.compiler) @@ -1340,9 +1349,10 @@ argp.add_argument( choices=[ 'default', 'gcc4.4', 'gcc4.6', 'gcc4.8', 'gcc4.9', 'gcc5.3', 'gcc7.2', 'gcc_musl', 'clang3.4', 'clang3.5', 'clang3.6', 'clang3.7', 'clang7.0', - 'python2.7', 'python3.4', 'python3.5', 'python3.6', 'python3.7', 'pypy', - 'pypy3', 'python_alpine', 'all_the_cpythons', 'electron1.3', - 'electron1.6', 'coreclr', 'cmake', 'cmake_vs2015', 'cmake_vs2017' + 'python2.7', 'python3.4', 'python3.5', 'python3.6', 'python3.7', + 'python3.8', 'pypy', 'pypy3', 'python_alpine', 'all_the_cpythons', + 'electron1.3', 'electron1.6', 'coreclr', 'cmake', 'cmake_vs2015', + 'cmake_vs2017' ], default='default', help=